frontend-component
Next.js 16+ uses App Router with Server Components by default. Client Components are only used when interactivity is needed (hooks, event handlers, browser APIs).
Best use case
frontend-component is best used when you need a repeatable AI agent workflow instead of a one-off prompt. It is especially useful for teams working in multi. Next.js 16+ uses App Router with Server Components by default. Client Components are only used when interactivity is needed (hooks, event handlers, browser APIs).
Next.js 16+ uses App Router with Server Components by default. Client Components are only used when interactivity is needed (hooks, event handlers, browser APIs).
Users should expect a more consistent workflow output, faster repeated execution, and less time spent rewriting prompts from scratch.
Practical example
Example input
Use the "frontend-component" skill to help with this workflow task. Context: Next.js 16+ uses App Router with Server Components by default. Client Components are only used when interactivity is needed (hooks, event handlers, browser APIs).
Example output
A structured workflow result with clearer steps, more consistent formatting, and an output that is easier to reuse in the next run.
When to use this skill
- Use this skill when you want a reusable workflow rather than writing the same prompt again and again.
When not to use this skill
- Do not use this when you only need a one-off answer and do not need a reusable workflow.
- Do not use it if you cannot install or maintain the related files, repository context, or supporting tools.
Installation
Claude Code / Cursor / Codex
Manual Installation
- Download SKILL.md from GitHub
- Place it in
.claude/skills/frontend-component/SKILL.mdinside your project - Restart your AI agent — it will auto-discover the skill
How frontend-component Compares
| Feature / Agent | frontend-component | Standard Approach |
|---|---|---|
| Platform Support | Not specified | Limited / Varies |
| Context Awareness | High | Baseline |
| Installation Complexity | Unknown | N/A |
Frequently Asked Questions
What does this skill do?
Next.js 16+ uses App Router with Server Components by default. Client Components are only used when interactivity is needed (hooks, event handlers, browser APIs).
Where can I find the source code?
You can find the source code on GitHub using the link provided at the top of the page.
SKILL.md Source
# Frontend Component Skill
**Purpose**: Guidance for creating Next.js components following server/client patterns and existing component structures.
## Overview
Next.js 16+ uses App Router with Server Components by default. Client Components are only used when interactivity is needed (hooks, event handlers, browser APIs).
## Server vs Client Components
### Server Components (Default)
**When to Use**:
- Pages and layouts
- Static content
- Data fetching from API (when possible)
- SEO-optimized content
**Pattern**:
```typescript
// No "use client" directive
import { Metadata } from "next";
export const metadata: Metadata = {
title: "Page Title",
};
export default function PageComponent() {
return <div>Static content</div>;
}
```
**Example**: `frontend/app/layout.tsx`, `frontend/app/page.tsx`
### Client Components (When Needed)
**When to Use**:
- Interactive elements (buttons, forms, inputs)
- Event handlers (onClick, onChange, etc.)
- React hooks (useState, useEffect, useRouter, etc.)
- Browser APIs (localStorage, window, document, etc.)
- Real-time updates
- Drag and drop functionality
**Pattern**:
```typescript
"use client"; // MUST be first line
import { useState, useEffect } from "react";
import { useRouter } from "next/navigation";
interface ComponentProps {
prop1: string;
prop2?: number;
}
export default function ComponentName({ prop1, prop2 }: ComponentProps) {
const router = useRouter();
const [state, setState] = useState("");
useEffect(() => {
// Side effects
}, []);
return <div>{/* Component JSX */}</div>;
}
```
**Example**: `frontend/components/ProtectedRoute.tsx`, `frontend/app/signup/page.tsx`
## Component Structure Template
```typescript
"use client"; // Only if client component
/**
* Component Name
*
* Brief description of what this component does
*/
import { useState, useEffect } from "react";
import { ComponentType } from "@/types";
import { cn } from "@/lib/utils";
interface ComponentProps {
prop1: string;
prop2?: number;
className?: string;
}
export default function ComponentName({ prop1, prop2, className }: ComponentProps) {
// State
const [state, setState] = useState("");
// Effects
useEffect(() => {
// Side effects
}, []);
// Handlers
const handleClick = () => {
// Handler logic
};
// Render
return (
<div className={cn("base-classes", className)}>
{/* Component content */}
</div>
);
}
```
## Specific Component Patterns
### 1. ProtectedRoute Pattern
**From**: `frontend/components/ProtectedRoute.tsx`
```typescript
"use client";
import { useEffect, useState } from "react";
import { useRouter } from "next/navigation";
import { isAuthenticated } from "@/lib/auth";
import LoadingSpinner from "./LoadingSpinner";
interface ProtectedRouteProps {
children: React.ReactNode;
}
export default function ProtectedRoute({ children }: ProtectedRouteProps) {
const router = useRouter();
const [isAuthorized, setIsAuthorized] = useState(false);
const [isChecking, setIsChecking] = useState(true);
useEffect(() => {
async function checkAuth() {
try {
const authenticated = await isAuthenticated();
if (!authenticated) {
const currentPath = window.location.pathname;
if (currentPath !== "/signin") {
sessionStorage.setItem("redirectAfterLogin", currentPath);
}
router.push("/signin");
} else {
setIsAuthorized(true);
}
} catch (error) {
console.error("Auth check failed:", error);
router.push("/signin");
} finally {
setIsChecking(false);
}
}
checkAuth();
}, [router]);
if (isChecking) {
return (
<div className="min-h-screen flex items-center justify-center">
<LoadingSpinner size="large" />
</div>
);
}
if (!isAuthorized) {
return null;
}
return <>{children}</>;
}
```
**Pattern**:
- Check authentication on mount
- Show loading spinner during check
- Store intended destination in sessionStorage
- Redirect to `/signin` if not authenticated
- Only render children if authorized
### 2. LoadingSpinner Pattern
**From**: `frontend/components/LoadingSpinner.tsx`
```typescript
interface LoadingSpinnerProps {
size?: "small" | "medium" | "large";
color?: string;
label?: string;
}
export default function LoadingSpinner({
size = "medium",
color = "blue",
label = "Loading...",
}: LoadingSpinnerProps) {
const sizeClasses = {
small: "w-4 h-4 border-2",
medium: "w-8 h-8 border-3",
large: "w-12 h-12 border-4",
};
const colorClasses = {
blue: "border-blue-600 border-t-transparent",
gray: "border-gray-600 border-t-transparent",
white: "border-white border-t-transparent",
};
const spinnerClass = `${sizeClasses[size]} ${
colorClasses[color as keyof typeof colorClasses] || colorClasses.blue
} rounded-full animate-spin`;
return (
<div
className="flex items-center justify-center"
role="status"
aria-label={label}
aria-live="polite"
>
<div className={spinnerClass}></div>
<span className="sr-only">{label}</span>
</div>
);
}
```
**Pattern**:
- Multiple sizes (small, medium, large)
- Multiple colors (blue, gray, white)
- Accessibility labels (`role="status"`, `aria-label`, `aria-live`)
- Screen reader text with `sr-only` class
### 3. Form Handling Pattern
**From**: `frontend/app/signup/page.tsx`
```typescript
"use client";
import { useState } from "react";
import { useRouter } from "next/navigation";
import { api } from "@/lib/api";
import { isValidEmail, getPasswordStrength } from "@/lib/utils";
export default function SignupPage() {
const router = useRouter();
const [formData, setFormData] = useState({
name: "",
email: "",
password: "",
});
const [errors, setErrors] = useState<Record<string, string>>({});
const [isLoading, setIsLoading] = useState(false);
const [apiError, setApiError] = useState("");
const validateForm = (): boolean => {
const newErrors: Record<string, string> = {};
if (!formData.name.trim()) {
newErrors.name = "Name is required";
}
if (!formData.email.trim()) {
newErrors.email = "Email is required";
} else if (!isValidEmail(formData.email)) {
newErrors.email = "Please enter a valid email address";
}
// More validation...
setErrors(newErrors);
return Object.keys(newErrors).length === 0;
};
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
setApiError("");
if (!validateForm()) {
return;
}
setIsLoading(true);
try {
const response = await api.signup(formData);
if (response.success) {
router.push("/dashboard");
} else {
setApiError(response.message || "Signup failed");
}
} catch (error: any) {
setApiError(error.message || "An error occurred");
} finally {
setIsLoading(false);
}
};
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const { name, value } = e.target;
setFormData((prev) => ({ ...prev, [name]: value }));
// Clear error for this field when user starts typing
if (errors[name]) {
setErrors((prev) => ({ ...prev, [name]: "" }));
}
};
return (
<form onSubmit={handleSubmit}>
{/* Form fields */}
</form>
);
}
```
**Pattern**:
- Separate state for form data, errors, loading, API errors
- Validation function that returns boolean
- Clear errors on input change
- Loading state during submission
- Try-catch for error handling
- Redirect on success
### 4. ToastNotification Pattern
**From**: `frontend/components/ToastNotification.tsx`
```typescript
"use client";
import { useEffect, useState } from "react";
import { ToastMessage, ToastType } from "@/types";
export function useToast() {
const [toasts, setToasts] = useState<ToastMessage[]>([]);
const showToast = (type: ToastType, message: string, duration?: number) => {
const id = `toast-${Date.now()}-${Math.random()}`;
const newToast: ToastMessage = {
id,
type,
message,
duration,
};
setToasts((prev) => [...prev, newToast]);
};
const dismissToast = (id: string) => {
setToasts((prev) => prev.filter((toast) => toast.id !== id));
};
return {
toasts,
showToast,
dismissToast,
success: (message: string, duration?: number) => showToast("success", message, duration),
error: (message: string, duration?: number) => showToast("error", message, duration),
// ...
};
}
```
**Pattern**:
- Custom hook for toast management
- Auto-dismiss with duration
- Stack multiple toasts
- Helper methods (success, error, warning, info)
## Tailwind CSS Patterns
### 1. Utility Classes Only
```typescript
<div className="flex items-center justify-center gap-4 p-6 bg-white rounded-lg shadow-md">
```
**Pattern**: Use Tailwind utility classes, no inline styles
### 2. Conditional Classes with `cn()` Utility
```typescript
import { cn } from "@/lib/utils";
<div className={cn(
"base-classes",
condition && "conditional-classes",
className // Allow prop override
)}>
```
**Pattern**: Use `cn()` from `@/lib/utils` for conditional classes
### 3. Dark Mode Support
```typescript
<div className="bg-white dark:bg-gray-800 text-gray-900 dark:text-white">
```
**Pattern**: Use `dark:` prefix for dark mode styles
### 4. Responsive Design
```typescript
<div className="w-full sm:w-1/2 md:w-1/3 lg:w-1/4">
```
**Pattern**: Use breakpoint prefixes (`sm:`, `md:`, `lg:`, `xl:`)
## Accessibility Patterns (WCAG 2.1 AA)
### 1. ARIA Labels
```typescript
<button aria-label="Close dialog">×</button>
<div role="status" aria-live="polite" aria-label="Loading...">
```
**Pattern**: Always provide `aria-label` for icon-only buttons
### 2. Semantic HTML
```typescript
<nav>
<ul>
<li><a href="/">Home</a></li>
</ul>
</nav>
```
**Pattern**: Use semantic HTML elements (`nav`, `main`, `section`, `article`, etc.)
### 3. Keyboard Navigation
```typescript
<button
onClick={handleClick}
onKeyDown={(e) => {
if (e.key === "Enter" || e.key === " ") {
handleClick();
}
}}
>
```
**Pattern**: Ensure keyboard accessibility for all interactive elements
### 4. Screen Reader Text
```typescript
<span className="sr-only">Loading content</span>
```
**Pattern**: Use `sr-only` class for screen reader-only text
### 5. Focus Management
```typescript
<input
autoFocus
className="focus:outline-none focus:ring-2 focus:ring-blue-500"
/>
```
**Pattern**: Always provide visible focus indicators
## File Naming Conventions
- **Pages**: kebab-case (e.g., `signup.tsx`, `signin.tsx`)
- **Components**: PascalCase (e.g., `TaskList.tsx`, `TaskItem.tsx`)
- **Layouts**: `layout.tsx`
- **Error Pages**: `error.tsx`, `not-found.tsx`
## Constitution Requirements
- **FR-033**: Next.js 16+ App Router structure ✅
- **FR-034**: Server components default, client when needed ✅
- **FR-035**: Error boundaries ✅
- **FR-036**: WCAG 2.1 AA compliance ✅
- **FR-037**: TypeScript strict mode ✅
- **FR-038**: Prettier formatting ✅
- **FR-039**: ESLint rules ✅
## References
- **Specification**: `specs/002-frontend-todo-app/spec.md` - Component specifications
- **Existing Components**: `frontend/components/*.tsx` - Component examples
- **Existing Pages**: `frontend/app/*.tsx` - Page examples
## Advanced Component Patterns
### 1. Drag and Drop Pattern (Phase 7 - T065)
**Library**: `@dnd-kit/core`
```typescript
"use client";
import { DndContext, closestCenter, KeyboardSensor, PointerSensor, useSensor, useSensors } from "@dnd-kit/core";
import { SortableContext, sortableKeyboardCoordinates, useSortable, verticalListSortingStrategy } from "@dnd-kit/sortable";
export default function SortableTaskList({ tasks, onReorder }: Props) {
const sensors = useSensors(
useSensor(PointerSensor),
useSensor(KeyboardSensor, {
coordinateGetter: sortableKeyboardCoordinates,
})
);
const handleDragEnd = (event: DragEndEvent) => {
const { active, over } = event;
if (over && active.id !== over.id) {
onReorder(active.id, over.id);
}
};
return (
<DndContext sensors={sensors} collisionDetection={closestCenter} onDragEnd={handleDragEnd}>
<SortableContext items={tasks.map(t => t.id)} strategy={verticalListSortingStrategy}>
{tasks.map(task => (
<SortableTaskItem key={task.id} task={task} />
))}
</SortableContext>
</DndContext>
);
}
```
**Pattern**: Use `@dnd-kit/core` for drag and drop, handle reorder on drag end
### 2. Undo/Redo Pattern (Phase 7 - T066)
```typescript
"use client";
import { useReducer } from "react";
interface HistoryState<T> {
past: T[];
present: T;
future: T[];
}
function historyReducer<T>(state: HistoryState<T>, action: { type: string; newPresent?: T }): HistoryState<T> {
const { past, present, future } = state;
switch (action.type) {
case "UNDO":
if (past.length === 0) return state;
return {
past: past.slice(0, past.length - 1),
present: past[past.length - 1],
future: [present, ...future],
};
case "REDO":
if (future.length === 0) return state;
return {
past: [...past, present],
present: future[0],
future: future.slice(1),
};
case "SET":
if (action.newPresent === present) return state;
return {
past: [...past, present],
present: action.newPresent!,
future: [],
};
default:
return state;
}
}
export function useHistory<T>(initialPresent: T) {
const [state, dispatch] = useReducer(historyReducer, {
past: [],
present: initialPresent,
future: [],
});
const undo = () => dispatch({ type: "UNDO" });
const redo = () => dispatch({ type: "REDO" });
const set = (newPresent: T) => dispatch({ type: "SET", newPresent });
return { state: state.present, set, undo, redo, canUndo: state.past.length > 0, canRedo: state.future.length > 0 };
}
```
**Pattern**: Use `useReducer` with history pattern for undo/redo functionality
### 3. Real-time Updates with Polling (Phase 7 - T067)
```typescript
"use client";
import { useEffect, useRef } from "react";
export function usePolling(callback: () => Promise<void>, interval: number = 5000) {
const intervalRef = useRef<NodeJS.Timeout | null>(null);
useEffect(() => {
const poll = async () => {
try {
await callback();
} catch (error) {
console.error("Polling error:", error);
}
};
// Initial call
poll();
// Set up polling interval
intervalRef.current = setInterval(poll, interval);
// Cleanup
return () => {
if (intervalRef.current) {
clearInterval(intervalRef.current);
}
};
}, [callback, interval]);
}
```
**Pattern**: Use `setInterval` for polling, cleanup on unmount, handle errors gracefully
### 4. Inline Editing Pattern (Phase 7 - T068)
```typescript
"use client";
import { useState } from "react";
export default function InlineEditable({ value, onSave }: Props) {
const [isEditing, setIsEditing] = useState(false);
const [editValue, setEditValue] = useState(value);
const handleSave = () => {
onSave(editValue);
setIsEditing(false);
};
const handleCancel = () => {
setEditValue(value);
setIsEditing(false);
};
if (isEditing) {
return (
<input
value={editValue}
onChange={(e) => setEditValue(e.target.value)}
onBlur={handleSave}
onKeyDown={(e) => {
if (e.key === "Enter") handleSave();
if (e.key === "Escape") handleCancel();
}}
autoFocus
/>
);
}
return (
<span onClick={() => setIsEditing(true)} className="cursor-pointer">
{value}
</span>
);
}
```
**Pattern**: Toggle edit mode, save on blur/Enter, cancel on Escape
### 5. Performance Optimization Patterns (Phase 8 - T072)
#### Code Splitting with `next/dynamic`
```typescript
import dynamic from "next/dynamic";
// Lazy load heavy components
const TaskStatistics = dynamic(() => import("@/components/TaskStatistics"), {
loading: () => <LoadingSpinner />,
ssr: false, // Disable SSR if not needed
});
const TaskDetailModal = dynamic(() => import("@/components/TaskDetailModal"), {
loading: () => <LoadingSpinner />,
});
```
**Pattern**: Use `next/dynamic` for code splitting, provide loading fallback
#### Image Optimization
```typescript
import Image from "next/image";
<Image
src="/image.jpg"
alt="Description"
width={500}
height={300}
loading="lazy"
placeholder="blur"
/>
```
**Pattern**: Use Next.js `Image` component for automatic optimization
### 6. Error Boundary Pattern (Phase 8 - T074)
```typescript
"use client";
import React, { Component, ErrorInfo, ReactNode } from "react";
interface Props {
children: ReactNode;
fallback?: ReactNode;
}
interface State {
hasError: boolean;
error?: Error;
}
export default class ErrorBoundary extends Component<Props, State> {
constructor(props: Props) {
super(props);
this.state = { hasError: false };
}
static getDerivedStateFromError(error: Error): Partial<State> {
return { hasError: true, error };
}
componentDidCatch(error: Error, errorInfo: ErrorInfo): void {
console.error("ErrorBoundary caught an error:", error, errorInfo);
// Log to error tracking service
}
render() {
if (this.state.hasError) {
return (
this.props.fallback || (
<div className="p-4 bg-red-50 border border-red-200 rounded">
<h2 className="text-red-800 font-bold">Something went wrong</h2>
<p className="text-red-600">{this.state.error?.message}</p>
<button onClick={() => this.setState({ hasError: false })}>Try again</button>
</div>
)
);
}
return this.props.children;
}
}
```
**Pattern**: Class component, catch errors, provide fallback UI, log errors
### 7. PWA Patterns (Phase 8 - T069, T070, T071)
#### Service Worker Setup
```typescript
// public/sw.js or use next-pwa
if ("serviceWorker" in navigator) {
window.addEventListener("load", () => {
navigator.serviceWorker
.register("/sw.js")
.then((registration) => {
console.log("SW registered:", registration);
})
.catch((error) => {
console.error("SW registration failed:", error);
});
});
}
```
**Pattern**: Register service worker on page load, handle registration errors
#### IndexedDB for Offline Storage
```typescript
import { openDB, DBSchema, IDBPDatabase } from "idb";
interface TaskDB extends DBSchema {
tasks: {
key: number;
value: Task;
indexes: { "by-user-id": string };
};
}
export async function getDB(): Promise<IDBPDatabase<TaskDB>> {
return openDB<TaskDB>("todo-db", 1, {
upgrade(db) {
const taskStore = db.createObjectStore("tasks", { keyPath: "id" });
taskStore.createIndex("by-user-id", "user_id");
},
});
}
export async function saveTaskOffline(task: Task) {
const db = await getDB();
await db.put("tasks", task);
}
export async function getTasksOffline(userId: string): Promise<Task[]> {
const db = await getDB();
return db.getAllFromIndex("tasks", "by-user-id", userId);
}
```
**Pattern**: Use `idb` library for IndexedDB, create stores and indexes, handle offline data
#### Offline Sync Mechanism
```typescript
export async function syncOfflineChanges(userId: string) {
const db = await getDB();
const offlineTasks = await db.getAllFromIndex("tasks", "by-user-id", userId);
for (const task of offlineTasks) {
if (task.syncStatus === "pending") {
try {
await api.createTask(userId, task);
await db.put("tasks", { ...task, syncStatus: "synced" });
} catch (error) {
console.error("Sync failed for task:", task.id, error);
}
}
}
}
// Call on connection restore
window.addEventListener("online", () => {
syncOfflineChanges(currentUserId);
});
```
**Pattern**: Track sync status, sync on connection restore, handle sync errors
### 8. Caching Strategies (Phase 8 - T073)
```typescript
// Cache API responses
const cache = new Map<string, { data: any; timestamp: number }>();
const CACHE_DURATION = 5 * 60 * 1000; // 5 minutes
export async function getCachedData<T>(key: string, fetcher: () => Promise<T>): Promise<T> {
const cached = cache.get(key);
if (cached && Date.now() - cached.timestamp < CACHE_DURATION) {
return cached.data;
}
const data = await fetcher();
cache.set(key, { data, timestamp: Date.now() });
return data;
}
```
**Pattern**: Use Map for in-memory cache, check expiration, update cache on fetch
### 9. Error Logging and Tracking (Phase 8 - T075)
```typescript
export function logError(error: Error, context?: Record<string, any>) {
console.error("Error:", error, context);
// Send to error tracking service (e.g., Sentry)
if (typeof window !== "undefined" && (window as any).Sentry) {
(window as any).Sentry.captureException(error, {
extra: context,
});
}
// Or send to custom endpoint
fetch("/api/log-error", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
message: error.message,
stack: error.stack,
context,
timestamp: new Date().toISOString(),
}),
}).catch((err) => console.error("Failed to log error:", err));
}
```
**Pattern**: Log to console, send to error tracking service, include context
## Common Patterns Summary
1. ✅ Use Server Components by default
2. ✅ Add `"use client"` only when needed
3. ✅ Use TypeScript interfaces for props
4. ✅ Use `cn()` utility for conditional classes
5. ✅ Always include accessibility attributes
6. ✅ Use semantic HTML elements
7. ✅ Provide loading states
8. ✅ Handle errors gracefully
9. ✅ Use Tailwind utility classes
10. ✅ Support dark mode with `dark:` prefix
11. ✅ Use `@dnd-kit/core` for drag and drop
12. ✅ Use `useReducer` for undo/redo
13. ✅ Use `setInterval` for polling with cleanup
14. ✅ Use `next/dynamic` for code splitting
15. ✅ Use ErrorBoundary for error handling
16. ✅ Use IndexedDB for offline storage
17. ✅ Sync offline changes on connection restore
18. ✅ Cache API responses with expiration
19. ✅ Log errors to tracking serviceRelated Skills
web-component-design
Master React, Vue, and Svelte component patterns including CSS-in-JS, composition strategies, and reusable component architecture. Use when building UI component libraries, designing component APIs, or implementing frontend design systems.
next-cache-components
Next.js 16 Cache Components - PPR, use cache directive, cacheLife, cacheTag, updateTag
ui-component-patterns
Build reusable, maintainable UI components following modern design patterns. Use when creating component libraries, implementing design systems, or building scalable frontend architectures. Handles React patterns, composition, prop design, TypeScript, and component best practices.
hig-components-system
Apple HIG guidance for system experience components: widgets, live activities, notifications, complications, home screen quick actions, top shelf, watch faces, app clips, and app shortcuts. Use when asked about: "widget design", "live activity", "notification design", "complication", "home screen quick action", "top shelf", "watch face", "app clip", "app shortcut", "system experience". Also use when the user says "how do I design a widget," "what should my notification look like," "how do Live Activities work," "should I make an App Clip," or asks about surfaces outside the main app. Cross-references: hig-components-status for progress in widgets, hig-inputs for interaction patterns, hig-technologies for Siri and system integration.
hig-components-status
Apple HIG guidance for status and progress UI components including progress indicators, status bars, and activity rings. Use this skill when asked about: "progress indicator", "progress bar", "loading spinner", "status bar", "activity ring", "progress display", determinate vs indeterminate progress, loading states, or fitness tracking rings. Also use when the user says "how do I show loading state," "should I use a spinner or progress bar," "what goes in the status bar," or asks about activity indicators. Cross-references: hig-components-system for widgets and complications, hig-inputs for gesture-driven progress controls, hig-technologies for HealthKit and activity ring data integration.
hig-components-search
Apple HIG guidance for navigation-related components including search fields, page controls, and path controls. Use this skill when the user says "how should search work in my app," "I need a breadcrumb," "how do I paginate content," or asks about search field, search bar, page control, path control, breadcrumb, navigation component, search UX, search suggestions, search scopes, paginated content navigation, or file path hierarchy display. Cross-references: hig-components-menus, hig-components-controls, hig-components-dialogs, hig-patterns.
hig-components-menus
Apple HIG guidance for menu and button components including menus, context menus, dock menus, edit menus, the menu bar, toolbars, action buttons, pop-up buttons, pull-down buttons, disclosure controls, and standard buttons. Use this skill when the user says "how should my buttons look," "what goes in the menu bar," "should I use a context menu or action sheet," "how do I design a toolbar," or asks about button design, menu design, context menu, toolbar, menu bar, action button, pop-up button, pull-down button, disclosure control, dock menu, edit menu, or any menu/button component layout and behavior. Cross-references: hig-components-search, hig-components-controls, hig-components-dialogs.
hig-components-layout
Apple Human Interface Guidelines for layout and navigation components. Use this skill when the user asks about sidebar, split view, tab bar, tab view, scroll view, window design, panel, list view, table view, column view, outline view, navigation structure, app layout, boxes, ornaments, or organizing content hierarchically in Apple apps. Also use when the user says how should I organize my app, what navigation pattern should I use, my layout breaks on iPad, how do I build a sidebar, should I use tabs or a sidebar, or my app doesn't adapt to different screen sizes. Cross-references: hig-foundations for layout/spacing principles, hig-platforms for platform-specific navigation, hig-patterns for multitasking and full-screen, hig-components-content for content display.
hig-components-dialogs
Apple HIG guidance for presentation components including alerts, action sheets, popovers, sheets, and digit entry views. Use this skill when the user says 'should I use an alert or a sheet,' 'how do I show a confirmation dialog,' 'when should I use a popover,' 'my modals are annoying users,' or asks about alert design, action sheet, popover, sheet, modal, dialog, digit entry, confirmation dialog, warning dialog, modal presentation, non-modal content, destructive action confirmation, or overlay UI patterns. Cross-references: hig-components-menus, hig-components-controls, hig-components-search, hig-patterns.
hig-components-controls
Apple HIG guidance for selection and input controls including pickers, toggles, sliders, steppers, segmented controls, combo boxes, text fields, text views, labels, token fields, virtual keyboards, rating indicators, and gauges.
hig-components-content
Apple Human Interface Guidelines for content display components. Use this skill when the user asks about charts component, collection view, image view, web view, color well, image well, activity view, lockup, data visualization, content display, displaying images, rendering web content, color pickers, or presenting collections of items in Apple apps. Also use when the user says how should I display charts, what's the best way to show images, should I use a web view, how do I build a grid of items, what component shows media, or how do I present a share sheet. Cross-references: hig-foundations for color/typography/accessibility, hig-patterns for data visualization patterns, hig-components-layout for structural containers, hig-platforms for platform-specific component behavior.
frontend-ui-dark-ts
Build dark-themed React applications using Tailwind CSS with custom theming, glassmorphism effects, and Framer Motion animations. Use when creating dashboards, admin panels, or data-rich interfaces with a refined dark aesthetic.