Skip to content

Component Checklist

This is the checklist I use when building UI components.

It keeps quality consistent as the component library grows, and it prevents small issues from turning into long-term UI debt.

  • What problem does this component solve?
  • Where will it be used?
  • What are the expected variants and states?
  • What should the default behavior be?
  • Component name is clear and consistent
  • Props are minimal and intentional
  • Sensible defaults are provided
  • The component is composable (slots/children where appropriate)
  • No “magic” behavior hidden behind props

At minimum, every component should define:

  • Default state
  • Hover + active behavior (if interactive)
  • Focus-visible behavior
  • Disabled state
  • Loading state (if relevant)
  • Error state (if relevant)

If the component supports variants:

  • Variants are documented and consistent
  • Variant naming matches design intent (not implementation details)
  • No variant overlaps or confusing edge cases
  • Keyboard navigation works as expected
  • Focus states are visible and intentional
  • Labels and names are correct (especially for form components)
  • ARIA is only used when necessary
  • Color contrast holds up in light and dark mode
  • Reduced motion is respected (when animations are involved)
  • Uses semantic tokens (not raw palette values)
  • Spacing matches layout conventions
  • Borders/shadows follow the system’s visual language
  • Works in both light and dark themes
  • Includes a minimal usage snippet
  • Includes key do/don’t guidance when misuse is likely
  • Describes intended use cases (and non-goals) if helpful

Every component should have Storybook stories that document:

  • Default usage
  • Variants
  • Sizes (if supported)
  • Key states (disabled/loading/error)
  • Edge cases (long text, icons, narrow containers)
  • Stories are stable (no random data, no time-based rendering)
  • The component is visually testable in isolation
  • Any intentional visual change is reviewed and approved
  • Avoids unnecessary re-renders or watchers
  • No layout shift (especially loading states)
  • Handles slow/late JS gracefully (when relevant)
  • Works at small screen sizes
  • Handles long labels/content gracefully
  • Doesn’t break layout when nested in real pages
  • No console warnings or runtime errors
  • The component is easy to use without reading the source code

The goal isn’t perfection, it’s consistency.

A component system scales when every component follows the same expectations, even as the library grows and priorities shift.