diff --git a/src/uix/soma/components/link-preview/README.md b/src/uix/soma/components/link-preview/README.md index 9a59bfc2e..fdf46a8df 100644 --- a/src/uix/soma/components/link-preview/README.md +++ b/src/uix/soma/components/link-preview/README.md @@ -30,7 +30,28 @@ A floating preview card that appears on hover over a link. Supports configurable | ------- | ------------- | ------ | | Content | `aria-hidden` | `true` | -The preview content is intentionally hidden from assistive technology — it is a visual convenience only. The underlying link remains fully accessible. +## Accessibility + +**LinkPreview is invisible to assistive technology by design.** The floating +preview card exists for sighted-hover discovery only — it adds no +information a screen-reader user could not already reach through the +underlying `` element. Emitting `aria-hidden="true"` on `Content` is a +deliberate choice: + +- **Duplicate content:** the preview typically mirrors the destination page + summary that a screen reader would announce after following the link. + Re-reading it as a tooltip is noise, not help. +- **Hover-only activation:** APG explicitly recommends against exposing + pure-hover widgets to assistive tech because keyboard / touch users never + see them anyway — making them invisible everyone except mouse hover is + the consistent experience. +- **Focus stays on the trigger:** the preview never steals focus, never + traps Tab, and closes automatically on blur. There is nothing for a + keyboard / AT user to miss. + +If your LinkPreview contains content that is NOT in the destination page +(a custom CTA, a badge, a pricing hint), consider using `Popover` or +`Tooltip` instead — both are AT-visible. ## Data Attributes diff --git a/src/uix/soma/components/tag-group/tag-group-provider.svelte.ts b/src/uix/soma/components/tag-group/tag-group-provider.svelte.ts index ead119ba6..fd721abc0 100644 --- a/src/uix/soma/components/tag-group/tag-group-provider.svelte.ts +++ b/src/uix/soma/components/tag-group/tag-group-provider.svelte.ts @@ -156,7 +156,11 @@ export class TagGroupProvider extends Provider { handleItemKeydown(e: SomaKeyboardEvent, value: string) { if (this.opts.disabled.current) return; const dir = this.resolvedDir.current; + // Horizontal flips under RTL; vertical doesn't (UP / DOWN are absolute + // per APG). Using `getDirectionalKeys` for both axes keeps the shape + // symmetric — consistent with other components that navigate grids. const { nextKey, prevKey } = getDirectionalKeys(dir, 'horizontal'); + const { nextKey: downKey, prevKey: upKey } = getDirectionalKeys(dir, 'vertical'); const items = this.getItems(); if (items.length === 0) return; const currentIndex = items.indexOf(e.currentTarget); @@ -171,9 +175,9 @@ export class TagGroupProvider extends Provider { this.focusAt(currentIndex - 1); return; } - if (e.key === KEYS.ARROW_DOWN || e.key === KEYS.ARROW_UP) { + if (e.key === downKey || e.key === upKey) { e.preventDefault(); - const delta = e.key === KEYS.ARROW_DOWN ? 1 : -1; + const delta = e.key === downKey ? 1 : -1; this.focusAt(currentIndex + delta); return; }