- Create detailed README.md with quick start and demo accounts - Add complete UI primitives documentation with examples - Document architecture patterns and design decisions - Update REBUILD_PLAN.md marking Phase 2 as complete - Include component usage guides and testing documentation - Document accessibility compliance and performance considerations Documentation provides complete developer onboarding experience with practical examples and architectural guidance. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
629 lines
14 KiB
Markdown
629 lines
14 KiB
Markdown
# UI Primitives Documentation
|
|
|
|
A comprehensive guide to the Black Canyon Tickets component library featuring production-ready UI primitives with WCAG AA accessibility compliance.
|
|
|
|
## Design System Foundation
|
|
|
|
### Design Tokens Integration
|
|
|
|
All components use CSS custom properties from our design token system:
|
|
|
|
```css
|
|
/* Automatically available in all components */
|
|
--color-primary-50 through --color-primary-950
|
|
--color-surface-primary, --color-surface-secondary
|
|
--color-text-primary, --color-text-secondary
|
|
--font-size-xs through --font-size-4xl
|
|
--spacing-1 through --spacing-20
|
|
--border-radius-sm through --border-radius-2xl
|
|
```
|
|
|
|
### Theme Support
|
|
|
|
Every component automatically supports light and dark themes without additional configuration.
|
|
|
|
## Core UI Primitives
|
|
|
|
### Button Component
|
|
|
|
Production-ready button with multiple variants, sizes, and states.
|
|
|
|
#### Props Interface
|
|
|
|
```typescript
|
|
interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
|
|
variant?: 'primary' | 'secondary' | 'outline' | 'ghost' | 'danger';
|
|
size?: 'sm' | 'md' | 'lg' | 'xl';
|
|
loading?: boolean;
|
|
leftIcon?: React.ReactNode;
|
|
rightIcon?: React.ReactNode;
|
|
fullWidth?: boolean;
|
|
}
|
|
```
|
|
|
|
#### Usage Examples
|
|
|
|
```tsx
|
|
import { Button } from '@/components/ui/Button';
|
|
import { PlusIcon, ArrowRightIcon } from 'lucide-react';
|
|
|
|
// Basic variants
|
|
<Button variant="primary">Primary Action</Button>
|
|
<Button variant="secondary">Secondary Action</Button>
|
|
<Button variant="outline">Outline Button</Button>
|
|
<Button variant="ghost">Ghost Button</Button>
|
|
<Button variant="danger">Delete Item</Button>
|
|
|
|
// Sizes
|
|
<Button size="sm">Small</Button>
|
|
<Button size="md">Medium (default)</Button>
|
|
<Button size="lg">Large</Button>
|
|
<Button size="xl">Extra Large</Button>
|
|
|
|
// With icons
|
|
<Button leftIcon={<PlusIcon size={16} />}>
|
|
Add Event
|
|
</Button>
|
|
|
|
<Button rightIcon={<ArrowRightIcon size={16} />}>
|
|
Continue
|
|
</Button>
|
|
|
|
// Loading state
|
|
<Button loading>Processing...</Button>
|
|
|
|
// Full width
|
|
<Button fullWidth variant="primary">
|
|
Full Width Button
|
|
</Button>
|
|
```
|
|
|
|
#### Accessibility Features
|
|
|
|
- **Keyboard Navigation**: Full keyboard support with Enter/Space activation
|
|
- **Focus Management**: Visible focus indicators with proper contrast
|
|
- **Screen Reader**: Proper button semantics and loading state announcements
|
|
- **Touch Targets**: Minimum 44px touch target size on mobile
|
|
|
|
---
|
|
|
|
### Input Component
|
|
|
|
Comprehensive form input with validation, labels, and help text.
|
|
|
|
#### Props Interface
|
|
|
|
```typescript
|
|
interface InputProps extends React.InputHTMLAttributes<HTMLInputElement> {
|
|
label?: string;
|
|
helperText?: string;
|
|
error?: string;
|
|
leftIcon?: React.ReactNode;
|
|
rightIcon?: React.ReactNode;
|
|
variant?: 'default' | 'filled';
|
|
}
|
|
```
|
|
|
|
#### Usage Examples
|
|
|
|
```tsx
|
|
import { Input } from '@/components/ui/Input';
|
|
import { MailIcon, EyeIcon, EyeOffIcon } from 'lucide-react';
|
|
|
|
// Basic input with label
|
|
<Input
|
|
label="Email Address"
|
|
type="email"
|
|
placeholder="enter your email"
|
|
required
|
|
/>
|
|
|
|
// With helper text
|
|
<Input
|
|
label="Password"
|
|
type="password"
|
|
helperText="Must be at least 8 characters"
|
|
/>
|
|
|
|
// With error state
|
|
<Input
|
|
label="Username"
|
|
error="Username is already taken"
|
|
value={username}
|
|
onChange={setUsername}
|
|
/>
|
|
|
|
// With icons
|
|
<Input
|
|
label="Search Events"
|
|
leftIcon={<SearchIcon size={16} />}
|
|
placeholder="Search by name or venue"
|
|
/>
|
|
|
|
// Filled variant
|
|
<Input
|
|
variant="filled"
|
|
label="Event Description"
|
|
placeholder="Describe your event"
|
|
/>
|
|
```
|
|
|
|
#### Validation Integration
|
|
|
|
```tsx
|
|
// With React Hook Form
|
|
import { useForm } from 'react-hook-form';
|
|
|
|
const { register, formState: { errors } } = useForm();
|
|
|
|
<Input
|
|
label="Email"
|
|
{...register('email', {
|
|
required: 'Email is required',
|
|
pattern: {
|
|
value: /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i,
|
|
message: 'Invalid email address'
|
|
}
|
|
})}
|
|
error={errors.email?.message}
|
|
/>
|
|
```
|
|
|
|
#### Accessibility Features
|
|
|
|
- **Label Association**: Proper label-input association with unique IDs
|
|
- **Error Announcement**: Screen reader announcements for validation errors
|
|
- **Required Indicators**: Visual and semantic required field indicators
|
|
- **Keyboard Navigation**: Full keyboard support with Tab navigation
|
|
|
|
---
|
|
|
|
### Select Component
|
|
|
|
Accessible dropdown selection with search and custom styling.
|
|
|
|
#### Props Interface
|
|
|
|
```typescript
|
|
interface SelectOption {
|
|
value: string;
|
|
label: string;
|
|
disabled?: boolean;
|
|
}
|
|
|
|
interface SelectProps {
|
|
options: SelectOption[];
|
|
value?: string;
|
|
defaultValue?: string;
|
|
placeholder?: string;
|
|
label?: string;
|
|
error?: string;
|
|
disabled?: boolean;
|
|
required?: boolean;
|
|
onChange?: (value: string) => void;
|
|
}
|
|
```
|
|
|
|
#### Usage Examples
|
|
|
|
```tsx
|
|
import { Select } from '@/components/ui/Select';
|
|
|
|
const ticketTypes = [
|
|
{ value: 'general', label: 'General Admission' },
|
|
{ value: 'vip', label: 'VIP Access' },
|
|
{ value: 'student', label: 'Student Discount' }
|
|
];
|
|
|
|
// Basic select
|
|
<Select
|
|
label="Ticket Type"
|
|
options={ticketTypes}
|
|
placeholder="Choose ticket type"
|
|
onChange={setSelectedType}
|
|
/>
|
|
|
|
// With error state
|
|
<Select
|
|
label="Event Category"
|
|
options={categories}
|
|
error="Please select a category"
|
|
required
|
|
/>
|
|
|
|
// Disabled option
|
|
const venues = [
|
|
{ value: 'main', label: 'Main Hall' },
|
|
{ value: 'ballroom', label: 'Grand Ballroom' },
|
|
{ value: 'outdoor', label: 'Outdoor Stage', disabled: true }
|
|
];
|
|
```
|
|
|
|
#### Accessibility Features
|
|
|
|
- **Keyboard Navigation**: Arrow keys, Enter, Escape, Tab support
|
|
- **Screen Reader**: Proper combobox semantics with expanded/collapsed states
|
|
- **Focus Management**: Visible focus indicators for options
|
|
- **ARIA Labels**: Comprehensive ARIA labeling for complex interactions
|
|
|
|
---
|
|
|
|
### Card Component
|
|
|
|
Flexible container component with multiple variants and compositional API.
|
|
|
|
#### Props Interface
|
|
|
|
```typescript
|
|
interface CardProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
variant?: 'default' | 'outlined' | 'elevated';
|
|
padding?: 'none' | 'sm' | 'md' | 'lg';
|
|
}
|
|
```
|
|
|
|
#### Usage Examples
|
|
|
|
```tsx
|
|
import { Card } from '@/components/ui/Card';
|
|
|
|
// Basic card
|
|
<Card>
|
|
<h3>Event Details</h3>
|
|
<p>Join us for an unforgettable evening</p>
|
|
</Card>
|
|
|
|
// Card variants
|
|
<Card variant="outlined" padding="lg">
|
|
<Card.Header>
|
|
<h2>Premium Event</h2>
|
|
<Badge variant="success">Available</Badge>
|
|
</Card.Header>
|
|
<Card.Content>
|
|
<p>Exclusive access to premium seating</p>
|
|
</Card.Content>
|
|
<Card.Footer>
|
|
<Button variant="primary">Purchase Tickets</Button>
|
|
</Card.Footer>
|
|
</Card>
|
|
|
|
// Elevated card for important content
|
|
<Card variant="elevated" className="hover:shadow-lg transition-shadow">
|
|
<EventCard event={event} />
|
|
</Card>
|
|
```
|
|
|
|
#### Compositional API
|
|
|
|
```tsx
|
|
// Using sub-components for structured layout
|
|
<Card>
|
|
<Card.Header className="border-b">
|
|
<div className="flex justify-between items-center">
|
|
<h3>Order Summary</h3>
|
|
<Button variant="ghost" size="sm">Edit</Button>
|
|
</div>
|
|
</Card.Header>
|
|
|
|
<Card.Content className="space-y-4">
|
|
<OrderLineItem />
|
|
<OrderLineItem />
|
|
</Card.Content>
|
|
|
|
<Card.Footer className="border-t bg-surface-secondary">
|
|
<div className="flex justify-between font-semibold">
|
|
<span>Total</span>
|
|
<span>$149.00</span>
|
|
</div>
|
|
</Card.Footer>
|
|
</Card>
|
|
```
|
|
|
|
---
|
|
|
|
### Alert Component
|
|
|
|
Status messages and notifications with multiple severity levels.
|
|
|
|
#### Props Interface
|
|
|
|
```typescript
|
|
interface AlertProps {
|
|
variant?: 'info' | 'success' | 'warning' | 'error';
|
|
title?: string;
|
|
children: React.ReactNode;
|
|
icon?: React.ReactNode;
|
|
dismissible?: boolean;
|
|
onDismiss?: () => void;
|
|
}
|
|
```
|
|
|
|
#### Usage Examples
|
|
|
|
```tsx
|
|
import { Alert } from '@/components/ui/Alert';
|
|
import { CheckCircleIcon, AlertTriangleIcon } from 'lucide-react';
|
|
|
|
// Success alert
|
|
<Alert variant="success" title="Order Confirmed">
|
|
Your tickets have been purchased successfully. Check your email for confirmation.
|
|
</Alert>
|
|
|
|
// Warning alert
|
|
<Alert variant="warning" title="Limited Availability">
|
|
Only 3 tickets remaining for this event.
|
|
</Alert>
|
|
|
|
// Error alert with custom icon
|
|
<Alert
|
|
variant="error"
|
|
icon={<AlertTriangleIcon size={20} />}
|
|
dismissible
|
|
onDismiss={hideAlert}
|
|
>
|
|
Payment processing failed. Please try again or contact support.
|
|
</Alert>
|
|
|
|
// Info alert without title
|
|
<Alert variant="info">
|
|
Event details have been updated. Refresh to see changes.
|
|
</Alert>
|
|
```
|
|
|
|
#### Accessibility Features
|
|
|
|
- **ARIA Roles**: Proper alert/alertdialog roles for screen readers
|
|
- **Color Independence**: Icons and text convey meaning beyond color
|
|
- **Focus Management**: Dismissible alerts receive appropriate focus
|
|
- **Live Regions**: Dynamic alerts announced to screen readers
|
|
|
|
---
|
|
|
|
### Badge Component
|
|
|
|
Small status indicators and labels with semantic meaning.
|
|
|
|
#### Props Interface
|
|
|
|
```typescript
|
|
interface BadgeProps extends React.HTMLAttributes<HTMLSpanElement> {
|
|
variant?: 'default' | 'primary' | 'secondary' | 'success' | 'warning' | 'error';
|
|
size?: 'sm' | 'md' | 'lg';
|
|
pill?: boolean;
|
|
}
|
|
```
|
|
|
|
#### Usage Examples
|
|
|
|
```tsx
|
|
import { Badge } from '@/components/ui/Badge';
|
|
|
|
// Status badges
|
|
<Badge variant="success">Available</Badge>
|
|
<Badge variant="warning">Limited</Badge>
|
|
<Badge variant="error">Sold Out</Badge>
|
|
|
|
// Different sizes
|
|
<Badge size="sm">New</Badge>
|
|
<Badge size="md">Featured</Badge>
|
|
<Badge size="lg">Premium</Badge>
|
|
|
|
// Pill style
|
|
<Badge variant="primary" pill>VIP Access</Badge>
|
|
|
|
// In context with event cards
|
|
<EventCard>
|
|
<div className="flex justify-between items-start">
|
|
<h3>Concert Night</h3>
|
|
<Badge variant="success">Available</Badge>
|
|
</div>
|
|
</EventCard>
|
|
```
|
|
|
|
## Component Composition Patterns
|
|
|
|
### Form Composition
|
|
|
|
```tsx
|
|
import { Card, Input, Select, Button, Alert } from '@/components/ui';
|
|
|
|
function EventForm() {
|
|
return (
|
|
<Card variant="outlined" padding="lg">
|
|
<Card.Header>
|
|
<h2>Create New Event</h2>
|
|
</Card.Header>
|
|
|
|
<Card.Content className="space-y-6">
|
|
{error && (
|
|
<Alert variant="error" dismissible onDismiss={clearError}>
|
|
{error}
|
|
</Alert>
|
|
)}
|
|
|
|
<Input
|
|
label="Event Name"
|
|
placeholder="Enter event name"
|
|
required
|
|
/>
|
|
|
|
<Select
|
|
label="Event Category"
|
|
options={categories}
|
|
placeholder="Select category"
|
|
/>
|
|
|
|
<Input
|
|
label="Description"
|
|
multiline
|
|
rows={4}
|
|
placeholder="Describe your event"
|
|
/>
|
|
</Card.Content>
|
|
|
|
<Card.Footer>
|
|
<div className="flex gap-3">
|
|
<Button variant="outline" fullWidth>
|
|
Save Draft
|
|
</Button>
|
|
<Button variant="primary" fullWidth>
|
|
Publish Event
|
|
</Button>
|
|
</div>
|
|
</Card.Footer>
|
|
</Card>
|
|
);
|
|
}
|
|
```
|
|
|
|
### Status Display Pattern
|
|
|
|
```tsx
|
|
import { Badge, Alert, Button } from '@/components/ui';
|
|
|
|
function TicketStatus({ ticket }) {
|
|
const getStatusBadge = (status) => {
|
|
const variants = {
|
|
available: 'success',
|
|
limited: 'warning',
|
|
sold_out: 'error'
|
|
};
|
|
|
|
return (
|
|
<Badge variant={variants[status]}>
|
|
{status.replace('_', ' ').toUpperCase()}
|
|
</Badge>
|
|
);
|
|
};
|
|
|
|
return (
|
|
<div className="space-y-4">
|
|
<div className="flex justify-between items-center">
|
|
<h3>{ticket.name}</h3>
|
|
{getStatusBadge(ticket.status)}
|
|
</div>
|
|
|
|
{ticket.status === 'limited' && (
|
|
<Alert variant="warning">
|
|
Only {ticket.remaining} tickets left
|
|
</Alert>
|
|
)}
|
|
|
|
<Button
|
|
variant="primary"
|
|
disabled={ticket.status === 'sold_out'}
|
|
fullWidth
|
|
>
|
|
{ticket.status === 'sold_out' ? 'Sold Out' : 'Purchase'}
|
|
</Button>
|
|
</div>
|
|
);
|
|
}
|
|
```
|
|
|
|
## Design Token Usage
|
|
|
|
### Color System
|
|
|
|
```tsx
|
|
// Using semantic color tokens
|
|
<div className="bg-surface-primary text-text-primary border border-border-primary">
|
|
Content with theme-aware colors
|
|
</div>
|
|
|
|
// Status colors
|
|
<Alert variant="success"> // Uses --color-success-* tokens
|
|
<Badge variant="error"> // Uses --color-error-* tokens
|
|
```
|
|
|
|
### Typography Scale
|
|
|
|
```tsx
|
|
// Using typography tokens
|
|
<h1 className="text-4xl">Main Heading</h1> // --font-size-4xl
|
|
<h2 className="text-2xl">Section Heading</h2> // --font-size-2xl
|
|
<p className="text-base">Body text</p> // --font-size-base
|
|
<small className="text-sm">Helper text</small> // --font-size-sm
|
|
```
|
|
|
|
### Spacing System
|
|
|
|
```tsx
|
|
// Using spacing tokens
|
|
<div className="p-4 m-2 space-y-6"> // --spacing-4, --spacing-2, --spacing-6
|
|
<Card padding="lg"> // --spacing-8 (internal)
|
|
<div className="space-between-3"> // --spacing-3
|
|
```
|
|
|
|
## Testing Components
|
|
|
|
All UI primitives include comprehensive test coverage:
|
|
|
|
```typescript
|
|
// Example test for Button component
|
|
test('Button renders with correct variant styles', async ({ page }) => {
|
|
await page.goto('/ui-showcase');
|
|
|
|
// Test primary variant
|
|
const primaryButton = page.getByTestId('button-primary');
|
|
await expect(primaryButton).toHaveClass(/bg-primary/);
|
|
|
|
// Test accessibility
|
|
await expect(primaryButton).toBeEnabled();
|
|
await primaryButton.focus();
|
|
await expect(primaryButton).toBeFocused();
|
|
|
|
// Test keyboard interaction
|
|
await primaryButton.press('Enter');
|
|
await expect(page.getByText('Button clicked')).toBeVisible();
|
|
});
|
|
```
|
|
|
|
## Accessibility Compliance
|
|
|
|
### WCAG AA Standards
|
|
|
|
All components meet WCAG AA requirements:
|
|
|
|
- **Color Contrast**: 4.5:1 minimum ratio for normal text, 3:1 for large text
|
|
- **Keyboard Navigation**: Full keyboard support for all interactive elements
|
|
- **Screen Reader Support**: Proper semantic HTML and ARIA labels
|
|
- **Focus Management**: Visible focus indicators with sufficient contrast
|
|
|
|
### Testing Tools
|
|
|
|
```bash
|
|
# Run accessibility tests
|
|
npm run test:a11y
|
|
|
|
# Generate accessibility report
|
|
npm run a11y:report
|
|
|
|
# Visual contrast validation
|
|
npm run test:contrast
|
|
```
|
|
|
|
## Performance Considerations
|
|
|
|
### Bundle Size Optimization
|
|
|
|
- **Tree Shaking**: Import only the components you need
|
|
- **CSS Custom Properties**: Reduced CSS bundle size with design tokens
|
|
- **Minimal Dependencies**: Core components have zero external dependencies
|
|
|
|
```tsx
|
|
// Efficient imports
|
|
import { Button, Input } from '@/components/ui'; // Tree-shaken
|
|
|
|
// Avoid importing entire library
|
|
import * as UI from '@/components/ui'; // Not recommended
|
|
```
|
|
|
|
### Runtime Performance
|
|
|
|
- **Memoization**: Components use React.memo where appropriate
|
|
- **Event Handling**: Optimized event listeners with proper cleanup
|
|
- **Re-render Optimization**: Props designed to minimize unnecessary re-renders
|
|
|
|
---
|
|
|
|
**Component library built with CrispyGoat quality standards - accessible, performant, and developer-friendly.** |