# Design System
import { Callout, Kbd } from '@/components/mdx';
# Design System
**@loke/design-system** is a pre-styled, accessible React component library built on Tailwind CSS v4. It provides production-ready components — Button, Card, Dialog, Form inputs, and more — along with layout primitives and a comprehensive color system. All styles are pre-compiled and ship as standard CSS, so you can use it with no build tool configuration.
This section covers everything you need to use the design system effectively:
* **Quick Start** — Get running in 5 minutes
* **[Form Input](/docs/design-system/form-input)** — Button, Input, Select, Checkbox, and more
* **[Feedback & Status](/docs/design-system/feedback-status)** — Alert, Badge, Toast, Spinner, and more
* **[Overlay & Navigation](/docs/design-system/overlay-navigation)** — Dialog, Dropdown, Tabs, Accordion, and more
* **[Data Display](/docs/design-system/data-display)** — Card, Table, Avatar, Text, and more
* **[Layout](/docs/design-system/layout)** — Box, Stack, Columns, and Inline primitives for structure
* **[Utilities](/docs/design-system/utilities)** — Helper functions and responsive utilities
* **[Guides](/docs/guides)** — Tailwind integration, color system, accessibility, and more
***
## Quick Start
This guide walks you through adding the LOKE Design System to an existing React project. By the end, you'll have a working setup with components rendering correctly.
The design system is designed to be plug-and-play. Install it, import the styles, and start using components — no additional configuration required.
***
## 1. Install the package
```bash
# bun (recommended)
bun add @loke/design-system
# npm
npm install @loke/design-system
# pnpm
pnpm add @loke/design-system
```
To use icons, also install the icon package:
```bash
bun add @loke/icons
```
***
## 2. Check your TypeScript config
The design system uses the `exports` field in `package.json` for granular imports. Your `tsconfig.json` must use a module resolution strategy that supports this.
Set the following in your `tsconfig.json`:
```json
{
"compilerOptions": {
"module": "esnext",
"moduleResolution": "bundler"
}
}
```
If you see Cannot find module '@loke/design-system/button' errors, this is almost always a `moduleResolution` issue. The `"nodenext"` setting can cause problems with package exports — switch to `"bundler"` to resolve it.
***
## 3. Import the styles
Add the design system stylesheet to your app's root layout or entry point. This single import provides all component styles, theme variables, and color tokens.
### Next.js
```tsx
// app/layout.tsx
import "@loke/design-system/styles";
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
{children}
);
}
```
### Vite / other frameworks
```tsx
// main.tsx or index.tsx
import "@loke/design-system/styles";
import { createRoot } from "react-dom/client";
import { App } from "./App";
createRoot(document.getElementById("root")!).render();
```
That's the only setup step. The design system ships pre-compiled CSS — you don't need to install or configure Tailwind CSS, PostCSS, or any other CSS tooling.
***
## 4. Use your first component
Import components individually from their specific paths:
```tsx
import { Button } from "@loke/design-system/button";
export function MyPage() {
return (
Hello, Design System
);
}
```
Components are imported from `@loke/design-system/` — not from the package root. This keeps your bundles small through tree-shaking.
```tsx
// Correct
import { Button } from "@loke/design-system/button";
import { Card, CardHeader, CardTitle, CardContent } from "@loke/design-system/card";
import { Input } from "@loke/design-system/input";
// Wrong — there is no barrel export
import { Button } from "@loke/design-system";
```
***
## 5. Build a simple page
Here's a more complete example combining several components:
```tsx
import { Button } from "@loke/design-system/button";
import { Card, CardHeader, CardTitle, CardContent, CardFooter } from "@loke/design-system/card";
import { Input } from "@loke/design-system/input";
import { Label } from "@loke/design-system/label";
import { Stack } from "@loke/design-system/stack";
export function LoginPage() {
return (
Sign in
);
}
```
***
## Dark mode
The design system supports dark mode via a CSS class. Add the `dark` class to your `` element to activate it:
```tsx
// Toggle dark mode
document.documentElement.classList.toggle("dark");
```
All components and color tokens automatically adapt when dark mode is active.
***
## What's included
When you import `@loke/design-system/styles`, you get:
* **Component styles** — all visual styles for every component
* **Color tokens** — semantic colors like `primary`, `secondary`, `muted`, `destructive`
* **Dark mode** — automatic dark mode support via the `.dark` class
* **Base styles** — sensible defaults for borders, backgrounds, and typography
* **Common CSS utilities** — a set of pre-compiled utility classes for spacing, layout, and more
You do **not** need to install Tailwind CSS separately. The design system bundles everything it needs.
If you want to use Tailwind CSS utilities beyond what the design system provides (e.g., for custom layout or one-off styling), see the [Tailwind CSS Guide](/docs/guides/tailwind) for setup instructions.
***
## Troubleshooting
### "Cannot find module '@loke/design-system/button'"
Set `"moduleResolution": "bundler"` and `"module": "esnext"` in your `tsconfig.json`. The `"nodenext"` resolution strategy doesn't always resolve package `exports` correctly in all toolchains.
### Styles not appearing
Make sure you've imported the stylesheet in your root layout or entry file:
```tsx
import "@loke/design-system/styles";
```
This import must run before any components render.
### Components look unstyled or broken
Check that you don't have conflicting global CSS that resets component styles. The design system's base layer sets `border-color` and `outline` on all elements — other CSS resets may conflict.
***
## Next steps
* [Form Input](/docs/design-system/form-input) — Button, Input, Select, Checkbox, and more
* [Feedback & Status](/docs/design-system/feedback-status) — Alert, Badge, Toast, Spinner, and more
* [Overlay & Navigation](/docs/design-system/overlay-navigation) — Dialog, Dropdown, Tabs, Accordion, and more
* [Data Display](/docs/design-system/data-display) — Card, Table, Avatar, Text, and more
* [Layout](/docs/design-system/layout) — layout primitives (Box, Stack, Columns, etc.)
* [Utilities](/docs/design-system/utilities) — reusable helpers and responsive utilities
* [Tailwind CSS Guide](/docs/guides/tailwind) — using Tailwind alongside the design system
* [Color System](/docs/guides/colors) — brand colors and semantic tokens
* [Icons](/docs/icons) — the LOKE icon library
# Accessibility Guide
import { Callout } from '@/components/mdx';
# Accessibility Guide
Accessibility is a core requirement for all LOKE applications. This guide outlines the accessibility features built into the design system and provides best practices for creating accessible interfaces.
## Why Accessibility Matters
* Inclusivity: Making our applications usable by people with disabilities
* Legal Compliance: Meeting accessibility standards and regulations
* Better UX for Everyone: Accessibility improvements benefit all users
* SEO Benefits: Many accessibility practices improve search engine visibility
***
## Design System Accessibility Features
The LOKE Design System includes several built‑in accessibility features:
### Keyboard Navigation
* All interactive components are keyboard accessible
* Focus states are clearly visible
* Logical tabbing order is maintained
* Keyboard shortcuts are consistent
### Screen Reader Support
* Semantic HTML is used throughout components
* ARIA attributes are correctly implemented
* Form elements have proper labels and descriptions
* Dialogs announce their presence appropriately
### Color and Contrast
* Color schemes meet WCAG 2.1 AA standards
* Text has sufficient contrast against backgrounds
* Information is not conveyed by color alone
* Focus states have adequate visibility
### Responsive Design
* Content resizes appropriately for different zoom levels
* Layouts adapt to different screen sizes
* Touch targets are appropriately sized for mobile
***
## Using Components Accessibly
### Buttons and Links
```jsx
// Good: Button with clear purpose
// Good: Icon button with accessible label
// Good: Alternative approach with VisuallyHidden
// Avoid: Icon-only button without accessible name
```
### Forms
```jsx
// Good: Properly labeled form controls
(
Email
We'll never share your email with anyone else.
)}
/>
// Avoid: Inputs without labels
```
### Images and Icons
```jsx
// Good: Image with alt text
// Good: Decorative image marked as such
// Good: SVG icon with title for assistive tech
// Avoid: Image without alt text
```
### Dialog and Modals
```jsx
// Good: Dialog with proper ARIA attributes
```
### Content Structure
```jsx
// Good: Proper heading hierarchy
Page TitleSection Title
Section content...
Subsection Title
Subsection content...
// Avoid: Skipping heading levels
Page Title
Section Title
```
***
## Accessibility Checklist
Use this checklist when implementing interfaces with the LOKE Design System:
### Keyboard Navigation
* [ ] All interactive elements can be accessed using the Tab key
* [ ] Focus order is logical and follows content flow
* [ ] Focus is visible at all times with good contrast
* [ ] No keyboard traps exist (except in modals with proper handling)
* [ ] Custom widgets provide keyboard interaction (arrow keys, escape, etc.)
### Screen Readers
* [ ] Proper heading structure is used (h1, h2, etc.)
* [ ] Images have appropriate alt text
* [ ] Form controls have associated labels
* [ ] ARIA landmarks are used appropriately
* [ ] Dynamic content changes are announced
* [ ] Status messages are conveyed to screen readers
### Visual Design
* [ ] Text color has sufficient contrast against backgrounds
* [ ] Information is not conveyed by color alone
* [ ] UI is usable at 200% zoom
* [ ] Text can be resized without loss of functionality
* [ ] Content is readable in both light and dark modes
### Content and Interactions
* [ ] Error messages are clear and suggest solutions
* [ ] Sufficient time is given for reading and interaction
* [ ] Motion and animations can be paused/reduced
* [ ] Instructions are clear and do not rely on sensory characteristics
* [ ] Link text is descriptive (no “click here” or “read more”)
***
## Testing Accessibility
### Automated Testing
Use automated tools as a first check:
* Lighthouse (in Chrome DevTools)
* axe DevTools (Chrome extension)
### Manual Testing
Always supplement automated tests with manual testing:
1. Keyboard navigation: Navigate using only the keyboard
2. Screen reader testing: Test with VoiceOver (macOS), NVDA (Windows), or other screen readers
3. Zoom testing: Test at 200% zoom
4. Contrast checking: Verify text contrast meets WCAG AA standards
5. Reduced motion: Test with reduced motion settings enabled
***
## Common Accessibility Issues
### 1) Missing Alternative Text
```jsx
// Issue
// Fix
```
### 2) Poor Color Contrast
```jsx
// Issue
Low-contrast text
// Fix
Improved contrast text
```
### 3) Missing Form Labels
```jsx
// Issue
// Fix
```
### 4) Non-descriptive Links
```jsx
// Issue
Click here
// Fix
View Privacy Policy
```
### 5) Missing Focus Styles
```css
/* Issue */
*:focus { outline: none; }
/* Fix - The design system provides appropriate focus styles by default
Do not remove these styles */
```
***
## Resources
* W3C Web Content Accessibility Guidelines (WCAG): [https://www.w3.org/WAI/standards-guidelines/wcag/](https://www.w3.org/WAI/standards-guidelines/wcag/)
* WebAIM Contrast Checker: [https://webaim.org/resources/contrastchecker/](https://webaim.org/resources/contrastchecker/)
* A11y Project Checklist: [https://www.a11yproject.com/checklist/](https://www.a11yproject.com/checklist/)
* MDN Accessibility Documentation: [https://developer.mozilla.org/en-US/docs/Web/Accessibility](https://developer.mozilla.org/en-US/docs/Web/Accessibility)
***
## Conclusion
Accessibility is everyone’s responsibility. By using the LOKE Design System components as intended and following the guidelines in this document, you’ll create interfaces that are accessible to all users. When in doubt, test with real assistive technologies and seek feedback from users with diverse abilities.
# Color System
import { Callout } from '@/components/mdx';
import { ColorPalette } from '@/components/colors/ColorPalette';
# Color System
The @loke/design-system provides a comprehensive color system designed for accessibility, consistency, and flexibility across light and dark modes. Colors are expressed as CSS variables and primarily defined in OKLCH for better perceptual uniformity.
The interactive palette below reflects your current theme. Use the toggle to switch between light and dark and copy values in different formats (OKLCH, HEX, RGB, HSL).
***
## Usage
The color system is implemented using CSS variables with support for both light and dark themes.
```css
.my-element {
background-color: var(--card);
color: var(--card-foreground);
}
```
In React components using Tailwind CSS:
```tsx
Card Content
```
***
## Color Palette
Our color system is organized into semantic categories (Base UI, Component, Sidebar, Action, Subtle UI, Data Visualization, and Brand). Explore and copy values:
***
## Color Decision Guidelines
When choosing colors for your UI:
1. Use semantic colors — choose by function, not by appearance.
2. Maintain contrast — ensure text and essential UI meet accessibility standards.
3. Be consistent — the same meaning should use the same color systemwide.
4. Consider dark mode — test both light and dark modes for each state.
***
## Accessibility Standards
All color combinations in our system are designed to meet WCAG 2.1 AA contrast requirements where applicable. Primary CTAs and critical text aim for AAA where possible.
```tsx
// Example: Emphasized action
// Example: Subtle content
This is less prominent supporting text.
```
```css
/* Example: Using tokens in CSS-in-JS or global CSS */
.cta {
background: var(--primary);
color: var(--primary-foreground);
}
.subtle {
color: var(--muted-foreground);
}
```
# Contribution Guide
import { Callout } from '@/components/mdx';
# Contribution Guide
This guide outlines the process and standards for contributing to the LOKE Design System. Whether you're fixing a bug, improving documentation, or adding a new component, this guide will help you understand how to contribute effectively.
The LOKE Design System is maintained internally for LOKE products. All LOKE team members are encouraged to contribute improvements that benefit our product ecosystem.
## Overview
The LOKE Design System is built and maintained specifically for LOKE applications. Contributions from LOKE team members help ensure the system evolves with our product needs and maintains consistency across our ecosystem.
## Getting Started
### Repository Setup
1. Clone the repository:
```bash
git clone https://github.com/LOKE/design-system-beta
cd design-system-beta
```
2. Install dependencies:
```bash
bun install
```
3. Start the development environment:
```bash
bun dev
```
This will launch the documentation site where you can explore components, test your changes, and see live documentation updates.
## Development Workflow
### Branch Strategy
* `main`: The production branch containing the latest stable release
* `feature/*`: Feature branches for new components or significant changes
* `fix/*`: Branches for bug fixes
Always create a new branch from `main` when starting work on a new feature or fix:
```bash
git checkout main
git pull
git checkout -b feature/your-feature-name
```
### Creating Changesets
We use [changesets](https://github.com/changesets/changesets) to manage versioning and changelogs.
Before submitting a PR, create a changeset that describes your changes:
```bash
bun changeset
```
Follow the prompts to:
1. Select the package(s) you've modified
2. Choose the appropriate semver increment (patch, minor, major)
3. Write a description of your changes
This will create a markdown file in the `.changeset` directory that will be used to generate the changelog when the changes are released.
### Code Standards
The repository includes Biome and TypeScript configurations that enforce code standards. Run the linter before submitting your PR:
```bash
bun lint
```
To check TypeScript types:
```bash
bun check-types
```
### Component Development Guidelines
When creating or modifying components for LOKE products:
1. **Modular Structure**: Each component should be in its own directory
2. **TypeScript**: All components must be written in TypeScript for type safety
3. **Documentation**: Create comprehensive MDX documentation pages
4. **Accessibility**: Ensure all components meet WCAG 2.1 AA standards
5. **Testing**: Include relevant tests for your component
6. **Performance**: Optimize for real-world LOKE product usage patterns
7. **Brand Consistency**: Follow LOKE design principles and visual identity
### Folder Structure
Components should follow this folder structure:
```
packages/design-system/src/components/your-component/
├── index.ts # Exports from the component
├── YourComponent.tsx # Main component implementation
└── YourComponent.test.tsx # Component tests (if applicable)
```
Documentation should be added to the docs site:
```
apps/docs/src/content/docs/components/
└── your-component.mdx # Component documentation page
```
## Pull Request Process
1. **Create a PR**: Push your branch and create a pull request against `main`
2. **CI Checks**: Ensure all CI checks pass (linting, type checking, tests)
3. **Code Review**: Request review from team members
4. **Feedback**: Address any feedback from reviewers
5. **Approval**: Once approved, your PR will be merged by a maintainer
## Release Process
Releases are managed by the design system maintainers. The process generally follows these steps:
1. Changesets are collected from merged PRs
2. Maintainers run the release workflow which:
* Updates versions based on changesets
* Generates changelogs
* Publishes to the package registry
## Adding New Components
When adding a new component:
1. **Research**: Ensure the component is needed and not duplicating existing functionality
2. **Design Review**: Get design approval for the component
3. **Implementation**: Develop the component following our guidelines
4. **Documentation**: Create comprehensive documentation and stories
5. **Testing**: Thoroughly test the component, including accessibility tests
6. **Example Usage**: Include example usage in your PR description
### Component Documentation Template
Documentation for each component should include:
* Component purpose and use cases
* Props API documentation
* Examples of basic and advanced usage
* Accessibility considerations
* Any known limitations or caveats
## Updating Existing Components
When updating existing components:
1. **Backward Compatibility**: Consider the impact on existing usage
2. **Semver**: Follow semantic versioning guidelines
* **Patch**: Bug fixes and minor changes that don't affect the API
* **Minor**: New features that don't break existing functionality
* **Major**: Breaking changes to the component API
3. **Migration Guide**: For breaking changes, provide a migration guide
## Icons
To add new icons to the system:
1. Place the SVG file in the `src/icons/svg/{source}` directory
2. Run the icon generation script:
```bash
bun build:icons
```
3. This will generate the React component and update exports
Follow these guidelines for icon SVGs:
* Use a 24×24 viewBox
* Use simple paths with minimal points
* Use a consistent stroke width (typically 2px)
* Remove unnecessary metadata
## Styling Guidelines
* Use the built-in theme variables for colors
* Follow the spacing scale for margins and padding
* Use the Tailwind class naming convention
## Testing
Components should be tested for:
* **Functionality** — Core behaviors work as expected
* **Accessibility** — WCAG 2.1 AA compliance
* **Responsive behavior** — Works across LOKE product viewport sizes
* **Cross-browser compatibility** — Tested in browsers used by LOKE customers
* **Type safety** — TypeScript types are accurate and helpful
To run type checks:
```bash
bun check-types
```
To run linting:
```bash
bun lint
```
Always test your components in a real LOKE product environment when possible to ensure they work as expected in production.
## Documentation Best Practices
* Use clear, concise language
* Include examples for different use cases
* Document all props with types and descriptions
* Explain any non-obvious behaviors
* Provide accessibility information
## Troubleshooting
### Common Issues
1. **Development server not starting**: Try clearing caches and reinstalling dependencies
```bash
rm -rf node_modules .next
bun install
bun dev
```
2. **Type errors**: Ensure all packages are built and dependencies are up to date
```bash
bun run build
bun check-types
```
3. **Build errors**: Make sure all dependencies are properly installed
```bash
bun install
```
## Getting Help
If you need help contributing to the LOKE Design System:
* **Documentation** — Check existing documentation and component examples
* **Team** — Reach out to other LOKE engineers on Slack
* **Codebase** — Look for similar components or patterns in the repository
* **Design Team** — Consult with LOKE designers for visual and UX guidance
Questions about design decisions or component usage? The LOKE design team is here to help ensure consistency across our products.
## Conclusion
Thank you for contributing to the LOKE Design System! Your efforts help improve the quality and consistency of all LOKE products.
Remember:
* **This system serves LOKE products** — design decisions should align with LOKE's product needs
* **Quality over speed** — take time to ensure accessibility, performance, and maintainability
* **Documentation matters** — good docs help other LOKE developers use components correctly
* **Ask questions** — the team is here to help you contribute effectively
The design system is a living project that evolves with LOKE's needs. Your contributions shape the future of our product ecosystem.
# Design Principles
# Design Principles
This document outlines the core design principles that guide the LOKE Design System. These principles help maintain consistency, quality, and usability across all LOKE applications.
## Consistency
Consistency is key to providing a cohesive user experience across all LOKE products. This means using the same patterns, components, and styles throughout our applications.
### Guidelines
* Use design system components rather than creating custom variants
* Maintain consistent spacing using the design system's spacing scale
* Follow established patterns for similar interactions
* Use consistent terminology in the interface
### Examples
**Good:**
```jsx
// Using standard design system components
Transaction Details
```
## Modularity
Build complex interfaces from simple, reusable components. This approach makes our code more maintainable and allows for greater flexibility.
### Guidelines
* Compose complex UIs from simple components
* Keep components focused on a single responsibility
* Use layout components (`Box`, `Stack`, `Columns`) to structure content
* Avoid creating monolithic components with many responsibilities
### Examples
**Good:**
```jsx
User Profile
```
**Avoid:**
```jsx
```
## Accessibility
All LOKE interfaces must be accessible to all users, including those with disabilities. This isn't just a nice-to-have; it's an essential design requirement.
### Guidelines
* Ensure sufficient color contrast for text and interactive elements
* Provide text alternatives for non-text content
* Ensure keyboard navigability for all interactive elements
* Use semantic HTML and ARIA attributes correctly
* Test with screen readers and other assistive technologies
### Examples
**Good:**
```jsx
// Or using VisuallyHidden
```
**Avoid:**
```jsx
```
## Responsiveness
LOKE applications should work well on all device sizes and orientations. Our design system includes responsive capabilities built into its components.
### Guidelines
* Use responsive component props for adaptable layouts
* Test on different screen sizes including mobile and large displays
* Avoid fixed dimensions that might break on smaller screens
* Implement appropriate touch targets for mobile interfaces
### Examples
**Good:**
```jsx
Content 1Content 2Content 3Content 4
```
**Avoid:**
```jsx
Content 1Content 2Content 3Content 4
// This will be 4 columns on all screen sizes, which is problematic on mobile
```
## Performance
User interfaces should be fast and efficient, avoiding unnecessary complexity that might impact performance.
### Guidelines
* Import only the components and utilities you need
* Use memoization for expensive computations
* Avoid excessive re-renders by using appropriate hooks and patterns
* Consider code splitting for large applications
* Test performance on lower-end devices
### Examples
**Good:**
```jsx
// Import only what you need
import { Button } from '@loke/design-system/button';
import { Card } from '@loke/design-system/card';
```
**Avoid:**
```jsx
// Importing everything
import * as DesignSystem from '@loke/design-system';
// Using deeply nested destructuring that may prevent tree-shaking
const { Button, Card } = DesignSystem;
```
## Clarity
Interfaces should be clear and intuitive, helping users accomplish their goals without confusion.
### Guidelines
* Use clear, descriptive labels for interactive elements
* Provide helpful feedback for user actions
* Use appropriate visual hierarchy to guide user attention
* Balance simplicity and functionality
* Use consistent patterns for similar interactions
### Examples
**Good:**
```jsx
```
**Avoid:**
```jsx
;
{
isOpen && (
Settings
{/* Settings content */}
);
}
```
## Visual Hierarchy
Establish a clear visual hierarchy to guide users through the interface and highlight what's most important.
### Guidelines
* Use typography scale to indicate information hierarchy
* Apply whitespace strategically to group related elements
* Use color and contrast to direct attention
* Consider the reading flow when arranging elements
### Examples
**Good:**
```jsx
Quarterly ReportQ3 2023 Financial Results
${revenue.toLocaleString()}
Total RevenueKey MetricsNew Customers: {newCustomers}Retention Rate: {retentionRate}%
```
**Avoid:**
```jsx
Q3 2023 Financial Results
Quarterly Report
${revenue.toLocaleString()} Total Revenue
New Customers: {newCustomers}
Retention Rate: {retentionRate}%
```
## Feedback
Provide clear feedback to users to confirm their actions and communicate system status.
### Guidelines
* Indicate loading states with appropriate visual cues
* Confirm successful actions with feedback
* Show clear error messages when things go wrong
* Use appropriate animations to communicate state transitions
* Ensure feedback is accessible to all users
### Examples
**Good:**
```jsx
;
{
isSuccess && Form submitted successfully!;
}
{
error && (
Error{error.message}
);
}
```
**Avoid:**
```jsx
;
{
isSuccess &&
Success!
;
}
{
error &&
Error: Something went wrong.
;
}
```
## Conclusion
These design principles are not just guidelines—they represent LOKE's commitment to creating high-quality, user-friendly applications. By following these principles, we ensure that our products are consistent, accessible, and delightful to use.
When implementing interfaces with the LOKE Design System, regularly refer back to these principles to guide your decisions and maintain the high quality standards we strive for.
# Guides
# Guides
These guides cover integration, design language, best practices, and reference materials that apply across the design system. Whether you're getting started with Tailwind, learning our design principles, ensuring accessibility, or understanding our color system, you'll find what you need here.
***
## Setup & Integration
### Tailwind CSS
Learn how Tailwind CSS relates to the design system — what's pre-compiled and available without setup, when you might want to install Tailwind in your project, and how to configure it. Whether you're using the pre-compiled stylesheet or building your own Tailwind setup, this guide explains the trade-offs and shows you how to work effectively with both approaches.
***
## Design Language & Foundations
### Design Principles
The core principles that guide every decision in the LOKE Design System: consistency, modularity, accessibility, responsiveness, performance, clarity, visual hierarchy, and feedback. Read this to understand the *why* behind the system's design, and to ensure your interfaces align with LOKE's design philosophy. Includes good and bad examples for each principle.
### Color System
Explore the design system's semantic color tokens, usage guidelines, and interactive palette preview. Colors automatically adapt between light and dark modes. This guide explains how to choose colors by function (not appearance), access tokens via CSS custom properties or Tailwind classes, and maintain accessible contrast ratios throughout your interface.
### Brand
Visual identity assets and branding guidelines for LOKE — logos, wordmarks, and approved brand usage. Use this when you need official brand assets for marketing, product, or communication materials.
***
## Best Practices
### Accessibility Guide
Build interfaces that work for everyone, including people with disabilities. This guide covers keyboard navigation, screen reader support, color contrast, and testing strategies. Includes a practical checklist, common issues and fixes, and code examples showing accessible and inaccessible patterns for buttons, forms, images, and dialogs.
***
## Reference & Contribution
### Component Reference
Full API reference for all design system components. Look here when you need detailed prop documentation, examples, and advanced usage patterns for any component.
### Contribution Guide
Want to improve the design system? This guide covers the contribution workflow, code standards, testing requirements, and release process. Whether you're adding a new component, fixing a bug, or updating documentation, start here to understand how LOKE's design system is maintained and evolved.
# Contributing
import { Callout, Kbd } from '@/components/mdx';
# Contributing
This page covers deeper technical details about the LOKE Design System for contributors — including architecture concepts, theming, common patterns, and how to write documentation.
Looking to get started using the design system? See the [Quick Start](/docs) guide instead. This page is for contributors who need deeper context.
***
## Key concepts
* Individual imports
* Import only what you use to keep bundles small
* TypeScript‑first
* Rich types across components and utilities
* Tailwind‑based styling
* Class‑driven, utility‑first styling
* Accessibility baked in
* Sensible ARIA usage, keyboard navigation, visible focus
* Dark mode
* Fully themed, light and dark compatible
***
## Installation
Install the package in your app:
```bash
# bun (recommended)
bun add @loke/design-system
# npm
npm install @loke/design-system
```
For a step-by-step walkthrough including TypeScript configuration, see the [Quick Start Guide](/docs).
***
## Project setup
Ensure your `tsconfig.json` uses bundler module resolution:
```json
{
"compilerOptions": {
"module": "esnext",
"moduleResolution": "bundler"
}
}
```
Add the design system styles in your root (e.g. Next.js app layout or entry file):
```tsx
// app/layout.tsx or main entry
import '@loke/design-system/styles';
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
{children}
);
}
```
That’s it — the system includes its CSS variables and Tailwind integration. You can begin importing components individually.
***
## Usage guidelines
### Import only what you need
```tsx
// Good: individual imports
import { Button } from '@loke/design-system/button';
import { Card, CardHeader, CardTitle, CardContent } from '@loke/design-system/card';
```
```tsx
// Example component usage (MDX or app code)
Card Title
Card content
```
Tips:
* Prefer individual imports: import {'{ Button }'} from '@loke/design-system/button'
* Compose primitives (e.g. Box, Stack, Columns) for consistent spacing and layout
* Keep accessibility in mind (labels, alt text, keyboard flows)
***
## Layout primitives
The system includes primitives to build consistent layouts:
```tsx
import { Box } from '@loke/design-system/box';
import { Stack } from '@loke/design-system/stack';
import { Columns, Column } from '@loke/design-system/columns';
function MyLayout() {
return (
Page Title
Column 1Column 2Column 3
);
}
```
***
## Icons
Use the included icon set for a consistent look:
```tsx
import { Search, ArrowRight } from '@loke/icons';
```
***
## Theming and colors
### Semantic tokens
The system ships a semantic color palette via CSS variables:
* \--primary / --primary-foreground
* \--secondary / --secondary-foreground
* \--background / --foreground
* \--card / --card-foreground
* \--muted / --muted-foreground
* \--accent / --accent-foreground
* \--destructive / --destructive-foreground
* \--border, --input, --ring
Use them via Tailwind tokens or directly with CSS vars:
```tsx
Card Content
```
```css
.my-element {
background: var(--accent);
color: var(--accent-foreground);
}
```
See the interactive palette and guidelines:
* Color System: /docs/brand/colors
### Dark mode
Enable dark mode by toggling the dark class on the root:
```tsx
function ThemeToggle() {
const [isDark, setIsDark] = React.useState(false);
React.useEffect(() => {
document.documentElement.classList.toggle('dark', isDark);
}, [isDark]);
return (
);
}
```
***
## Common patterns
### Forms
```tsx
import { Form, FormField, FormItem, FormLabel, FormControl } from '@loke/design-system/form';
import { Input } from '@loke/design-system/input';
import { Button } from '@loke/design-system/button';
function LoginForm() {
// Assume form setup with your favorite form library
return (
);
}
```
### Data display
```tsx
import {
Table,
TableHeader,
TableBody,
TableRow,
TableHead,
TableCell,
} from '@loke/design-system/table';
import { Badge } from '@loke/design-system/badge';
function DataTable({ data }: { data: { id: string; name: string; status: 'active' | 'inactive' }[] }) {
return (
);
}
```
***
## Accessibility
* Use semantic HTML and labeled controls
* Ensure sufficient color contrast
* Verify keyboard and screen reader flows
* Prefer component APIs over ad‑hoc markup
Read the full guide:
* Accessibility Guide: /docs/guides/accessibility
***
## Quick links for LOKE developers
* [Quick Start](/docs) — Get up and running fast
* [Tailwind CSS Guide](/docs/guides/tailwind) — How Tailwind relates to the design system
* [Color System](/docs/guides/colors) — LOKE brand colors and semantic tokens
* [Logo Guidelines](/docs/guides/brand/logos) — Official LOKE logo assets
* [Accessibility Guide](/docs/guides/accessibility) — Building inclusive experiences
* [Component Guide](/docs/guides/reference/component-guide) — Comprehensive component reference
***
## Tailwind CSS
The design system is built with Tailwind CSS, but you do **not** need to install Tailwind to use it. All styles are pre-compiled and included when you import `@loke/design-system/styles`.
If you're familiar with Tailwind, you can use utility classes alongside design system components — common classes like `p-4`, `flex`, `gap-4`, `bg-primary`, etc. are included in the pre-compiled stylesheet.
The layout components ([Box](/docs/design-system/layout/box), [Stack](/docs/design-system/layout/stack), [Columns](/docs/design-system/layout/columns)) provide equivalent functionality to common Tailwind layout patterns through a props-based API.
For full details, see the [Tailwind CSS Guide](/docs/guides/tailwind).
***
## Troubleshooting
* Styles not loading
* Ensure import '@loke/design-system/styles' is present in your root
* Dark mode not toggling
* Confirm the dark class is being added to html
* Type errors
* Verify you're importing the correct path for a component (individual import paths)
* "Cannot find module" errors
* Set moduleResolution: "bundler" in your `tsconfig.json`
***
## Writing documentation with MDX
This site uses custom components to enhance documentation. Here's what's available:
### Custom MDX components
You can use the following custom components inside MDX pages to keep content consistent and easy to scan.
### Callout
```tsx
This is an informational callout used to surface important context.
This indicates a successful action or a positive state.
This warns the reader about potential issues.
This highlights a critical problem or a blocking issue.
```
### Kbd
Use `` for keyboard keys or shortcuts.
Examples:
* Press Cmd + K to open search
* Take a screenshot with Shift + Cmd + 4
* Confirm with Enter and cancel with Esc
Variants:
* Default: Ctrl
* Small: Ctrl
* Outline: Ctrl
* Large: Ctrl
### TypeTable
Use TypeTable (from fumadocs-ui) to quickly document API props for a component.
```tsx
import { TypeTable } from 'fumadocs-ui/components/type-table';
) => void',
},
}}
/>
```
***
## Next steps for contributors
* [Contribution Guide](/docs/guides/contribution) — How to add or improve components
* Review the [Color System](/docs/guides/colors) and [Logo Guidelines](/docs/guides/brand/logos) to maintain LOKE brand consistency
* Use layout primitives ([Box](/docs/design-system/layout/box), [Stack](/docs/design-system/layout/stack), [Columns](/docs/design-system/layout/columns)) to establish consistent structure
* Reference the [Accessibility Guide](/docs/guides/accessibility) while building features to ensure all LOKE products are inclusive
* Check the [Component Guide](/docs/guides/reference/component-guide) to understand when to use each component
# Tailwind CSS
import { Callout, Kbd } from '@/components/mdx';
# Tailwind CSS
The LOKE Design System is built with [Tailwind CSS](https://tailwindcss.com) internally, but you **do not need to install Tailwind** to use the design system. All styles are pre-compiled and shipped as standard CSS.
This guide explains the relationship between Tailwind and the design system, and when you might want to set up Tailwind in your own project.
***
## Do I need Tailwind?
**No.** The design system works without Tailwind installed in your project. When you import the stylesheet:
```tsx
import "@loke/design-system/styles";
```
You get pre-compiled CSS that includes all component styles, color tokens, and a set of common utility classes. No build tools, PostCSS plugins, or Tailwind configuration needed.
The design system is plug-and-play. Install it, import the styles, and start using components. Tailwind is an implementation detail — not a requirement.
***
## What is Tailwind CSS?
If you've never used Tailwind before, here's the short version: Tailwind is a CSS framework that provides small, single-purpose CSS classes you apply directly in your HTML/JSX. Instead of writing CSS in a separate file, you compose styles using class names.
```tsx
// Traditional CSS approach
```
Each class does one thing: `p-4` sets padding, `bg-white` sets background color, `rounded-lg` sets border radius. You combine them to build up your styles.
Common patterns you'll see in examples:
| Class | What it does |
| ------------ | ---------------------------------------- |
| `p-4` | Padding on all sides (1rem) |
| `px-4` | Horizontal padding |
| `py-2` | Vertical padding |
| `m-4` | Margin on all sides |
| `mt-2` | Top margin |
| `flex` | Display flex |
| `gap-4` | Gap between flex/grid children |
| `w-full` | Width 100% |
| `text-sm` | Small text size |
| `bg-primary` | Background using the primary color token |
| `rounded-lg` | Rounded corners |
| `border` | 1px border |
For a full reference, see the [Tailwind CSS documentation](https://tailwindcss.com/docs).
***
## What ships with the design system
The pre-compiled stylesheet (`@loke/design-system/styles`) includes:
1. **All component styles** — everything needed for design system components to render correctly
2. **Theme tokens** — CSS custom properties for colors, radii, and animations that components use
3. **Common utility classes** — a subset of Tailwind utilities pre-compiled for convenience
The included utilities cover the most common layout and styling needs: spacing (`p-*`, `m-*`, `gap-*`), flexbox (`flex`, `items-center`, `justify-between`), sizing (`w-full`, `h-*`), grid (`grid`, `grid-cols-*`), positioning, borders, shadows, typography, and more.
This means you can use Tailwind-style classes in your own components without installing Tailwind:
```tsx
import { Button } from "@loke/design-system/button";
export function Header() {
return (
My App
);
}
```
The pre-compiled stylesheet includes utilities that the design system itself uses, plus a broad set of common classes. If you use a Tailwind class that isn't included, it simply won't have any effect. If you find yourself needing classes that aren't available, consider [setting up Tailwind in your project](#setting-up-tailwind-in-your-project).
***
## Layout components vs. Tailwind classes
The design system includes layout components like [Box](/docs/design-system/layout/box), [Stack](/docs/design-system/layout/stack), [Columns](/docs/design-system/layout/columns), and [Inline](/docs/design-system/layout/inline). These provide a props-based API for common layout patterns. If you're comfortable with Tailwind, you can achieve the same results with utility classes directly.
Here's how they compare:
### Vertical stack
```tsx
// Using the Stack component
import { Stack } from "@loke/design-system/stack";
Item 1
Item 2
Item 3
// Equivalent Tailwind classes
Item 1
Item 2
Item 3
```
### Horizontal row
```tsx
// Using the Inline component
import { Inline } from "@loke/design-system/inline";
LabelNew
// Equivalent Tailwind classes
LabelNew
```
### Grid columns
```tsx
// Using the Columns component
import { Columns } from "@loke/design-system/columns";
OneTwoThree
// Equivalent Tailwind classes
OneTwoThree
```
### Spacing and backgrounds
```tsx
// Using the Box component
import { Box } from "@loke/design-system/box";
Content
// Equivalent Tailwind classes
Content
```
### Responsive layout
The layout components support responsive values via arrays, where each value maps to a breakpoint (`[mobile, sm, md, lg]`):
```tsx
// Using Box with responsive props
Content
// Equivalent Tailwind classes
Content
```
### Which should I use?
Use whichever you prefer — both approaches are valid. Here are some considerations:
* **Layout components** are useful if you're not familiar with CSS/Tailwind, or if you want a more React-like API with type-checked props
* **Tailwind classes** give you more flexibility and are the standard approach if you're already comfortable with CSS
* **Mix and match** — you can use layout components for structure and Tailwind classes for fine-tuning, or vice versa. All components accept a `className` prop
***
## Using color tokens
The design system defines semantic color tokens as CSS custom properties. These are available as Tailwind color classes whether or not you have Tailwind installed in your project:
```tsx
// Background colors
Primary background
Secondary background
Card background
Muted background
Destructive background
// Text colors
Default text
Secondary text
Accent text
// Border colors
Default border
Primary border
```
These tokens automatically adapt for dark mode when the `dark` class is on the `` element. See the [Color System](/docs/guides/colors) page for the full palette.
***
## CSS custom properties
You can also use the design system's tokens directly in your own CSS via custom properties:
```css
.my-custom-element {
background: var(--card);
color: var(--card-foreground);
border: 1px solid var(--border);
border-radius: var(--radius);
}
```
Available tokens include:
* `--background` / `--foreground`
* `--card` / `--card-foreground`
* `--primary` / `--primary-foreground`
* `--secondary` / `--secondary-foreground`
* `--muted` / `--muted-foreground`
* `--accent` / `--accent-foreground`
* `--destructive` / `--destructive-foreground`
* `--border`, `--input`, `--ring`
* `--radius`
* `--brand-50` through `--brand-950`
***
## Setting up Tailwind in your project
If you need Tailwind utilities beyond what ships with the design system — for example, arbitrary values, additional responsive breakpoints, or classes that aren't pre-compiled — you can install Tailwind in your project.
### 1. Install Tailwind CSS
```bash
bun add -d tailwindcss @tailwindcss/postcss
```
### 2. Configure PostCSS
Create or update `postcss.config.mjs`:
```js
const config = {
plugins: {
"@tailwindcss/postcss": {},
},
};
export default config;
```
### 3. Set up your stylesheet
Replace the `import "@loke/design-system/styles"` import in your entry point with a custom CSS file that imports Tailwind and the design system's theme:
```css
/* globals.css */
@import "tailwindcss";
@import "@loke/design-system/styles/tailwind";
@plugin "tailwindcss-animate";
/* Scan the design system source so its classes are included */
@source "node_modules/@loke/design-system/dist";
@custom-variant dark (&:is(.dark *));
@layer base {
* {
@apply border-border outline-ring/50;
}
body {
@apply bg-background text-foreground;
}
}
```
Then import this file in your app entry instead:
```tsx
// app/layout.tsx
import "./globals.css";
```
The `@loke/design-system/styles/tailwind` import provides the theme configuration (color tokens, radii, animations) without the pre-compiled utilities. Tailwind will generate the utility classes itself based on what your code uses.
### 4. Install the animate plugin
If you use components that animate (like Accordion), install the animation plugin:
```bash
bun add -d tailwindcss-animate
```
***
## The `cn` utility
The design system exports a `cn` utility for merging class names. It combines [clsx](https://github.com/lukeed/clsx) (conditional classes) with [tailwind-merge](https://github.com/dcastil/tailwind-merge) (conflict resolution):
```tsx
import { cn } from "@loke/design-system/cn";
function MyComponent({ className, isActive }: { className?: string; isActive: boolean }) {
return (
Content
);
}
```
`cn` is useful when you want to:
* Conditionally apply classes
* Let consumers override styles via a `className` prop
* Resolve conflicting Tailwind classes (e.g., `cn("p-4", "p-2")` results in `"p-2"`)
See the [cn utility reference](/docs/ui/lib/cn) for details.
***
## Summary
| Question | Answer |
| ------------------------------------------------ | ------------------------------------------------------------------------------------------ |
| Do I need to install Tailwind? | No. The design system ships pre-compiled CSS. |
| Can I use Tailwind classes? | Yes. Common utility classes are included in the pre-compiled stylesheet. |
| Can I use layout components instead of Tailwind? | Yes. Box, Stack, Columns, and Inline provide equivalent functionality with a props API. |
| When should I install Tailwind myself? | When you need utilities beyond what's pre-compiled, or want full Tailwind in your project. |
| Do the color tokens work without Tailwind? | Yes. They're standard CSS custom properties. |
# AI Agent Skills (TanStack Intent)
# AI Agent Skills (TanStack Intent)
All three LOKE packages ship `SKILL.md` files via `@tanstack/intent`. These skills guide AI agents through common tasks — composing overlays, building forms, using icons, and more.
***
## 1. Run install
```bash
npx @tanstack/intent@latest install
```
This prints a skill — a prompt you paste into your AI agent. The skill instructs your agent to:
1. Check for existing `intent-skills` mappings in your config files (`AGENTS.md`, `CLAUDE.md`, `.cursorrules`, etc.)
2. Run `npx @tanstack/intent@latest list` to discover available skills from your installed packages
3. Scan your repository structure to understand your project
4. Propose relevant skill-to-task mappings based on your codebase patterns
5. Ask if you want a target other than `AGENTS.md`
6. Write or update an `intent-skills` block in your agent config
If an `intent-skills` block already exists, the agent updates that file in place. If none exists, `AGENTS.md` is the default target.
***
## 2. Use skills in your workflow
When your AI agent works on a task matching a skill mapping, it loads the corresponding `SKILL.md` into context automatically. This means agents can discover and apply best practices without manual prompting — they get domain-specific guidance tailored to the LOKE libraries directly in their context.
***
## 3. Keep skills up-to-date
Skills version with each package release. Updating a package brings updated skills — no manual action needed:
```bash
bun update @loke/design-system @loke/ui @loke/icons
```
To see what skills are available:
```bash
npx @tanstack/intent@latest list
```
To check for skills referencing outdated source docs:
```bash
npx @tanstack/intent@latest stale
```
***
## Available skills
### @loke/design-system skills
These skills cover all design system components and theming. Load paths: `node_modules/@loke/design-system/skills//SKILL.md`
| Skill | Covers |
| ------------------------ | -------------------------------------------------------------------------------------------- |
| `getting-started` | Install, Tailwind v4 config, stylesheet import, TooltipProvider setup |
| `forms` | Form components: Input, Select, Checkbox, RadioGroup, Switch, Textarea, Calendar, DatePicker |
| `display-components` | Alert, Badge, Avatar, Card, Heading, Text, Separator, Pagination, Skeleton |
| `data-tables` | Table component patterns and column configuration |
| `layout` | Box, Stack, Inline, Columns, MaxWidthWrapper, PageLayout, VisuallyHidden |
| `overlay-composition` | Dialog, Sheet, Popover, DropdownMenu, Command, Tooltip, Toast — "use client" boundaries |
| `interactive-components` | Accordion, Collapsible, Tabs, Sidebar |
| `theming` | CSS custom properties, dark mode, color token customization |
### @loke/ui skills
These skills cover headless primitives, utility functions, and hooks. Load paths: `node_modules/@loke/ui/skills//SKILL.md`
| Skill | Covers |
| ------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `loke-ui` | Overview of all headless primitives and when to use @loke/ui vs @loke/design-system |
| `choosing-the-right-component` | Decision guide for picking the right primitive |
| `accordion` | Accordion primitive |
| `alert-dialog` | AlertDialog primitive |
| `checkbox` | Checkbox primitive |
| `collapsible` | Collapsible primitive |
| `command` | Command (combobox/search) primitive |
| `context-and-collection` | Context and Collection utilities |
| `dialog` | Dialog primitive |
| `dropdown-menu` | DropdownMenu and Menu primitives |
| `hooks` | useCallbackRef, useControllableState, useDirection, useEscapeKeydown, useId, useIsDocumentHidden, useIsHydrated, useLayoutEffect, useMobile, usePrevious, useSize |
| `label` | Label primitive |
| `overlay-infrastructure` | Portal, Presence, DismissableLayer, FocusGuards |
| `popover` | Popover primitive |
| `primitive-and-slot` | Primitive and Slot utilities |
| `radio-group` | RadioGroup primitive |
| `select` | Select primitive |
| `switch` | Switch primitive |
| `tabs` | Tabs primitive |
| `tooltip` | Tooltip primitive |
### @loke/icons skills
These skills cover icon discovery, usage, and customization. Load paths: `node_modules/@loke/icons/skills//SKILL.md`
| Skill | Covers |
| --------------------- | ------------------------------------------------- |
| `use-icons` | Importing and rendering icons in React |
| `find-icons` | Searching the icon catalog to find the right icon |
| `add-icons` | Adding new SVG icons to the library |
| `create-custom-icons` | Creating custom icon components |
# @loke/ui
import Link from 'fumadocs-core/link';
import { Callout } from '@/components/mdx';
# @loke/ui
`@loke/ui` is a comprehensive toolkit of unstyled, accessible React components and utilities that power the LOKE Design System. It provides the behavior and accessibility foundation without any visual opinions, giving you complete control over styling and design.
Use `@loke/ui` when you need low-level control over appearance, are building highly specialized components, or want to avoid design-system dependencies in utility libraries.
## Philosophy
* **Headless**: Components provide behavior and accessibility; you bring the styles.
* **Accessible by default**: Every primitive follows WAI-ARIA patterns, includes full keyboard support, and is tested with screen readers.
* **Framework-agnostic utilities**: Hooks and lib utilities work anywhere React is used, not just within design-system components.
* **Composable**: Build complex widgets by combining simpler primitives and utilities.
* **Typed**: Full TypeScript support with predictable, documented APIs.
## When to use @loke/ui vs @loke/design-system
| Scenario | Use @loke/design-system | Use @loke/ui |
| ------------------------------------------------------------- | ----------------------- | ------------ |
| Building a standard button, card, or input | ✓ | — |
| Need pre-made, consistent styling | ✓ | — |
| Building a standard form | ✓ | — |
| Need complete styling control | — | ✓ |
| Building a specialized component (rich editor, custom select) | — | ✓ |
| Avoiding design-system dependencies | — | ✓ |
| Learning or prototyping interaction patterns | — | ✓ |
When in doubt, start with `@loke/design-system`. Use primitives when you have a specific reason to customize.
## What's included
### Primitives
26 unstyled, accessible headless components that form the foundation of `@loke/design-system`. Components like Dialog, Popover, Accordion, Tabs, and others provide complete behavior and accessibility with zero styling assumptions.
**Use when**: You need custom styling, building specialized components, or want to understand how the design system components work.
### Hooks
Small, focused React hooks for common UI patterns: state management (controlled/uncontrolled), DOM measurement, keyboard handling, environment detection, and accessibility. Hooks can be used independently from primitives.
**Use when**: Building custom components, need a specific behavior pattern, or integrating with your own UI framework.
### Lib
Framework-agnostic utility functions and low-level primitives for building accessible components: context creation, event composition, ref composition, DOM measurement, focus management, dismissable layers, and number utilities.
**Use when**: Building component libraries, need fine-grained control over interactions, or want reusable utilities for complex widgets.
## Install
```bash
bun add @loke/ui
```
## Import patterns
Import from granular entry points for best tree-shaking:
```tsx
// Primitives
import { Dialog, DialogTrigger, DialogContent } from '@loke/ui/dialog';
import { Accordion, AccordionItem, AccordionTrigger } from '@loke/ui/accordion';
// Hooks
import { useControllableState } from '@loke/ui/use-controllable-state';
import { useMobile } from '@loke/ui/use-mobile';
// Lib
import { createContext } from '@loke/ui/context';
import { composeRefs } from '@loke/ui/compose-refs';
```
Never import from the package root; use specific subpaths.
**Design System Components**: If you want pre-styled, ready-to-use components, see [@loke/design-system](/docs/design-system). Those components are built on top of these primitives and handle all the styling for you.
## Where to start
* **Building a custom component?** Start with Primitives to understand what's available and how components compose.
* **Need a specific behavior?** Check Hooks for state management, keyboard handling, or environment detection.
* **Building a component library?** Explore Lib utilities for context, event composition, and DOM utilities.
# Contributing Icons
import { Callout, Kbd } from '@/components/mdx';
# Contributing Icons
The `@loke/icons` library contains 107 carefully crafted icons. New icons are generated from SVG source files using a build script. This guide walks you through the process of adding icons to the library.
Icons are auto-generated from SVG sources. Always run bun run gen after adding or updating SVGs.
***
## Step 1: Add your SVG
**Location:** `packages/icons/src/meta/`
**Naming convention:** Use PascalCase for SVG filenames (matching React component conventions).
Examples:
* `SearchIcon.svg`
* `ChevronUp.svg`
* `MailAlert.svg`
**SVG requirements:**
* Include a `viewBox` attribute (e.g., `viewBox="0 0 24 24"`)
* Prefer stroke-based designs for consistency with the icon library style
* Keep dimensions square (24×24 is standard)
* Simplify paths when possible
Example SVG structure:
```xml
```
***
## Step 2: Add metadata (optional)
Metadata helps organize, tag, and alias icons for search and filtering. Create a JSON file with the same base name as your SVG.
**Location:** `packages/icons/src/meta/.json`
**Schema:**
```json
{
"tags": ["keyword1", "keyword2", "keyword3"],
"categories": ["ui", "navigation", "commerce"],
"aliases": [
{
"name": "AlternativeName"
},
{
"name": "OldName",
"deprecated": true,
"deprecationReason": "Use SearchIcon instead",
"toBeRemovedInVersion": "2.0.0"
}
]
}
```
**Fields:**
| Field | Type | Description |
| ------------ | ---------- | ----------------------------------------------------------------------------- |
| `tags` | `string[]` | Keywords for searching/filtering (e.g., "search", "find", "magnifying-glass") |
| `categories` | `string[]` | Icon categories for organization (see available categories below) |
| `aliases` | `object[]` | Alternative import names (optional, useful for backward compatibility) |
**Available categories:**
* `ui` — General UI elements (menu, checkbox, button, etc.)
* `navigation` — Navigation-related (arrows, chevrons, etc.)
* `commerce` — Commerce-related (cart, payment, discount, etc.)
* `notifications` — Alerts, bells, messages
* `media` — Images, video, play, pause
* `arrows` — Directional arrows
* `social` — Social media
* `finance` — Money, currency, dollar signs
* `time` — Clock, calendar, schedule
* `user` — User profiles, people
* And 27 more...
**Example metadata file:**
```json
{
"tags": ["search", "find", "magnifying glass", "lookup"],
"categories": ["ui", "navigation"],
"aliases": [
{
"name": "SearchIcon"
},
{
"name": "Magnifier",
"deprecated": true,
"deprecationReason": "Use Search instead",
"toBeRemovedInVersion": "1.5.0"
}
]
}
```
***
## Step 3: Generate icons
After adding SVG and metadata files, run the generation script:
```bash
cd packages/icons
bun run gen
```
This script will:
1. Parse all SVG files in `src/meta/`
2. Convert SVG paths to React component format
3. Generate TypeScript components in `src/icons/` (kebab-case filenames)
4. Create or update metadata JSON files if missing
5. Regenerate `src/loke-icons.ts` (exports all icons)
6. Regenerate `src/aliases.ts` (exports aliases)
7. Regenerate `src/index.ts` (main entry point)
8. Format all files with Biome
***
## Step 4: Build and verify
Compile the package for distribution:
```bash
cd packages/icons
bun run build
```
This generates the `dist/` folder with compiled JavaScript and TypeScript declarations.
Verify the icon appears in documentation and can be imported:
```tsx
import { Search } from '@loke/icons';
function App() {
return ;
}
```
***
## Step 5: Commit
Commit all generated and source files together:
```bash
git add packages/icons/src/meta/*.svg
git add packages/icons/src/meta/*.json
git add packages/icons/src/icons/
git add packages/icons/src/loke-icons.ts
git add packages/icons/src/aliases.ts
git add packages/icons/src/index.ts
git commit -m "feat(icons): add Search icon"
```
Always commit the generated files alongside source SVGs. The generated components are part of the published package.
***
## Icon metadata schema (detailed)
### Tags
Keywords that describe the icon. Use common synonyms:
```json
{
"tags": [
"search",
"find",
"magnifying glass",
"lookup",
"query",
"filter"
]
}
```
### Categories
Assign icons to one or more of 37 categories for organization:
```json
{
"categories": ["ui", "navigation"]
}
```
### Aliases
Define alternative names for the icon (useful for backward compatibility or multiple naming conventions):
```json
{
"aliases": [
{
"name": "SearchIcon"
},
{
"name": "Magnifier",
"deprecated": true,
"deprecationReason": "Use Search instead",
"toBeRemovedInVersion": "2.0.0"
}
]
}
```
**Alias properties:**
| Property | Type | Description |
| ---------------------- | --------- | --------------------------------------------- |
| `name` | `string` | Alternative import name |
| `deprecated` | `boolean` | Mark as deprecated (optional) |
| `deprecationReason` | `string` | Reason for deprecation (optional) |
| `toBeRemovedInVersion` | `string` | Version when alias will be removed (optional) |
***
## Workflow example
1. **Add SVG:**
```
packages/icons/src/meta/NotificationBell.svg
```
2. **Add metadata:**
```
packages/icons/src/meta/notification-bell.json
{
"tags": ["alert", "notification", "bell", "sound"],
"categories": ["notifications", "ui"],
"aliases": [
{ "name": "BellAlert" }
]
}
```
3. **Generate:**
```bash
cd packages/icons && bun run gen
```
4. **Build:**
```bash
bun run build
```
5. **Verify:**
```tsx
import { NotificationBell, BellAlert } from '@loke/icons';
```
6. **Commit:**
```bash
git add packages/icons/
git commit -m "feat(icons): add NotificationBell icon"
```
***
## Best practices
* **Consistent style:** Match the stroke width, roundness, and visual weight of existing icons
* **Descriptive names:** Use clear, descriptive names that indicate what the icon represents
* **Good tags:** Add 3-5 relevant keywords for discoverability
* **Test imports:** Verify the icon can be imported after generation
* **SVG optimization:** Keep SVG files clean and minimal; complex shapes should be simplified
* **Aliases for variants:** If you have multiple similar icons, use aliases to provide alternative names
***
## Troubleshooting
**Icon isn't appearing after gen:**
* Verify the SVG filename uses PascalCase
* Check that `src/meta/` contains the SVG file
* Run `bun run gen` again
* Check for build errors in the console
**Import path is wrong:**
* The generated component name is kebab-case version of the filename
* Example: `SearchIcon.svg` → `import { SearchIcon } from '@loke/icons'`
**Metadata not generated:**
* Metadata JSON files are optional; if missing, `gen` creates a basic one
* You can manually edit metadata after generation
**Build fails:**
* Run `bun run lint` to check for syntax errors
* Verify SVG is valid XML
* Check that all SVGs have `viewBox` attributes
***
## Resources
* **Icon library:** [@loke/icons on npm](https://www.npmjs.com/package/@loke/icons)
* **Source code:** `packages/icons/` in the monorepo
* **Build script:** `packages/icons/gen.ts`
* **Documentation:** `packages/icons/README.md`
# Icon Gallery
import { IconGalleryServer } from '@/components/icons/icon-gallery-server';
Browse all icons from the `@loke/icons` package. Click any icon to copy its import statement.
# Icons
import { Callout } from '@/components/mdx';
# Icons
**@loke/icons** is a curated collection of 110+ icons designed as React components. Built to pair seamlessly with the LOKE Design System, each icon supports customizable size, color, and stroke width — letting you adapt them for any context. Icons are exported individually for optimal tree-shaking, and many have aliases for common naming conventions.
[Browse the Icon Gallery →](/docs/icons/gallery) to search and preview all available icons.
***
## Installation
```bash
bun add @loke/icons
```
***
## Usage
Import icons individually for optimal tree-shaking:
```tsx
import { SearchIcon, UserIcon, SettingsIcon } from "@loke/icons";
function Example() {
return (
);
}
```
***
## Props
All icons accept the following props:
| Prop | Type | Default | Description |
| --------------------- | ------------------ | -------------- | --------------------------------------------- |
| `size` | `number \| string` | `24` | Width and height of the icon |
| `color` | `string` | `currentColor` | Stroke color of the icon |
| `strokeWidth` | `number` | `2` | Width of the icon strokes |
| `absoluteStrokeWidth` | `boolean` | `false` | Keep stroke width absolute regardless of size |
Icons also accept all standard SVG attributes.
***
## Aliases
Many icons have aliases that match common naming conventions. For example:
```tsx
// These are equivalent
import { SearchIcon } from "@loke/icons";
import { Search } from "@loke/icons";
// Material-style aliases
import { Person } from "@loke/icons"; // Alias for UserIcon
import { Delete } from "@loke/icons"; // Alias for TrashIcon
import { Home } from "@loke/icons"; // Alias for HouseIcon
```
***
## Best Practices
* Use semantic icon names that match their purpose (e.g., `TrashIcon` for delete actions)
* Maintain consistent icon sizes within the same context
* Ensure sufficient color contrast for accessibility
* Use `aria-label` or `aria-hidden` for accessibility when icons convey meaning
* Prefer individual imports over importing the entire library
***
## Accessibility
When using icons, consider accessibility:
```tsx
// Decorative icon (hidden from screen readers)
// Icon with meaning (provide label)
// Icon with visible text
```
***
## Icon Gallery
[View the full Icon Gallery →](/docs/icons/gallery) to browse all available icons with:
* **Search** by name, alias, or tag
* **Filter** by category
* **Customize** color, size, and stroke width
* **Copy** import statements with a single click
***
## Contributing
Want to add a new icon? See the [Contributing guide](/docs/icons/contributing).
# Alert Dialog
import { Callout, Kbd } from '@/components/mdx';
import { TypeTable } from 'fumadocs-ui/components/type-table';
import { Button, buttonVariants } from '@loke/design-system/button';
import { DefaultAlertDialogExample, DestructiveConfirmAlertDialogExample, CustomStyledAlertDialogExample, FormAlertDialogExample, TriggerAsChildAlertDialogExample } from '@/components/examples/components/alert-dialog';
# Alert Dialog
Alert Dialog is a focused, modal confirmation dialog used for high‑stakes actions (delete, sign‑out, irreversible changes). It traps focus, prevents background interaction, and guides users to a clear primary action or a safe cancel.
Use Alert Dialog only when a decision is required before continuing. For inline feedback that doesn’t block interaction, use Alert.
***
## Features
* Modal and focus‑managed by default (no background interaction)
* Accessible semantics (role="alertdialog") with required description
* Clear action structure with primary Action and secondary Cancel
* Keyboard support: Esc to close, focus trapped within dialog
* Composable pieces: Trigger, Content, Header, Footer, Title, Description, Action, Cancel
* Theming with className or by composing with Button styles
***
## Usage
```tsx
import {
AlertDialog,
AlertDialogTrigger,
AlertDialogContent,
AlertDialogTitle,
AlertDialogDescription,
AlertDialogAction,
AlertDialogCancel,
AlertDialogFooter,
AlertDialogHeader,
} from '@loke/design-system/alert-dialog';
export default function Example() {
return (
Delete accountAre you absolutely sure?
This action cannot be undone. This will permanently delete your account
and remove your data from our servers.
Cancel
Delete
);
}
```
Tips:
* Always include a concise Title and meaningful Description (required for accessibility).
* Make the primary Action explicit (e.g. “Delete”, “Sign out”) and the Cancel safe.
* Prefer buttonVariants to style actions consistently with Buttons.
***
## Props
### AlertDialog
void',
},
}}
/>
### AlertDialogTrigger
### AlertDialogContent
### Structure helpers
',
},
AlertDialogFooter: {
description: 'Layout wrapper for actions (Cancel/Action).',
type: 'React.HTMLAttributes',
},
}}
/>
### Title and Description
### Cancel and Action
***
## Examples
### Default
```tsx
Open Alert DialogAre you sure?…Cancel
Continue
```
### Destructive confirm
```tsx
{/* header, title, description */}
{/* footer with cancel and destructive action */}
```
### Custom styling
```tsx
Open custom dialog…
```
### With form elements
```tsx
Open form dialog
{/* Title + Description */}
CancelSubmit
```
### Trigger asChild
Use asChild on the trigger to style and render your own element without extra DOM.
```tsx
…
```
***
## Accessibility
* Uses role="alertdialog" to indicate a high‑priority, attention‑demanding modal.
* Focus is trapped inside the dialog while open; Esc closes it.
* The initial focus moves to Cancel for a safe default.
* A Description is required so screen readers have sufficient context (a dev warning is shown in development if missing).
* Background interaction is blocked and the overlay provides visual separation.
***
## Best practices
* Keep the title short and the description specific about consequences.
* Make destructive actions visually distinct and secondary actions safe.
* Don’t overload the dialog—focus on one clear decision.
* Prefer inline alternatives (e.g. Alert) when a modal is not required.
* Ensure keyboard access: triggers must be focusable, actions reachable, and Esc must close.
# Alert
import { Callout, Kbd } from '@/components/mdx';
import { TypeTable } from 'fumadocs-ui/components/type-table';
import { Alert, AlertTitle, AlertDescription } from '@loke/design-system/alert';
import { AlertCircle, AlertTriangle, CheckCircle, Info } from '@loke/icons';
import { DefaultAlertExample, DestructiveAlertExample, WithIconAlertExample, TitleOnlyAlertExample, DescriptionOnlyAlertExample, CustomContentAlertExample, MultipleAlertsExample, LongContentAlertExample, DismissButtonAlertExample } from '@/components/examples/components/alert';
# Alert
The Alert component surfaces inline messages that draw attention without interrupting flow. Use it for confirmations, information, warnings, and errors that don't require a modal.
Use Alert for inline feedback that complements the surrounding UI. For disruptive, confirm‑before‑continue flows, use Alert Dialog.
***
## Features
* Accessible by default (role="alert")
* Title and description building blocks
* Variants for tone: default and destructive
* Works with icons from the system
* Fully composable; bring your own content and layout classes
***
## Usage
```tsx
import { Alert, AlertTitle, AlertDescription } from '@loke/design-system/alert';
import { AlertCircle } from '@loke/icons';
export default function Example() {
return (
Heads up!
You can add components to your app using the CLI.
);
}
```
Tips:
* Add an icon as the first child for quick visual scanning.
* Prefer concise AlertTitle with supporting details in AlertDescription.
* Use the destructive variant for errors and critical issues.
***
## Props
### Alert
### AlertTitle
### AlertDescription
***
## Examples
### Default
```tsx
Heads up!You can add components to your app using the CLI.
```
### Destructive
Error
Your session has expired. Please log in again.
```tsx
```
### With icon
Information
This is an informational alert with an icon.
```tsx
```
### Title only
This is an alert with only a title.
```tsx
```
### Description only
This is an alert with only a description.
```tsx
```
### Custom content
```tsx
Success
Your changes have been saved successfully.
```
### Multiple alerts
Information
This is an informational alert.
Warning
This action cannot be undone.
Success
Your profile has been updated.
```tsx
```
### Long content
```tsx
Terms and Conditions
By using this application, you agree to our terms and conditions...
We reserve the right to modify these terms...
```
### With a dismiss button (custom)
```tsx
Update AvailableA new update is available. Install it now?
```
***
## Accessibility
* Uses role="alert" so assistive tech announces the message.
* Make the title concise and the description specific with actionable guidance if relevant.
* Don’t rely on color alone; pair icons and text for clarity.
* Ensure sufficient color contrast for text and focus states.
***
## Best practices
* Reserve destructive for errors or high‑severity warnings.
* Keep titles short; details go in the description.
* Use icons sparingly to reinforce meaning.
* Place alerts near related content so users understand the context quickly.
* Avoid stacking too many alerts; prioritize or consolidate messaging.
# Badge
import { Callout, Kbd } from '@/components/mdx';
import { TypeTable } from 'fumadocs-ui/components/type-table';
import { Badge } from '@loke/design-system/badge';
import { VariantsBadgeExample, WithIconBadgeExample, SizesBadgeExample, NumbersBadgeExample, RemovableBadgesExample, CustomStyledBadgeExample } from '@/components/examples/components/badge';
# Badge
Badges are compact, visually distinct labels for status, counts, or categories. They support multiple variants and can be made removable for chip‑like interactions.
Use Badge to highlight short bits of information. Keep text concise. For interactive “chips”, provide an onRemove handler to render a removable badge.
***
## Features
* Variants: default, secondary, destructive, outline
* Optional removable behavior via onRemove
* Keyboard‑focus styles and accessible rendering
* Easy customization using utility classes
***
## Usage
```tsx
import { Badge } from '@loke/design-system/badge';
export default function Example() {
return (
DefaultNewErrorBeta
);
}
```
Tips:
* Use short, scannable text (1–2 words or small numbers)
* Choose the variant that matches semantic tone (e.g., destructive for errors)
* Prefer className for one‑off style tweaks
***
## Props
void',
},
className: {
description: 'Additional classes for custom styling (e.g., color overrides, sizing).',
type: 'string',
},
style: {
description: 'Inline styles for one‑off adjustments.',
type: 'React.CSSProperties',
},
}}
/>
***
## Examples
### Variants
```tsx
DefaultSecondaryDestructiveOutline
```
### With icon
```tsx
New feature
```
### Sizes (typographic)
```tsx
);
}
```
### Custom styling
```tsx
Custom
```
***
## Accessibility
* Badges are typically decorative labels. Ensure the surrounding UI conveys meaning to screen readers.
* When using numbers in badges, provide nearby text context (e.g., “Notifications”).
* Removable badges render as a button when onRemove is provided. Ensure the label content is meaningful (e.g., the tag name) so the action is clear.
***
## Best practices
* Keep text concise; avoid wrapping long content inside badges
* Use variants consistently to convey meaning (e.g., destructive for errors)
* Don’t overuse badges—too many reduce their visual impact
* Prefer onRemove for interactive chip behavior; otherwise keep badges non‑interactive
# Feedback & Status
import Link from "fumadocs-core/link";
# Feedback & Status
Feedback and status components communicate outcomes, confirmations, and loading states to users. Choosing the right component depends on how intrusive and persistent the message needs to be.
## Feedback patterns
**Inline feedback (stays on page):** Use Alert for messages that complement the surrounding UI. Alerts are perfect for contextual validation errors, informational notices, or warnings that relate directly to content on the screen. They remain visible until dismissed or the issue is resolved.
**Transient notifications (auto-dismiss):** Use Toast for brief, non-blocking messages that appear temporarily and disappear automatically. Toasts are ideal for action confirmations ("Saved!"), quick notifications, or status updates that don't require user interaction. They stack and can be dismissed manually.
**Blocking confirmations (require response):** Use Alert Dialog only for critical confirmations that demand explicit user acknowledgement. Reserve this for destructive or irreversible actions (delete account, discard changes) where the user must understand the consequence before proceeding.
## Loading states
**For skeleton placeholders:** Use Skeleton to show a content placeholder while data loads. Skeletons match the layout of real content and improve perceived performance by giving users a sense of what's coming.
**For loading indicators:** Use Spinner for small inline loading states (button spinners, mini loaders) or when you don't need a full skeleton. Spinners are compact and work well in buttons or next to text.
## Status labeling
Use Badge to label items with metadata—status tags (Active, Pending), counts, or category labels. Badges are small, non-interactive, and designed for quick visual scanning.
## Components
| Component | Pattern | Best for | Dismissal |
| --------------------------------------------------------------------------------- | -------------- | ----------------------------------------- | --------------------------- |
| Alert | Inline | Contextual errors, warnings, info on page | Manual or resolved |
| Toast | Transient | Action confirmations, quick notifications | Auto-dismiss (4s) or manual |
| Alert Dialog | Blocking modal | Destructive action confirmation | Requires explicit yes/no |
| Skeleton | Loading | Placeholder while fetching content | Replaced with real content |
| Spinner | Loading | Compact inline loading indicator | Disappears when done |
| Badge | Status label | Metadata tags, status indicators | Persistent or dynamic |
## Quick decision tree
* **User just completed an action and needs confirmation?** → Toast
* **Validation error or warning for content on the page?** → Alert
* **Must the user confirm before an irreversible action?** → Alert Dialog
* **Content is loading?** → Skeleton (if replacing layout) or Spinner (inline)
* **Need to label an item's status?** → Badge
# Skeleton
import { Callout } from '@/components/mdx';
import { TypeTable } from 'fumadocs-ui/components/type-table';
import { BasicSkeletonExample, SkeletonCardExample, SkeletonListExample, SkeletonFormExample } from '@/components/examples/components/skeleton';
# Skeleton
The Skeleton component provides animated placeholders that mimic the layout of content while it loads. This improves perceived performance and creates a smoother user experience.
Match skeleton shapes and sizes to your actual content for a seamless transition.
***
## Features
* Animated pulse effect
* Customizable size and shape via className
* Adapts to container dimensions
* Works for text, images, buttons, and more
* Lightweight implementation
***
## Usage
```tsx
import { Skeleton } from '@loke/design-system/skeleton';
export default function Example() {
return (
);
}
```
Tips:
* Use `className` to set dimensions and border radius.
* Create skeleton layouts that match your actual content structure.
* Avoid using skeletons for very short loading times (under 300ms).
***
## Props
### Skeleton
The Skeleton component accepts all standard `div` HTML attributes.
***
## Examples
### Basic skeleton
```tsx
```
### Card skeleton
```tsx
```
### List skeleton
```tsx
{[...Array(3)].map((_, i) => (
))}
```
### Form skeleton
```tsx
```
***
## Accessibility
* Skeletons are purely visual placeholders with no semantic meaning.
* Use `aria-busy="true"` on the parent container while loading.
* Consider using `aria-hidden="true"` on skeleton elements.
* Provide alternative text or announcements for screen readers during loading.
***
## Best practices
* Match skeleton dimensions to actual content for smooth transitions.
* Use consistent spacing to maintain layout stability.
* Group related skeletons to represent content structure.
* Avoid skeleton flicker—don't show for very short loads (under 300ms).
* Consider using a minimum display time to prevent jarring transitions.
* Use rounded shapes for avatars and sharp corners for cards/text.
* Don't overload the page with too many animated elements.
# Spinner
import { Callout } from '@/components/mdx';
import { TypeTable } from 'fumadocs-ui/components/type-table';
import { BasicSpinnerExample, SpinnerSizesExample, SpinnerColorsExample, SpinnerWithTextExample } from '@/components/examples/components/spinner';
# Spinner
The Spinner component provides an animated loading indicator for operations in progress. It communicates to users that content is loading or an action is being processed.
Spinner uses the `output` element with `aria-label="Loading"` for accessibility.
***
## Features
* Four size variants (sm, md, lg, xl)
* Three color options (primary, secondary, accent)
* Smooth spin animation
* Accessible loading announcement
* Screen reader support
***
## Usage
```tsx
import { Spinner } from '@loke/design-system/spinner';
export default function Example() {
return ;
}
```
Tips:
* Use appropriate size based on context (sm for buttons, lg for page loading).
* Match spinner color to the surrounding UI context.
* Consider adding descriptive text alongside the spinner.
***
## Props
### Spinner
***
## Examples
### Basic spinner
```tsx
```
### Sizes
```tsx
```
### Colors
```tsx
```
### With text
```tsx
Loading...
```
***
## Accessibility
* Uses `output` element for live region behavior.
* Includes `aria-label="Loading"` for screen reader announcement.
* Hidden visual label with screen reader text "Loading...".
* Communicates loading state to assistive technologies.
***
## Best practices
* Use spinners for operations that take more than 300ms.
* Choose an appropriate size for the context (smaller in buttons, larger for page loads).
* Consider using skeleton loaders instead for content-heavy loading states.
* Add descriptive text when the loading context isn't obvious.
* Avoid multiple spinners on the same screen—it can be overwhelming.
* Use consistent spinner placement across similar interactions.
* Consider disabling interactive elements while loading.
# Toast
import { Callout } from '@/components/mdx';
import { TypeTable } from 'fumadocs-ui/components/type-table';
import { BasicToastExample, ToastTypesExample, ToastWithActionExample, ToastPromiseExample } from '@/components/examples/components/toast';
# Toast
The Toast component provides non-blocking notifications that appear temporarily to inform users of actions, events, or status changes. Toasts automatically dismiss and can include actions.
Add the `Toaster` component once at your app's root to enable toasts throughout your application.
***
## Features
* Multiple toast types (success, error, warning, info, loading)
* Action buttons and cancel buttons
* Promise-based toasts for async operations
* Stacked display with expand-on-hover
* Swipe to dismiss
* Keyboard shortcut support
* Customizable duration
* Custom icons
***
## Usage
```tsx
import { Toaster, toast } from '@loke/design-system/toast';
// Add Toaster to your app root
function App() {
return (
<>
>
);
}
// Trigger toasts anywhere
function MyComponent() {
return (
);
}
```
Tips:
* Place `Toaster` at your app root.
* Use `toast.success()`, `toast.error()`, etc. for styled variants.
* Use `toast.promise()` for async operations.
***
## Toast API
### Basic toast
```tsx
toast('Event has been created');
// With description
toast('Event created', {
description: 'Your event has been added to the calendar.',
});
```
### Typed toasts
```tsx
toast.success('Successfully saved!');
toast.error('Something went wrong');
toast.warning('Please review your input');
toast.info('New features available');
toast.loading('Loading...');
```
### With actions
```tsx
toast('File uploaded', {
action: {
label: 'Undo',
onClick: () => console.log('Undo'),
},
});
```
### Promise toast
```tsx
toast.promise(saveData(), {
loading: 'Saving...',
success: 'Data saved!',
error: 'Could not save data.',
});
```
### Dismiss toast
```tsx
const toastId = toast('Message');
toast.dismiss(toastId); // Dismiss specific toast
toast.dismiss(); // Dismiss all toasts
```
***
## Props
### Toaster
### Toast options
void }',
},
cancel: {
description: 'Secondary/cancel action button.',
type: '{ label: ReactNode, onClick: () => void }',
},
closeButton: {
description: 'Show close button for this toast.',
type: 'boolean',
},
dismissible: {
description: 'Whether the toast can be dismissed.',
type: 'boolean',
default: 'true',
},
onDismiss: {
description: 'Callback when toast is dismissed.',
type: '(toast) => void',
},
onAutoClose: {
description: 'Callback when toast auto-closes.',
type: '(toast) => void',
},
}}
/>
***
## Examples
### Basic toasts
```tsx
```
### Toast types
```tsx
```
### With action
```tsx
```
### Promise toast
```tsx
```
***
## Accessibility
* Uses `aria-live="polite"` for non-intrusive announcements.
* Toast container has `role="region"` with accessible label.
* Keyboard shortcut (Alt+T by default) focuses the toast list.
* Close buttons have accessible labels.
* Toasts can be dismissed with Escape key.
* Action buttons are focusable and keyboard accessible.
***
## Best practices
* Keep toast messages brief and actionable.
* Use appropriate toast types for the message context.
* Avoid showing too many toasts at once.
* Set reasonable durations (longer for important messages).
* Provide undo actions when appropriate.
* Don't use toasts for critical information that requires attention.
* Use promise toasts for async operations to show loading state.
* Test toast behavior on mobile (swipe to dismiss).
# Button
import { Callout, Kbd } from '@/components/mdx';
import { TypeTable } from 'fumadocs-ui/components/type-table';
import { Button, buttonVariants } from '@loke/design-system/button';
import { ArrowRight, Plus, Trash } from '@loke/icons';
import { VariantsButtonExample, SizesButtonExample, WithIconsButtonExample, DisabledStatesButtonExample, WidthButtonExample, JustificationButtonExample, AsChildButtonExample, CustomStylesAndVariantsButtonExample } from '@/components/examples/components/button';
# Button
The Button component is a flexible, accessible trigger for actions and navigation. It supports multiple visual variants and sizes, optional full‑width presentation, content justification, and composition via `asChild`.
Prefer Button for primary actions. For text‑only affordances inside paragraphs, consider the link variant. Use buttonVariants to style anchors or custom triggers consistently.
***
## Features
* Variants: default, destructive, outline, secondary, ghost, link
* Sizes: default, sm, lg, icon
* Layout controls: full/fit width, content justification
* `asChild` composition to render other elements with button styling
* Sensible focus styles and disabled state
* Optional icon sizing control via `iconSize`
***
## Usage
```tsx
import { Button } from '@loke/design-system/button';
import { ArrowRight } from '@loke/icons';
export default function Example() {
return (
);
}
```
Tips:
* Use the `icon` size for icon‑only buttons and set an accessible label with aria-label.
* Set width="full" for full‑width buttons (e.g., mobile forms).
* Use justify to align content (e.g., between with two elements).
***
## Props
',
},
}}
/>
***
## Examples
### Variants
```tsx
```
### Sizes
```tsx
```
### With icons
```tsx
```
### Disabled states
```tsx
```
### Width
```tsx
```
### Justification
```tsx
```
### As child
Use asChild to render a different element with Button styles and behavior without introducing extra DOM.
```tsx
```
### Custom styles and buttonVariants
```tsx
```
***
## Accessibility
* Icon‑only buttons must have an accessible name via aria-label.
* Ensure the button’s action is clear and concise in its label.
* When used inside forms, set type appropriately (e.g., type="button" to avoid accidental submission).
* The component includes visible focus styling by default; ensure it remains discernible against your theme.
***
## Best practices
* Choose a variant that communicates intent (e.g., destructive for deletion).
* Keep labels short and action‑oriented (“Save”, “Create”, “Delete”).
* Group related actions and de‑emphasize secondary actions (use secondary, ghost, or link).
* Prefer size="icon" for icon‑only buttons; include an aria-label.
* Use buttonVariants for non‑button elements that should look and feel like buttons (e.g., anchors).
# Calendar
import { Callout, Kbd } from '@/components/mdx';
import { TypeTable } from 'fumadocs-ui/components/type-table';
import { Calendar } from '@loke/design-system/calendar';
import { SingleCalendarExample, MultipleCalendarExample, RangeCalendarExample, DisabledDatesCalendarExample, MinMaxCalendarExample, MultiMonthCalendarExample, WeekNumbersCalendarExample, YearSelectorCalendarExample } from '@/components/examples/components/calendar';
# Calendar
The Calendar component provides a rich date selection interface supporting single dates, multiple dates, or date ranges. It includes month navigation, customizable date constraints, and various display options.
For a complete date picker experience with an input field and popover, consider using the DatePicker component which wraps Calendar with additional UI.
***
## Features
* Selection modes: single date, multiple dates, or date range
* Month navigation with previous/next buttons
* Optional year selector dropdown
* Min/max date constraints
* Custom disabled dates (array or function)
* Week numbers display
* Fixed weeks option for consistent height
* Multi-month display
* Customizable first day of week
* Outside days visibility control
* Initial focus support for accessibility
***
## Usage
```tsx
import { Calendar } from '@loke/design-system/calendar';
export default function Example() {
const [date, setDate] = useState(new Date());
return (
);
}
```
Tips:
* Use `mode="single"` for selecting a single date.
* Use `mode="range"` for date range selection (e.g., booking dates).
* Set `minDate` and `maxDate` to constrain selectable dates.
* Enable `showWeekNumber` for calendars that need week-based navigation.
***
## Props
void',
},
minDate: {
description: 'Earliest selectable date. Dates before this are disabled.',
type: 'Date',
},
maxDate: {
description: 'Latest selectable date. Dates after this are disabled.',
type: 'Date',
},
disabled: {
description: 'Dates to disable. Can be an array of dates or a function.',
type: 'Date[] | ((date: Date) => boolean)',
},
numberOfMonths: {
description: 'Number of months to display side by side.',
type: 'number',
default: '1',
},
defaultMonth: {
description: 'Initial month to display (uncontrolled).',
type: 'Date',
},
month: {
description: 'Currently displayed month (controlled).',
type: 'Date',
},
onMonthChange: {
description: 'Callback when the displayed month changes.',
type: '(month: Date) => void',
},
firstDayOfWeek: {
description: 'First day of the week (0 = Sunday, 1 = Monday, etc.).',
type: '0 | 1 | 2 | 3 | 4 | 5 | 6',
default: '0',
},
showWeekNumber: {
description: 'Whether to display ISO week numbers.',
type: 'boolean',
default: 'false',
},
showOutsideDays: {
description: 'Whether to show days from adjacent months.',
type: 'boolean',
default: 'false',
},
fixedWeeks: {
description: 'Always show 6 weeks for consistent calendar height.',
type: 'boolean',
default: 'false',
},
initialFocus: {
description: 'Focus the selected day or today on mount.',
type: 'boolean',
default: 'false',
},
captionProps: {
description: 'Props for the caption/header component.',
type: 'CaptionProps',
},
'className / style': {
description: 'Styling hooks for custom appearance.',
type: 'string | React.CSSProperties',
},
}}
/>
***
## Examples
### Single date selection
```tsx
const [date, setDate] = useState(new Date());
```
### Multiple date selection
```tsx
const [dates, setDates] = useState([]);
```
### Date range selection
```tsx
const [range, setRange] = useState();
```
### Disabled dates
```tsx
// Disable weekends
date.getDay() === 0 || date.getDay() === 6}
/>
// Or disable specific dates
```
### Min and max dates
```tsx
```
### Multiple months
```tsx
```
### Week numbers
```tsx
```
### Year selector
```tsx
```
***
## Accessibility
* Calendar uses semantic table markup for screen reader compatibility.
* Keyboard navigation with arrow keys moves between days.
* Days are focusable with proper `tabIndex` management.
* Selected state is conveyed via `aria-selected` attributes.
* Disabled days are marked with `disabled` attribute.
* Use `initialFocus` to ensure keyboard users land on a meaningful date when the calendar opens.
***
## Best practices
* Set appropriate `minDate`/`maxDate` constraints to prevent invalid selections.
* Use `mode="range"` with `numberOfMonths={2}` for better date range UX.
* Enable `showWeekNumber` for business applications that reference week numbers.
* Consider `fixedWeeks` to prevent layout shifts when navigating months.
* Use `captionProps.showYearSelector` when users need to navigate to distant dates.
* Pair with `Label` component for form accessibility.
# Checkbox
import { Callout } from '@/components/mdx';
import { TypeTable } from 'fumadocs-ui/components/type-table';
import { BasicCheckboxExample, CheckboxWithLabelExample, IndeterminateCheckboxExample, DisabledCheckboxExample, CheckboxGroupExample } from '@/components/examples/components/checkbox';
# Checkbox
The Checkbox component provides a control for binary choices. It supports checked, unchecked, and indeterminate states, making it suitable for forms, settings, and multi-select scenarios.
Use checkboxes when users can select multiple options from a list, or for single opt-in/opt-out choices.
***
## Features
* Three states: checked, unchecked, and indeterminate
* Controlled and uncontrolled modes
* Custom check indicator with animated transitions
* Form integration with native checkbox behavior
* Accessible with proper ARIA attributes
* Works with Label component for click-to-toggle
***
## Usage
```tsx
import { Checkbox } from '@loke/design-system/checkbox';
export default function Example() {
return (
);
}
```
Tips:
* Always pair checkboxes with labels for accessibility.
* Use `onCheckedChange` for controlled behavior.
* The `checked` prop can be `true`, `false`, or `"indeterminate"`.
***
## Props
void',
},
disabled: {
description: 'Whether the checkbox is disabled.',
type: 'boolean',
default: 'false',
},
required: {
description: 'Whether the checkbox is required in a form.',
type: 'boolean',
default: 'false',
},
name: {
description: 'The name of the checkbox for form submission.',
type: 'string',
},
value: {
description: 'The value submitted with the form when checked.',
type: 'string',
default: '"on"',
},
className: {
description: 'Additional CSS classes for custom styling.',
type: 'string',
},
}}
/>
***
## Examples
### Basic checkbox
```tsx
```
### Checkbox with label
```tsx
```
***
## Accessibility
* Uses native checkbox semantics with `role="checkbox"`.
* Supports keyboard navigation (Space to toggle).
* Properly conveys checked state via `aria-checked`.
* Label association enables click-to-toggle.
* Focus states are visible for keyboard users.
* Disabled state is properly communicated.
***
## Best practices
* Always provide a label for each checkbox.
* Use `required` for mandatory form fields.
* Group related checkboxes together with a fieldset and legend.
* Use indeterminate state for "select all" scenarios with partial selection.
* Keep checkbox labels concise and action-oriented.
* Consider using switches for instant-apply settings instead of checkboxes.
# DatePicker
import { Callout, Kbd } from '@/components/mdx';
import { TypeTable } from 'fumadocs-ui/components/type-table';
import { SingleDatePickerExample, RangeDatePickerExample, DatePickerWithConstraintsExample } from '@/components/examples/components/date-picker';
# DatePicker
The DatePicker component wraps the Calendar in a popover with a trigger button, providing a complete date selection interface. It supports all Calendar modes including single date, multiple dates, and date ranges.
DatePicker passes all props through to the underlying Calendar component. See the Calendar docs for additional configuration options.
***
## Features
* Popover-based date selection
* Trigger button with formatted date display
* All Calendar selection modes (single, multiple, range)
* Automatic date formatting
* Customizable placeholder text
* All Calendar props supported
***
## Usage
```tsx
import { DatePicker } from '@loke/design-system/date-picker';
export default function Example() {
const [date, setDate] = useState(new Date());
return (
);
}
```
Tips:
* The trigger button displays the selected date(s) formatted.
* For range mode, both dates are shown with a separator.
* For multiple dates, it shows a count when more than one is selected.
***
## Props
void',
},
className: {
description: 'Additional CSS classes for the container.',
type: 'string',
},
}}
/>
All additional props are passed to the underlying Calendar component. See Calendar documentation for minDate, maxDate, disabled, and other options.
***
## Examples
### Single date picker
```tsx
const [date, setDate] = useState();
```
### Range date picker
```tsx
const [range, setRange] = useState();
```
### Date picker with constraints
```tsx
const [date, setDate] = useState();
```
***
## Accessibility
* Button trigger has proper focus states.
* Popover is keyboard accessible.
* Calendar within popover supports full keyboard navigation.
* Dates are properly announced to screen readers.
* Disabled dates are communicated.
***
## Best practices
* Use a descriptive placeholder that indicates what date is expected.
* Set appropriate date constraints with minDate/maxDate for valid ranges.
* For date ranges, use `numberOfMonths={2}` to show both months side by side.
* Consider pairing with Label for form accessibility.
* Handle undefined selection state for optional date fields.
# Form & Input
import Link from "fumadocs-core/link";
# Form & Input
Form and input components help you build accessible, validated forms that integrate seamlessly with `react-hook-form` and provide a consistent user experience across text inputs, selections, toggles, and date pickers.
## Choosing the right input
**For text entry:** Use Input for short text (names, emails, URLs) and Textarea for longer content (descriptions, comments). Both support placeholder text, icons, and clearable states.
**For selections:** Use Select for dropdown menus when you have a predefined list of options. Use Radio Group when users must choose exactly one option from a small, visible list. Use Checkbox for multiple independent yes/no choices or multi-select scenarios.
**For toggles:** Use Switch for boolean settings (on/off, enabled/disabled). Switches are ideal for immediate state changes without form submission.
**For dates and times:** Use Calendar for inline date selection, or Date Picker for a popover date/datetime selector—both integrate with form validation.
**For labels and actions:** Pair inputs with Label for accessibility. Use Button to trigger form submissions or secondary actions.
## Integration with react-hook-form
All form components work with `react-hook-form` via standard `onChange` and `value` props. Use `controller` or hook into form state to bind inputs:
```tsx
import { useForm } from "react-hook-form";
import { Input } from "@loke/design-system/input";
import { Label } from "@loke/design-system/label";
export default function MyForm() {
const { register, handleSubmit } = useForm();
return (
);
}
```
## Components
| Component | Use case | Key features |
| -------------------------------------------------------------------------- | ---------------------------------------------- | ------------------------------------------------- |
| Input | Single-line text entry (name, email, search) | Auto icons by type, clearable, focus states |
| Textarea | Multi-line text entry (descriptions, comments) | Resizable, consistent padding, accessible |
| Select | Choose from predefined options | Keyboard navigation, searchable, grouped options |
| Radio Group | Single choice from visible options | Horizontal or vertical layout, keyboard support |
| Checkbox | Multiple independent toggles | Indeterminate state, label support, accessible |
| Switch | Boolean settings (on/off, enable/disable) | Instant feedback, keyboard accessible |
| Calendar | Inline date selection widget | Month/year navigation, accessible navigation |
| Date Picker | Date/datetime selection via popover | Calendar + time picker, timezone aware |
| Label | Accessible form field labels | Required indicator support, focus pairing |
| Button | Trigger actions or submit forms | Multiple variants (primary, destructive, outline) |
# Input
import { Callout, Kbd } from '@/components/mdx';
import { TypeTable } from 'fumadocs-ui/components/type-table';
import { BasicInputExample, InputTypesExample, InputWithIconsExample, InputWithClearExample, InputStatesExample } from '@/components/examples/components/input';
# Input
The Input component provides a consistent text input field with automatic icon assignment based on input type, custom icon support, and clearable functionality.
Input automatically displays appropriate icons for email, password, search, date, and time types.
***
## Features
* Standard HTML input types support
* Automatic icons based on input type
* Custom icon support
* Clearable input with clear button
* Consistent styling with form components
* File input styling
* Proper focus and disabled states
***
## Usage
```tsx
import { Input } from '@loke/design-system/input';
export default function Example() {
return (
);
}
```
Tips:
* Use the appropriate `type` for automatic icon display.
* Add `onClear` prop to show a clear button.
* Pass a custom `icon` to override the automatic icon.
***
## Props
void',
},
placeholder: {
description: 'Placeholder text.',
type: 'string',
},
disabled: {
description: 'Whether the input is disabled.',
type: 'boolean',
default: 'false',
},
className: {
description: 'Additional CSS classes.',
type: 'string',
},
}}
/>
All standard HTML input attributes are also supported.
***
## Automatic Icons
The Input component automatically displays icons based on the input type:
| Type | Icon |
| ---------------- | -------- |
| `email` | Mail |
| `password` | Lock |
| `search` | Search |
| `date` | Calendar |
| `time` | Clock |
| `datetime-local` | Calendar |
***
## Examples
### Basic inputs
```tsx
```
### Input types with icons
```tsx
```
### Custom icons
```tsx
import { User, Phone, Globe } from '@loke/icons';
```
### Clearable input
```tsx
const [value, setValue] = useState('');
setValue(e.target.value)}
onClear={() => setValue('')}
placeholder="Type something..."
/>
```
### Input states
```tsx
```
***
## Accessibility
* Uses native HTML input element for full accessibility support.
* Focus states are clearly visible with ring styles.
* Disabled state is communicated visually and via `disabled` attribute.
* Labels should be associated via `id` or wrapping `Label` component.
* Placeholder text provides input hints but should not replace labels.
***
## Best practices
* Always pair inputs with labels for accessibility.
* Use appropriate input types for better mobile keyboards.
* Provide helpful placeholder text as hints, not instructions.
* Use `onClear` for search inputs and filters.
* Consider using `FormField` wrapper for form validation.
* Set appropriate `autocomplete` attributes for autofill.
* Use `required` attribute for mandatory fields.
# Label
import { Callout, Kbd } from '@/components/mdx';
import { TypeTable } from 'fumadocs-ui/components/type-table';
import { BasicLabelExample, LabelWithInputExample, LabelWithCheckboxExample, LabelStatesExample } from '@/components/examples/components/label';
# Label
The Label component provides accessible labels for form inputs. It's designed to work seamlessly with other form components and handles click interactions properly.
Always use the `htmlFor` prop to associate labels with their corresponding form inputs.
***
## Features
* Semantic `