From 7a74c6e186476ff320f9568ffab7f9a19a69cb7d Mon Sep 17 00:00:00 2001 From: HardMax71 Date: Fri, 2 Oct 2026 16:40:59 +0200 Subject: [PATCH] fix(attachments): show the remove button on keyboard focus and touch In the grid and inline variants the remove button was opacity-0 until group-hover. Tab focus landed on a button that stayed invisible, and Tailwind v4 wraps hover variants in @media (hover: hover), so on touch screens the button never appeared. It now also shows on focus-visible and on coarse pointers. --- .changeset/attachments-remove-button-focus.md | 5 +++ .../components/(chatbot)/attachments.mdx | 2 +- .../elements/__tests__/attachments.test.tsx | 45 +++++++++++++++++++ packages/elements/src/attachments.tsx | 4 +- 4 files changed, 53 insertions(+), 3 deletions(-) create mode 100644 .changeset/attachments-remove-button-focus.md create mode 100644 packages/elements/__tests__/attachments.test.tsx diff --git a/.changeset/attachments-remove-button-focus.md b/.changeset/attachments-remove-button-focus.md new file mode 100644 index 00000000..371e6b4b --- /dev/null +++ b/.changeset/attachments-remove-button-focus.md @@ -0,0 +1,5 @@ +--- +"ai-elements": patch +--- + +Show the AttachmentRemove button on keyboard focus and on touch screens diff --git a/apps/docs/content/components/(chatbot)/attachments.mdx b/apps/docs/content/components/(chatbot)/attachments.mdx index 0302fdf4..125b734b 100644 --- a/apps/docs/content/components/(chatbot)/attachments.mdx +++ b/apps/docs/content/components/(chatbot)/attachments.mdx @@ -165,7 +165,7 @@ Displays the filename and optional media type. ### `` -Remove button that appears on hover. +Remove button that appears on hover or keyboard focus. It is always visible on touch screens and in the `list` variant. { + it("is visible on keyboard focus and on touch screens in the grid variant", () => { + render( + + + + + + ); + + expect(screen.getByRole("button", { name: "Remove" })).toHaveClass( + "focus-visible:opacity-100", + "pointer-coarse:opacity-100" + ); + }); + + it("is visible on keyboard focus and on touch screens in the inline variant", () => { + render( + + + + + + ); + + expect(screen.getByRole("button", { name: "Remove" })).toHaveClass( + "focus-visible:opacity-100", + "pointer-coarse:opacity-100" + ); + }); +}); diff --git a/packages/elements/src/attachments.tsx b/packages/elements/src/attachments.tsx index cc7b2495..3c010ed0 100644 --- a/packages/elements/src/attachments.tsx +++ b/packages/elements/src/attachments.tsx @@ -342,13 +342,13 @@ export const AttachmentRemove = ({ variant === "grid" && [ "absolute top-2 right-2 size-6 rounded-full p-0", "bg-background/80 backdrop-blur-sm", - "opacity-0 transition-opacity group-hover:opacity-100", + "opacity-0 transition-opacity group-hover:opacity-100 focus-visible:opacity-100 pointer-coarse:opacity-100", "hover:bg-background", "[&>svg]:size-3", ], variant === "inline" && [ "size-5 rounded p-0", - "opacity-0 transition-opacity group-hover:opacity-100", + "opacity-0 transition-opacity group-hover:opacity-100 focus-visible:opacity-100 pointer-coarse:opacity-100", "[&>svg]:size-2.5", ], variant === "list" && ["size-8 shrink-0 rounded p-0", "[&>svg]:size-4"],