a11y(frontend): focus rings, ARIA labels, skip-link across ui components
This commit is contained in:
+57
-1
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user