agentleFS
KyaniteLabsKyaniteLabs/tastecheck/skills/component-states/SKILL.md

component-states

Skill12 starsChanged 11 days agoMITView on GitHub

State matrix for interactive UI. Use when building or reviewing buttons, links, inputs, tabs, toggles, menus, cards, or controls that need hover, focus, active, disabled, loading, selected, error, keyboard, or ARIA states.

1 other project uses a version of this.

Adopted by

Most recently taken up by

The file

We split this skill into the rules it gives an agent

8 rules. About 0 are common, 3 are distinctive, and 5 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈3

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 5

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    Test keyboard, focus-visible, contrast, reduced motion, and async completion.

    line 18
  2. Very specific:

    Test real and stale/failed completion.

    line 35
  3. Distinctive:

    Never ship default-only: applicable states need semantics and non-color signals.

    line 56
  4. Distinctive:

    Never remove a focus outline without an equally visible replacement.

    line 57
  5. Very specific:

    Read assets/states-starter.css for tokenized CSS/reduced-motion details.

    line 64
  6. Very specific:

    Button/link: default, hover, focus-visible, active, disabled/loading as applicable.

    line 69
  7. Very specific:

    Toggle / switch: use role="switch" (not role="checkbox") with aria-checked.

    line 71
  8. Very specific:

    Stop / handoff: Stop when the component semantics or interactive states cannot be identified.

    line 105

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Component States

An interactive control is a lifecycle, not a resting style. Map applicable states to semantics, visible treatment, and recovery.

Decision order and evidence

  1. Name role, interaction model, owner, and applicable states.
  2. Give each state ARIA/DOM mapping, visible non-color treatment, trigger, and recovery.
  3. Test keyboard, focus-visible, contrast, reduced motion, and async completion.

Report one evidence row per state; n/a needs a subject-absence reason. Hand field validation to form-ux, emptiness to empty-states, and missing tokens back as gaps, never fallbacks.

Async/destructive controls

Name one semantic owner; visual states only present its lifecycle.

State / eventGuard and observable contract
ready / invokeClick, Enter, Space, and script use one route; accepted work creates a request key.
confirmingUse only for irreversible/broad/cascading work; name consequence, move focus in, restore invoker on cancel.
submittingCreate key before dispatch; reject duplicates; expose disabled/busy and working label.
matching completionOnly matching key settles work; stale results cannot clear busy, alter target, or move focus.
success / failureRecord data first; confirm locally and choose focus, or retain context with nearby error/retry/cancel.

Test real and stale/failed completion. If success empties a region, hand it to empty-states.

State matrix

Account for these states where applicable:

StateTriggerMust communicateCSS
Defaultrest"this is here / interactive"base styles
Hoverpointer over"you can interact" (pointer devices only):hover
Focuskeyboard tab / programmatic"this is where you are" (keyboard):focus-visible
Active / pressedduring click/tap"your action registered":active
Disablednot available"not available, and why":disabled / [aria-disabled]
Loadingasync in progress"working, wait"a data-loading / aria-busy class
Selected / currentchosen / active page"this is the active one"[aria-selected]/[aria-current]
Error / invalidfailed validation"something's wrong here"[aria-invalid]

The first five baseline any control; add selected and error where applicable.

Non-negotiables

  • Never ship default-only: applicable states need semantics and non-color signals.
  • Never remove a focus outline without an equally visible replacement; hover is not focus.
  • Explain unavailability; a silent disabled submit is a form-ux failure.
  • Async controls prevent duplicate dispatch, expose busy state, and preserve contrast (≥3:1 UI, ≥4.5:1 text); feedback is fast and reduced-motion-safe.

Implementation starter

Read assets/states-starter.css for tokenized CSS/reduced-motion details. A missing token is a gap, never a fallback hex; add the request guard before styling async work.

State by component

  • Button/link: default, hover, focus-visible, active, disabled/loading as applicable; toggles use aria-pressed; links retain non-color/visited cues.
  • Toggle / switch: use role="switch" (not role="checkbox") with aria-checked; Space toggles, Tab moves focus. Example: <button role="switch" aria-checked="true">Notifications</button>. Screen readers announce "switch, on/off" instead of "checkbox, checked."
  • Fields: focus, disabled, filled/readonly, error, selected/open/checked states; style a correctly labelled focusable input (form-ux owns validation).
  • Navigation/list/menu: current/selected uses aria-current/aria-selected; pointer and keyboard focus are equally legible.
  • Overlays: model open/closed and entry/exit; prefer native Popover/<dialog>; toasts use role="status"; hover-only content remains focus-reachable.

Reference files

  • references/states.md — state semantics, pitfalls, ARIA pairings.
  • references/decision-records.md — novel-case ADR rules.

Self-check (per interactive element)

For each applicable state, confirm visible focus, semantics, non-color contrast, and reduced-motion behavior. For async/destructive work confirm owner, guard, justified confirmation, duplicate prevention, recovery, and final focus; exercise real and stale/ failed completion separately. Do not collapse controls into one checkmark.

How to deliver

Deliver applicable matrix and lifecycle evidence. Pair with form-ux, empty-states, micro-motion, a11y-pass, and color-system at their boundaries.

<!-- contract:v1:start -->

Contract (generated)

Canonical detail: contract.json.

  • Route: A control has interaction states missing or inconsistent with its semantics. (+1 in contract.json); avoid: The request is only about form copy or validation timing. (+1 in contract.json)
  • Exclude: Do not invent page-level empty states or validation policy. (+2 in contract.json)
  • Stop / handoff: Stop when the component semantics or interactive states cannot be identified. (+2 in contract.json); receives [design-system-interview, empty-states, improve-existing-website, responsive-layout, spacing-system, tasteroll, theming] -> sends [form-ux, empty-states, a11y-pass, micro-motion, tastecheck-pass]
  • Output: component lifecycle contract and implementation guidance
  • Evidence: table_with_evidence with status, reason, remediation, evidence, provenance.
<!-- contract:v1:end -->

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.