Skip to content

Commit 159a706

Browse files
committed
fix(chat): reveal the remove control on keyboard focus
On a fine pointer the badge is transparent until hover, so tabbing to it left a sighted keyboard user unable to see which attachment Enter would remove. The focus-visible chain carries higher specificity than the hide rule, so it wins regardless of source order.
1 parent 839d8eb commit 159a706

2 files changed

Lines changed: 13 additions & 2 deletions

File tree

apps/sim/app/workspace/[workspaceId]/home/components/user-input/components/attached-files-list/attached-files-list.test.tsx

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,16 @@ describe('AttachedFilesList', () => {
7373
expect(wrapper?.className).toMatch(/max-w-/)
7474
})
7575

76+
it('reveals the remove control on keyboard focus, not only on hover', () => {
77+
render([file({})])
78+
79+
const remove = container.querySelector('button[aria-label^="Remove"]')
80+
// Hidden only where a pointer can reveal it, and focus has to reveal it there too —
81+
// otherwise a keyboard user tabs onto a fully transparent control.
82+
expect(remove?.className).toContain('hover-hover:opacity-0')
83+
expect(remove?.className).toContain('hover-hover:focus-visible:opacity-100')
84+
})
85+
7686
it('drops the image and reveals the type icon when the preview fails to decode', () => {
7787
render([file({ name: 'photo.heic', type: 'image/heic', previewUrl: '/api/files/serve/x' })])
7888

apps/sim/app/workspace/[workspaceId]/home/components/user-input/components/attached-files-list/attached-files-list.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -116,8 +116,9 @@ const AttachedFileChip = React.memo(function AttachedFileChip({
116116
}}
117117
aria-label={`Remove ${file.name}`}
118118
/* Visible by default so a coarse pointer never has to discover it through an
119-
emulated hover; fine pointers get the reveal-on-hover treatment. */
120-
className='absolute top-[2px] right-[2px] flex size-[16px] items-center justify-center rounded-full border border-[var(--border)] bg-[var(--surface-2)] text-[var(--text-body)] transition-opacity hover-hover:opacity-0 hover-hover:group-hover:opacity-100'
119+
emulated hover; fine pointers get reveal-on-hover, plus reveal-on-focus so
120+
it is never transparent while it holds the keyboard focus. */
121+
className='absolute top-[2px] right-[2px] flex size-[16px] items-center justify-center rounded-full border border-[var(--border)] bg-[var(--surface-2)] text-[var(--text-body)] transition-opacity hover-hover:opacity-0 hover-hover:focus-visible:opacity-100 hover-hover:group-hover:opacity-100'
121122
>
122123
<X className='size-[10px]' />
123124
</button>

0 commit comments

Comments
 (0)