frontend-patterns

star 147

Use when frontend UI work needs accessibility, responsive layout, loading/error states, performance guardrails, or DESIGN.md authoring from screenshots, existing UI, user preferences, or chosen visual inspiration under an approved visual direction.

romiluz13 By romiluz13 schedule Updated 4/23/2026

name: frontend-patterns description: "Use when frontend UI work needs accessibility, responsive layout, loading/error states, performance guardrails, or DESIGN.md authoring from screenshots, existing UI, user preferences, or chosen visual inspiration under an approved visual direction." allowed-tools: Read Grep Glob LSP

Frontend Patterns

Overview

User interfaces exist to help users accomplish tasks. Every UI decision should make the user's task easier or the interface more accessible.

Core principle: Design for user success, not aesthetic preference.

This skill is advisory. Explicit user instructions, CLAUDE.md, repo standards, and approved plans override every suggestion here.

Reference Files

Read only the references needed for the current UI task:

  • references/ui-state-and-feedback.md for loading/error/empty/success ordering, skeleton vs spinner, and mutation feedback
  • references/accessibility-and-forms.md for WCAG-oriented checks, keyboard/focus, labels, form patterns, and mobile usability
  • references/performance-and-layout.md for responsive checks, motion, overflow, URL state, performance guardrails, and light/dark mode checks
  • references/design-md-authoring.md for creating or updating a spec-aligned project-local DESIGN.md from screenshots, existing UI, user preferences, or a selected inspiration style
  • references/design-md-inspiration-index.md only when the user asks for a style reference, brand-like direction, moodboard, or DESIGN.md-style examples

Focus Areas (Reference Pattern)

  • React component architecture (hooks, context, performance)
  • Responsive CSS with Tailwind/CSS-in-JS
  • State management (Redux, Zustand, Context API)
  • Frontend performance (lazy loading, code splitting, memoization)
  • Accessibility (WCAG compliance, ARIA labels, keyboard navigation)

Approach (Reference Pattern)

  1. Component-first thinking - reusable, composable UI pieces
  2. Mobile-first responsive design - start small, scale up
  3. Performance budgets - aim for sub-3s load times
  4. Semantic HTML and proper ARIA attributes
  5. Type safety with TypeScript when applicable

Advisory Guardrails

Use this skill to add:

  • accessibility checks
  • responsive/layout verification
  • performance and loading-state checks
  • optional style ideas when the user explicitly wants them

Do not use this skill to override an explicit visual direction, component contract, or approved workflow.

Component Output Checklist

Every frontend deliverable should include:

  • Complete React component with props interface
  • Styling solution (Tailwind classes or styled-components)
  • State management implementation if needed
  • Basic unit test structure
  • Accessibility checklist for the component
  • Performance considerations and optimizations

Focus on working code over explanations. Include usage examples in comments.

The Iron Law

NO UI DESIGN BEFORE USER FLOW IS UNDERSTOOD

If you haven't mapped what the user is trying to accomplish, you cannot design UI.

Design Thinking (Pre-Code)

Before writing any UI code, commit to answers for:

  1. Purpose: What specific problem does this interface solve?
  2. Tone: Choose an aesthetic direction and commit to it:
    • Brutally minimal, maximalist, retro-futuristic, organic/natural
    • Luxury/refined, playful/toy-like, editorial/magazine, brutalist/raw
    • Art deco/geometric, soft/pastel, industrial/utilitarian
  3. Constraints: Framework requirements, performance budget, accessibility level
  4. Differentiation: What's the ONE thing someone will remember about this UI?

Key insight: Bold maximalism and refined minimalism both work. The enemy is indecision and generic defaults.

DESIGN.md Authoring

Read references/design-md-authoring.md before creating or updating a spec-aligned project-local DESIGN.md, especially when the user provides screenshots, existing UI, visual preferences, or asks the agent to preserve a design direction.

When inspiration is needed, read references/design-md-inspiration-index.md to choose a style family. Treat inspiration as input to the project's own design contract, not as an instruction to copy another company's UI.

Mock-Fidelity Inventory (No Silent Loss)

A build can pass every test and still quietly omit the hero, the signature motif, or whole sections the design called for. Apply VBC's anti-stub "no silent loss" discipline to UI: a green test suite is not proof the design shipped.

Once a design/mock is approved, before coding, INVENTORY its major visible ingredients and decide an implementation path for each:

Ingredient Examples Implementation path
Hero / focal moment Headline + primary CTA, signature visual Build now / phase 2 (explicit) / cut (approved)
Signature motifs Grain, gradients, custom cursor, illustration style Build now / approximate / cut (approved)
Sections Each distinct band/region in the mock Build now / phase 2 (explicit) / cut (approved)
Interactions Hover, scroll, motion, transitions Build now / static fallback / cut (approved)
States Empty/loading/error variants shown in mock Build now (states are not optional)

Every ingredient gets exactly one path. "Cut" and "phase 2" are legitimate, but only when explicitly named — never reached by omission.

Verification — pair this with VBC's Goal-Backward Lens. The goal is the approved design, not the diff. Walk backward from each inventoried ingredient and confirm it is present (or was explicitly deferred/cut). Treat any silently-dropped major ingredient — present in the approved mock, absent in the build, never explicitly deferred — as a P0 fidelity defect, equal in severity to a broken task flow. Report it; do not let a passing test suite paper over it.

UI State References

Read references/ui-state-and-feedback.md before finalizing loading, error, empty, success, or mutation states. Keep the state order explicit; do not invent UI states ad hoc.

Motion & Animation

Rule Do Don't
Reduced motion Honor prefers-reduced-motion Ignore user preferences
Properties Animate transform/opacity only Animate width/height/top/left
Transitions List properties explicitly Use transition: all
Duration 150-300ms for micro-interactions Too fast (<100ms) or slow (>500ms)
Interruptible Allow animation cancellation Lock UI during animation
/* CORRECT: Compositor-friendly, respects preferences */
@media (prefers-reduced-motion: no-preference) {
  .card { transition: transform 200ms ease-out, opacity 200ms ease-out; }
  .card:hover { transform: translateY(-2px); opacity: 0.95; }
}

Accessibility And Forms

Read references/accessibility-and-forms.md when the task touches keyboard navigation, forms, labels, focus, contrast, or touch ergonomics.

Success Criteria Framework

Every UI must have explicit success criteria:

  1. Task completion: Can user complete their goal?
  2. Error recovery: Can user recover from mistakes?
  3. Accessibility: Can all users access it?
  4. Performance: Does it feel responsive?

Layout And Performance References

Read references/performance-and-layout.md for responsive checks, motion rules, overflow handling, URL state, touch/mobile, and color-mode validation.

Universal Questions (Answer First)

ALWAYS answer before designing/reviewing:

  1. What is the user trying to accomplish? - Specific task, not feature
  2. What are the steps? - Click by click
  3. What can go wrong? - Every error state
  4. Who might struggle? - Accessibility needs
  5. What's the existing pattern? - Project conventions

User Flow First

Before any UI work, map the flow:

User Flow: Create Account
1. User lands on signup page
2. User enters email
3. User enters password
4. User confirms password
5. System validates inputs (inline)
6. User clicks submit
7. System processes (loading state)
8. Success: User sees confirmation + redirect
9. Error: User sees error + can retry

For each step, identify:

  • What user sees
  • What user does
  • What feedback they get
  • What can go wrong

UX Review Checklist

Check Criteria Example Issue
Task completion Can user complete goal? Button doesn't work
Discoverability Can user find what they need? Hidden navigation
Feedback Does user know what's happening? No loading state
Error handling Can user recover from errors? No error message
Efficiency Can user complete task quickly? Too many steps

Severity levels:

  • BLOCKS: User cannot complete task
  • IMPAIRS: User can complete but with difficulty
  • MINOR: Small friction, not blocking

Visual Design Checklist

Check Good Bad
Hierarchy Clear visual priority Everything same size
Spacing Consistent rhythm Random gaps
Alignment Elements aligned to grid Misaligned elements
Interactive states Hover/active/focus distinct No state changes
Feedback Clear response to actions Silent interactions

Visual Creativity (Avoid AI Slop)

When creating frontends, avoid generic AI aesthetics:

  • Fonts: Choose distinctive typography, not defaults (avoid Inter, Roboto, Arial, system fonts)
  • Colors: Commit to cohesive palette. Dominant colors with sharp accents > safe gradients
  • Avoid: Purple gradients on white, predictable layouts, cookie-cutter Bootstrap/Tailwind defaults
  • Icons: Use SVG icons (Heroicons, Lucide, Simple Icons). NEVER use emoji as UI icons
  • Cursor: Add cursor-pointer to ALL clickable elements
  • Hover: Use color/opacity transitions. Avoid scale transforms that shift layout
  • Backgrounds: Add depth with subtle textures, gradients, or grain instead of flat colors

Make creative choices that feel designed for the specific context. No two designs should look the same.

Two-Altitude Reflex Check

Generic isn't only the obvious defaults — it's also the predictable dodge away from the defaults. Run both tests before committing a visual direction:

  • First-order test: Could you guess the theme/palette from the category alone? ("Fintech → blue + sans-serif." "AI tool → purple gradient + dark mode.") If yes, it's generic. Reject.
  • Second-order test: Could you guess it from category + anti-references? Once everyone "avoids the purple gradient," the avoidance itself becomes a reflex — fintech that dodges blue lands on the same off-black + lime, AI tools that dodge purple all land on the same warm-beige + serif. If the choice is predictable given what people now flee toward, it's still generic. Reject.

The second test catches dodging reflex #1 straight into reflex #2. The cure for both is the same: derive the direction from the specific product, audience, and content — not from the category or from what the category is currently fleeing.

Reflex-reject lists (maintained, pruned as families saturate):

Reflex-reject fonts Reflex-reject aesthetic lanes
Inter, Roboto, Arial, system-ui defaults Purple/violet gradient on white (AI-tool reflex #1)
Geist / Geist Mono (now over-saturated) Off-black + acid-lime "anti-corporate" (reflex #2)
Space Grotesk as a default "modern" pick Warm-beige + serif "anti-AI" editorial (reflex #2)
Generic Google-Fonts pairing of the month Glassmorphism cards on gradient mesh

Prune a lane out of this list once it genuinely stops being a reflex, and add new families in as they saturate. The list is a moving target on purpose; a stale blocklist becomes its own reflex.

Spatial Composition (Break the Grid)

Move beyond safe, centered layouts:

Technique Effect When to Use
Asymmetry Dynamic tension, visual interest Hero sections, feature highlights
Overlap Depth, connection between elements Cards, images, testimonials
Diagonal flow Energy, movement Landing pages, marketing
Grid-breaking Emphasis, surprise Key CTAs, focal points
Generous negative space Luxury, breathing room Premium products, editorial
Controlled density Information-rich, productive Dashboards, data-heavy UIs

Rule: Match spatial composition to the aesthetic direction chosen in Design Thinking. Minimalist = negative space. Maximalist = controlled density.

Design-System Drift Classifier

When a feature deviates from the design system, "it looks a bit off" is not an actionable finding. For each deviation, classify the root cause — the class determines the fix:

Root cause What it means Fix
Missing token The system has no value for this need (a shade, spacing step, radius) Patch the value — add the token to the system, then use it
One-off impl A token/component exists, but this feature reimplemented it locally Swap to the shared component/token; delete the one-off
Conceptual misalignment The feature's interaction model fights the system's Rework the flow — patching pixels won't fix it

Flow-shape match. Beyond tokens, a feature's flow shape must match its neighbors. Inconsistent flow shape reads as broken even when every pixel is on-system:

  • Modal vs. full-page — if sibling editors open a modal, don't ship a full-page route (or vice versa).
  • Save-on-blur vs. explicit submit — if neighboring forms autosave, a lone submit-button form is a conceptual misalignment, not a styling nit.

Require the feature's flow shape to match neighboring features, or to carry an explicit, approved reason for diverging. Treat an unexplained flow-shape mismatch as a conceptual-misalignment deviation, not a minor one.

Component Patterns

Buttons

// Primary action button with all states
<button
  type="button"
  onClick={handleAction}
  disabled={isLoading || isDisabled}
  aria-busy={isLoading}
  aria-disabled={isDisabled}
  className={cn(
    'btn-primary',
    isLoading && 'btn-loading'
  )}
>
  {isLoading ? (
    <>
      <Spinner aria-hidden />
      <span>Processing...</span>
    </>
  ) : (
    'Submit'
  )}
</button>

Forms with Validation

<form onSubmit={handleSubmit} noValidate>
  <div className="form-field">
    <label htmlFor="email">
      Email <span aria-hidden>*</span>
      <span className="sr-only">(required)</span>
    </label>
    <input
      id="email"
      type="email"
      value={email}
      onChange={handleChange}
      aria-invalid={errors.email ? 'true' : undefined}
      aria-describedby={errors.email ? 'email-error' : 'email-hint'}
      required
    />
    <span id="email-hint" className="hint">
      We'll never share your email
    </span>
    {errors.email && (
      <span id="email-error" role="alert" className="error">
        {errors.email}
      </span>
    )}
  </div>
</form>

Loading States

function DataList({ isLoading, data, error }) {
  if (isLoading) {
    return (
      <div aria-live="polite" aria-busy="true">
        <Spinner />
        <span>Loading items...</span>
      </div>
    );
  }

  if (error) {
    return (
      <div role="alert" className="error-state">
        <p>Failed to load items: {error.message}</p>
        <button onClick={retry}>Try again</button>
      </div>
    );
  }

  if (!data?.length) {
    return (
      <div className="empty-state">
        <p>No items found</p>
        <button onClick={createNew}>Create your first item</button>
      </div>
    );
  }

  return <ul>{data.map(item => <Item key={item.id} {...item} />)}</ul>;
}

Error Messages

// Inline error with recovery action
<div role="alert" className="error-banner">
  <Icon name="error" aria-hidden />
  <div>
    <p className="error-title">Upload failed</p>
    <p className="error-detail">File too large. Maximum size is 10MB.</p>
  </div>
  <button onClick={selectFile}>Choose different file</button>
</div>

Red Flags - STOP and Reconsider

If you find yourself:

  • Designing UI before mapping user flow
  • Focusing on aesthetics before functionality
  • Ignoring accessibility ("we'll add it later")
  • Not handling error states
  • Not providing loading feedback
  • Using color alone to convey information
  • Making decisions based on "it looks nice"

STOP. Go back to user flow.

Rationalization Prevention

Excuse Reality
"Most users don't use keyboard" Some users ONLY use keyboard.
"We'll add accessibility later" Retrofitting is 10x harder.
"Error states are edge cases" Errors happen. Handle them.
"Loading is fast, no need for state" Network varies. Show state.
"It looks better without labels" Unlabeled inputs are inaccessible.
"Users can figure it out" If it's confusing, fix it.

Anti-patterns Blocklist (Flag These)

Anti-pattern Why It's Wrong Fix
user-scalable=no Blocks accessibility zoom Remove it
maximum-scale=1 Blocks accessibility zoom Remove it
transition: all Performance + unexpected effects List properties explicitly
outline-none without replacement Removes focus indicator Add focus-visible:ring-*
<div onClick> Not keyboard accessible Use <button> or <a>
Images without width/height Causes layout shift (CLS) Add explicit dimensions
Form inputs without labels Inaccessible Add <label> or aria-label
Icon buttons without aria-label Unnamed to screen readers Add aria-label
Emoji icons (🚀 ✨ 💫) Unprofessional, inconsistent Use SVG icons
Hardcoded date/number formats Breaks internationalization Use Intl.DateTimeFormat
autoFocus everywhere Disorienting, mobile issues Use sparingly, desktop only

Output Format

## Frontend Review: [Component/Feature]

### User Flow
[Step-by-step what user is trying to do]

### Success Criteria
- [ ] User can complete [task]
- [ ] User can recover from errors
- [ ] All users can access (keyboard, screen reader)
- [ ] Interface feels responsive

### UX Issues
| Severity | Issue | Location | Impact | Fix |
|----------|-------|----------|--------|-----|
| BLOCKS | [Issue] | `file:line` | [Impact] | [Fix] |

### Accessibility Issues
| WCAG | Issue | Location | Fix |
|------|-------|----------|-----|
| 1.4.3 | [Issue] | `file:line` | [Fix] |

### Visual Issues
| Issue | Location | Fix |
|-------|----------|-----|
| [Issue] | `file:line` | [Fix] |

### Recommendations
1. [Most critical fix]
2. [Second fix]

UI States Checklist (CRITICAL)

Before completing ANY UI component:

States

  • Error state handled and shown to user
  • Loading state shown ONLY when no data exists
  • Empty state provided for all collections/lists
  • Success state with appropriate feedback
  • Non-trivial state-order or skeleton/spinner decisions checked against references/ui-state-and-feedback.md

Buttons & Mutations

  • Buttons disabled during async operations
  • Buttons show loading indicator
  • Mutations have onError handler with user feedback
  • No double-click possible on submit buttons

Data Handling

  • State order: Error → Loading (no data) → Empty → Success
  • All user actions have feedback (toast/visual)

Final Check

Before completing frontend work:

  • User flow mapped and understood
  • All states handled (loading, error, empty, success)
  • Keyboard navigation works
  • Screen reader tested
  • Color contrast verified (4.5:1 minimum)
  • Touch targets adequate on mobile (44px+)
  • Error messages clear and actionable
  • Success criteria met
  • No emoji icons (SVG only)
  • prefers-reduced-motion respected
  • Light/dark mode contrast verified
  • cursor-pointer on all clickable elements
  • No transition: all in codebase
Install via CLI
npx skills add https://github.com/romiluz13/cc10x --skill frontend-patterns
Repository Details
star Stars 147
call_split Forks 23
navigation Branch main
article Path SKILL.md
More from Creator