Quickstart Guide
Get up and running with Stride in under 5 minutes. This guide walks you through creating a complete user profile form with brand theming.
Prerequisites
Make sure you’ve completed the installation steps before continuing.
Build Your First Component
Let’s create a user profile form that showcases Stride’s components, accessibility features, and theming capabilities.
Import components
Start by importing the components you’ll need:import {
Button,
Card,
CardHeader,
CardTitle,
CardDescription,
CardContent,
CardFooter,
Input,
Switch,
Badge,
} from 'stride-ds';
import 'stride-ds/styles';
All components are fully typed with TypeScript. Your IDE will provide autocomplete for props.
Create the form component
Build a simple profile form using Stride components:'use client'; // Required for Next.js App Router
import { useState } from 'react';
import {
Button,
Card,
CardHeader,
CardTitle,
CardDescription,
CardContent,
CardFooter,
Input,
Switch,
Badge,
} from 'stride-ds';
export function ProfileForm() {
const [emailNotifications, setEmailNotifications] = useState(true);
return (
<Card variant="elevated" className="max-w-md">
<CardHeader>
<div className="flex items-center justify-between">
<CardTitle>User Profile</CardTitle>
<Badge variant="success">Active</Badge>
</div>
<CardDescription>
Update your profile information and preferences
</CardDescription>
</CardHeader>
<CardContent className="space-y-4">
<Input
label="Full Name"
placeholder="Enter your name"
isRequired
/>
<Input
label="Email Address"
type="email"
placeholder="[email protected]"
isRequired
/>
<Input
label="Bio"
placeholder="Tell us about yourself"
helperText="Optional - shown on your public profile"
/>
<div className="flex items-center justify-between py-2">
<div>
<label className="font-medium text-sm">
Email Notifications
</label>
<p className="text-xs text-[var(--text-secondary)]">
Receive updates about your account
</p>
</div>
<Switch
isSelected={emailNotifications}
onChange={setEmailNotifications}
/>
</div>
</CardContent>
<CardFooter>
<Button variant="secondary">Cancel</Button>
<Button variant="primary">Save Changes</Button>
</CardFooter>
</Card>
);
}
Notice how we’re using semantic tokens like var(--text-secondary) for custom styling. This ensures your styles adapt to different brands.
Add brand theming (optional)
Apply a brand theme to your entire application:import { BrandInitializer } from 'stride-ds';
import { ProfileForm } from './ProfileForm';
export default function App() {
return (
<>
<BrandInitializer brand="coral" />
<div className="min-h-screen bg-[var(--bg-primary)] p-8">
<ProfileForm />
</div>
</>
);
}
Available brands:
stride (default) - Modern blue theme
coral - Warm orange-red theme
forest - Natural green theme
runswap - Energetic purple theme
acme - Modern indigo tech theme
Run your application
Start your development server and see your form in action:Your form is now live with full accessibility, keyboard navigation, and brand theming!
Complete Working Example
Here’s the full code for a production-ready profile page:
'use client';
import { useState } from 'react';
import {
Button,
Card,
CardHeader,
CardTitle,
CardDescription,
CardContent,
CardFooter,
Input,
Switch,
Badge,
Alert,
BrandInitializer,
} from 'stride-ds';
import 'stride-ds/styles';
export default function ProfilePage() {
const [emailNotifications, setEmailNotifications] = useState(true);
const [fullName, setFullName] = useState('');
const [email, setEmail] = useState('');
const [bio, setBio] = useState('');
const [saved, setSaved] = useState(false);
const handleSave = () => {
// Validate and save logic here
setSaved(true);
setTimeout(() => setSaved(false), 3000);
};
return (
<>
<BrandInitializer brand="stride" />
<main className="min-h-screen bg-[var(--bg-secondary)] p-8">
<div className="max-w-2xl mx-auto space-y-6">
<div>
<h1 className="text-3xl font-bold text-[var(--text-primary)]">
Account Settings
</h1>
<p className="text-[var(--text-secondary)] mt-2">
Manage your profile and notification preferences
</p>
</div>
{saved && (
<Alert variant="success" title="Success">
Your profile has been updated successfully.
</Alert>
)}
<Card variant="elevated">
<CardHeader>
<div className="flex items-center justify-between">
<CardTitle>User Profile</CardTitle>
<Badge variant="success">Active</Badge>
</div>
<CardDescription>
Update your profile information and preferences
</CardDescription>
</CardHeader>
<CardContent className="space-y-4">
<Input
label="Full Name"
placeholder="Enter your name"
value={fullName}
onChange={(e) => setFullName(e.target.value)}
isRequired
/>
<Input
label="Email Address"
type="email"
placeholder="[email protected]"
value={email}
onChange={(e) => setEmail(e.target.value)}
isRequired
/>
<Input
label="Bio"
placeholder="Tell us about yourself"
value={bio}
onChange={(e) => setBio(e.target.value)}
helperText="Optional - shown on your public profile"
/>
<div className="border-t border-[var(--border-primary)] pt-4" />
<div className="flex items-center justify-between py-2">
<div>
<label className="font-medium text-sm text-[var(--text-primary)]">
Email Notifications
</label>
<p className="text-xs text-[var(--text-secondary)] mt-1">
Receive updates about your account activity
</p>
</div>
<Switch
isSelected={emailNotifications}
onChange={setEmailNotifications}
aria-label="Toggle email notifications"
/>
</div>
</CardContent>
<CardFooter>
<Button variant="secondary" onPress={() => window.history.back()}>
Cancel
</Button>
<Button
variant="primary"
onPress={handleSave}
isDisabled={!fullName || !email}
>
Save Changes
</Button>
</CardFooter>
</Card>
</div>
</main>
</>
);
}
Understanding the Code
Let’s break down the key concepts:
Component Composition
Stride components are designed to be composed together:
<Card> {/* Container */}
<CardHeader> {/* Visual grouping */}
<CardTitle /> {/* Semantic heading */}
</CardHeader>
<CardContent> {/* Main content area */}
<Input /> {/* Form fields */}
</CardContent>
<CardFooter> {/* Actions */}
<Button /> {/* Interactive elements */}
</CardFooter>
</Card>
Semantic Design Tokens
Use CSS variables for custom styling:
// ✅ Good - Uses semantic tokens
<div className="bg-[var(--bg-primary)] text-[var(--text-primary)]" />
// ❌ Avoid - Hard-coded colors break theming
<div className="bg-white text-gray-900" />
Common tokens:
- Text:
--text-primary, --text-secondary, --text-tertiary
- Background:
--bg-primary, --bg-secondary, --bg-tertiary
- Interactive:
--interactive-primary, --interactive-primary-hover
- Borders:
--border-primary, --border-secondary, --border-focus
- Status:
--status-success, --status-warning, --status-danger
React Aria Integration
All components use React Aria for accessibility:
<Button onPress={() => console.log('clicked')}>
{/* onPress works with clicks, keyboard, and touch */}
Click me
</Button>
<Input
isRequired {/* Adds ARIA required attribute */}
isDisabled={false} {/* Manages aria-disabled */}
aria-label="Email" {/* Custom ARIA labels supported */}
/>
Component Variants
Most components support variants for different styles:
{/* Button variants */}
<Button variant="primary">Primary</Button>
<Button variant="secondary">Secondary</Button>
<Button variant="ghost">Ghost</Button>
<Button variant="destructive">Delete</Button>
{/* Card variants */}
<Card variant="outlined">Outlined</Card>
<Card variant="elevated">Elevated</Card>
<Card variant="interactive">Interactive</Card>
{/* Badge variants */}
<Badge variant="default">Default</Badge>
<Badge variant="success">Success</Badge>
<Badge variant="warning">Warning</Badge>
<Badge variant="danger">Danger</Badge>
Dynamic Brand Switching
You can change brands dynamically at runtime:
'use client';
import { useState } from 'react';
import { applyBrandTheme } from 'stride-ds';
import { Button } from 'stride-ds';
export function BrandSwitcher() {
const [currentBrand, setCurrentBrand] = useState('stride');
const brands = [
{ id: 'stride', name: 'Stride', color: 'blue' },
{ id: 'coral', name: 'Coral', color: 'orange' },
{ id: 'forest', name: 'Forest', color: 'green' },
{ id: 'runswap', name: 'Runswap', color: 'purple' },
{ id: 'acme', name: 'Acme', color: 'indigo' },
];
const switchBrand = (brandId: string) => {
applyBrandTheme(brandId);
setCurrentBrand(brandId);
};
return (
<div className="flex gap-2">
{brands.map((brand) => (
<Button
key={brand.id}
variant={currentBrand === brand.id ? 'primary' : 'secondary'}
size="sm"
onPress={() => switchBrand(brand.id)}
>
{brand.name}
</Button>
))}
</div>
);
}
Brand preferences are automatically saved to localStorage and persist across sessions.
Next Steps
Now that you’ve built your first component, explore more features:
Component Library
Explore all 18+ available components
Brand System
Create custom brands and themes
Design Tokens
Learn about the token system
Accessibility
Best practices for accessible UIs
TypeScript Guide
Advanced TypeScript patterns
Customization
Extend and customize components
Common Patterns
Disable buttons during async operations:<Button
variant="primary"
isDisabled={isLoading}
onPress={async () => {
setIsLoading(true);
await saveProfile();
setIsLoading(false);
}}
>
{isLoading ? 'Saving...' : 'Save'}
</Button>
Toggle dark mode by adding a class to the root element:const toggleDarkMode = () => {
document.documentElement.classList.toggle('dark');
};
All semantic tokens automatically adapt to dark mode.