npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@datawire-ai/busyfile-design-library

v1.30.10

Published

Design system for busyfile

Readme

BusyFile Design System

Design system library for Busyfile Applications

Installation

Design system library for Busyfile Applications

Installation

# Using npm
npm install busyfile-design-system

# Using pnpm
pnpm add busyfile-design-system

Development

Development

Prerequisites

  • Node.js - v22.19
  • pnpm - v10.15
  • Node.js - v22.19
  • pnpm - v10.15

Setup

# Clone the repository
git clone https://github.com/your-username/busyfile-design-system.git
cd busyfile-design-system

# Install dependencies
pnpm install

# Start development server
pnpm dev

# Start Storybook
pnpm storybook

# Build the library
pnpm build

# Run tests
pnpm test

Development Workflow

  1. Fork the repository
  2. Create a feature branch
  3. Make your changes
  4. Create changeset pnpm changeset:add & pnpm changeset version
  5. Submit a pull request

PRs & Changeset Process

  • [ ] Do not run changeset until your PR is ready for merge
    • [ ] Complete all required changes
    • [ ] Apply PR review feedback
    • [ ] Get the PR reviewed
  • [ ] Once reviews are done and PR is approved
    • [ ] Run the changeset scripts
    • [ ] Get the PR reviewed and approved again
    • [ ] Merge into main
  • [ ] If you receive comments after creating a changeset
    • [ ] Delete the generated changeset files
    • [ ] Apply PR feedback
    • [ ] Push the changes and get them reviewed again
    • [ ] Repeat until the PR is ready for merge into main
  • [ ] Do not publish from your local on npm

Development Workflow

  1. Fork the repository
  2. Create a feature branch
  3. Make your changes
  4. Create changeset pnpm changeset:add & pnpm changeset version
  5. Submit a pull request

PRs & Changeset Process

  • [ ] Do not run changeset until your PR is ready for merge
    • [ ] Complete all required changes
    • [ ] Apply PR review feedback
    • [ ] Get the PR reviewed
  • [ ] Once reviews are done and PR is approved
    • [ ] Run the changeset scripts
    • [ ] Get the PR reviewed and approved again
    • [ ] Merge into main
  • [ ] If you receive comments after creating a changeset
    • [ ] Delete the generated changeset files
    • [ ] Apply PR feedback
    • [ ] Push the changes and get them reviewed again
    • [ ] Repeat until the PR is ready for merge into main
  • [ ] Do not publish from your local on npm

Project Structure

src/
├── components/          # React components
│   └── ui/
│       ├── badge/       # Badge component
│       │   ├── badge.tsx
│       │   ├── badge.types.ts
│       │   ├── badge.utils.ts
│       │   └── badge.test.tsx
        ├── badge.stories.tsx
│       ├── button/      # Button component
│       │   ├── button.tsx
│       │   ├── button.types.ts
│       │   ├── button.utils.ts
│       │   └── button.test.tsx
|       ├── button.stories.tsx
│       ├── divider/     # Divider component
│       │   ├── divider.tsx
│       │   ├── divider.types.ts
│       │   └── divider.test.tsx
|       ├── divider.stories.tsx
│       └── index.ts     # Component exports
├── lib/                 # Utility functions
│   └── utils.ts
├── styles/
│   └── style.css           # Global styles
├── App.tsx              # Demo application
├── main.tsx             # Application entry point
└── index.ts             # Main package exports

│   └── ui/
│       ├── badge/       # Badge component
│       │   ├── badge.tsx
│       │   ├── badge.types.ts
│       │   ├── badge.utils.ts
│       │   └── badge.test.tsx
        ├── badge.stories.tsx
│       ├── button/      # Button component
│       │   ├── button.tsx
│       │   ├── button.types.ts
│       │   ├── button.utils.ts
│       │   └── button.test.tsx
|       ├── button.stories.tsx
│       ├── divider/     # Divider component
│       │   ├── divider.tsx
│       │   ├── divider.types.ts
│       │   └── divider.test.tsx
|       ├── divider.stories.tsx
│       └── index.ts     # Component exports
├── lib/                 # Utility functions
│   └── utils.ts
├── styles/
│   └── style.css           # Global styles
├── App.tsx              # Demo application
├── main.tsx             # Application entry point
└── index.ts             # Main package exports

Testing

Testing

# Run all tests
pnpm test

# Run tests in watch mode
pnpm test:watch

# Run tests with coverage
pnpm test:coverage

# Run tests in browser
pnpm test:browser

Storybook

Storybook

Storybook provides an interactive playground for all components:

# Start Storybook
pnpm storybook

# Build Storybook
pnpm build-storybook

Visit http://localhost:6006 to explore components, test props, and see examples.

Configuration

Configuration

Tailwind CSS

The design system includes a pre-configured Tailwind CSS setup. You can extend it in your project:

// tailwind.config.js
module.exports = {
  content: [
    './src/**/*.{js,ts,jsx,tsx}',
    './node_modules/busyfile-design-system/**/*.{js,ts,jsx,tsx}',
    './src/**/*.{js,ts,jsx,tsx}',
    './node_modules/busyfile-design-system/**/*.{js,ts,jsx,tsx}',
  ],
  theme: {
    extend: {
      // Your custom theme extensions
    },
    },
  },
  plugins: [],
};
  plugins: [],
};

Typography

The BusyFile Design System provides a consistent typography scale based on Nunito with predefined sizes and line-heights from Figma.

| Token | Font Size | Line Height | Example Class | | ------------------- | --------- | ----------- | ----------------- | | --text-display-lg | 3rem | 1.2rem | text-display-lg | | --text-display-md | 2.25rem | 1.2rem | text-display-md | | --text-display-sm | 1.875rem | 1.2rem | text-display-sm | | --text-display-xs | 1.5rem | 1.2rem | text-display-xs | | --text-xl | 1.25rem | 1.6rem | text-xl | | --text-lg | 1.125rem | 1.6rem | text-lg | | --text-md | 1rem | 1.6rem | text-md | | --text-sm | 0.875rem | 1.6rem | text-sm | | --text-xs | 0.75rem | 1.6rem | text-xs |

Usage

Colors

The BusyFile Design System defines a unified color palette for primary, neutral, and semantic states. These tokens can be used directly as Tailwind utility classes like bg-primary-30 or text-neutral-60.

Primary Colors

| Token | Hex | Example Class | | -------------------- | --------- | --------------- | | --color-primary-0 | #36060a | bg-primary-0 | | --color-primary-10 | #6a131d | bg-primary-10 | | --color-primary-20 | #a52432 | bg-primary-20 | | --color-primary-30 | #e33549 | bg-primary-30 | | --color-primary-40 | #f17b83 | bg-primary-40 | | --color-primary-50 | #f5b5b9 | bg-primary-50 | | --color-primary-60 | #fceaea | bg-primary-60 |

Neutral Colors

| Token | Hex | Example Class | | -------------------- | --------- | --------------- | | --color-neutral-0 | #0a0a0a | bg-neutral-0 | | --color-neutral-10 | #1f1f1f | bg-neutral-10 | | --color-neutral-20 | #333333 | bg-neutral-20 | | --color-neutral-30 | #474747 | bg-neutral-30 | | --color-neutral-40 | #5c5c5c | bg-neutral-40 | | --color-neutral-50 | #707070 | bg-neutral-50 | | --color-neutral-60 | #858585 | bg-neutral-60 | | --color-neutral-70 | #999999 | bg-neutral-70 | | --color-neutral-80 | #adadad | bg-neutral-80 | | --color-neutral-90 | #c2c2c2 | bg-neutral-90 | | --color-neutral-95 | #d6d6d6 | bg-neutral-95 | | --color-neutral-99 | #f1f1f1 | bg-neutral-99 |

Semantic Colors

| State | Light | Dark | Example Classes | | ----------- | --------- | --------- | ------------------------------ | | Error | #f9dcdf | #bf2234 | bg-error-l, bg-error-d | | Warning | #fbf2da | #e8b321 | bg-warning-l, bg-warning-d | | Success | #c5fce3 | #099a59 | bg-success-l, bg-success-d |

Usage

<div className="bg-primary-30 text-white p-4 rounded">
  Primary Button
</div>

<div className="bg-error-d text-white p-4 rounded">
  Error Alert
</div>

Card

The Card component provides a flexible and styled container for displaying grouped content consistently across your application.
It supports multiple visual variants and customizable shadow colors via both theme variables and direct color values.

Usage

import { Card } from '@/components/ui/card';

export function Example() {
  return (
    <section className="space-y-6">
      {/* Widget 1 - Inner Shadow */}
      <Card variant="widget-1" shadowColor="#3649EA">
        <h3 className="text-lg font-semibold">Widget 1 Card</h3>
        <p>This card uses an inner shadow and supports a custom inset color.</p>
      </Card>

      {/* Widget 2 - Border with Shadow */}
      <Card variant="widget-2">
        <h3 className="text-lg font-semibold">Widget 2 Card</h3>
        <p>This card has a border with a subtle drop shadow.</p>
      </Card>
    </section>
  );
}

| Prop | Type | Default | Description | | ------------- | ----------------------------------- | ------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | variant | "widget-1" | "widget-2" | "widget-1" | Determines the visual style of the card. | | shadowColor | string | undefined | Optional. Accepts either a HEX value (e.g. #3649EA) or a theme color variable (e.g. var(--color-primary-1)) to customize the inner shadow color for widget-1. | | asChild | boolean | false | If true, renders the component as a child element using Radix’s <Slot> for better composition. | | className | string | undefined | Adds custom class names for additional styling. | | children | React.ReactNode | — | Content inside the card. | | ...props | React.HTMLAttributes<HTMLElement> | — | Additional HTML attributes are spread onto the root element. |

Toggle Button

A customizable and accessible toggle button (switch) component. Supports both controlled (Toggle) and uncontrolled/stateful (StatefulToggle) usage.

Usage

// Controlled toggle
'use client';

import * as React from 'react';
import { Toggle } from '@/components/ui/toggle-button';

export default function Example() {
  const [checked, setChecked] = React.useState(false);

  return (
    <div className="flex items-center gap-3">
      <Toggle
        id="dark-mode"
        checked={checked}
        onCheckedChange={setChecked}
        className="data-[state=checked]:bg-green-500 data-[state=unchecked]:bg-gray-300"
      />
      <label
        htmlFor="dark-mode"
        className="cursor-pointer select-none text-sm font-medium"
      >
        Enable Dark Mode
      </label>
    </div>
  );
}

Props

| Prop | Type | Default | Description | | ----------------- | --------------------------------------------------- | ------- | --------------------------------------------------------------- | | checked | boolean | false | Controls the switch state (on/off). | | defaultChecked | boolean | false | Sets the initial state when using the switch uncontrolled. | | onCheckedChange | (checked: boolean) => void | | Callback function fired when the checked state changes. | | disabled | boolean | false | Disables the switch if true. | | id | string | | Used to pair the switch with a <label> for accessibility. | | className | string | | Apply custom Tailwind/utility classes. | | ...props | React.ComponentProps<typeof SwitchPrimitive.Root> | | Any additional props supported by Radix SwitchPrimitive.Root. |

Radio Button

A radio button is a user interface element that allows the user to select one option from a list of mutually exclusive options. They are typically used in interfaces where the user needs to choose a single option from a set of options, such as in a survey or form.

Usage

'use client';

import { RadioGroup, RadioGroupItem } from './radio-button';

export default function Example() {
  return (
    <RadioGroup defaultValue="option1" className="flex flex-col gap-3">
      <RadioGroupItem value="option1">Option 1</RadioGroupItem>
      <RadioGroupItem value="option2">Option 2</RadioGroupItem>
      <RadioGroupItem value="option3" disabled>
        Option 3 (Disabled)
      </RadioGroupItem>
    </RadioGroup>
  );
}

Props

| Prop | Type | Default | Description | | --------------- | ------------------------- | -------- | --------------------------------------------- | | value | string | – | Controlled value of the selected radio. | | defaultValue | string | – | Uncontrolled initial value. | | onValueChange | (value: string) => void | – | Callback fired when the value changes. | | name | string | auto-gen | Name for the underlying native radio inputs. | | disabled | boolean | false | Disables all radios inside the group. | | className | string | – | Tailwind/custom classes for the root wrapper. | | children | React.ReactNode | – | One or more <RadioGroupItem />. |

The Skeleton component is used to display a placeholder while content is loading. It supports custom dimensions, border radius, and animations. It also includes a SkeletonText variant for rendering multiple placeholder text lines.

Usage

import { Skeleton, SkeletonText } from "@/components/ui/skeleton";

// Basic skeleton block
<Skeleton width={120} height={20} />

// Rounded skeleton (e.g., avatar)
<Skeleton width={40} height={40} borderRadius="50%" />

// Animated skeleton
<Skeleton width="100%" height={16} animation="pulse" />

// Multi-line skeleton text
<SkeletonText lines={3} />

Props

| Prop | Type | Default | Description | | -------------- | ---------------------- | ------- | ------------------------------------ | | className | string | - | Custom classes for styling. | | animation | "shimmer" \| "pulse" | - | Animation style for skeleton. | | width | number \| string | - | Width of the skeleton (px, %, etc.). | | height | number \| string | - | Height of the skeleton. | | borderRadius | number \| string | 4px | Border radius (px or CSS value). | | style | React.CSSProperties | - | Inline styles override. |

Typography

The BusyFile Design System provides a consistent typography scale based on Nunito with predefined sizes and line-heights from Figma.

| Token | Font Size | Line Height | Example Class | | ------------------- | --------- | ----------- | ----------------- | | --text-display-lg | 3rem | 1.2rem | text-display-lg | | --text-display-md | 2.25rem | 1.2rem | text-display-md | | --text-display-sm | 1.875rem | 1.2rem | text-display-sm | | --text-display-xs | 1.5rem | 1.2rem | text-display-xs | | --text-xl | 1.25rem | 1.6rem | text-xl | | --text-lg | 1.125rem | 1.6rem | text-lg | | --text-md | 1rem | 1.6rem | text-md | | --text-sm | 0.875rem | 1.6rem | text-sm | | --text-xs | 0.75rem | 1.6rem | text-xs |

Usage

Colors

The BusyFile Design System defines a unified color palette for primary, neutral, and semantic states. These tokens can be used directly as Tailwind utility classes like bg-primary-30 or text-neutral-60.

Primary Colors

| Token | Hex | Example Class | | -------------------- | --------- | --------------- | | --color-primary-0 | #36060a | bg-primary-0 | | --color-primary-10 | #6a131d | bg-primary-10 | | --color-primary-20 | #a52432 | bg-primary-20 | | --color-primary-30 | #e33549 | bg-primary-30 | | --color-primary-40 | #f17b83 | bg-primary-40 | | --color-primary-50 | #f5b5b9 | bg-primary-50 | | --color-primary-60 | #fceaea | bg-primary-60 |

Neutral Colors

| Token | Hex | Example Class | | -------------------- | --------- | --------------- | | --color-neutral-0 | #0a0a0a | bg-neutral-0 | | --color-neutral-10 | #1f1f1f | bg-neutral-10 | | --color-neutral-20 | #333333 | bg-neutral-20 | | --color-neutral-30 | #474747 | bg-neutral-30 | | --color-neutral-40 | #5c5c5c | bg-neutral-40 | | --color-neutral-50 | #707070 | bg-neutral-50 | | --color-neutral-60 | #858585 | bg-neutral-60 | | --color-neutral-70 | #999999 | bg-neutral-70 | | --color-neutral-80 | #adadad | bg-neutral-80 | | --color-neutral-90 | #c2c2c2 | bg-neutral-90 | | --color-neutral-95 | #d6d6d6 | bg-neutral-95 | | --color-neutral-99 | #f1f1f1 | bg-neutral-99 |

Semantic Colors

| State | Light | Dark | Example Classes | | ----------- | --------- | --------- | ------------------------------ | | Error | #f9dcdf | #bf2234 | bg-error-l, bg-error-d | | Warning | #fbf2da | #e8b321 | bg-warning-l, bg-warning-d | | Success | #c5fce3 | #099a59 | bg-success-l, bg-success-d |

Usage

<div className="bg-primary-30 text-white p-4 rounded">
  Primary Button
</div>

<div className="bg-error-d text-white p-4 rounded">
  Error Alert
</div>

## Badge

The `Badge` component is used to display small status indicators, tags, or labels.
It supports multiple variants, types `(filled / outline)`, and accepts custom children (icons, avatars, flags, etc.).

### Usage

tsx

{/_ Outline badges _/} Outlined

{/_ With icons _/} Success with Icon


# Checkbox

The `Checkbox` is a user interface element that allows the user to select one or more options from a list of independent options. They are typically used in interfaces where the user needs to choose one or more options from a set of options, such as in a filter menu.

## Usage

```tsx
import { Checkbox } from '@/components/ui/checkbox';

export function Example() {
  return (
    <div className="flex items-center gap-2">
      <Checkbox id="terms" />
      <label htmlFor="terms" className="text-sm text-neutral-black-1">
        Accept terms and conditions
      </label>
    </div>
  );
}

### Props

| Prop              | Type                                            | Default | Description                                                    |
| ----------------- | ----------------------------------------------- | ------- | -------------------------------------------------------------- |
| `className`       | `string`                                        | `—`     | Custom class names for styling.                                |
| `checked`         | `boolean \| "indeterminate"`                    | `—`     | Controlled state of the checkbox.                              |
| `defaultChecked`  | `boolean`                                       | `false` | Uncontrolled initial checked state.                            |
| `disabled`        | `boolean`                                       | `false` | Disables the checkbox when true.                               |
| `onCheckedChange` | `(checked: boolean \| "indeterminate") => void` | `—`     | Callback fired when the checked state changes.                 |
| `id`              | `string`                                        | `—`     | Used to associate the checkbox with a `<label>` via `htmlFor`. |
| `name`            | `string`                                        | `—`     | Name of the checkbox input (useful in forms).                  |
| `value`           | `string`                                        | `—`     | Value associated with the checkbox input.                      |

# Timeline

A flexible and customizable timeline component built with React. Supports different visual styles (`filled`, `outlined`, and `icon`), visited/unvisited states, connectors, and custom content.

## Usage

```tsx
import { Timeline } from '@/components/timeline';
import { CheckCircle } from 'lucide-react';

<Timeline
  variant="icon"
  items={[
    {
      id: 'step-1',
      title: 'Step 1',
      description: 'This is the first step of the process.',
      icon: <CheckCircle size={16} />,
    },
    {
      id: 'step-2',
      title: 'Step 2',
      description: 'This step contains extra details.',
      content: <CustomComponent />,
      icon: <CheckCircle size={16} />,
    },
    {
      id: 'step-3',
      title: 'Step 3',
      notVisited: true,
      icon: <CheckCircle size={16} />,
    },
  ]}
/>;
```

### Props

| Prop        | Type                                                                                                                                  | Default      | Description                                                                                                                                    |
| ----------- | ------------------------------------------------------------------------------------------------------------------------------------- | ------------ | ---------------------------------------------------------------------------------------------------------------------------------------------- |
| `items`     | `Array<{ id: string; title: string; description?: string; content?: React.ReactNode; icon?: React.ReactNode; notVisited?: boolean }>` | **Required** | Timeline steps data. Each item requires a unique `id` and `title`. Optional fields include `description`, `content`, `icon`, and `notVisited`. |
| `variant`   | `"filled" \| "outlined" \| "icon"`                                                                                                    | `"filled"`   | Style variant of the timeline dot. `"icon"` allows passing a custom `icon` for each item.                                                      |
| `className` | `string`                                                                                                                              | `-`          | Custom classes for the root wrapper.                                                                                                           |

# Button

The `Button` component is a core interactive element in the design system. It supports multiple variants, sizes, and icons while ensuring accessibility and consistency.

## Usage

```tsx
<Button variant="default">Default</Button>
<Button variant="primary">Primary</Button>
<Button variant="outline" size="sm">Outline Small</Button>
<Button size="icon"><Icon /></Button>
```

## Badge

The `Badge` component is used to display small status indicators, tags, or labels.
It supports multiple variants, types `(filled / outline)`, and accepts custom children (icons, avatars, flags, etc.).

### Usage

```tsx
<div className="flex gap-2 flex-wrap">
  <Badge variant="primary">Primary</Badge>
  <Badge variant="success">Success</Badge>
  <Badge variant="warning">Warning</Badge>
  <Badge variant="error">Error</Badge>
  <Badge variant="gray">Gray</Badge>
  <Badge variant="blue">Blue</Badge>
  <Badge variant="purple">Purple</Badge>
  <Badge variant="pink">Pink</Badge>
  <Badge variant="rose">Rose</Badge>

  {/* Outline badges */}
  <Badge variant="blue" type="outline">
    Outlined
  </Badge>

  {/* With icons */}
  <Badge variant="success">
    <span className="mr-1">✔</span>
    Success with Icon
  </Badge>
</div>
```

| Prop       | Type                                                                         | Default     | Description                                                   |
| ---------- | ---------------------------------------------------------------------------- | ----------- | ------------------------------------------------------------- |
| `variant`  | `"primary" \| "success" \| "warning" \| "error" \| "secondary" \| "neutral"` | `"primary"` | Color style of the badge.                                     |
| `type`     | `"filled" \| "outline"`                                                      | `"filled"`  | Whether the badge is filled or outlined.                      |
| `children` | `React.ReactNode`                                                            | —           | Content inside the badge (text, icons, avatars, flags, etc.). |

## Divider

The `Divider` component is used to separate content visually.
It supports `vertical` and `horizontal` orientations, with configurable thickness (size) and custom width/height.

```tsx
<div className="flex flex-col gap-4">
  {/* Horizontal Divider */}
  <Divider orientation="horizontal" size={2} />

  {/* Vertical Divider */}
  <div className="flex items-center gap-4">
    <span>Left</span>
    <Divider orientation="vertical" size={2} height={40} />
    <span>Right</span>
  </div>
</div>
```

| Prop          | Type                         | Default        | Description                                                           |
| ------------- | ---------------------------- | -------------- | --------------------------------------------------------------------- |
| `orientation` | `"horizontal" \| "vertical"` | `"horizontal"` | Orientation of the divider.                                           |
| `size`        | `1 \| 2 \| 3 \| 4`           | `1`            | Thickness of the divider (height for horizontal, width for vertical). |
| `color`       | `string`                     | `#D9DAE4`      | Color of the divider line.                                            |

### BreadCrumb

A `breadcrumb` is a navigational element that helps users understand their current location within a website or application. Breadcrumbs enhance user experience by providing a clear path for navigation, allowing users to backtrack easily or move up within the site's hierarchy.

## Usage

```tsx
import {
  Breadcrumb,
  BreadcrumbList,
  BreadcrumbItem,
  BreadcrumbLink,
  BreadcrumbPage,
  BreadcrumbSeparator,
  BreadcrumbEllipsis,
} from '@/components/ui/breadcrumb';

export default function Example() {
  return (
    <Breadcrumb>
      <BreadcrumbList>
        <BreadcrumbItem>
          <BreadcrumbLink href="/">Home</BreadcrumbLink>
        </BreadcrumbItem>
        <BreadcrumbSeparator />
        <BreadcrumbItem>
          <BreadcrumbLink href="/projects">Projects</BreadcrumbLink>
        </BreadcrumbItem>
        <BreadcrumbSeparator />
        <BreadcrumbItem>
          <BreadcrumbPage>Project Alpha</BreadcrumbPage>
        </BreadcrumbItem>
      </BreadcrumbList>
    </Breadcrumb>
  );
}
```

### Props

| Component               | Props                                                                         | Description                                                               |
| ----------------------- | ----------------------------------------------------------------------------- | ------------------------------------------------------------------------- |
| **Breadcrumb**          | All native `nav` props                                                        | Root container with `aria-label="breadcrumb"`.                            |
| **BreadcrumbList**      | `className?` + all native `ol` props                                          | Wrapper for breadcrumb items (`<ol>`). Adds spacing & layout classes.     |
| **BreadcrumbItem**      | `className?` + all native `li` props                                          | Represents each breadcrumb node (`<li>`).                                 |
| **BreadcrumbLink**      | `asChild?: boolean`, `className?`, all native `a` props                       | Renders a link. If `asChild` is true, uses Radix `Slot` instead of `<a>`. |
| **BreadcrumbPage**      | `className?` + all native `span` props                                        | Represents the current page. Adds `aria-current="page"`.                  |
| **BreadcrumbSeparator** | `children?` (defaults to `<ChevronRight />`), `className?`, native `li` props | Separator between items. You can replace with custom icon/text.           |
| **BreadcrumbEllipsis**  | `className?` + all native `span` props                                        | Renders an ellipsis with `MoreHorizontal` icon for collapsed paths.       |

### Stepper

A re-usable stepper component to lead users through multi-step workflows (checkout, sign-up, forms, etc.).
Supports numeric, dots, progress, and labeled versions.

### Example

```tsx
const steps = [
  { title: 'Account Setup' },
  { title: 'Profile Info' },
  { title: 'Preferences' },
  { title: 'Confirmation' },
];

export default function Example() {
  return (
    <div className="space-y-6">
      {/* Numeric */}
      <Stepper steps={steps} variant="numeric" />

      {/* Dots */}
      <Stepper steps={steps} variant="dots" />

      {/* Progress */}
      <Stepper steps={steps} variant="progress" />

      {/* Labeled */}
      <Stepper steps={steps} variant="labeled" />
    </div>
  );
}
```

## Props

| Prop           | Type                     | Default     | Description                        |
| -------------- | ------------------------ | ----------- | ---------------------------------- | ---------- | ----------- | --------------------------- |
| `steps`        | `{ title?: string }[]`   | `[]`        | Steps with optional labels         |
| `variant`      | `"numeric"               | "dots"      | "progress"                         | "labeled"` | `"numeric"` | Visual style of the stepper |
| `initialStep`  | `number`                 | `0`         | Starting step index                |
| `onStepChange` | `(step: number) => void` | `undefined` | Callback when step changes         |
| `showControls` | `boolean`                | `true`      | Show back/next navigation controls |
| `className`    | `string`                 | `undefined` | Additional Tailwind classes        |

### SelectOption

A custom dropdown supporting single, multi(with chips), and grouped selections. Built with React and Tailwind CSS.

### Usage

```tsx
import { useState } from 'react';
import { SelectOption } from '@/components/select-option';

const options = [
  { label: 'Option 1', value: 'opt1' },
  { label: 'Option 2', value: 'opt2' },
];

export default function Demo() {
  const [single, setSingle] = useState('');
  const [multi, setMulti] = useState<string[]>([]);

  return (
    <>
      <SelectOption
        options={options}
        value={single}
        onChange={(val) => setSingle(val as string)}
        placeholder="Single select"
      />

      <SelectOption
        options={options}
        multiple
        value={multi}
        onChange={(val) => setMulti(val as string[])}
        placeholder="Multi select"
      />
    </>
  );
}
```

### Props

| Prop          | Type                                      | Default       | Description                                |
| ------------- | ----------------------------------------- | ------------- | ------------------------------------------ |
| `options`     | `SelectOptionType[] \| SelectGroupType[]` | required      | List of options (flat or grouped)          |
| `multiple`    | `boolean`                                 | `false`       | Enables multi-select with chips            |
| `placeholder` | `string`                                  | `"Select..."` | Placeholder text when no value is selected |
| `disabled`    | `boolean`                                 | `false`       | Disables the select                        |
| `error`       | `string`                                  | `undefined`   | Error message, highlights border           |
| `helperText`  | `string`                                  | `undefined`   | Helper text shown below the select         |
| `value`       | `string \| string[]`                      | internal      | Controlled value                           |
| `onChange`    | `(value: string \| string[]) => void`     | optional      | Callback when value changes                |

### TypeScript

Full TypeScript support is included. No additional types package needed.

## Building

```tsx
bash
# Build for production
pnpm build

# Build types
pnpm build:types

# Build Storybook
pnpm build-storybook
```

Made with ❤️ by the BusyFile team