Overview
We welcome contributions to Stride Design System! This guide covers everything from setup to submitting pull requests, including our changeset workflow and component development patterns.
Getting Started
Prerequisites
Node.js 18+ and npm
Git
A GitHub account
Basic knowledge of React, TypeScript, and Tailwind CSS
Repository Setup
Clone the repository
git clone [repo-url]
cd stride-ds
npm install
Start development environment
# Launch Storybook for component development
npm run storybook
# Or run the Next.js development app
npm run dev
Create a feature branch
git checkout -b feature/my-new-component
Branch naming conventions:
feature/component-name - New components or features
fix/issue-description - Bug fixes
docs/what-changed - Documentation updates
refactor/area-changed - Code refactoring
Development Workflow
Available Scripts
# Development
npm run dev # Next.js dev server (http://localhost:3000)
npm run storybook # Storybook (http://localhost:6006)
# Building
npm run build # Build Next.js app
npm run build:lib # Build library (Vite)
npm run build:types # Generate TypeScript types
npm run build:styles # Build CSS styles
npm run prepublishOnly # Complete build for publishing
# Quality
npm run lint # Run ESLint
npm run build-storybook # Build Storybook for production
Creating a New Component
File Structure
Every component follows this structure:
src/components/ui/MyComponent/
├── index.ts # Exports
├── MyComponent.tsx # Component implementation
└── MyComponent.stories.tsx # Storybook documentation
Component Template
Use this template for new components:
src/components/ui/MyComponent/MyComponent.tsx
"use client" ;
import React from "react" ;
import { cva , type VariantProps } from "class-variance-authority" ;
import { cn } from "@/lib/utils" ;
// Define variants with semantic tokens
const myComponentVariants = cva (
[
"base-classes" ,
"[transition-duration:var(--transition-normal)]" ,
],
{
variants: {
variant: {
default: "[color:var(--text-primary)]" ,
secondary: "[color:var(--text-secondary)]" ,
},
size: {
sm: "[font-size:var(--font-size-sm)]" ,
md: "[font-size:var(--font-size-md)]" ,
lg: "[font-size:var(--font-size-lg)]" ,
},
},
defaultVariants: {
variant: "default" ,
size: "md" ,
},
}
);
// Define props interface
export interface MyComponentProps
extends React . HTMLAttributes < HTMLDivElement >,
VariantProps < typeof myComponentVariants > {
children ?: React . ReactNode ;
}
// Implement with forwardRef
export const MyComponent = React . forwardRef < HTMLDivElement , MyComponentProps >(
({ className , variant , size , children , ... props }, ref ) => {
return (
< div
className = { cn ( myComponentVariants ({ variant , size , className })) }
ref = { ref }
{ ... props }
>
{ children }
</ div >
);
}
);
MyComponent . displayName = "MyComponent" ;
Export Component
src/components/ui/MyComponent/index.ts
export * from './MyComponent' ;
// Add to main index file
export * from './components/ui/MyComponent' ;
Storybook Development
Creating Stories
Stories document component usage and variants:
src/components/ui/MyComponent/MyComponent.stories.tsx
import type { Meta , StoryObj } from "@storybook/nextjs" ;
import { MyComponent } from "./MyComponent" ;
const meta : Meta < typeof MyComponent > = {
title: "Stride DS/MyComponent" ,
component: MyComponent ,
parameters: {
layout: "centered" ,
},
tags: [ "autodocs" ],
argTypes: {
variant: {
control: { type: "select" },
options: [ "default" , "secondary" ],
},
size: {
control: { type: "select" },
options: [ "sm" , "md" , "lg" ],
},
},
};
export default meta ;
type Story = StoryObj < typeof meta >;
export const Default : Story = {
args: {
children: "My Component" ,
variant: "default" ,
size: "md" ,
},
};
export const AllVariants : Story = {
render : () => (
< div className = "flex gap-4" >
< MyComponent variant = "default" > Default </ MyComponent >
< MyComponent variant = "secondary" > Secondary </ MyComponent >
</ div >
),
};
Storybook Best Practices
Document All Variants Create a story for each variant combination to showcase all possibilities.
Interactive Controls Use argTypes to provide interactive controls in Storybook.
Accessibility Tests Include accessibility parameters for automated a11y testing.
Real Use Cases Show practical examples of how the component would be used.
Design Tokens
Adding Brand Tokens
Brand-specific colors and typography go in src/app/brands.css:
.brand-stride {
/* Brand colors */
--brand-accent-500 : #2563eb ;
--brand-accent-600 : #1d4ed8 ;
/* Custom typography */
--font-family-display : 'Outfit' , sans-serif ;
/* Semantic mapping */
--text-accent : var ( --brand-accent-500 );
--interactive-primary : var ( --brand-accent-500 );
}
.brand-stride.dark {
--brand-accent-500 : #60a5fa ;
--brand-accent-600 : #3b82f6 ;
}
Adding Foundation Tokens
Spacing, radius, and shadows go in src/styles.css:
:root {
/* Spacing */
--spacing-xs : 0.25 rem ;
--spacing-sm : 0.5 rem ;
--spacing-md : 1 rem ;
--spacing-lg : 1.5 rem ;
--spacing-xl : 2 rem ;
/* Border radius */
--radius-sm : 0.25 rem ;
--radius-md : 0.5 rem ;
--radius-lg : 0.75 rem ;
--radius-full : 9999 px ;
/* Shadows */
--shadow-sm : 0 1 px 2 px rgba ( 0 , 0 , 0 , 0.05 );
--shadow-md : 0 4 px 6 px rgba ( 0 , 0 , 0 , 0.1 );
--shadow-lg : 0 10 px 15 px rgba ( 0 , 0 , 0 , 0.1 );
}
Adding Component Tokens
Component-specific tokens also go in src/styles.css:
:root {
/* Button tokens */
--button-height-sm : 2 rem ;
--button-height-md : 2.5 rem ;
--button-height-lg : 3 rem ;
--button-padding-sm : 0.5 rem 1 rem ;
--button-padding-md : 0.75 rem 1.5 rem ;
--button-padding-lg : 1 rem 2 rem ;
--radius-button : 0.5 rem ;
/* Input tokens */
--input-height-sm : 2 rem ;
--input-height-md : 2.5 rem ;
--input-height-lg : 3 rem ;
}
Changeset Workflow
What are Changesets?
Changesets track changes and automate versioning and changelog generation. Every PR that changes functionality must include a changeset.
Creating a Changeset
Make your changes
Implement your feature or fix.
Select change type
Choose the appropriate version bump:
patch (0.0.1): Bug fixes, small improvements
minor (0.1.0): New features, new components
major (1.0.0): Breaking changes
Write description
Provide a clear description of your changes: ✅ Good: "Add new Toast component with success/error variants"
✅ Good: "Fix Button focus styles in dark mode"
❌ Bad: "Update stuff"
❌ Bad: "Changes"
Commit the changeset
The changeset file is created in .changeset/ directory: git add .changeset/
git commit -m "feat: add toast component"
Changeset Examples
New Component
Bug Fix
Breaking Change
npm run changeset
# Select: minor
# Description: Add Alert component with info, success, warning, and error variants
npm run changeset
# Select: patch
# Description: Fix Button focus ring not showing in Safari
npm run changeset
# Select: major
# Description: Rename Card 'elevated' variant to 'shadow' for consistency
Git Commit Guidelines
Follow Conventional Commits :
type ( scope ): description
# Examples:
feat(button ): add loading state with spinner
fix(card ): resolve border radius in safari
docs(readme ): update installation instructions
style(input ): improve focus ring visibility
refactor(utils ): simplify classname helper
test ( button ): add accessibility tests
chore(deps ): update tailwind to latest
Commit Types
New features or components feat(toast ): add Toast component
feat(button ): add leftIcon and rightIcon props
Bug fixes fix(button ): resolve focus ring in dark mode
fix(input ): correct label alignment
Documentation changes docs(readme ): add Next.js 15 setup guide
docs(button ): update component examples
Formatting, styling (no code logic changes) style(card ): improve spacing consistency
style: format code with prettier
Code refactoring without changing behavior refactor(utils ): simplify cn () implementation
refactor(button ): extract icon logic to separate hook
Adding or updating tests test ( button ): add keyboard navigation tests
test : increase coverage for Input component
Maintenance tasks, dependency updates chore(deps ): update react-aria to v3.30.0
chore: configure github actions
Pull Request Process
Test your changes
# Build the library
npm run build:lib
npm run build:types
npm run build:styles
# Run linting
npm run lint
# Test in Storybook
npm run storybook
Commit and push
git add .
git commit -m "feat: add new component"
git push origin feature/my-component
Open pull request
Go to GitHub repository
Click “Compare & pull request”
Fill out the PR template:
Clear title and description
Link related issues
Add screenshots for UI changes
Note breaking changes
Address review feedback
# Make requested changes
git add .
git commit -m "fix: address review feedback"
git push origin feature/my-component
Release Process
Automated Releases
Stride uses an automated release workflow:
Developer creates changeset (you did this!)
PR is merged to main branch
GitHub Actions detects changesets
Version Packages PR is created automatically
Maintainer reviews and merges version PR
Automatic publication to npm with release notes
You don’t need to manually version or publish! The changeset workflow handles everything automatically.
Component Development Patterns
React Aria Integration
Many Stride components use React Aria for accessibility:
import {
Button as AriaButton ,
type ButtonProps as AriaButtonProps ,
} from "react-aria-components" ;
export interface ButtonProps extends AriaButtonProps {
// Add custom props
}
export const Button = React . forwardRef < HTMLButtonElement , ButtonProps >(
( props , ref ) => {
return < AriaButton ref = { ref } { ... props } /> ;
}
);
Always Use Semantic Tokens
// ❌ Don't use hardcoded values
const styles = "bg-blue-500 text-white" ;
// ✅ Use semantic tokens
const styles = "[background-color:var(--interactive-primary)] [color:var(--interactive-primary-text)]" ;
Proper TypeScript Types
// ✅ Export props interface
export interface ComponentProps extends HTMLAttributes < HTMLDivElement > {}
// ✅ Use VariantProps for variants
export interface ComponentProps extends VariantProps < typeof variants > {}
// ✅ Proper forwardRef typing
export const Component = React . forwardRef < HTMLDivElement , ComponentProps >();
Getting Help
Discord Community Join our Discord for questions and discussions.
GitHub Issues Report bugs or request features on GitHub.
Documentation Check the docs for guides and examples.
Code Examples Browse existing components for patterns.
Next Steps
Styling Guide Learn styling patterns and best practices
TypeScript Guide Master TypeScript patterns in Stride