LibreChat/packages/client
Marco Beretta 26ba2c2954
️ a11y: improve keyboard operability, focus retention, and accessible naming (#14600)
* fix: improve accessibility with semantic HTML and keyboard support

* fix: preserve focus on attachments and stop CSS leaking into label text

Passing `Wrapper` to FileRow as an inline arrow made it a new component type on
every render, so React remounted the whole file row. A keyboard user who tabbed
to an attachment thumbnail lost focus to <body> the moment the upload settled.
Hoist the wrappers to module scope so their identity is stable.

BlinkAnimation rendered a <style> tag into the DOM; stylesheet text becomes part
of the ancestor's textContent and leaks raw CSS into label readouts. Move the
keyframes into the tailwind config, named logo-blink to avoid colliding with the
existing `blink` keyframes in style.css, and honour prefers-reduced-motion.

* fix: make preset row actions reachable by keyboard

The pin, edit and delete buttons on a preset row were hidden with `invisible`,
which sets visibility: hidden and removes them from the tab order entirely. The
`group-focus-within` variant meant to reveal them never fired, because nothing
inside the row ever receives DOM focus during keyboard navigation. Verified in a
browser: arrowing and tabbing through the presets menu skipped the row and the
buttons reported focusable: false, while hovering made them focusable.

Hide them with opacity instead, which keeps them in the tab order, and reveal on
focus as well as hover. At rest they still compute to opacity 0, so there is no
visual change.

* fix: harden a11y heading, Space activation, and preset hit targets

Gate the page heading on a title that matches the routed conversation so
stale Recoil state is not announced during navigation. Ignore key-repeat
on role=button TooltipAnchor activation while still blocking Space scroll.
Disable pointer events on transparent preset actions until hover or focus.

* fix: address a11y review follow-ups and eslint formatting

Use the shared layout test harness for ChatView heading tests, default
role=button TooltipAnchors into the tab order, ship spinner keyframes in
package CSS, and let native preset buttons handle activation once.
2026-08-05 13:03:30 -04:00
..
src ️ a11y: improve keyboard operability, focus retention, and accessible naming (#14600) 2026-08-05 13:03:30 -04:00
babel.config.js 🪟 feat: DataTable update + Various UI enhancements (#9698) 2025-12-11 16:39:06 -05:00
jest.config.js ⬆️ chore: Migrate off deprecated @ariakit/react-core to @ariakit/react-components (#13940) 2026-06-24 23:13:57 -04:00
jest.resolver.cjs ⬆️ chore: Migrate off deprecated @ariakit/react-core to @ariakit/react-components (#13940) 2026-06-24 23:13:57 -04:00
jest.setup.ts 🪟 feat: DataTable update + Various UI enhancements (#9698) 2025-12-11 16:39:06 -05:00
package.json 🌯 chore: Retire Rollup-Era devDependencies After tsdown Migration (#14496) 2026-07-28 22:08:52 -04:00
tailwind.config.js
tsconfig.json refactor: Migrate @librechat/client build to tsdown (#13596) 2026-06-08 11:20:03 -04:00
tsconfig.test.json 🪟 feat: DataTable update + Various UI enhancements (#9698) 2025-12-11 16:39:06 -05:00
tsdown.config.mjs 🌀 ci: Deterministic Circular Dependency Checks (#14579) 2026-08-01 14:43:26 -04:00