a11y(frontend): focus rings, ARIA labels, skip-link across ui components

This commit is contained in:
Tyler
2026-06-20 16:51:36 -06:00
parent b980e77cf2
commit b37fb5a26c
8 changed files with 113 additions and 10 deletions
+57 -1
View File
@@ -144,12 +144,28 @@
background-clip: content-box;
}
/* Focus ring — accent, 2px, with offset */
/* Focus ring — accent, 2px, with offset.
Components override this with Tailwind focus-visible:ring-* utilities
for a ring+offset combo that matches the rest of the design system.
This base rule covers anything that doesn't opt in (links in
prose, native checkboxes, etc.). */
:focus-visible {
outline: 2px solid hsl(var(--ring));
outline-offset: 2px;
border-radius: 6px;
}
/* Respect reduced-motion users globally. */
@media (prefers-reduced-motion: reduce) {
*,
*::before,
*::after {
animation-duration: 0.001ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.001ms !important;
scroll-behavior: auto !important;
}
}
}
@layer components {
@@ -197,6 +213,46 @@
box-shadow: 0 0 12px hsl(var(--accent) / 0.5);
}
/* Skip link — invisible until focused. Sits above the scan element on
first paint so it is the first Tab stop in the app. */
.skip-link {
position: fixed;
top: 0.75rem;
left: 0.75rem;
z-index: 100;
display: inline-flex;
align-items: center;
height: 2.25rem;
padding: 0 0.875rem;
border-radius: 0.625rem;
background-color: hsl(var(--card));
color: hsl(var(--foreground));
border: 1px solid hsl(var(--border));
box-shadow:
inset 0 1px 0 0 hsl(0 0% 100% / 0.04),
0 8px 24px hsl(0 0% 0% / 0.45);
font-size: 12.5px;
font-weight: 600;
letter-spacing: 0.01em;
transform: translateY(-200%);
transition: transform 150ms ease-out;
}
.skip-link:focus-visible {
transform: translateY(0);
outline: none;
box-shadow:
inset 0 1px 0 0 hsl(0 0% 100% / 0.04),
0 0 0 2px hsl(var(--background)),
0 0 0 4px hsl(var(--ring)),
0 8px 24px hsl(0 0% 0% / 0.45);
}
/* Reduced motion: skip the slide. */
@media (prefers-reduced-motion: reduce) {
.skip-link {
transition: none;
}
}
/* Keyboard hint chip */
.kbd {
display: inline-flex;