Build & Push Docker Image / build (push) Has been cancelled
Refresh the homepage around new hero/services/roadmap sections, shared design tokens, and updated brand assets. Co-authored-by: Cursor <cursoragent@cursor.com>
2.7 KiB
2.7 KiB
Accessibility
Accessibility is priority #1 in the design system hierarchy. Visual polish never overrides perceivable, operable UI.
Color contrast
- Body text (
foregroundonbackground) and muted text must remain readable in both themes. - Do not place
muted-foregroundon muted backgrounds without checking contrast. - Primary buttons use white label on
#29a19c—do not lower primary opacity on labels. - Never convey meaning by color alone (pair with text/icon).
Focus ring
Visible focus is mandatory for keyboard users.
| Control | Pattern |
|---|---|
| Button | focus-visible:ring-[3px] focus-visible:ring-ring/40 focus-visible:border-ring |
| Input | focus-visible:ring-[3px] focus-visible:ring-primary/25 focus-visible:border-primary |
| Generic | Prefer ring tokens; never outline-none without replacement |
Do not remove focus styles from cards/links that are interactive.
Keyboard navigation
- All buttons, links, and controls reachable via Tab.
- Menus / sheets / dialogs use Radix primitives (focus trap + Escape).
- Maintain logical RTL tab order; avoid positive
tabIndexexcept when necessary. - Icon-only controls need accessible names.
ARIA expectations
| Case | Requirement |
|---|---|
| Icon button | aria-label |
| Decorative icon/image | aria-hidden / empty alt |
| Expandable | aria-expanded + controls id |
| Dialogs / sheets | Titled (SheetTitle, DialogTitle) — sr-only if visually hidden |
| Invalid fields | aria-invalid + error text |
| Landmark nav | aria-label on primary <nav> |
| Decorative sections | aria-hidden on .section-decor |
Prefer native semantics (button, a, label) before ARIA.
Reduced motion
- Honor
prefers-reduced-motion. MotionRevealalready disables motion.- New CSS animations need a reduced-motion override.
- Do not autoplay motion-critical content.
Touch targets
| Control | Minimum |
|---|---|
| Default button | 40×40 (h-10) |
| Large button | 48×48 |
| Icon button | 40×40 |
| Compact button | 32×32 — avoid for primary mobile actions |
| Input | ≥ 36px height (h-9); 48px when paired with lg submit |
Forms
- Visible labels (not placeholder-only).
- Error text associated with fields.
- Preserve browser autofill / zoom-safe 16px text on mobile inputs.
Images & media
- Meaningful
alt. - Do not flash high-contrast animations.
Checklist snippet
- Keyboard only can complete the flow
- Focus visible on all interactive elements
- Contrast OK in light and dark
- Reduced motion OK
- SR labels on icon buttons
- No keyboard trap outside modals
Related
- forms.md
- motion.md
- dark-mode.md
- Cursor rule:
.cursor/rules/accessibility.mdc