DO NOT invoke directly - loaded by workflow agents via cc10x-router. Conditionally loaded by: code-reviewer (UI code), component-builder (UI component), bug-investigator (UI bug), integration-verifier (UI flow testing), planner (UI planning). Provides frontend patterns: UX, visual design, accessibility, responsive design. Iron Law: NO UI DESIGN BEFORE USER FLOW IS UNDERSTOOD.
/plugin marketplace add romiluz13/cc10x/plugin install cc10x@cc10xThis skill is limited to using the following tools:
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.
Violating the letter of this process is violating the spirit of frontend design.
NO UI DESIGN BEFORE USER FLOW IS UNDERSTOOD
If you haven't mapped what the user is trying to accomplish, you cannot design UI.
Every UI must have explicit success criteria:
ALWAYS answer before designing/reviewing:
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:
| 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:
| Check | Criterion | How to Verify |
|---|---|---|
| Keyboard | All interactive elements keyboard accessible | Tab through entire flow |
| Focus visible | Current focus clearly visible | Tab and check highlight |
| Focus order | Logical tab order | Tab matches visual order |
| Labels | All inputs have labels | Check <label> or aria-label |
| Alt text | Images have meaningful alt | Check alt attributes |
| Color contrast | 4.5:1 for text, 3:1 for large | Use contrast checker |
| Color alone | Info not conveyed by color only | Check without color |
| Screen reader | Content accessible via SR | Test with VoiceOver/NVDA |
For each issue found:
- [WCAG 2.1 1.4.3] Color contrast at `component:line`
- Current: 3.2:1 (fails AA)
- Required: 4.5:1
- Fix: Change text color to #333 (7.1:1)
| 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 |
// 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>
<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>
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>;
}
// 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>
| Breakpoint | Check |
|---|---|
| Mobile (< 640px) | Touch targets 44px+, no horizontal scroll |
| Tablet (640-1024px) | Layout adapts, navigation accessible |
| Desktop (> 1024px) | Content readable, not too wide |
If you find yourself:
STOP. Go back to user flow.
| 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. |
## 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]
Before completing frontend work:
This skill should be used when the user asks to "create an agent", "add an agent", "write a subagent", "agent frontmatter", "when to use description", "agent examples", "agent tools", "agent colors", "autonomous agent", or needs guidance on agent structure, system prompts, triggering conditions, or agent development best practices for Claude Code plugins.
This skill should be used when the user asks to "create a slash command", "add a command", "write a custom command", "define command arguments", "use command frontmatter", "organize commands", "create command with file references", "interactive command", "use AskUserQuestion in command", or needs guidance on slash command structure, YAML frontmatter fields, dynamic arguments, bash execution in commands, user interaction patterns, or command development best practices for Claude Code.
This skill should be used when the user asks to "create a hook", "add a PreToolUse/PostToolUse/Stop hook", "validate tool use", "implement prompt-based hooks", "use ${CLAUDE_PLUGIN_ROOT}", "set up event-driven automation", "block dangerous commands", or mentions hook events (PreToolUse, PostToolUse, Stop, SubagentStop, SessionStart, SessionEnd, UserPromptSubmit, PreCompact, Notification). Provides comprehensive guidance for creating and implementing Claude Code plugin hooks with focus on advanced prompt-based hooks API.