---
name: frontend-ui-engineering
description: Use this skill when building or modifying production-quality user-facing interfaces. Builds accessible, responsive, visually polished UIs with proper component architecture, design system adherence, and WCAG 2.1 AA compliance.
---
# Frontend UI Engineering
## Overview
Build production-quality user interfaces that are accessible, performant, and visually polished. The goal is UI that looks like it was built by a design-aware engineer at a top company — not like it was generated by an AI. This means real design system adherence, proper accessibility, thoughtful interaction patterns, and no generic "AI aesthetic."
## When to Use
- Building new UI components or pages
- Modifying existing user-facing interfaces
- Implementing responsive layouts
- Adding interactivity or state management
- Fixing visual or UX issues
## Component Architecture
### File Structure
Colocate everything related to a component:
```
src/components/
TaskList/
TaskList.tsx # Component implementation
TaskList.test.tsx # Tests
types.ts # Component-specific types (if needed)
```
### Component Patterns
**Prefer composition over configuration:**
```tsx
// Good: Composable
// Avoid: Over-configured
```
**Separate data fetching from presentation:**
```tsx
// Container: handles data
export function TaskListContainer() {
const { tasks, isLoading, error } = useTasks();
if (isLoading) return ;
if (error) return ;
if (tasks.length === 0) return ;
return ;
}
// Presentation: handles rendering
export function TaskList({ tasks }: { tasks: Task[] }) {
return
{tasks.map(task => )}
;
}
```
## State Management
Choose the simplest approach that works:
```
Local state (useState) → Component-specific UI state
Lifted state → Shared between 2-3 sibling components
Context → Theme, auth, locale (read-heavy, write-rare)
URL state (searchParams) → Filters, pagination, shareable UI state
Server state (React Query) → Remote data with caching
Global store (Zustand, Redux) → Complex client state shared app-wide
```
**Avoid prop drilling deeper than 3 levels.** If you're passing props through components that don't use them, introduce context or restructure the component tree.
## Design System Adherence
### Reference-led UI Quality
When the product needs a distinct visual direction:
1. Collect evidence before choosing a layout
2. Study 2-3 relevant screens. Record decisions about hierarchy, density, navigation, controls, responsive behavior, and interaction states
3. Turn those decisions into a short design contract before implementation
4. Rebuild using the product's own components, tokens, content, and visual language
5. Never copy another product's branding, proprietary text, or exact layout
### Avoid the AI Aesthetic
| AI Default | Why It Is a Problem | Production Quality |
|---|---|---|
| Purple/indigo color schemes | Models default to visually "safe" palettes | Use the project's actual color palette |
| Excessive gradients | Add visual noise, clash with design systems | Flat or subtle gradients from the design system |
| Maximum border-radius everywhere | Ignores the hierarchy of corner radii in real designs | Consistent border-radius from the design system |
| Generic hero sections | Template-driven, no connection to real content | Content-first layouts |
| Lorem ipsum-style copy | Hides layout problems that real content reveals | Realistic placeholder content |
| Oversized padding | Destroys visual hierarchy, wastes screen space | Consistent spacing scale |
| Stock card grids | Ignores information priority and scanning patterns | Purpose-driven layouts |
| Shadow-heavy design | Competes with content, slows rendering on low-end devices | Subtle or no shadows unless specified |
### Spacing and Layout
Use a consistent spacing scale. Don't invent values:
```css
/* Use the scale: 0.25rem increments (or whatever the project uses) */
/* Good */ padding: 1rem; /* 16px */
/* Good */ gap: 0.75rem; /* 12px */
/* Bad */ padding: 13px; /* Not on any scale */
/* Bad */ margin-top: 2.3rem; /* Not on any scale */
```
### Typography
Respect the type hierarchy:
```
h1 → Page title (one per page)
h2 → Section title
h3 → Subsection title
body → Default text
small → Secondary/helper text
```
Don't skip heading levels. Don't use heading styles for non-heading content.
### Color
- Use semantic color tokens: `text-primary`, `bg-surface`, `border-default` — not raw hex values
- Ensure sufficient contrast (4.5:1 for normal text, 3:1 for large text)
- Don't rely solely on color to convey information
## Accessibility (WCAG 2.1 AA)
### Keyboard Navigation
Every interactive element must be keyboard accessible:
```tsx
// ✓ Focusable by default
// ✓ Custom element with keyboard support
{ if (e.key === 'Enter' || e.key === ' ') handleClick(); }}
onClick={handleClick}
>Click me
```
### ARIA Labels
```tsx
// Label interactive elements that lack visible text
// Label form inputs
```
### Focus Management
```tsx
// Move focus when content changes (e.g., dialog opens)
function Dialog({ isOpen, onClose }: DialogProps) {
useEffect(() => {
if (isOpen) closeButtonRef.current?.focus();
}, [isOpen]);
// Trap focus inside dialog when open
}
```
### Meaningful Empty and Error States
```tsx
// Don't show blank screens
function TaskList({ tasks }: { tasks: Task[] }) {
if (tasks.length === 0) {
return (
No tasks yet
Get started by creating a new task.
);
}
return
...
;
}
```
## Responsive Design
Design for mobile first, then expand. Test at these breakpoints: 320px, 768px, 1024px, 1440px.
```tsx
// Mobile-first responsive using Tailwind
```
## Loading and Transitions
```tsx
// Skeleton loading (not spinners for content areas)
function TaskListSkeleton() {
return (
{Array.from({ length: 3 }).map((_, i) => (
))}
);
}
// Optimistic updates for perceived speed
function useToggleTask() {
// Update UI immediately, rollback on error
}
```
## Common Rationalizations
| Rationalization | Reality |
|---|---|
| "Accessibility is a nice-to-have" | It's a legal requirement in many jurisdictions and an engineering quality standard. |
| "We'll make it responsive later" | Retrofitting responsive design is 3x harder than building it from the start. |
| "The design isn't final, so I'll skip styling" | Use the design system defaults. Unstyled UI creates a broken first impression. |
| "This is just a prototype" | Prototypes become production code. Build the foundation right. |
| "The AI aesthetic is fine for now" | It signals low quality. Use the project's actual design system from the start. |
## Red Flags
- Components with more than 200 lines (split them)
- Inline styles or arbitrary pixel values
- Missing error states, loading states, or empty states
- No keyboard navigation testing
- Color as the sole indicator of state (red/green without text or icons)
- Generic "AI look" (purple gradients, oversized cards, stock layouts)
## Verification
After building UI:
- [ ] Component renders without console errors
- [ ] All interactive elements are keyboard accessible (Tab through the page)
- [ ] Screen reader can convey the page's content and structure
- [ ] Responsive: works at 320px, 768px, 1024px, 1440px
- [ ] Loading, empty, error, success, and permission states handled when applicable
- [ ] Follows the project's design system (spacing, colors, typography)
- [ ] The rendered result passes a final UI-specific finish-gate review
- [ ] No accessibility warnings in dev tools or axe-core