AgentSkillsCN

ui-skills

全面的 React、Next.js、Vue、Svelte 以及 Tailwind CSS 前端/UI 开发技能。提供关于组件架构、无障碍设计、响应式设计、状态管理,以及现代 CSS 技术的指导。无论是在构建组件、页面、样式设计,还是开发交互式功能时,此技能都会自动触发。

SKILL.md
--- frontmatter
name: ui-skills
description: Comprehensive UI/frontend development skill for React, Next.js, Vue, Svelte, and Tailwind CSS. Provides guidance on component architecture, accessibility, responsive design, state management, and modern CSS techniques. Automatically triggers for any frontend/UI work including building components, pages, styling, and interactive features.

UI Skills - Frontend Development Guide

Overview

This skill provides comprehensive guidance for modern UI/frontend development across multiple frameworks and libraries. Use this skill whenever you're working on user interfaces, components, styling, or interactive features.

When This Skill Activates

This skill automatically activates when:

  • Building or modifying UI components (React, Vue, Svelte, etc.)
  • Working with Next.js, Create React App, Vite, or other frontend tooling
  • Implementing styles with Tailwind CSS, CSS Modules, or styled-components
  • Creating layouts, forms, navigation, or interactive elements
  • Implementing responsive design or accessibility features
  • Working with state management (React hooks, Zustand, Redux, Pinia, etc.)

Design System Selection

IMPORTANT: Before starting ANY new UI work, you should invoke the ui-portfolio-design skill to help the user select a design direction. This ensures consistent, intentional aesthetics from the start.

To invoke the portfolio selection:

  1. Detect when starting new UI work (not modifying existing components)
  2. Present the portfolio selection from /docs/ui-portfolio/index.html
  3. Once user selects a direction, apply that design system consistently

Skip portfolio selection only when:

  • Modifying existing components (maintain current style)
  • User explicitly requests a specific style
  • Working in a codebase with established design system

Core Principles

1. Component Architecture

Single Responsibility

  • Each component should do one thing well
  • Extract complex logic into custom hooks or composables
  • Keep components small and focused (< 200 lines)

Composition Over Complexity

typescript
// Good: Composable, reusable
<Card>
  <CardHeader>
    <CardTitle>Dashboard</CardTitle>
  </CardHeader>
  <CardContent>
    {children}
  </CardContent>
</Card>

// Avoid: Monolithic with too many props
<Card
  title="Dashboard"
  showHeader
  headerAlign="left"
  contentPadding="large"
  // ... 20 more props
/>

Props Design

  • Use discriminated unions for variants
  • Prefer children over render props when possible
  • Make common use cases simple, advanced use cases possible
  • Use TypeScript for prop validation

2. Accessibility (a11y)

Always Include

  • Semantic HTML elements (<button>, <nav>, <main>, etc.)
  • ARIA labels where needed (aria-label, aria-describedby)
  • Keyboard navigation (Tab, Enter, Escape, Arrow keys)
  • Focus management (visible focus states, focus trapping in modals)
  • Color contrast ratios (WCAG AA minimum: 4.5:1 for text)

Common Patterns

typescript
// Accessible button
<button
  onClick={handleClick}
  aria-label="Close dialog"
  aria-pressed={isActive}
>
  <Icon aria-hidden="true" />
  Close
</button>

// Accessible form input
<div>
  <label htmlFor="email" className="block mb-2">
    Email Address
  </label>
  <input
    id="email"
    type="email"
    aria-describedby="email-hint"
    aria-invalid={hasError}
  />
  <span id="email-hint" className="text-sm text-gray-600">
    We'll never share your email
  </span>
</div>

// Skip to main content
<a href="#main-content" className="sr-only focus:not-sr-only">
  Skip to main content
</a>
<main id="main-content">
  {/* content */}
</main>

3. Responsive Design

Mobile-First Approach

  • Start with mobile layout, enhance for larger screens
  • Use Tailwind breakpoints: sm:, md:, lg:, xl:, 2xl:
  • Test at breakpoints: 320px, 768px, 1024px, 1440px

Fluid Typography & Spacing

css
/* Use clamp for fluid sizing */
font-size: clamp(1rem, 2vw + 0.5rem, 2rem);

/* Or Tailwind responsive utilities */
<h1 className="text-2xl sm:text-3xl lg:text-5xl">

Container Queries (when supported)

css
@container (min-width: 400px) {
  .card { grid-template-columns: 1fr 1fr; }
}

4. State Management

Local State First

  • Use component state (useState, ref) for UI-only state
  • Lift state only when needed by multiple components
  • Use context sparingly (avoid overuse)

Server State

  • Use TanStack Query (React Query) for server data
  • Implement optimistic updates for better UX
  • Handle loading, error, and success states

Form State

  • React Hook Form for complex forms
  • Controlled vs uncontrolled inputs (prefer uncontrolled with refs)
  • Validation with Zod or Yup
typescript
// Good: Server state with TanStack Query
const { data, isLoading, error } = useQuery({
  queryKey: ['user', userId],
  queryFn: () => fetchUser(userId),
})

// Good: Form state with React Hook Form
const { register, handleSubmit, formState: { errors } } = useForm()

5. Performance

Lazy Loading

typescript
// Code splitting
const Dashboard = lazy(() => import('./Dashboard'))

// Image optimization
<Image
  src="/hero.jpg"
  alt="Hero"
  loading="lazy"
  width={1200}
  height={600}
/>

Memoization

  • Use useMemo for expensive calculations
  • Use useCallback for stable function references
  • Use memo() for expensive components
  • Don't over-optimize - profile first

Virtual Lists

  • Use react-virtual for long lists (> 100 items)
  • Implement infinite scroll with Intersection Observer

6. Styling Best Practices

Tailwind CSS

  • Use @apply sparingly (components only)
  • Prefer utility classes in JSX
  • Extract repeated patterns to components, not @apply
  • Use arbitrary values when needed: w-[347px]

Component Variants

typescript
// Using class-variance-authority (cva)
const buttonVariants = cva(
  "rounded font-medium transition-colors", // base
  {
    variants: {
      variant: {
        default: "bg-blue-600 text-white hover:bg-blue-700",
        outline: "border border-gray-300 hover:bg-gray-50",
        ghost: "hover:bg-gray-100",
      },
      size: {
        sm: "px-3 py-1.5 text-sm",
        md: "px-4 py-2 text-base",
        lg: "px-6 py-3 text-lg",
      },
    },
    defaultVariants: {
      variant: "default",
      size: "md",
    },
  }
)

CSS Modules (when not using Tailwind)

  • Use for component-scoped styles
  • Name files Component.module.css
  • Compose styles with composes

7. Component Patterns

Compound Components

typescript
// API that reads well
<Tabs defaultValue="overview">
  <TabsList>
    <TabsTrigger value="overview">Overview</TabsTrigger>
    <TabsTrigger value="analytics">Analytics</TabsTrigger>
  </TabsList>
  <TabsContent value="overview">
    {/* content */}
  </TabsContent>
</Tabs>

Render Props (when composition isn't enough)

typescript
<DataFetcher url="/api/users">
  {({ data, loading, error }) => (
    loading ? <Spinner /> : <UserList users={data} />
  )}
</DataFetcher>

Slots Pattern (React, Vue)

typescript
// React
<Layout
  header={<Header />}
  sidebar={<Sidebar />}
  footer={<Footer />}
>
  {children}
</Layout>

8. Error Handling

Error Boundaries (React)

typescript
<ErrorBoundary fallback={<ErrorPage />}>
  <App />
</ErrorBoundary>

Error States in UI

typescript
if (error) {
  return (
    <Alert variant="error">
      <AlertTitle>Failed to load data</AlertTitle>
      <AlertDescription>
        {error.message}
        <Button onClick={retry}>Try Again</Button>
      </AlertDescription>
    </Alert>
  )
}

9. Animation & Transitions

Framer Motion (React)

typescript
<motion.div
  initial={{ opacity: 0, y: 20 }}
  animate={{ opacity: 1, y: 0 }}
  exit={{ opacity: 0 }}
  transition={{ duration: 0.2 }}
>
  {content}
</motion.div>

CSS Transitions (Tailwind)

html
<div className="transition-all duration-200 hover:scale-105">

Reduced Motion

css
@media (prefers-reduced-motion: reduce) {
  * {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
}

10. Testing

Component Tests

  • Test user interactions, not implementation
  • Use Testing Library queries (getByRole, getByLabelText)
  • Test accessibility (keyboard nav, screen reader labels)

Visual Regression

  • Consider Storybook + Chromatic for component libraries
  • Screenshot tests for critical UI

Framework-Specific Guidance

React / Next.js

File Organization

code
src/
  components/
    ui/          # Reusable UI primitives (Button, Input, Card)
    features/    # Feature-specific components
  hooks/         # Custom hooks
  lib/           # Utilities, API clients
  app/           # Next.js app router

Server Components (Next.js 13+)

  • Default to Server Components
  • Use Client Components only when needed (interactivity, hooks)
  • Pass server data as props to client components

Data Fetching

typescript
// Server Component
async function Page() {
  const data = await fetch('https://api.example.com/data')
  return <Dashboard data={data} />
}

// Client Component with TanStack Query
'use client'
function Dashboard() {
  const { data } = useQuery(...)
  return <div>{data}</div>
}

Vue / Nuxt

Composition API

  • Prefer <script setup> syntax
  • Use composables for reusable logic
  • Leverage auto-imports

Reactivity

typescript
// Reactive state
const state = reactive({ count: 0 })

// Computed properties
const doubled = computed(() => state.count * 2)

// Watch for changes
watch(() => state.count, (newVal) => {
  console.log(newVal)
})

Svelte / SvelteKit

Reactivity

svelte
<script>
  let count = 0
  $: doubled = count * 2  // Reactive declaration
</script>

<button on:click={() => count++}>
  Count: {count}, Doubled: {doubled}
</button>

Stores

typescript
// Writable store
const count = writable(0)

// Derived store
const doubled = derived(count, $count => $count * 2)

// Auto-subscription in components
<script>
  import { count } from './stores'
</script>

<div>{$count}</div>

Common Anti-Patterns to Avoid

❌ Don't

Over-Abstraction

typescript
// TOO GENERIC
<FlexBox direction="column" justify="center" align="items" gap={4}>

Prop Drilling

  • Passing props through 3+ levels
  • Solution: Context, composition, or state management

Inline Functions in JSX (if causing perf issues)

typescript
// Can cause re-renders
<button onClick={() => handleClick(id)}>

Magic Numbers

typescript
// Bad
<div className="w-[347px] h-[291px]">

// Good
<div className="w-80 h-72"> // or semantic sizes

Ignoring Loading States

typescript
// Bad: Just shows nothing while loading
{data && <UserList users={data} />}

// Good: Show skeleton or spinner
{isLoading ? <Skeleton /> : <UserList users={data} />}

✅ Do

Use Semantic HTML

html
<button> for actions, not <div onClick>
<a> for navigation, not <div onClick>
<nav>, <main>, <article>, <section>

Keep Props Simple

typescript
// Good: Clear, typed props
interface ButtonProps {
  variant?: 'default' | 'outline' | 'ghost'
  size?: 'sm' | 'md' | 'lg'
  disabled?: boolean
  onClick?: () => void
  children: React.ReactNode
}

Handle Edge Cases

  • Empty states (no data)
  • Loading states (fetching data)
  • Error states (failed request)
  • Disabled states (form submission)

Tools & Libraries

Essential

  • Tailwind CSS - Utility-first CSS
  • TanStack Query - Server state management
  • React Hook Form - Form state
  • Zod - Schema validation

UI Components

  • shadcn/ui - Copy-paste components
  • Radix UI - Headless components
  • Headless UI - Tailwind-specific

Animation

  • Framer Motion - React animations
  • Auto-animate - Drop-in animations

Icons

  • Lucide React - Icon library
  • Heroicons - Tailwind icons

Workflow

Starting New UI Work

  1. Check for existing design system

    • Look for existing components in components/ui/
    • Check for Tailwind config, color schemes
    • Review any design documentation
  2. If no design system exists

    • Invoke ui-portfolio-design skill
    • Present portfolio selection to user
    • Load chosen design system specifications
  3. Build components

    • Start with semantic HTML
    • Apply styles (Tailwind or CSS Modules)
    • Add interactivity (event handlers, state)
    • Implement accessibility features
    • Handle loading/error states
  4. Test & refine

    • Test keyboard navigation
    • Test at different screen sizes
    • Test with screen reader (if possible)
    • Review with user

Modifying Existing UI

  1. Understand current patterns

    • Read existing component code
    • Identify naming conventions
    • Note styling approach (Tailwind, CSS Modules, etc.)
  2. Maintain consistency

    • Match existing component structure
    • Use same styling patterns
    • Follow established naming conventions
  3. Improve incrementally

    • Fix accessibility issues when found
    • Suggest refactors only when asked
    • Don't rewrite working code without reason

Best Practices Summary

  1. Accessibility First - Always include semantic HTML, ARIA labels, keyboard nav
  2. Mobile First - Start mobile, enhance for desktop
  3. Performance - Lazy load, code split, optimize images
  4. Composition - Small, reusable components
  5. Type Safety - Use TypeScript for props and state
  6. Error Handling - Always handle loading, error, empty states
  7. Testing - Test user behavior, not implementation
  8. Consistency - Follow existing patterns in the codebase

When to Ask for Clarification

  • Design direction unclear - Invoke portfolio selection
  • Accessibility requirements - Ask about target WCAG level
  • Browser support - Ask about target browsers/devices
  • Performance constraints - Ask about expected data volume
  • State management - Ask if existing solution is in place

Remember: Before starting new UI work, consider invoking the ui-portfolio-design skill to select a design direction. This ensures intentional, cohesive aesthetics from the start.