@krrli/cm-designsystem
v1.33.1
Published
A modern React component library built with TypeScript, Tailwind CSS, and Storybook.
Readme
CM Design System
A modern React component library built with TypeScript, Tailwind CSS, and Storybook.
Table of Contents
- Usage in Your Project
- Technical Stack
- Development
- Icon Generation
- Visual Testing
- Contributing
- Continuous Integration
- EditorConfig & VS Code Settings
Usage in Your Project
To use the components and styles in your project:
- Install the package:
npm i @krrli/cm-designsystem- Import the bundled CSS in your app entry (e.g.,
main.tsxorApp.tsx):
import "cm-designsystem/dist/cm-designsystem.css";- Import and use components as needed:
import { Button } from "cm-designsystem";
function App() {
return (
<Button label="Click me" intent="primary" size="md" onClick={() => {}} />
);
}Technical Stack
- React 19 with TypeScript
- Vite for fast development and building
- Tailwind CSS v4 for styling
- Storybook for component documentation
- Vitest for unit testing
- Playwright for visual regression testing
- Radix UI Primitives for accessible component primitives
- @vitejs/plugin-react for Fast Refresh
Development
Quick Start Development
# Install dependencies
npm install
# Start Storybook development server
npm run storybookStorybook will be available at http://localhost:6006
📚 View the deployed Storybook: https://ost-cas-fea-25-26.github.io/cm-designsystem/
Quality Checks
Run all quality checks before committing:
npm run preflight # Runs format, lint, type-check, test, and buildIndividual commands:
# Formatting
npm run format # Auto-format all files with Prettier
npm run format:check # Check formatting without making changes
# Linting
npm run lint # Check for linting errors
npm run lint:fix # Auto-fix linting errors where possible
# Type Checking
npx tsc -b --noEmit # Run TypeScript type checking
# Testing
npm test # Run unit tests with Vitest
# Building
npm run build # Build the project
npm run build-storybook # Build Storybook for productionCode Style
We enforce consistent code style using automated tools:
Prettier Configuration:
- Uses double quotes
- 2-space indentation
- Semicolons required
- Line width: 80 characters
- Includes Tailwind CSS class sorting plugin
ESLint Configuration:
- TypeScript ESLint rules
- React and React Hooks best practices
- JSX Accessibility (a11y) rules
- Import sorting and organization
- Storybook rules
- Prettier integration (no conflicts)
TypeScript Guidelines
We follow a consistent pattern for component type definitions:
Standard Component Pattern:
import { tv, type VariantProps } from "tailwind-variants";
// 1. Define styles with tailwind-variants
const buttonStyles = tv({
variants: {
intent: {
primary: ["bg-slate-600"],
secondary: ["bg-violet-600"],
},
size: {
md: ["pt-3", "pb-3"],
lg: ["pt-4", "pb-4"],
},
},
});
// 2. Extract variant types from styles
type ButtonVariants = VariantProps<typeof buttonStyles>;
// 3. Define specific union types for variant options
type ButtonIntent = "primary" | "secondary";
type ButtonSize = "md" | "lg";
// 4. Create component props interface extending variants
interface ButtonProps extends ButtonVariants {
label: string;
onClick: () => void;
className?: string;
}When to use type vs interface:
type: For VariantProps, union types, and type aliasesinterface: For component props (always extends variants)export: Export interfaces for public component APIs
Best Practices:
- Always extend
VariantPropsfor styled components - Define union types for variant options to ensure type safety
- Export prop interfaces for components
- Use strict TypeScript (enabled by default)
Project Structure
Components and their Storybook stories are co-located in the same folder for better organization:
src/components/
├── button/
│ ├── Button.tsx # Component implementation
│ ├── Button.stories.tsx # Storybook stories
│ └── Button.test.tsx # Unit tests (if applicable)
├── avatar/
│ ├── Avatar.tsx
│ └── Avatar.stories.tsx
└── ...Benefits of co-location:
- ✅ Related files stay together
- ✅ Easier to find and maintain stories
- ✅ Clear 1:1 relationship between components and documentation
- ✅ Stories serve as living documentation and examples
Story file naming: Always use ComponentName.stories.tsx format for Storybook to auto-discover them.
Icon Generation
SVG icons are automatically converted to React components with proper accessibility support.
Workflow
Add SVG files to
src/components/icons/svg/Optimize SVGs (optional but recommended):
npx svgo -f src/components/icons/svgGenerate React components:
npm run icons:generate
Configuration
Edit svg.config.json to customize the generation process:
{
"sourceDir": "src/components/icons/svg",
"outputDir": "src/components/icons/generated",
"baseComponentImport": {
"name": "IconBase",
"path": "../IconBase"
}
}Usage Example
import { Calendar, LogOut } from "src/components/icons/generated";
export function Example() {
return (
<div className="flex gap-2 text-slate-600">
<Calendar />
<LogOut className="text-red-600" />
</div>
);
}How it works:
- File names are converted to PascalCase (
log-out.svg→LogOut) - Fill colors are normalized to
currentColorfor theming - All icons are wrapped in
IconBasefor accessibility - A barrel export (
index.ts) is generated automatically
Visual Testing
We use Playwright for visual regression testing against Storybook. Tests run in Docker for consistent results across environments.
Setup
Build the Docker image (first time only):
npm run e2e:buildRunning Tests
npm run e2e:test # Run visual regression tests
npm run e2e:update # Update baseline snapshotsViewing Reports
View test reports locally:
npx playwright show-reportGitHub Artifacts: Test reports are uploaded as CI artifacts. Download and view them with:
npx playwright show-report <path/to/extracted-artifact>Configuration
- Docker: Tests run in containers for consistency across environments
- Network: Storybook accepts connections from
host.docker.internal - Tolerance: 1% pixel difference allowed (
maxDiffPixelRatio: 0.01) - Files:
playwright.config.tsand.storybook/main.ts
Contributing
Pull Request Process
Create a feature branch:
git checkout -b feature/initials/your-feature-nameUse format:
feature/<mm or ci>/<description>Make your changes and ensure quality:
npm run preflightCommit with conventional commits (see below)
Push to your feature branch:
git push origin feature/initials/your-feature-nameCreate a pull request to
mainWait for CI checks to pass
Request review from team members
Address feedback and merge
Commit Messages
We use Conventional Commits for consistent versioning and changelog generation.
Format:
<type>: <description>
[optional body]Types:
feat: New featurefix: Bug fixdocs: Documentation changesstyle: Code style/formatting (no logic change)refactor: Code refactoring (no feature/bug change)test: Adding or updating testschore: Maintenance tasks (dependencies, config, etc.)perf: Performance improvements
Examples:
feat: add new Button variant
fix: correct Typography component spacing
docs: update README with visual testing guide
chore: update dependencies
test: add tests for TextLink componentContinuous Integration
All pull requests are automatically validated through our CI pipeline.
Required Checks
- ✅ Format & Lint - Code must be properly formatted and pass linting
- ✅ Type Check - No TypeScript errors
- ✅ Tests - All unit tests must pass
- ✅ Build - Project must build successfully
- ✅ Build Storybook - Storybook must build successfully
- ✅ Visual Tests - Playwright visual regression tests must pass
Pipeline Triggers
- Pull requests to
main - Pushes to
main
Why No Pre-commit Hooks?
We intentionally don't use pre-commit hooks (like Husky):
- ✅ Quality checks in CI can't be bypassed
- ✅ Faster local development workflow
- ✅ CI is the single source of truth
Note: You're encouraged to run npm run preflight locally before pushing!
EditorConfig & VS Code Settings
This project uses a strict .editorconfig to ensure consistent code style across all editors and platforms. Most formatting rules (indentation, line endings, trailing whitespace, etc.) are enforced automatically if you have the EditorConfig extension installed in VS Code.
Additionally, the repository includes a .vscode/settings.json file to avoid conflicts between VS Code's built-in formatting and EditorConfig:
{
"editor.formatOnSave": true,
"files.trimTrailingWhitespace": false,
"files.insertFinalNewline": false,
"files.eol": "\n"
}- No further VS Code settings are required—just make sure the EditorConfig extension is enabled.
- These settings ensure that formatting is always consistent, regardless of individual developer/editor preferences.
