Build an accessible attachment list
Announce attachment progress and expose state-aware download and removal actions.Description
Requirements
Export an AttachmentList component from src/App.tsx.
Render one named list with one stable list item for each attachment.
Expose each file name and include it in the accessible name of row actions and progress.
For uploading entries, render a clamped determinate progressbar from progress zero through one.
Announce meaningful status changes without repeating unchanged state on every render.
Enable download only for uploaded attachments with a nonempty downloadUrl and invoke onDownload once.
Expose a remove button for every attachment and invoke onRemove with the matching descriptor.
Disable both actions for a row while either returned promise is pending, preventing duplicate calls.
Preserve caller order across progress and status updates, keyed by attachment ID.
Do not mutate, sort, or add fields to the array or attachment objects.
Upload progress
report.pdf is uploading at progress 0.42
Its row exposes a 42% progressbar named with report.pdf
Progress is connected to the file rather than announced as an unlabeled number.
Uploaded action
notes.txt becomes uploaded with a downloadUrl
Download notes.txt becomes available while Remove notes.txt remains available
Actions describe both intent and target file.
Constraints
Treat IDs as stable attachment identitiesClamp progress for display without changing the inputDo not announce the initial status inventory as a transition
Hints
Hint 1
Keep pending action IDs and prior statuses in component-owned maps or sets.
Hint 2
Generate action labels from the attachment name so identical icons stay distinguishable.
Hint 3
Compare status by ID after each update and write only changed transitions to a stable live region.