Skip to content

fix(card): interactive variant lacks semantic guidance, no ARIA states, no reduced-motion #42

Description

@Samyssmile

Problem

The ct-card component — specifically the ct-card--interactive variant — is semantically underspecified and encourages accessibility anti-patterns.

1. Interactive variant has no semantic guidance

ct-card--interactive adds cursor: pointer and :focus-visible styles, but gives no indication of what HTML element should be used. This makes it trivially easy to create a clickable <div>, which is a WCAG failure (no keyboard activation, no role, no accessible name). The CSS should either scope the interactive styles to a.ct-card--interactive / button.ct-card--interactive, or the pattern needs strong documentation.

2. No ARIA state selectors

The interactive card has no styles for common states:

  • No aria-selected (for selectable card grids)
  • No aria-expanded (for cards that toggle content)
  • No data-state (for active/loading/disabled states)

Other components handle this well — Toggle Group uses aria-pressed, Tabs uses aria-selected, Chip uses aria-pressed.

3. No aria-labelledby pattern

A card rendered as <section> needs an accessible name. The merge conflict in CardAndTable.stories.js exposes this gap: the stricter version requires aria-labelledby referencing the card heading, while the current version doesn't enforce it at all. Without this, screen reader users get an unnamed region landmark.

4. Missing prefers-reduced-motion

The interactive card has transition: box-shadow, border-color but no @media (prefers-reduced-motion: reduce) block. This is inconsistent with Accordion, Toast, Dropdown, Sidebar, and Datepicker which all respect this.

5. No disabled state

Unlike Button, FormControls, and ToggleGroup, the interactive card has no :disabled or [aria-disabled="true"] styling. An interactive element without a disabled state is incomplete.

Expected behavior

  • Add [aria-disabled="true"] styles (opacity, pointer-events, cursor)
  • Add [aria-selected="true"] styles for card-grid selection patterns
  • Add @media (prefers-reduced-motion: reduce) to disable transitions
  • Document that interactive cards must use <a> or <button> (or have role + tabindex)
  • Enforce aria-labelledby on <section> cards in the story/tests

Files

  • components/components.css lines 466–522
  • stories/CardAndTable.stories.js (has unresolved merge conflict)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions