Skip to content

Composer attachments wrap into rows: twenty files is ~850px of composer, and it should be a carousel #927

Description

@DEENUU1

Attachments in the chat composer are a wrapping grid of full-size file cards. One
file already looks wedged between the usage strip and the input; twenty files push
the transcript off the screen.

The arithmetic

frontend/src/components/chat/chat-input.tsx:339 lays them out as:

<div className="flex flex-wrap items-start gap-2 pb-2">

Each card is FileCard, which is w-56 (224px) and about 120px tall - a name
row, a 64px thumbnail or preview block, and a type/size line
(src/components/files/file-card.tsx:63). At a typical chat column that is three
cards to a row, so:

Files Rows Composer grows by
1 1 ~120px
6 2 ~250px
20 7 ~850px

There is no max-height, no scroll container and no cap on how many can be
attached, so twenty files is a composer taller than the viewport with the message
box somewhere below the fold.

What it should be

A single-row carousel, directly above the input. One row, fixed height,
horizontal scroll - snap points, arrows for pointer users on hover, keyboard
reachable, and the count visible somewhere so "how many did I attach" is
answerable without scrolling the row.

And a compact card for the composer. The 64px-thumbnail card is right where
#133 put it - in the transcript, where a file is content somebody reads. In the
composer a file is a pending thing being confirmed, and the useful facts are:
is it the right file, how big, and how do I remove it. A chip-height card - 32px
thumb or icon, truncated name, size, × - fits five or six across the same width
and makes the row legible at twenty.

That is a compact variant of FileCard, not a fourth card component. #136
collapsed four file viewers and three notions of "what kind of file is this" into
one for exactly this reason, and FileCard is now what the transcript, the Files
panel, the workspace browser and the run timeline all draw. A composer-only card
would be the fifth.

Details worth deciding once:

  • Pending uploads share the row, in the order they were dropped, so a file
    does not jump position when its upload finishes.
  • Remove stays reachable at every size - the current × is a 12px icon in the
    card corner; at chip height it needs its own hit area, and the aria-label
    already exists (removeAttachment).
  • A ceiling, or not. Twenty is a fine number of files to attach and a bad
    number to render; scrolling handles the render. Whether the upload should be
    capped is a separate question and belongs with Chat uploads are capped at a hardcoded 10MB while every setting says 50 #498 (uploads capped at a
    hardcoded 10MB while every setting says 50), not here.
  • The strip is its own band above the input, not a block wedged between the
    usage strip (Context 4.8% · $0.0099 · workspace 1% full) and the textarea.
    Today those three read as one confused header; the attachments belong visually
    attached to the input they are about.

Done when

  • Any number of attachments occupies one row of fixed height, scrolled
    horizontally, with the composer's own height unchanged.
  • The card in the composer is a compact variant of FileCard, shared, not a new
    component.
  • The row sits above the input as its own band, distinct from the usage strip.
  • A test mounts the composer with twenty attachments and asserts one row - the
    kind of assertion that fails if somebody restores the wrap.

Related

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

effort:mA day or twoenhancementNew feature or requestfrontendNext.js app, BFF proxies, permission gating

Projects

  • Status
    Done

Relationships

None yet

Development

No branches or pull requests

Issue actions