# What Is the 8-State Component Checklist in Hallmark?

> Understand the 8-state component checklist in Hallmark. Ensure comprehensive UI accessibility and user experience with Default, Hover, Focus, Active, Disabled, Loading, Error, and Success states.

- Repository: [Hassan El Mghari/hallmark](https://github.com/Nutlope/hallmark)
- Tags: deep-dive
- Published: 2026-07-13

---

**The 8-state component checklist in Hallmark requires every interactive UI component to implement eight distinct states—Default, Hover, Focus, Active/Pressed, Disabled, Loading, Error, and Success—ensuring comprehensive accessibility and user experience coverage.**

The Hallmark design system, maintained in the `Nutlope/hallmark` repository, enforces a rigorous quality standard through its **8-state component checklist**. This methodology mandates that every interactive element must account for the full spectrum of user interactions, from initial render through completion or failure states, as defined in [`skills/hallmark/references/interaction-and-states.md`](https://github.com/Nutlope/hallmark/blob/main/skills/hallmark/references/interaction-and-states.md).

## The Eight Required Component States

According to the repository's interaction guidelines, each state serves a specific purpose in the user experience:

1. **Default** — The resting state with no user interaction. Use solid borders, neutral backgrounds, and muted placeholder text.

2. **Hover** — Triggered when a pointer rests over the element, but only when `@media (hover: hover)` is true. The treatment must maintain constant border width while optionally shifting colors or applying a 1px translate.

3. **Focus** — Keyboard or programmatic focus via `:focus-visible`. Requires a visible focus ring using `outline: 2px solid var(--color-focus)` with no layout shift.

4. **Active / Pressed** — The moment of interaction (click/tap). Implement darker backgrounds or press-in effects (e.g., `translate(0 1px)`), keeping borders consistent.

5. **Disabled** — Non-interactive elements. Set `opacity: 0.5`, `cursor: not-allowed`, `aria-disabled="true"`, and `tabindex="-1"`.

6. **Loading** — Async processing states. Display inline spinners, keep labels readable, and mark with `aria-busy="true"`.

7. **Error** — Failed validation or operations. Apply red borders, set `aria-invalid="true"`, and replace helper text with error messages.

8. **Success** — Completed operations. Show green checkmarks or success accents with subtle border changes.

## Implementation Guide

### HTML Structure

Start with semantic markup that includes ARIA attributes to support the state system:

```html
<button
  class="btn"
  aria-disabled="false"
  aria-busy="false"
  aria-invalid="false">
  Submit
</button>

```

### CSS Implementation

The [`interaction-and-states.md`](https://github.com/Nutlope/hallmark/blob/main/interaction-and-states.md) reference specifies precise CSS patterns for each state, including media queries for hover support and transparent outline reservations for focus rings:

```css
.btn {
  border: 1px solid var(--color-rule-2);
  background: var(--color-paper);
  color: var(--color-ink);
  cursor: pointer;
  outline: 2px solid transparent;          /* reserve slot for focus ring */
  transition: background 0.15s, outline 0.15s;
}

/* Hover – only on devices that support hover */
@media (hover: hover) {
  .btn:hover {
    background: var(--color-paper-2);
  }
}

/* Focus – keyboard focus */
.btn:focus-visible {
  outline-color: var(--color-focus);
  outline-offset: 2px;
}

/* Active / pressed */
.btn:active {
  background: var(--color-paper-3);
  transform: translate(0 1px);
}

/* Disabled */
.btn[aria-disabled="true"] {
  opacity: 0.5;
  cursor: not-allowed;
}

/* Loading */
.btn[aria-busy="true"] {
  position: relative;
  color: transparent;                     /* hide label */
}
.btn[aria-busy="true"]::after {
  content: "";
  position: absolute;
  inset: 0;
  background: url('/spinner.svg') center no-repeat;
}

/* Error */
.btn[aria-invalid="true"] {
  border-color: var(--color-error);
}

/* Success */
.btn.success {
  border-color: var(--color-success);
  background: var(--color-success-bg);
}

```

### Component Preview Pattern

The [`component-cookbook.md`](https://github.com/Nutlope/hallmark/blob/main/component-cookbook.md) file recommends creating a preview wrapper that renders all eight states simultaneously for visual auditing:

```tsx
// ComponentName.preview.tsx
import { ComponentName } from './ComponentName';

export default function Preview() {
  return (
    <>
      <h3>Default</h3><ComponentName />
      <h3>Hover</h3><ComponentName className="hover" />
      <h3>Focus</h3><ComponentName className="focus" />
      <h3>Active</h3><ComponentName className="active" />
      <h3>Disabled</h3><ComponentName disabled />
      <h3>Loading</h3><ComponentName loading />
      <h3>Error</h3><ComponentName error />
      <h3>Success</h3><ComponentName success />
    </>
  );
}

```

## Key Reference Files

The checklist is defined across three critical files in the repository:

- **[`skills/hallmark/references/interaction-and-states.md`](https://github.com/Nutlope/hallmark/blob/main/skills/hallmark/references/interaction-and-states.md)** — Detailed state descriptions, visual guidelines, and CSS recipes
- **[`skills/hallmark/SKILL.md`](https://github.com/Nutlope/hallmark/blob/main/skills/hallmark/SKILL.md)** — High-level requirements referencing the 8-state checklist
- **[`skills/hallmark/references/component-cookbook.md`](https://github.com/Nutlope/hallmark/blob/main/skills/hallmark/references/component-cookbook.md)** — Implementation examples and the demo wrapper pattern

## Summary

- The **8-state component checklist** mandates Default, Hover, Focus, Active, Disabled, Loading, Error, and Success states for every interactive component in the Hallmark system.
- Missing any state results in a failed Hallmark audit, rendering the component unfinished.
- Implementation requires specific ARIA attributes (`aria-disabled`, `aria-busy`, `aria-invalid`) and CSS considerations like `@media (hover: hover)`.
- The [`interaction-and-states.md`](https://github.com/Nutlope/hallmark/blob/main/interaction-and-states.md) file provides the authoritative reference for these requirements.

## Frequently Asked Questions

### What happens if a component is missing one of the eight states?

According to the Hallmark specification in [`SKILL.md`](https://github.com/Nutlope/hallmark/blob/main/SKILL.md), components missing any of the eight required states are considered unfinished and will fail a Hallmark audit. All states must be present and visually distinct before a component can be shipped.

### How should Hover states behave on touch devices?

The Hover state must only apply when `@media (hover: hover)` is true. This prevents sticky hover styles on touch-only devices where hover interactions are not available, ensuring the UI remains clean and predictable.

### Why is the border width required to stay constant during state changes?

Maintaining constant border width during Hover and Active states prevents layout shifts that could cause unexpected reflows or visual instability. This aligns with the Hallmark guideline of "no layout shift" for interactive elements, ensuring smooth transitions between states.

### Where can I find the official documentation for the 8-state checklist?

The canonical reference is located in [`skills/hallmark/references/interaction-and-states.md`](https://github.com/Nutlope/hallmark/blob/main/skills/hallmark/references/interaction-and-states.md) within the Nutlope/hallmark repository, with high-level requirements outlined in [`skills/hallmark/SKILL.md`](https://github.com/Nutlope/hallmark/blob/main/skills/hallmark/SKILL.md). The [`component-cookbook.md`](https://github.com/Nutlope/hallmark/blob/main/component-cookbook.md) file provides practical implementation examples.