Files

@cherrystudio/ui

Cherry Studio UI component library for React applications.

Features

  • 🎨 Design System: Full Cherry Studio design tokens with 17 color families, 11 shades, and semantic theme mappings
  • 🌓 Dark Mode: Built-in light and dark theme support
  • 🚀 Tailwind v4: Built on top of the latest Tailwind CSS v4
  • 📦 Flexible Imports: Two style integration modes for different adoption paths
  • 🔷 TypeScript: Complete type definitions and editor support
  • 🎯 Low Collision: CSS variable isolation without taking over app runtime state by default

🚀 Quick Start

Install

npm install @cherrystudio/ui
# peer dependencies
npm install motion react react-dom tailwindcss

The recommended integration style in this repository is to use the package export entry points: @cherrystudio/ui @cherrystudio/ui/components @cherrystudio/ui/icons @cherrystudio/ui/utils @cherrystudio/ui/styles/*

Two Integration Modes

Mode 1: Full Theme Contract

Use the full Cherry Studio design system so Tailwind theme tokens resolve to Cherry Studio values.

/* app.css */
@import '@cherrystudio/ui/styles/theme.css';

Characteristics:

  • Use standard Tailwind utility names directly (bg-primary, bg-red-500, p-md, rounded-lg)
  • Colors resolve to Cherry Studio design values
  • Includes the extended spacing scale (p-5xs through p-8xl, 16 semantic sizes)
  • Includes the extended radius scale (rounded-4xs through rounded-3xl, plus rounded-round)
  • ⚠️ Overrides the default Tailwind theme contract for the imported app bundle

Example:

<Button className="bg-primary text-red-500 p-md rounded-lg">
  {/* bg-primary -> Cherry Studio brand color */}
  {/* text-red-500 -> Cherry Studio red-500 */}
  {/* p-md -> semantic spacing token */}
  {/* rounded-lg -> semantic radius token */}
</Button>

{/* Extended utility classes */}
<div className="p-5xs">Tiny spacing (0.5rem)</div>
<div className="p-xs">Extra small spacing (1rem)</div>
<div className="p-sm">Small spacing (1.5rem)</div>
<div className="p-md">Medium spacing (2.5rem)</div>
<div className="p-lg">Large spacing (3.5rem)</div>
<div className="p-xl">Extra large spacing (5rem)</div>
<div className="p-8xl">Maximum spacing (15rem)</div>

<div className="rounded-4xs">Tiny radius (0.03125rem)</div>
<div className="rounded-xs">Small radius (0.125rem)</div>
<div className="rounded-md">Medium radius (0.5rem)</div>
<div className="rounded-xl">Large radius (0.875rem)</div>
<div className="rounded-round">Full radius (999px)</div>

Mode 2: Selective Token Consumption 🎯

Import only the design tokens and decide which theme mappings your app wants to expose.

/* app.css */
@import 'tailwindcss';
@import '@cherrystudio/ui/styles/tokens.css';

/* Re-export only the parts you need */
@theme {
  --color-primary: var(--cs-primary); /* Use the Cherry Studio primary color */
  --color-red-500: oklch(...); /* Keep your own red scale */
  --spacing-md: var(--cs-size-md); /* Reuse Cherry Studio spacing */
  --radius-lg: 1rem; /* Keep your own radius */
}

Characteristics:

  • Does not override the full Tailwind theme
  • Gives access to all Cherry Studio design tokens through CSS variables (var(--cs-primary), var(--cs-red-500))
  • Lets you choose what to adopt and what to keep
  • Works well when you already have a design system and only want selected Cherry Studio tokens

Example:

{/* Use Cherry Studio tokens directly via CSS variables */}
<button style={{ backgroundColor: 'var(--cs-primary)' }}>
  Use the Cherry Studio brand color
</button>

{/* Keep your original Tailwind theme untouched */}
<div className="bg-red-500">
  Use the default Tailwind red
</div>

{/* Available CSS variables */}
<div
  style={{
    color: 'var(--cs-primary)', // Brand color
    backgroundColor: 'var(--cs-red-500)', // Red-500
    padding: 'var(--cs-size-md)', // Spacing
    borderRadius: 'var(--cs-radius-lg)', // Radius
  }}
/>

CSS Variable Rules

To avoid mixing tokens, theme mappings, and runtime overrides, use the following rules:

  1. --cs-* is the design token namespace, sourced from tokens/*
  2. --color-*, --radius-*, and --font-* are public theme contracts and should be the default choice for components and external consumers
  3. --cs-theme-* is a runtime override input and should only be used for controlled runtime overrides
  4. --primary is a compatibility alias kept for shadcn / Tailwind ecosystem compatibility and should not be preferred in new code

Default consumption rules:

  1. Regular application packages should depend on @cherrystudio/ui/styles/theme.css by default
  2. Regular application packages should prefer public contracts such as --color-* and should not bind directly to primitive tokens like --cs-brand-500
  3. Only design-system-adjacent packages that explicitly need token-level access should depend on @cherrystudio/ui/styles/tokens.css
  4. Runtime theme logic should only write to controlled entry variables such as --cs-theme-*, not directly to derived --color-* variables

Usage

Basic Components

import { Button, Input } from '@cherrystudio/ui'

function App() {
  return (
    <div>
      <Button variant="primary" size="md">Click me</Button>
      <Input
        type="text"
        placeholder="Type here"
        onChange={(value) => console.log(value)}
      />
    </div>
  )
}

Modular Imports

// Components only
import { Button } from '@cherrystudio/ui/components'

// Utilities only
import { cn, formatFileSize } from '@cherrystudio/ui/utils'

Development

# Install dependencies
pnpm install

# Development mode
pnpm dev

# Build
pnpm build

# Type check
pnpm type-check

# Run tests
pnpm test

Package Surface

The packages/ui workspace contains both runtime code and development-only assets.

  • Runtime surface:
    • src/
    • dist/ build output
    • package export entry points declared in package.json
  • Development assets:
    • stories/ and .storybook/
    • scripts/ used for icon and theme generation
    • icons/ source assets used by the generation pipeline
    • docs/ for migration and reference material

Only the runtime surface should be treated as consumable package API.

Directory Structure

docs/                    # Migration plans and reference docs
src/
├── components/
│   ├── primitives/     # Primitive components
│   ├── composites/     # Composite components
│   ├── icons/          # Icon runtime exports and catalogs
│   └── index.ts
├── hooks/              # React Hooks
├── lib/                # Internal utilities
├── styles/             # Tokens and theme entry files
├── utils/              # Utility functions
└── index.ts            # Main runtime entry point
scripts/                # Theme and icon generation tooling
stories/                # Storybook stories and sandbox usage
icons/                  # Raw icon assets for code generation

Naming Conventions

All file and directory names under packages/ui/ follow kebab-case (per shadcn CLI convention and project-wide rule §4.5 in ../../docs/references/naming-conventions.md). This covers primitives/, composites/, icons/, hooks/, and stories/ alike. Exported identifiers inside files remain PascalCase for components and camelCase for utilities and hooks.

Examples:

  • button.tsx exports Button
  • data-table.tsx exports DataTable
  • error-boundary/index.tsx exports ErrorBoundary
  • use-dnd-reorder.ts exports useDndReorder

Components

Button

A button component with multiple variants and sizes.

Props:

  • variant: 'primary' | 'secondary' | 'outline' | 'ghost' | 'danger'
  • size: 'sm' | 'md' | 'lg'
  • loading: boolean
  • fullWidth: boolean
  • leftIcon / rightIcon: React.ReactNode

Input

An input component with error handling and password visibility support.

Props:

  • type: 'text' | 'password' | 'email' | 'number'
  • error: boolean
  • errorMessage: string
  • onChange: (value: string) => void

Hooks

useDebounce

Debounces state updates or callback execution.

useLocalStorage

React hook wrapper for local storage.

useClickOutside

Detects clicks outside an element.

useCopyToClipboard

Copies text to the clipboard.

Utilities

cn(...inputs)

Class name merge helper built on top of clsx.

formatFileSize(bytes)

Formats byte sizes into readable strings.

debounce(func, delay)

Debounce helper.

throttle(func, delay)

Throttle helper.

License

MIT