---
name: getting-started
description: >
  Set up @loke/design-system in a new app. Install @loke/design-system,
  @loke/icons, @loke/ui. Configure Tailwind v4 with @theme block, :root
  CSS variables, @source directive pointing to the design system package.
  Add TooltipProvider. Set up .dark class dark mode. Granular subpath
  imports from @loke/design-system/<component>. Import stylesheet via
  @loke/design-system/styles. Activate when setting up or configuring the
  design system in a new or existing project.
type: lifecycle
library: '@loke/design-system'
library_version: '2.0.0-rc.6'
sources:
  - 'LOKE/merchant-frontends:packages/design-system/package.json'
  - 'LOKE/merchant-frontends:packages/design-system/src/styles/index.css'
  - 'LOKE/merchant-frontends:packages/design-system/src/styles/theme.css'
  - 'LOKE/merchant-frontends:packages/design-system/build.ts'
  - 'LOKE/merchant-frontends:packages/design-system/CHANGELOG.md'
  - 'LOKE/merchant-frontends:apps/office/src/styles.css'
---

## Setup

### 1. Install packages

```bash
bun add @loke/design-system @loke/icons @loke/ui
```

### 2. Configure Tailwind CSS

Create or update your app's CSS entry point. The consumer must duplicate the `@theme` block and `:root`/`.dark` variables, then add an `@source` directive pointing to the design system package so Tailwind v4 does not purge DS classes.

```css
/* src/styles.css */
@import "tailwindcss";

@plugin "tailwindcss-animate";

/* Point Tailwind at the DS package so its classes are not purged */
@source "../../../packages/design-system";  /* monorepo path -- see note below */

@custom-variant dark (&:is(.dark *));

@theme inline {
  --color-background: var(--background);
  --color-foreground: var(--foreground);
  --font-sans: var(--font-sans);
  --font-mono: var(--font-mono);
  --color-sidebar-ring: var(--sidebar-ring);
  --color-sidebar-border: var(--sidebar-border);
  --color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
  --color-sidebar-accent: var(--sidebar-accent);
  --color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
  --color-sidebar-primary: var(--sidebar-primary);
  --color-sidebar-foreground: var(--sidebar-foreground);
  --color-sidebar: var(--sidebar);
  --color-chart-5: var(--chart-5);
  --color-chart-4: var(--chart-4);
  --color-chart-3: var(--chart-3);
  --color-chart-2: var(--chart-2);
  --color-chart-1: var(--chart-1);
  --color-ring: var(--ring);
  --color-input: var(--input);
  --color-border: var(--border);
  --color-destructive-foreground: var(--destructive-foreground);
  --color-destructive: var(--destructive);
  --color-accent-foreground: var(--accent-foreground);
  --color-accent: var(--accent);
  --color-muted-foreground: var(--muted-foreground);
  --color-muted: var(--muted);
  --color-secondary-foreground: var(--secondary-foreground);
  --color-secondary: var(--secondary);
  --color-primary-foreground: var(--primary-foreground);
  --color-primary: var(--primary);
  --color-popover-foreground: var(--popover-foreground);
  --color-popover: var(--popover);
  --color-card-foreground: var(--card-foreground);
  --color-card: var(--card);
  --radius-sm: calc(var(--radius) - 4px);
  --radius-md: calc(var(--radius) - 2px);
  --radius-lg: var(--radius);
  --radius-xl: calc(var(--radius) + 4px);

  --animate-accordion-down: accordion-down 0.2s ease-out;
  --animate-accordion-up: accordion-up 0.2s ease-out;

  @keyframes accordion-down {
    from { height: 0; }
    to { height: var(--loke-accordion-content-height); }
  }
  @keyframes accordion-up {
    from { height: var(--loke-accordion-content-height); }
    to { height: 0; }
  }
}

:root {
  --background: oklch(96.47% 0.0167 274.82);
  --foreground: oklch(27.73% 0.0061 258.36);
  --card: oklch(99.16% 0.0029 247.85);
  --card-foreground: oklch(37.39% 0.0822 285.49);
  --popover: oklch(99.16% 0.0029 247.85);
  --popover-foreground: oklch(37.1% 0.0722 285.35);
  --primary: oklch(51.4% 0.2276 276.98);
  --primary-foreground: oklch(99.17% 0.0028 325.6);
  --secondary: oklch(72.29% 0.1438 163.11);
  --secondary-foreground: oklch(99.78% 0.0068 115.7);
  --muted: oklch(96.71% 0.0029 264.54);
  --muted-foreground: oklch(55.13% 0.0233 264.36);
  --accent: oklch(96.71% 0.0029 264.54);
  --accent-foreground: oklch(21.03% 0.0318 264.65);
  --destructive: oklch(58.52% 0.18 24.61);
  --destructive-foreground: oklch(98.48% 0.0213 193.18);
  --border: oklch(90.58% 0.013831 272.4947);
  --input: oklch(87.53% 0.0142 268.67);
  --ring: oklch(74.83% 0.1308 254.23);
  --radius: 0.5rem;

  --chart-1: oklch(0.62 0.15 162);
  --chart-2: oklch(0.58 0.14 198);
  --chart-3: oklch(0.62 0.16 53);
  --chart-4: oklch(0.58 0.22 285);
  --chart-5: oklch(0.58 0.22 16);

  --sidebar-ring: oklch(74.83% 0.1308 254.23);
  --sidebar-border: oklch(28.01% 0.0249 258.35);
  --sidebar-accent-foreground: oklch(72.47% 0.1495 160.94);
  --sidebar-accent: oklch(28.01% 0.0249 258.35);
  --sidebar-foreground: oklch(95.05% 0.0041 286.32);
  --sidebar: oklch(21.03% 0.0316 264.78);

  --brand-50: oklch(96% 0.04 276.98);
  --brand-100: oklch(92% 0.08 276.98);
  --brand-200: oklch(83% 0.13 276.98);
  --brand-300: oklch(74% 0.18 276.98);
  --brand-400: oklch(63% 0.21 276.98);
  --brand-500: oklch(51.4% 0.2276 276.98);
  --brand-600: oklch(42% 0.2 276.98);
  --brand-700: oklch(33% 0.17 276.98);
  --brand-800: oklch(24% 0.13 276.98);
  --brand-900: oklch(15% 0.09 276.98);
  --brand-950: oklch(5% 0.05 276.98);
}

.dark {
  --background: oklch(15% 0.02 274.82);
  --foreground: oklch(90% 0.01 258.36);
  --card: oklch(20% 0.01 247.85);
  --card-foreground: oklch(85% 0.04 283.75);
  --popover: oklch(18% 0.015 247.85);
  --popover-foreground: oklch(92% 0.07 285.35);
  --primary: oklch(60% 0.25 276.98);
  --primary-foreground: oklch(15% 0.01 325.6);
  --secondary: oklch(55% 0.16 163.11);
  --secondary-foreground: oklch(15% 0.02 115.7);
  --muted: oklch(25% 0.01 264.54);
  --muted-foreground: oklch(75% 0.03 264.36);
  --accent: oklch(30% 0.05 264.54);
  --accent-foreground: oklch(95% 0.04 264.65);
  --destructive: oklch(60% 0.22 24.61);
  --destructive-foreground: oklch(15% 0.02 193.18);
  --border: oklch(30% 0.02 272.49);
  --input: oklch(28% 0.02 268.67);
  --ring: oklch(65% 0.18 254.23);

  --chart-1: oklch(0.70 0.13 162);
  --chart-2: oklch(0.68 0.12 198);
  --chart-3: oklch(0.68 0.14 53);
  --chart-4: oklch(0.66 0.18 285);
  --chart-5: oklch(0.65 0.19 16);

  --sidebar-ring: oklch(65% 0.18 254.23);
  --sidebar-border: oklch(28.01% 0.0249 258.35);
  --sidebar-accent-foreground: oklch(55% 0.16 163.11);
  --sidebar-accent: oklch(28.01% 0.0249 258.35);
  --sidebar-foreground: oklch(97% 0.01 286.32);
  --sidebar: oklch(20% 0.01 247.85);
}

@layer base {
  * {
    @apply border-border outline-ring/50;
  }
  body {
    @apply bg-background text-foreground;
  }
  button {
    @apply cursor-pointer;
  }
}
```

### 3. Import the stylesheet and add TooltipProvider

Import the DS stylesheet at your app entry point and wrap your tree with `TooltipProvider`.

```tsx
// src/main.tsx (or app entry)
import "@loke/design-system/styles";
import { TooltipProvider } from "@loke/design-system/tooltip";

export default function App() {
  return (
    <TooltipProvider>
      {/* your app */}
    </TooltipProvider>
  );
}
```

---

## Core Patterns

### Subpath imports

Every component lives at its own subpath. There is no barrel export.

```tsx
import { Button } from "@loke/design-system/button";
import { Input } from "@loke/design-system/input";
import { Dialog, DialogContent, DialogTitle } from "@loke/design-system/dialog";
import { cn } from "@loke/design-system/cn";
import { Badge } from "@loke/design-system/badge";
import { Tooltip, TooltipContent, TooltipTrigger } from "@loke/design-system/tooltip";
```

Full list of available subpaths (from `package.json` exports):

`accordion` `alert` `alert-dialog` `avatar` `badge` `box` `button` `calendar`
`card` `checkbox` `cn` `collapsible` `columns` `command` `date-picker` `dialog`
`dropdown-menu` `form` `heading` `inline` `input` `label` `max-width-wrapper`
`page-layout` `pagination` `popover` `radio-group` `responsive` `select`
`separator` `sheet` `sidebar` `skeleton` `slot` `spinner` `stack` `switch`
`table` `tabs` `text` `textarea` `toast` `tooltip` `use-mobile`

### Stylesheet import

```ts
import "@loke/design-system/styles";
```

Import once at the app entry point, before any component imports.

### Dark mode

Dark mode is class-based. Toggle by adding/removing the `dark` class on `<html>` or `<body>`.

```ts
document.documentElement.classList.toggle("dark");
```

The Tailwind custom variant is configured as:

```css
@custom-variant dark (&:is(.dark *));
```

This means any element inside a `.dark` ancestor gets dark styles applied.

### @source directive

**Monorepo (workspace package):**

```css
@source "../../../packages/design-system";
```

**External npm dependency:**

```css
@source "../node_modules/@loke/design-system";
```

Adjust the relative path to match your app's location relative to the DS package root.

---

## Common Mistakes

### 1. CRITICAL: Importing from barrel path instead of subpath

```tsx
// Wrong -- no barrel export exists
import { Button } from "@loke/design-system";

// Correct
import { Button } from "@loke/design-system/button";
```

### 2. CRITICAL: Using shadcn-style import paths

```tsx
// Wrong -- this is a shadcn/ui pattern, not used here
import { Button } from "@/components/ui/button";

// Correct
import { Button } from "@loke/design-system/button";
```

### 3. CRITICAL: Missing stylesheet import

```tsx
// Wrong -- components render unstyled
import { Button } from "@loke/design-system/button";

// Correct -- import the stylesheet once at app entry
import "@loke/design-system/styles";
import { Button } from "@loke/design-system/button";
```

### 4. HIGH: Using overlay components in server components

```tsx
// Wrong -- Dialog, Popover, Tooltip, Sheet etc. use browser APIs
// app/page.tsx (React Server Component)
import { Dialog } from "@loke/design-system/dialog";
export default function Page() {
  return <Dialog>...</Dialog>; // runtime error
}
```

```tsx
// Correct -- add "use client" boundary
// app/components/my-dialog.tsx
"use client";

import { Dialog, DialogContent, DialogTrigger } from "@loke/design-system/dialog";

export function MyDialog() {
  return (
    <Dialog>
      <DialogTrigger>Open</DialogTrigger>
      <DialogContent>Content</DialogContent>
    </Dialog>
  );
}
```

```tsx
// app/page.tsx
import { MyDialog } from "./components/my-dialog";

export default function Page() {
  return <MyDialog />;
}
```

### 5. HIGH: Importing primitives from @loke/design-system instead of @loke/ui

```tsx
// Wrong -- arrow, focus-scope, popper, portal, presence, roving-focus
// are internal primitives not exported from @loke/design-system
import { Presence } from "@loke/design-system/presence";
import { FocusScope } from "@loke/design-system/focus-scope";
import { Portal } from "@loke/design-system/portal";

// Correct -- primitives live in @loke/ui
import { Presence } from "@loke/ui/presence";
import { FocusScope } from "@loke/ui/focus-scope";
import { Portal } from "@loke/ui/portal";
```

> Fixed in v2.0.0-rc.5. Agents trained on older code may still generate this pattern.

### 6. HIGH: Hallucinating @radix-ui/react-* imports

```tsx
// Wrong -- @radix-ui packages are internal deps, not consumer-facing
import * as DialogPrimitive from "@radix-ui/react-dialog";
import * as PopoverPrimitive from "@radix-ui/react-popover";

// Correct -- use the DS exports directly
import { Dialog, DialogContent, DialogTrigger } from "@loke/design-system/dialog";
import { Popover, PopoverContent, PopoverTrigger } from "@loke/design-system/popover";
```

### 7. HIGH: Missing @source directive in consumer Tailwind CSS

```css
/* Wrong -- DS utility classes get purged at build time */
@import "tailwindcss";

@theme inline {
  /* ... */
}
```

```css
/* Correct -- monorepo */
@import "tailwindcss";
@source "../../../packages/design-system";

@theme inline {
  /* ... */
}
```

```css
/* Correct -- external npm */
@import "tailwindcss";
@source "../node_modules/@loke/design-system";

@theme inline {
  /* ... */
}
```

---

## See also

- `theming/SKILL.md` -- customizing colors and dark mode tokens
- `overlay-composition/SKILL.md` -- overlays require "use client" and TooltipProvider
