Claude Code Plugins

Community-maintained marketplace

Feedback
0
0

Generate production-ready React components with TypeScript, TailwindCSS, Framer Motion animations, and Radix UI. Includes accessibility compliance (WCAG 2.1 AA), responsive design, and dark mode support. Use when creating new UI features or refactoring components.

Install Skill

1Download skill
2Enable skills in Claude

Open claude.ai/settings/capabilities and find the "Skills" section

3Upload to Claude

Click "Upload skill" and select the downloaded ZIP file

Note: Please verify skill by going through its instructions before using it.

SKILL.md

name ui-component-workflow
description Generate production-ready React components with TypeScript, TailwindCSS, Framer Motion animations, and Radix UI. Includes accessibility compliance (WCAG 2.1 AA), responsive design, and dark mode support. Use when creating new UI features or refactoring components.
allowed-tools Read, Write, Edit, Glob, Grep, mcp__context7__*

UI Component Workflow Skill

Purpose

Streamline creation of accessible, animated, responsive React components following Justice Companion design system.

When Claude Uses This

  • Creating new feature UIs
  • Building form components
  • Adding animations
  • Implementing dialogs/modals
  • Refactoring legacy components
  • Accessibility improvements

Component Architecture

Directory Structure

src/
├── components/
│   ├── ui/              # Reusable primitives (Button, Input, etc.)
│   └── features/        # Feature-specific components
└── features/
    └── {feature}/
        ├── components/  # Feature components
        ├── hooks/       # Custom hooks
        └── {Feature}.tsx # Main feature component

Tech Stack

  • React 18.3 - Concurrent rendering, Suspense
  • TypeScript 5.9.3 - Type safety
  • TailwindCSS 3.4 - Utility-first styling
  • Framer Motion 11.15 - Animations
  • Radix UI - Accessible primitives
  • Lucide React - Icons

Component Template

Basic Component

// src/components/ui/Card.tsx
import { motion } from 'framer-motion';
import { cn } from '@/lib/utils';

interface CardProps extends React.HTMLAttributes<HTMLDivElement> {
  children: React.ReactNode;
  variant?: 'default' | 'elevated' | 'outlined';
}

export const Card = ({
  children,
  variant = 'default',
  className,
  ...props
}: CardProps) => {
  const variants = {
    default: 'bg-card text-card-foreground',
    elevated: 'bg-card text-card-foreground shadow-lg',
    outlined: 'border-2 border-border bg-background',
  };

  return (
    <motion.div
      initial={{ opacity: 0, y: 20 }}
      animate={{ opacity: 1, y: 0 }}
      transition={{ duration: 0.3 }}
      className={cn(
        'rounded-lg p-6',
        variants[variant],
        className
      )}
      {...props}
    >
      {children}
    </motion.div>
  );
};

Form Component with Validation

// src/components/features/cases/CreateCaseForm.tsx
import { zodResolver } from '@hookform/resolvers/zod';
import { useForm } from 'react-hook-form';
import { z } from 'zod';
import { Button } from '@/components/ui/Button';
import { Input } from '@/components/ui/Input';
import { Label } from '@/components/ui/Label';

const caseSchema = z.object({
  title: z.string().min(3, 'Title must be at least 3 characters'),
  description: z.string().min(10, 'Description must be at least 10 characters'),
  caseNumber: z.string().regex(/^[A-Z0-9-]+$/, 'Invalid case number format'),
});

type CaseFormData = z.infer<typeof caseSchema>;

export const CreateCaseForm = ({ onSubmit }: { onSubmit: (data: CaseFormData) => void }) => {
  const {
    register,
    handleSubmit,
    formState: { errors, isSubmitting },
  } = useForm<CaseFormData>({
    resolver: zodResolver(caseSchema),
  });

  return (
    <form onSubmit={handleSubmit(onSubmit)} className="space-y-4">
      <div>
        <Label htmlFor="title">Case Title</Label>
        <Input
          id="title"
          {...register('title')}
          aria-invalid={!!errors.title}
          aria-describedby={errors.title ? 'title-error' : undefined}
        />
        {errors.title && (
          <p id="title-error" className="text-sm text-destructive mt-1">
            {errors.title.message}
          </p>
        )}
      </div>

      <Button type="submit" disabled={isSubmitting}>
        {isSubmitting ? 'Creating...' : 'Create Case'}
      </Button>
    </form>
  );
};

Design System

Colors (Tailwind Config)

// tailwind.config.ts
export default {
  theme: {
    extend: {
      colors: {
        background: 'hsl(var(--background))',
        foreground: 'hsl(var(--foreground))',
        card: 'hsl(var(--card))',
        'card-foreground': 'hsl(var(--card-foreground))',
        primary: 'hsl(var(--primary))',
        'primary-foreground': 'hsl(var(--primary-foreground))',
        secondary: 'hsl(var(--secondary))',
        'secondary-foreground': 'hsl(var(--secondary-foreground))',
        destructive: 'hsl(var(--destructive))',
        'destructive-foreground': 'hsl(var(--destructive-foreground))',
        muted: 'hsl(var(--muted))',
        'muted-foreground': 'hsl(var(--muted-foreground))',
        accent: 'hsl(var(--accent))',
        'accent-foreground': 'hsl(var(--accent-foreground))',
        border: 'hsl(var(--border))',
        input: 'hsl(var(--input))',
        ring: 'hsl(var(--ring))',
      },
    },
  },
};

Animation Presets

// src/lib/animations.ts
import { Variants } from 'framer-motion';

export const fadeIn: Variants = {
  hidden: { opacity: 0 },
  visible: { opacity: 1, transition: { duration: 0.3 } },
};

export const slideUp: Variants = {
  hidden: { opacity: 0, y: 20 },
  visible: { opacity: 1, y: 0, transition: { duration: 0.3 } },
};

export const slideInFromRight: Variants = {
  hidden: { opacity: 0, x: 50 },
  visible: { opacity: 1, x: 0, transition: { duration: 0.3 } },
};

export const staggerContainer: Variants = {
  hidden: { opacity: 0 },
  visible: {
    opacity: 1,
    transition: {
      staggerChildren: 0.1,
    },
  },
};

export const scaleIn: Variants = {
  hidden: { opacity: 0, scale: 0.9 },
  visible: { opacity: 1, scale: 1, transition: { duration: 0.2 } },
};

Radix UI Integration

Dialog Example

// src/components/ui/Dialog.tsx
import * as DialogPrimitive from '@radix-ui/react-dialog';
import { X } from 'lucide-react';
import { cn } from '@/lib/utils';

const Dialog = DialogPrimitive.Root;
const DialogTrigger = DialogPrimitive.Trigger;

const DialogContent = ({ children, className, ...props }: DialogPrimitive.DialogContentProps) => (
  <DialogPrimitive.Portal>
    <DialogPrimitive.Overlay className="fixed inset-0 bg-black/50 backdrop-blur-sm" />
    <DialogPrimitive.Content
      className={cn(
        'fixed left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2',
        'w-full max-w-lg rounded-lg bg-card p-6 shadow-lg',
        'focus:outline-none',
        className
      )}
      {...props}
    >
      {children}
      <DialogPrimitive.Close className="absolute right-4 top-4">
        <X className="h-4 w-4" />
        <span className="sr-only">Close</span>
      </DialogPrimitive.Close>
    </DialogPrimitive.Content>
  </DialogPrimitive.Portal>
);

export { Dialog, DialogTrigger, DialogContent };

Accessibility Checklist

WCAG 2.1 AA Compliance

  • Keyboard Navigation: All interactive elements accessible via Tab/Arrow keys
  • Focus Indicators: Visible focus rings (use focus-visible:ring-2)
  • ARIA Labels: Proper aria-label, aria-describedby on inputs
  • Color Contrast: Minimum 4.5:1 for text, 3:1 for large text
  • Screen Reader Support: Test with NVDA (Windows) or VoiceOver (Mac)
  • Semantic HTML: Use <button>, <nav>, <main>, etc.
  • Alt Text: All images have descriptive alt attributes
  • Form Labels: Every input has associated <Label>

Accessibility Testing

# Install axe DevTools extension
# Run automated tests
pnpm test:e2e -- --grep "accessibility"

# Manual keyboard testing
# Tab through entire UI
# Shift+Tab to go backwards
# Enter/Space to activate
# Escape to close modals

Responsive Design

Breakpoints (Tailwind)

sm:  640px  (small tablets)
md:  768px  (tablets)
lg:  1024px (laptops)
xl:  1280px (desktops)
2xl: 1536px (large desktops)

Responsive Component Example

<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
  {cases.map(case => (
    <CaseCard key={case.id} {...case} />
  ))}
</div>

Dark Mode Support

Theme Toggle

// src/components/ThemeToggle.tsx
import { Moon, Sun } from 'lucide-react';
import { useTheme } from 'next-themes';

export const ThemeToggle = () => {
  const { theme, setTheme } = useTheme();

  return (
    <button
      onClick={() => setTheme(theme === 'dark' ? 'light' : 'dark')}
      className="p-2 rounded-lg hover:bg-accent"
      aria-label="Toggle theme"
    >
      {theme === 'dark' ? <Sun size={20} /> : <Moon size={20} />}
    </button>
  );
};

CSS Variables

/* src/index.css */
@layer base {
  :root {
    --background: 0 0% 100%;
    --foreground: 222.2 84% 4.9%;
    --primary: 221.2 83.2% 53.3%;
  }

  .dark {
    --background: 222.2 84% 4.9%;
    --foreground: 210 40% 98%;
    --primary: 217.2 91.2% 59.8%;
  }
}

Component Generation Workflow

Step 1: Plan Component

  • Define props interface
  • Identify Radix UI primitives needed
  • Choose animation variants
  • Plan accessibility features

Step 2: Create Component File

# Create feature component
touch "src/features/{feature}/components/{Component}.tsx"

# Create test file
touch "src/features/{feature}/components/{Component}.test.tsx"

Step 3: Implement Component

  • Use TypeScript for type safety
  • Apply Tailwind classes with cn() utility
  • Add Framer Motion animations
  • Ensure accessibility attributes

Step 4: Add Tests

// Component.test.tsx
import { render, screen } from '@testing-library/react';
import { Component } from './Component';

describe('Component', () => {
  it('renders correctly', () => {
    render(<Component />);
    expect(screen.getByRole('button')).toBeInTheDocument();
  });

  it('is keyboard accessible', () => {
    render(<Component />);
    const button = screen.getByRole('button');
    button.focus();
    expect(button).toHaveFocus();
  });
});

Step 5: Integrate

  • Import into feature module
  • Test in isolation
  • Test with dark mode
  • Test responsiveness
  • Run accessibility audit

Useful Commands

# Get latest React docs
mcp__context7__get-library-docs react

# Get Framer Motion examples
mcp__context7__get-library-docs framer-motion

# Get Radix UI component docs
mcp__context7__get-library-docs @radix-ui/react-dialog

References