# 7onic Design System — AI Guide (Full)
## What is 7onic?
Token-driven React design system with 42 components on Radix UI.
Single source of truth — design tokens to code. Use this to build any React service.
- Documentation: https://7onic.design
- npm: `@7onic-ui/react` (components) + `@7onic-ui/tokens` (design tokens)
- For tokens-only guide, see: https://7onic.design/llms.txt
---
# ═══ SECTION 1: PROJECT SETUP & AI RULES ═══
## How to Start
### Step 1: Ask the user (setup checklist)
Before writing any code, present this checklist and wait for answers:
1. **Framework** — Next.js / Vite (React SPA) / Remix / other?
2. **Dark mode** — Yes or no?
3. **Font** — Use default, or custom font? If custom, which font?
4. **Locale** — Which language(s)? (for CJK font loading)
5. **What are you building?** — Describe the project
**If the user answers in natural language** (e.g., "Make me a dashboard with dark mode, English only"), extract the answers from their message. **If any item is missing, ask a follow-up question for the missing items only.** Do not proceed until all 5 items are answered.
### Step 2: Install / Setup
⚠️ **DO NOT GUESS** — install procedures evolve with each Tailwind / Next / Vite version. Before writing any code, AI **MUST** fetch the live pages below and follow their instructions verbatim:
- **Official install page (SSOT)**: https://7onic.design/components/installation
- **Tailwind CSS official**: https://tailwindcss.com/docs/installation
The install instructions are intentionally **not duplicated in this file**. Setup details (packages, `tailwind.config.js`, `vite.config.ts`, `postcss.config.mjs`, `globals.css` patterns, framework default cleanup, layer wrap tips, etc.) are version-sensitive and change frequently — always defer to the live documentation above.
Apply user's answers from Step 1 after the install page steps are complete:
- Dark mode = yes → implement dark mode toggle (see below in this file)
- Custom font → load via `next/font/google` (Next.js) or Fontsource / CDN (Vite)
- Japanese / Korean locale → load Noto Sans JP / KR
⛔ **Do NOT proceed to Step 3 until install page setup is verified.**
### Icon Import Pattern (lucide-react)
⚠️ **`lucide-react` is NOT a 7onic dependency.** 7onic components themselves use inline SVG. Install separately if you want to use lucide icons in your app code:
```bash
npm install lucide-react
```
```tsx
// ✅ Official pattern — no suffix
import { Search, Settings, ChevronDown, X } from 'lucide-react'
// ❌ Legacy alias — avoid
import { SearchIcon, SettingsIcon } from 'lucide-react'
// ⚠️ Name collision with 7onic component — use alias
import { Badge } from '@7onic-ui/react'
import { Badge as BadgeIcon } from 'lucide-react'
```
### Step 3: Add Toaster to root layout (if using Toast)
Place ` ` once in your root layout file. Without this, `toast()` calls will not render.
```tsx
import { Toaster } from '@7onic-ui/react'
// In your root layout (e.g., app/layout.tsx)
{children}
```
### Step 4: Start building
Design freely based on user's project description. Always use 7onic components + tokens.
### Component Dependencies (auto-install during development)
| Component | Additional Package | When to install |
|---|---|---|
| Chart (Bar, Line, Area, Pie) | `recharts` | `npm install recharts` — import from `@7onic-ui/react/chart` (separate entry point) |
---
## ⛔ AI Rules — Whitelist System
### Core Principle
**Token values are user-defined.** Every project has different brand colors and design decisions. The token NAMES are the API — never assume or hardcode specific values.
### Whitelist — ONLY These Are Allowed
1. **7onic components + Props** — always prefer components over raw HTML
2. **Token classes** — colors, spacing, typography, radius, shadows, z-index, icon sizes, duration, easing, opacity, scale
3. **Tailwind structural utilities** — layout, positioning, display, overflow, sizing, and more:
- Layout: flex, grid, block, inline, hidden, container
- Position: relative, absolute, fixed, sticky, top-0, inset-0
- Flex/Grid: items-center, justify-between, gap-4, col-span-2
- Sizing: w-full, h-full, min-h-screen, max-w-7xl
- Spacing: space-x-*, space-y-*, divide-x, divide-y
- Overflow: overflow-hidden, overflow-auto, truncate, whitespace-nowrap
- Interaction: cursor-pointer, pointer-events-none, select-none
- Accessibility: sr-only
- Group/Peer: group, group-hover:*, peer, peer-checked:*
- Aspect: aspect-square, aspect-video
- Text: line-clamp-*, text-ellipsis
- Animation: animate-spin, animate-pulse, animate-bounce
- Any other Tailwind structural/layout utility not listed above is also allowed — as long as it does not hardcode colors, spacing values, font sizes, or other visual values that exist as tokens
- ⚠️ Utilities that implicitly use color (divide, border) must be paired with a token color:
`divide-y divide-border` ✅ / `divide-y` alone ❌ (may not adapt to dark mode)
`border border-border` ✅ / `border` alone ❌
4. **Tailwind visual utilities using token values** — gradients, transforms, transitions:
- Gradient: bg-gradient-to-r, from-primary, to-secondary (token colors only)
- Transform: rotate-45, translate-x-1
- Transition: transition-all, transition-colors (with token durations)
- Backdrop: backdrop-blur, backdrop-blur-sm
5. **Responsive prefixes** — sm:, md:, lg:, xl:, 2xl: (on allowed classes only)
6. **State prefixes** — hover:, focus:, active:, disabled: (on allowed classes only, token values only)
7. **Layout dimension arbitrary values** — height and width ONLY: h-[300px], max-w-[1200px] (when no token fits)
8. **Opacity modifier** — append `/0-100` to any token color for transparency:
- `bg-primary/50`, `text-foreground/70`, `border-border/30`
- Do NOT use `opacity-*` utility as a workaround — it affects the entire element including children
- `bg-primary/10` ✅ (only background is transparent) / `bg-primary opacity-10` ❌ (children also become transparent)
9. **Token-first rule** — Before adding any Tailwind utility, check if the property is already included in a design token. Typography tokens (`text-sm`, `text-md`, etc.) include both font-size AND line-height as a pair. Do NOT override with Tailwind line-height utilities:
- `text-sm` ✅ (token provides font-size + line-height)
- `text-sm leading-relaxed` ❌ (overrides token line-height)
- `text-sm leading-none` ❌ (overrides token line-height)
- `text-sm leading-[18px]` ❌ (hardcodes line-height)
**Everything not in this list is FORBIDDEN.**
⚠️ **Gradient/visual utilities must use token colors only:** `from-primary to-secondary` ✅ / `from-blue-500 to-purple-600` ❌
### Decision Tree — For Every UI Element
```
Step 1: Does a 7onic component exist for this?
→ YES: Use the component. Style via Props (variant/size/color).
className ONLY for layout (margin, width, flex positioning).
→ NO: Step 2
Step 2: Is this a layout/structural element? (flex container, grid, section wrapper)
→ YES: Use div/section + token classes only.
→ NO: Step 3
Step 3: Re-check the 42 components. Most UI can be built with component combinations.
→ Still no match: Use div + token classes only.
```
### ❌ Forbidden Patterns
```tsx
// ❌ HTML instead of components
→
→
→
→
// ❌ className overriding component styles
→
→
// ❌ Raw Tailwind colors
bg-blue-500, text-gray-700, bg-white, border-gray-200
// ❌ Dark mode prefix
dark:bg-gray-900, dark:text-white
// ❌ Arbitrary values (except layout dimensions)
p-[17px], text-[13px], rounded-[7px], z-[999]
// ❌ Inline styles
style={{ color: '#333', padding: '20px' }}
// ❌ @apply with raw values
@apply bg-blue-500
// ❌ Icon sizing with w/h
w-4 h-4, w-5 h-5 → icon-sm, icon-md
// ❌ Radix direct import
import * as Dialog from '@radix-ui/react-dialog' → import { Badge, Button, Card, Input, Table } from '@7onic-ui/react'
// ❌ Unnecessary component wrappers
function MyButton(props) { return } → Use Button directly
```
### When User Requests Custom Values
If the user explicitly asks for a value outside the token system:
```
User: "Change this background to #FF5733"
AI: "This color is not in the token system.
Apply this custom value bypassing the tokens?
Or I can use an existing token (bg-primary, bg-error, etc.)."
User: "Apply it"
AI: → Apply the custom value
```
| Situation | AI Behavior |
|---|---|
| User request within token range | Execute immediately |
| User request outside token range | Ask "bypass tokens?" → execute after confirmation |
| AI writing code on its own | Token system ONLY — never bypass |
### Third-Party Libraries
When a feature is needed that no 7onic component covers (map, video player, rich text editor, etc.):
- **Do NOT install any library without asking the user first**
- Ask: "Which library would you like to use for [feature]?"
- Install and use only after user's choice
### Token Customization Is the User's Responsibility
The token system covers all UI needs out of the box. As AI, use existing tokens only.
If the user needs custom values beyond existing tokens, they will handle it separately.
Customization guide: https://7onic.design/components/theming
**Never modify generated token files** — these are auto-generated from figma-tokens.json via sync-tokens. AI must never edit, add to, or delete from: `variables.css`, `light.css`, `dark.css`, `v3-preset.js`, `v4-theme.css`, `index.js`, `index.mjs`, `index.d.ts`, `tokens.json`
### Self-Check (after writing ANY code)
Before presenting code to the user, scan your own output for violations:
- [ ] Any raw color class? (`bg-blue-*`, `text-gray-*`, `bg-white`, `border-gray-*`)
- [ ] Any arbitrary value? (`p-[*]`, `text-[*]`, `rounded-[*]`, `z-[*]`)
- [ ] Any inline style? (`style={{ }}`)
- [ ] Any `dark:` prefix?
- [ ] Any `w-N h-N` for icons instead of `icon-*`?
- [ ] Any ``, ` `, `` instead of 7onic components?
- [ ] Any Radix direct import?
- [ ] Any className overriding component visual styles?
- [ ] Any `divide-*` or `border` without a token color? (`divide-y` alone → `divide-y divide-border`)
- [ ] Any `opacity-*` on element instead of color modifier? (`bg-primary opacity-10` → `bg-primary/10`)
**If ANY violation is found → fix it before showing code to the user.**
**Do NOT present code with violations. Fix first, then present.**
---
**When in doubt, check the documentation** — if component Props, token usage, or patterns are unclear, refer to the official docs before guessing:
- Component pages: `https://7onic.design/components/{name}` (e.g., `/components/button`, `/components/navigation-menu`)
- Token pages: `https://7onic.design/design-tokens/{name}` (e.g., `/design-tokens/colors`, `/design-tokens/spacing`)
- Do not guess — verify from documentation first
---
## Dark Mode — Automatic
Dark mode works automatically when using semantic tokens. No `dark:` prefix needed.
| ❌ NEVER | ✅ CORRECT |
|---|---|
| `bg-white dark:bg-gray-900` | `bg-background` |
| `text-gray-900 dark:text-gray-100` | `text-foreground` |
| `border-gray-200 dark:border-gray-700` | `border-border` |
### Dark Mode Toggle Implementation
Strategy: `dark` class on `` element.
**Required behavior:**
1. Toggle adds/removes `dark` class on ``
2. Persist choice to localStorage (key: `"theme"`)
3. On page load: check localStorage first → fallback to system preference
4. System preference: `window.matchMedia('(prefers-color-scheme: dark)')`
**Three states:** `'light'` | `'dark'` | `'system'`
**Minimal logic:**
- Read: `localStorage.getItem('theme') || 'system'`
- Apply: `document.documentElement.classList.toggle('dark', isDark)`
- Save: `localStorage.setItem('theme', newTheme)`
**Add a toggle button in the header** that cycles through light → dark → system (or light ↔ dark).
---
## Token Reference (Quick)
> Token values depend on the user's project configuration. Never assume specific hex values.
**Semantic Colors (theme-aware):**
- Background: `background`, `background-paper`, `background-elevated`, `background-muted`
- Text: `foreground`, `text-muted`, `text-subtle`, `text-link`, `text-primary`
- Status text: `text-info`, `text-success`, `text-error`, `text-warning`
- Intent (×6): `{intent}`, `{intent}-hover`, `{intent}-active`, `{intent}-tint`, `{intent}-foreground` — where intent = primary, secondary, success, warning, error, info
- Border: `border`, `border-subtle`, `border-strong`
- State: `disabled`, `disabled-text`, `focus-ring`, `focus-ring-error`
**Spacing:** 0, 0.5(2px), 1(4px), 1.5(6px), 2(8px), 2.5(10px), 3(12px), 3.5(14px), 4(16px), 5(20px), 6(24px), 7(28px), 8(32px), 10(40px), 12(48px), 14(56px), 16(64px), 20(80px), 24(96px)
**Font:** `font-sans` (user-defined), `font-mono` (user-defined)
**Font Sizes:** text-2xs(11px), text-xs(12px), text-sm(13px), text-md(14px), text-base(16px), text-lg(18px), text-xl(20px), text-2xl(24px), text-3xl(30px), text-4xl(36px), text-5xl(48px)
**Font Weights:** font-normal(400), font-semibold(600), font-bold(700)
**Radius:** rounded-none(0), rounded-sm(2), rounded-base(4), rounded-md(6), rounded-lg(8), rounded-xl(12), rounded-2xl(16), rounded-3xl(24), rounded-full(9999)
**Shadows:** shadow-xs, shadow-sm, shadow-md, shadow-lg, shadow-xl
**Z-Index:** z-sticky(100), z-dropdown(1000), z-overlay(1100), z-modal(2000), z-popover(2100), z-tooltip(2200), z-toast(3000)
**Icon Sizes:** icon-2xs(12px), icon-xs(14px), icon-sm(16px), icon-md(20px), icon-lg(24px), icon-xl(32px)
**Duration:** duration-instant(0), duration-fast(100), duration-micro(150), duration-normal(200), duration-slow(300), duration-slower(400), duration-slowest(500), duration-spin(1000)
**Easing:** ease-linear, ease-ease, ease-ease-in, ease-ease-out, ease-ease-in-out
**Opacity:** opacity-0 to opacity-100 (5% increments)
**Scale:** scale-50, scale-75, scale-95, scale-pressed(0.98)
**Breakpoints:** sm(640), md(768), lg(1024), xl(1280), 2xl(1536)
For detailed token reference, see: https://7onic.design/llms.txt
---
# ═══ SECTION 2: COMPONENT IMPORT PATTERNS ═══
## Import
```tsx
// All components from single package
import { Button, Card, Input, toast } from '@7onic-ui/react'
```
## Component Import
All components use Named imports. Works in every environment (Next.js App Router RSC, Client Components, Pages Router, Vite, CRA, CJS).
```tsx
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '@7onic-ui/react'
Title
Description
Content
Footer
```
### Compound Components (24)
Components that provide sub-components. Each sub is a Named export (`CardHeader`, `ModalContent`, `TabsList`, etc.).
Accordion, Alert, Avatar, Breadcrumb, Card, ChatInput, ChatMessage, Chart, Drawer, DropdownMenu, Field, MetricCard, Modal, NavigationMenu, Pagination, Popover, QuickReply, RadioGroup, Segmented, Select, Table, Tabs, ToggleGroup, Tooltip
Prefer dot-notation (``)? See **Compound Recipe** section at end of this document.
### Standalone Components (16)
Badge, Button, ButtonGroup, Checkbox, Divider, IconButton, Input, Progress, Skeleton, Slider, Spinner, Switch, Textarea, Toast, Toggle, TypingIndicator
---
# ═══ SECTION 3: ALL COMPONENTS (42) ═══
---
## Forms
### Button
```tsx
import { Button } from '@7onic-ui/react'
Submit
}>Cancel
Processing...
Learn more
```
| Prop | Type | Default | Description |
|---|---|---|---|
| variant | `'solid' \| 'outline' \| 'ghost' \| 'link'` | `'solid'` | Visual style |
| color | `'default' \| 'primary' \| 'secondary' \| 'destructive'` | `'default'` | Color scheme |
| size | `'xs' \| 'sm' \| 'md' \| 'default' \| 'lg'` | `'default'` | Height: 28/32/36/40/48px |
| radius | `'none' \| 'sm' \| 'base' \| 'default' \| 'lg' \| 'xl' \| '2xl' \| '3xl' \| 'full'` | `'default'` | Border radius |
| loading | `boolean` | `false` | Shows spinner, disables button |
| leftIcon | `ReactNode` | — | Icon before label |
| rightIcon | `ReactNode` | — | Icon after label |
| fullWidth | `boolean` | `false` | `w-full` |
| selected | `boolean` | — | Selected state (outline/ghost) |
| fontWeight | `'normal' \| 'semibold'` | per variant | Override font weight |
| pressEffect | `boolean` | `true` | Scale-down on press |
| asChild | `boolean` | `false` | Render as child element (Slot) |
| disabled | `boolean` | `false` | Disabled state |
**Icon sizing by button size:** xs/sm → icon-xs(14px), md/default/lg → icon-sm(16px)
---
### IconButton
```tsx
import { IconButton } from '@7onic-ui/react'
```
| Prop | Type | Default | Description |
|---|---|---|---|
| variant | `'solid' \| 'outline' \| 'ghost' \| 'subtle'` | `'solid'` | Visual style |
| color | `'default' \| 'primary' \| 'secondary' \| 'destructive'` | `'default'` | Color scheme |
| size | `'xs' \| 'sm' \| 'md' \| 'default' \| 'lg'` | `'default'` | 28/32/36/40/48px (square) |
| radius | Same as Button | `'default'` | Border radius |
| loading | `boolean` | `false` | Shows spinner |
| pressEffect | `boolean` | `true` | Scale-down on press |
| asChild | `boolean` | `false` | Slot pattern |
**Icon sizing:** xs → icon-xs(14px), sm/md → icon-sm(16px), default → icon-md(20px), lg → icon-lg(24px)
**Always provide `aria-label`** — no visible text.
---
### ButtonGroup
```tsx
import { Button, ButtonGroup } from '@7onic-ui/react'
Left
Center
Right
```
| Prop | Type | Default | Description |
|---|---|---|---|
| variant | `'outline' \| 'ghost'` | — | Applied to all children |
| size | Button sizes | — | Applied to all children |
| radius | Button radius values | — | Applied to all children |
| fontWeight | `'normal' \| 'semibold'` | — | Applied to all children |
| orientation | `'horizontal' \| 'vertical'` | `'horizontal'` | Layout direction |
| attached | `boolean` | `true` | Overlapping borders |
| disabled | `boolean` | `false` | Disable all children |
Provides context — child Buttons inherit variant/size/radius automatically.
---
### Input
```tsx
import { Input } from '@7onic-ui/react'
} />
} />
```
| Prop | Type | Default | Description |
|---|---|---|---|
| variant | `'default' \| 'filled'` | `'default'` | Border or filled background |
| size | `'xs' \| 'sm' \| 'default' \| 'lg' \| 'xl'` | `'default'` | Height: 36/40/44/48/56px |
| radius | `'none' \| 'sm' \| 'base' \| 'default' \| 'lg' \| 'xl' \| '2xl' \| '3xl' \| 'full'` | `'default'` | Border radius |
| error | `boolean` | `false` | Error border state |
| focusRing | `boolean` | `false` | Explicit focus ring (vs keyboard-only) |
| leftIcon | `ReactNode` | — | Left icon |
| rightIcon | `ReactNode` | — | Right icon |
**Works with Field wrapper** for label, error, char count. See Field section.
---
### Textarea
```tsx
import { Textarea } from '@7onic-ui/react'
```
| Prop | Type | Default | Description |
|---|---|---|---|
| variant | `'default' \| 'filled'` | `'default'` | Border or filled |
| size | `'compact' \| 'default'` | `'default'` | Padding density |
| radius | Same as Input | `'default'` | Border radius |
| resize | `'none' \| 'vertical' \| 'horizontal' \| 'both'` | `'vertical'` | Resize handle |
| error | `boolean` | `false` | Error state |
| focusRing | `boolean` | `false` | Explicit focus ring |
| rows | `number` | `4` | Initial row count |
---
### Select
```tsx
import { Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectTrigger, SelectValue } from '@7onic-ui/react'
Option A
Option B
Group
Option C
```
| Prop (Root) | Type | Default | Description |
|---|---|---|---|
| size | `'xs' \| 'sm' \| 'default' \| 'lg' \| 'xl'` | `'default'` | Trigger height |
| radius | Same as Input | `'default'` | Border radius |
| value | `string` | — | Controlled value |
| defaultValue | `string` | — | Uncontrolled default |
| onValueChange | `(value: string) => void` | — | Change handler |
**Sub-components:** Select.Trigger, Select.Value, Select.Content, Select.Item, Select.Group, Select.Label, Select.Separator
---
### DropdownMenu
```tsx
import { Button, DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuSeparator, DropdownMenuTrigger } from '@7onic-ui/react'
Options
Edit
Duplicate
Delete
```
| Prop (Content) | Type | Default | Description |
|---|---|---|---|
| radius | `'md' \| 'lg' \| 'xl'` | `'md'` | Border radius |
| size | `'sm' \| 'md' \| 'lg'` | `'md'` | Item density |
| flush | `boolean` | `false` | Full-width items (no padding) |
| sideOffset | `number` | `4` | Gap from trigger |
**Sub-components:** DropdownMenu.Trigger, DropdownMenu.Content, DropdownMenu.Item, DropdownMenu.CheckboxItem, DropdownMenu.RadioItem, DropdownMenu.Label, DropdownMenu.Separator, DropdownMenu.Group, DropdownMenu.Sub, DropdownMenu.SubTrigger, DropdownMenu.SubContent, DropdownMenu.Shortcut
---
### Checkbox
```tsx
import { Checkbox } from '@7onic-ui/react'
```
| Prop | Type | Default | Description |
|---|---|---|---|
| size | `'sm' \| 'default' \| 'lg'` | `'default'` | Checkbox size |
| radius | `'none' \| 'sm' \| 'md'` | `'sm'` | Border radius |
| weight | `'thin' \| 'bold'` | `'bold'` | Checkmark thickness |
| color | `'default' \| 'primary'` | `'default'` | Checked color |
| label | `string` | — | Label text |
| checked | `boolean \| 'indeterminate'` | — | Controlled state |
| defaultChecked | `boolean` | — | Uncontrolled default |
| onCheckedChange | `(checked: boolean \| 'indeterminate') => void` | — | Change handler |
| disabled | `boolean` | `false` | Disabled state |
---
### RadioGroup
```tsx
import { RadioGroup, RadioGroupItem } from '@7onic-ui/react'
```
| Prop (Root) | Type | Default | Description |
|---|---|---|---|
| size | `'sm' \| 'default' \| 'lg'` | `'default'` | Radio size |
| weight | `'thin' \| 'bold'` | `'bold'` | Indicator thickness |
| color | `'default' \| 'primary'` | `'default'` | Selected color |
| orientation | `'horizontal' \| 'vertical'` | `'vertical'` | Layout direction |
| value | `string` | — | Controlled value |
| defaultValue | `string` | — | Uncontrolled default |
| onValueChange | `(value: string) => void` | — | Change handler |
**Sub-components:** RadioGroup.Item (with `label` prop)
---
### Switch
```tsx
import { Switch } from '@7onic-ui/react'
```
| Prop | Type | Default | Description |
|---|---|---|---|
| size | `'sm' \| 'default' \| 'lg'` | `'default'` | Track size |
| color | `'default' \| 'primary' \| 'success' \| 'warning' \| 'error'` | `'default'` | Active track color |
| label | `string` | — | Label text |
| labelPosition | `'start' \| 'end' \| 'top' \| 'bottom'` | `'end'` | Label placement |
| startLabel | `string` | — | Left label (off state) |
| endLabel | `string` | — | Right label (on state) |
| checkedIcon | `ReactNode` | — | Icon when checked |
| uncheckedIcon | `ReactNode` | — | Icon when unchecked |
| checked | `boolean` | — | Controlled state |
| defaultChecked | `boolean` | — | Uncontrolled default |
| onCheckedChange | `(checked: boolean) => void` | — | Change handler |
| disabled | `boolean` | `false` | Disabled state |
---
### Toggle
```tsx
import { Toggle } from '@7onic-ui/react'
Active
```
| Prop | Type | Default | Description |
|---|---|---|---|
| variant | `'default' \| 'outline' \| 'ghost' \| 'outline-ghost'` | `'default'` | Visual style |
| size | `'xs' \| 'sm' \| 'md' \| 'default' \| 'lg'` | `'default'` | 28/32/36/40/48px |
| radius | Same as Button | `'default'` | Border radius |
| fontWeight | `'normal' \| 'semibold'` | per variant | Font weight |
| iconOnly | `boolean` | `false` | Square mode (no text padding) |
| pressEffect | `boolean` | `true` | Scale-down on press |
| pressed | `boolean` | — | Controlled state |
| defaultPressed | `boolean` | — | Uncontrolled default |
| onPressedChange | `(pressed: boolean) => void` | — | Change handler |
---
### ToggleGroup
```tsx
import { ToggleGroup, ToggleGroupItem } from '@7onic-ui/react'
```
| Prop (Root) | Type | Default | Description |
|---|---|---|---|
| type | `'single' \| 'multiple'` | required | Selection mode |
| variant | `'default' \| 'outline'` | `'default'` | Visual style |
| size | `'xs' \| 'sm' \| 'md' \| 'default' \| 'lg'` | `'default'` | Item size |
| radius | Same as Button | `'default'` | Border radius |
| fontWeight | `'normal' \| 'semibold'` | per variant | Font weight |
| orientation | `'horizontal' \| 'vertical'` | `'horizontal'` | Layout direction |
| value | `string \| string[]` | — | Controlled value |
| defaultValue | `string \| string[]` | — | Uncontrolled default |
| onValueChange | `(value) => void` | — | Change handler |
**Sub-components:** ToggleGroup.Item
---
### Segmented
```tsx
import { Segmented, SegmentedItem } from '@7onic-ui/react'
All
Active
Inactive
```
| Prop (Root) | Type | Default | Description |
|---|---|---|---|
| variant | `'default' \| 'outline' \| 'underline' \| 'ghost'` | `'default'` | Visual style |
| size | `'sm' \| 'md' \| 'default' \| 'lg'` | `'default'` | 32/36/40/48px (no xs) |
| radius | Same as Button (excl. none) | `'default'` | Border radius |
| fontWeight | `'normal' \| 'semibold'` | per variant | Font weight |
| value | `string` | — | Controlled value |
| defaultValue | `string` | — | Uncontrolled default |
| onValueChange | `(value: string) => void` | — | Change handler |
**Sub-components:** Segmented.Item
**Note:** Only 4 sizes (no xs) — intentional design decision.
---
### Slider
```tsx
import { Slider } from '@7onic-ui/react'
```
| Prop | Type | Default | Description |
|---|---|---|---|
| size | `'sm' \| 'default' \| 'lg'` | `'default'` | Track/thumb size |
| color | `'default' \| 'primary'` | `'default'` | Active track color |
| showTooltip | `'auto' \| 'always' \| 'never'` | `'never'` | Tooltip display |
| formatLabel | `(value: number) => string` | — | Tooltip value formatter |
| startContent | `ReactNode` | — | Left content (label/icon) |
| endContent | `ReactNode` | — | Right content (label/icon) |
| orientation | `'horizontal' \| 'vertical'` | `'horizontal'` | Direction |
| value | `number[]` | — | Controlled value(s) |
| defaultValue | `number[]` | — | Uncontrolled default |
| onValueChange | `(value: number[]) => void` | — | Change handler |
| min | `number` | `0` | Minimum value |
| max | `number` | `100` | Maximum value |
| step | `number` | `1` | Step increment |
---
### Field (Form Wrapper)
```tsx
import { Field, FieldCharCount, FieldError, FieldLabel, Input, Textarea } from '@7onic-ui/react'
Email
Bio
```
| Prop (Root) | Type | Default | Description |
|---|---|---|---|
| gap | `'none' \| 'xs' \| 'sm' \| 'default' \| 'lg'` | `'default'` | Gap between elements |
| error | `string \| boolean` | — | Error message (passed to children via context) |
| disabled | `boolean` | `false` | Disabled state (passed to children via context) |
**Sub-components:** Field.Label (with `required` prop), Field.Error, Field.CharCount
**Context:** Input, Textarea, Checkbox, RadioGroup, Select auto-detect Field context for error/disabled/id.
---
## Data Display
### Avatar
```tsx
import { Avatar, AvatarFallback, AvatarGroup, AvatarImage } from '@7onic-ui/react'
A
B
C
+2
```
| Prop (Root) | Type | Default | Description |
|---|---|---|---|
| size | `'xs' \| 'sm' \| 'default' \| 'lg' \| 'xl' \| '2xl'` | `'default'` | Avatar size |
| shape | `'circle' \| 'square'` | `'circle'` | Avatar shape |
| status | `'online' \| 'offline' \| 'busy' \| 'away'` | — | Status indicator dot |
| Prop (Fallback) | Type | Default | Description |
|---|---|---|---|
| name | `string` | — | Auto-generates initials |
| colorized | `string` | — | Pass a name/key string to enable deterministic colored fallback |
| colorVariant | `'vivid' \| 'soft'` | `'vivid'` | Color intensity |
| Prop (Group) | Type | Default | Description |
|---|---|---|---|
| max | `number` | — | Max visible avatars |
| size | Same as Root | — | Override all children |
| shape | Same as Root | — | Override all children |
**Sub-components:** Avatar.Image, Avatar.Fallback, Avatar.Group
---
### Badge
```tsx
import { Badge } from '@7onic-ui/react'
New
Active
{}}>Tag
```
| Prop | Type | Default | Description |
|---|---|---|---|
| variant | `'solid' \| 'subtle' \| 'outline'` | `'subtle'` | Visual style |
| color | `'default' \| 'primary' \| 'success' \| 'warning' \| 'error' \| 'info'` | `'default'` | Color scheme |
| size | `'sm' \| 'default' \| 'lg'` | `'default'` | Badge size |
| radius | `'sm' \| 'md' \| 'lg' \| 'xl' \| 'full'` | `'full'` | Border radius |
| icon | `ReactNode` | — | Leading icon |
| dot | `boolean` | `false` | Status dot indicator |
| removable | `boolean` | `false` | Shows remove button |
| onRemove | `() => void` | — | Remove handler |
| asChild | `boolean` | `false` | Slot pattern |
---
### Card
```tsx
import { Card, CardAction, CardContent, CardDescription, CardFooter, CardHeader, CardImage, CardTitle, IconButton } from '@7onic-ui/react'
}>Featured
Card description
Main content
Footer actions
```
| Prop (Root) | Type | Default | Description |
|---|---|---|---|
| variant | `'default' \| 'outline' \| 'ghost'` | `'default'` | Visual style |
| size | `'sm' \| 'default' \| 'lg'` | `'default'` | Padding scale |
| radius | `'sm' \| 'base' \| 'md' \| 'lg' \| 'xl' \| '2xl'` | `'xl'` | Border radius |
| direction | `'vertical' \| 'horizontal'` | `'vertical'` | Layout direction |
| interactive | `boolean` | `false` | Hover shadow + lift |
| asChild | `boolean` | `false` | Slot pattern |
| Prop (Image) | Type | Default | Description |
|---|---|---|---|
| overlay | `boolean` | `false` | Gradient overlay |
| overlayOpacity | `10-90` | `60` | Overlay darkness |
**Sub-components:** Card.Image, Card.Header, Card.Title (with `icon`), Card.Description, Card.Action, Card.Content, Card.Footer
---
### Table
```tsx
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@7onic-ui/react'
{}}>Name
Amount
John
$100
```
| Prop (Root) | Type | Default | Description |
|---|---|---|---|
| variant | `'default' \| 'bordered' \| 'striped'` | `'default'` | Visual style |
| size | `'sm' \| 'default' \| 'lg'` | `'default'` | Cell padding |
| stickyHeader | `boolean` | `false` | Sticky header row |
| Prop (Head) | Type | Default | Description |
|---|---|---|---|
| align | `'left' \| 'center' \| 'right'` | `'left'` | Text alignment |
| sortable | `boolean` | `false` | Shows sort indicator |
| sortDirection | `'asc' \| 'desc' \| null` | — | Current sort state |
| onSort | `() => void` | — | Sort handler |
| Prop (Row) | Type | Default | Description |
|---|---|---|---|
| interactive | `boolean` | `false` | Hover highlight |
| selected | `boolean` | `false` | Selected state |
| Prop (Cell) | Type | Default | Description |
|---|---|---|---|
| align | `'left' \| 'center' \| 'right'` | `'left'` | Text alignment |
**Sub-components:** Table.Header, Table.Body, Table.Footer, Table.Row, Table.Head, Table.Cell, Table.Caption
---
## Layout
### Tabs
```tsx
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@7onic-ui/react'
Tab 1
Tab 2
Content 1
Content 2
```
| Prop (List) | Type | Default | Description |
|---|---|---|---|
| variant | `'line' \| 'enclosed' \| 'pill'` | `'line'` | Tab style |
| size | `'sm' \| 'md' \| 'default' \| 'lg'` | `'default'` | Tab size |
| fitted | `boolean` | `false` | Full width tabs |
| color | `'default' \| 'primary'` | `'default'` | Active tab color |
| radius | `'none' \| 'sm' \| 'base' \| 'md' \| 'lg' \| 'xl' \| '2xl' \| '3xl' \| 'full'` | `'md'` | Border radius (enclosed/pill) |
**Sub-components:** Tabs.List, Tabs.Trigger, Tabs.Content
---
### Accordion
```tsx
import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from '@7onic-ui/react'
Section 1
Content 1
Section 2
Content 2
```
| Prop (Root) | Type | Default | Description |
|---|---|---|---|
| type | `'single' \| 'multiple'` | `'single'` | Expansion mode |
| variant | `'default' \| 'bordered' \| 'splitted'` | `'default'` | Visual style |
| size | `'sm' \| 'default' \| 'lg'` | `'default'` | Padding scale |
| iconPosition | `'left' \| 'right'` | `'right'` | Chevron placement |
| collapsible | `boolean` | `true` | Allow all closed (single only) |
**Sub-components:** Accordion.Item, Accordion.Trigger (with `icon` prop), Accordion.Content
---
### Divider
```tsx
import { Divider } from '@7onic-ui/react'
```
| Prop | Type | Default | Description |
|---|---|---|---|
| orientation | `'horizontal' \| 'vertical'` | `'horizontal'` | Direction |
| variant | `'solid' \| 'dashed' \| 'dotted'` | `'solid'` | Line style |
| color | `'default' \| 'muted' \| 'strong'` | `'default'` | Line color |
| spacing | `'sm' \| 'md' \| 'default' \| 'lg'` | `'default'` | Margin around line |
| label | `string` | — | Center label text |
| labelPosition | `'left' \| 'center' \| 'right'` | `'center'` | Label placement |
---
## Overlay
### Modal
```tsx
import { Button, Modal, ModalBody, ModalClose, ModalContent, ModalDescription, ModalFooter, ModalHeader, ModalOverlay, ModalPortal, ModalTitle, ModalTrigger } from '@7onic-ui/react'
Open Modal
Confirm
Are you sure?
Modal body content
Cancel
Confirm
```
| Prop (Content) | Type | Default | Description |
|---|---|---|---|
| size | `'xs' \| 'sm' \| 'md' \| 'lg' \| 'xl' \| 'full'` | `'sm'` | Modal width |
| scrollBehavior | `'inside' \| 'outside'` | `'outside'` | Scroll target |
| showCloseButton | `boolean` | `true` | Show X button |
**Sub-components:** Modal.Trigger, Modal.Portal, Modal.Overlay, Modal.Content, Modal.Header, Modal.Title, Modal.Description, Modal.Body, Modal.Footer, Modal.Close
**Required structure:** Portal → Overlay + Content. Don't forget Portal and Overlay.
---
### AlertModal
```tsx
import { AlertModal, AlertModalAction, AlertModalBody, AlertModalCancel, AlertModalContent, AlertModalDescription, AlertModalFooter, AlertModalHeader, AlertModalOverlay, AlertModalPortal, AlertModalTitle, AlertModalTrigger, Button } from '@7onic-ui/react'
Delete
Delete item?
This action cannot be undone.
Further confirmation details
Cancel
Delete
```
| Prop (Content) | Type | Default | Description |
|---|---|---|---|
| size | `'xs' \| 'sm'` | `'sm'` | AlertModal width (smaller than Modal by design) |
**Sub-components:** AlertModal.Trigger, AlertModal.Portal, AlertModal.Overlay, AlertModal.Content, AlertModal.Header, AlertModal.Title, AlertModal.Description, AlertModal.Body, AlertModal.Footer, AlertModal.Action, AlertModal.Cancel
**Required structure:** Portal → Overlay + Content (same as Modal). Use for destructive confirmations — renders as `role="alertdialog"` via Radix AlertDialog primitive. No close button by default (force user to Action or Cancel).
---
### Drawer
```tsx
import { Button, Drawer, DrawerBody, DrawerClose, DrawerContent, DrawerFooter, DrawerHeader, DrawerOverlay, DrawerPortal, DrawerTitle, DrawerTrigger } from '@7onic-ui/react'
Open Drawer
Settings
Content
Close
```
| Prop (Content) | Type | Default | Description |
|---|---|---|---|
| side | `'left' \| 'right' \| 'top' \| 'bottom'` | `'right'` | Slide direction |
| size | `'sm' \| 'md' \| 'lg' \| 'xl' \| 'full'` | `'md'` | Width/height |
| showCloseButton | `boolean` | `true` | Show X button |
**Sub-components:** Drawer.Trigger, Drawer.Portal, Drawer.Overlay, Drawer.Content, Drawer.Header, Drawer.Title, Drawer.Description, Drawer.Body, Drawer.Footer, Drawer.Close
---
### Tooltip
```tsx
import { Button, Tooltip, TooltipArrow, TooltipContent, TooltipPortal, TooltipProvider, TooltipTrigger } from '@7onic-ui/react'
Hover me
Tooltip text
```
| Prop (Root) | Type | Default | Description |
|---|---|---|---|
| delayDuration | `number` | `200` | Hover delay (ms) |
| Prop (Content) | Type | Default | Description |
|---|---|---|---|
| variant | `'default' \| 'inverted'` | `'default'` | Dark/light bg |
| size | `'sm' \| 'default'` | `'default'` | Padding scale |
| side | `'top' \| 'right' \| 'bottom' \| 'left'` | `'top'` | Placement |
| showArrow | `boolean` | `true` | Show arrow |
| sideOffset | `number` | `6` | Gap from trigger |
**⚠️ Tooltip.Provider is required** — wrap your app or section with it.
**Sub-components:** Tooltip.Provider, Tooltip.Trigger, Tooltip.Content, Tooltip.Arrow, Tooltip.Portal
---
### Popover
```tsx
import { Button, Popover, PopoverArrow, PopoverContent, PopoverPortal, PopoverTrigger } from '@7onic-ui/react'
Open
Popover content
```
| Prop (Content) | Type | Default | Description |
|---|---|---|---|
| variant | `'default' \| 'elevated'` | `'default'` | Shadow style |
| size | `'sm' \| 'default' \| 'lg'` | `'default'` | Padding scale |
| side | `'top' \| 'right' \| 'bottom' \| 'left'` | `'bottom'` | Placement |
| showArrow | `boolean` | `true` | Show arrow |
| showClose | `boolean` | `false` | Show X button |
**Sub-components:** Popover.Trigger, Popover.Content, Popover.Arrow, Popover.Close, Popover.Anchor, Popover.Portal
---
## Feedback
### Alert
```tsx
import { Alert, AlertDescription, AlertTitle } from '@7onic-ui/react'
{}}>
Success
Operation completed.
}>
Error
```
| Prop (Root) | Type | Default | Description |
|---|---|---|---|
| variant | `'default' \| 'outline' \| 'filled'` | `'default'` | Visual style |
| color | `'info' \| 'success' \| 'warning' \| 'error'` | `'info'` | Color scheme |
| size | `'sm' \| 'default' \| 'lg'` | `'default'` | Padding scale |
| radius | Same as Card | `'lg'` | Border radius |
| closable | `boolean` | `false` | Show close button |
| onClose | `() => void` | — | Close handler |
| icon | `ReactNode` | auto | Custom icon (auto-selects by color) |
| hideIcon | `boolean` | `false` | Hide icon |
**Sub-components:** Alert.Title, Alert.Description
---
### Toast (Imperative API)
```tsx
import { Toaster, toast } from '@7onic-ui/react'
// 1. Add Toaster provider to your app layout (once)
// 2. Call toast() anywhere
toast('Default notification')
toast.success('Saved successfully')
toast.error('Something went wrong')
toast.warning('Please check your input')
toast.info('New update available')
toast.loading('Processing...')
// With options
toast.success('Saved', {
description: 'Your changes have been saved.',
duration: 5000,
action: { label: 'Undo', onClick: () => {} },
})
// Promise
toast.promise(fetchData(), {
loading: 'Loading...',
success: 'Data loaded',
error: 'Failed to load',
})
// Dismiss
const id = toast('Message')
toast.dismiss(id) // Dismiss specific
toast.dismiss() // Dismiss all
```
| Prop (Toaster) | Type | Default | Description |
|---|---|---|---|
| position | `'top-left' \| 'top-center' \| 'top-right' \| 'bottom-left' \| 'bottom-center' \| 'bottom-right'` | `'bottom-right'` | Toast position |
| size | `'sm' \| 'default' \| 'lg'` | `'default'` | Toast size |
| duration | `number` | `4000` | Auto-dismiss ms (0 = persistent) |
| closeButton | `boolean` | `false` | Show close button |
| richColors | `boolean` | `true` | Filled color backgrounds |
| expand | `boolean` | `false` | Show all toasts expanded |
| visibleToasts | `number` | `5` | Max visible at once |
**⚠️ No Portal needed.** Just place ` ` in your root layout. Call `toast()` from anywhere.
---
### Progress
```tsx
import { Progress } from '@7onic-ui/react'
```
| Prop | Type | Default | Description |
|---|---|---|---|
| type | `'linear' \| 'circular'` | `'linear'` | Shape |
| value | `number` | `0` | Current value |
| max | `number` | `100` | Maximum value |
| size | `'sm' \| 'default' \| 'lg'` | `'default'` | Bar/circle size |
| variant | `'default' \| 'striped'` | `'default'` | Bar fill style |
| color | `'default' \| 'primary'` | `'default'` | Fill color |
| showValue | `boolean` | `false` | Show percentage text |
| formatLabel | `(value: number, max: number) => string` | — | Custom label |
| animated | `boolean` | `false` | Animate stripes |
---
### Spinner
```tsx
import { Spinner } from '@7onic-ui/react'
```
| Prop | Type | Default | Description |
|---|---|---|---|
| variant | `'ring' \| 'dots' \| 'bars' \| 'orbit'` | `'ring'` | Animation style |
| orbitStyle | `'ring' \| 'dots' \| 'cube' \| 'flip' \| 'morph'` | `'ring'` | Orbit sub-variant |
| size | `'sm' \| 'default' \| 'lg'` | `'default'` | Spinner size |
| color | `'default' \| 'primary' \| 'current'` | `'default'` | Color |
| speed | `'slow' \| 'default' \| 'fast'` | `'default'` | Animation speed |
| label | `string` | `'Loading'` | aria-label text |
---
### Skeleton
```tsx
import { Skeleton } from '@7onic-ui/react'
{/* Conditional rendering */}
```
| Prop | Type | Default | Description |
|---|---|---|---|
| variant | `'text' \| 'circular' \| 'rectangular'` | `'text'` | Shape |
| animation | `'pulse' \| 'wave' \| false` | `'pulse'` | Animation style |
| width | `number \| string` | — | Width (px or CSS) |
| height | `number \| string` | — | Height (px or CSS) |
| radius | `number \| string` | — | Border radius |
| count | `number` | `1` | Multi-line count |
| loading | `boolean` | `true` | Show skeleton vs children |
| children | `ReactNode` | — | Content (shown when loading=false) |
---
## Navigation
### Breadcrumb
```tsx
import { Breadcrumb, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator } from '@7onic-ui/react'
Home
Docs
Current
```
| Prop (Root) | Type | Default | Description |
|---|---|---|---|
| separator | `ReactNode` | ` ` | Custom separator (default: chevron right icon) |
| size | `'sm' \| 'default' \| 'lg'` | `'default'` | Text size |
| maxItems | `number` | — | Collapse threshold |
| itemsBeforeCollapse | `number` | `1` | Items before ellipsis |
| itemsAfterCollapse | `number` | `1` | Items after ellipsis |
**Sub-components:** Breadcrumb.List, Breadcrumb.Item, Breadcrumb.Link (with `asChild`), Breadcrumb.Page, Breadcrumb.Separator, Breadcrumb.Ellipsis
---
### Pagination
```tsx
import { Pagination, PaginationContent, PaginationItems, PaginationNext, PaginationPrevious } from '@7onic-ui/react'
{/* Quick mode — withControls (default: true), withEdges (default: false) */}
{/* Compound mode (custom layout) */}
```
| Prop (Root) | Type | Default | Description |
|---|---|---|---|
| total | `number` | `1` | Total pages |
| value | `number` | — | Controlled page |
| defaultValue | `number` | `1` | Uncontrolled default |
| onChange | `(page: number) => void` | — | Change handler |
| siblings | `number` | `1` | Pages beside current |
| boundaries | `number` | `1` | Pages at start/end |
| variant | `'default' \| 'outline' \| 'ghost'` | `'default'` | Visual style |
| color | `'default' \| 'primary'` | `'default'` | Active page color |
| size | `'xs' \| 'sm' \| 'default' \| 'lg' \| 'xl'` | `'default'` | Button size |
| radius | `'sm' \| 'base' \| 'md' \| 'lg' \| 'xl' \| 'full'` | `'md'` | Border radius |
| withControls | `boolean` | `true` | Auto-render previous/next buttons |
| withEdges | `boolean` | `false` | Auto-render first/last jump buttons |
| loop | `boolean` | `false` | Wrap around |
| disabled | `boolean` | `false` | Disabled state |
**Sub-components:** Pagination.Content, Pagination.Item, Pagination.Link, Pagination.Previous, Pagination.Next, Pagination.First, Pagination.Last, Pagination.Ellipsis, Pagination.Items
---
### NavigationMenu
```tsx
import { NavigationMenu, NavigationMenuContent, NavigationMenuGroup, NavigationMenuItem, NavigationMenuLink, NavigationMenuList, NavigationMenuTrigger, NavigationMenuViewport } from '@7onic-ui/react'
{/* Horizontal (header) */}
Home
Products
Product A
Product B
{/* Vertical (sidebar) */}
} active>Dashboard
```
| Prop (Root) | Type | Default | Description |
|---|---|---|---|
| orientation | `'horizontal' \| 'vertical'` | `'horizontal'` | Layout mode |
| size | `'sm' \| 'md' \| 'default' \| 'lg'` | `'default'` | Item size |
| collapsed | `boolean` | `false` | Icon-only mode (vertical) |
| radius | Same as Button | `'lg'` | Border radius |
| fontWeight | `'normal' \| 'semibold'` | `'normal'` | Font weight |
| delayDuration | `number` | `200` | Hover delay before content opens (horizontal only, ms) |
| skipDelayDuration | `number` | `300` | Reset delay when moving between triggers (horizontal only, ms) |
| Prop (Link) | Type | Default | Description |
|---|---|---|---|
| active | `boolean` | `false` | Current page indicator |
| icon | `ReactNode` | — | Leading icon |
| asChild | `boolean` | `false` | Slot pattern |
| Prop (Item) | Type | Default | Description |
|---|---|---|---|
| value | `string` | — | Identifier for controlled state (horizontal menus) |
| defaultOpen | `boolean` | `false` | Initial open state for vertical collapsible item |
| Prop (Indicator) | Type | Default | Description |
|---|---|---|---|
| color | `'default' \| 'primary'` | `'default'` | Indicator color (horizontal variant only) |
**Sub-components:** NavigationMenu.List, NavigationMenu.Item, NavigationMenu.Trigger, NavigationMenu.Content, NavigationMenu.Link, NavigationMenu.Group (vertical only, with `label`), NavigationMenu.Indicator (horizontal only), NavigationMenu.Viewport
---
## Charts
### Chart (Container + Sub-components)
All chart types use the Chart namespace:
```tsx
import { ChartArea, ChartBar, ChartLegend, ChartLegendContent, ChartLine, ChartPie, ChartTooltip, ChartTooltipContent, ChartXAxis, ChartYAxis } from '@7onic-ui/react/chart'
const chartConfig = {
revenue: { label: 'Revenue', color: 'var(--color-chart-1)' },
profit: { label: 'Profit', color: 'var(--color-chart-2)' },
}
{/* Line Chart */}
} />
} />
{/* Bar Chart */}
} />
{/* Area Chart */}
} />
{/* Pie Chart */}
} />
```
**⚠️ chartConfig is REQUIRED.** It maps data keys to labels and colors.
| Prop (Container) | Type | Default | Description |
|---|---|---|---|
| config | `ChartConfig` | required | Data key → label/color mapping |
| hoverFade | `boolean` | `false` | Fade non-hovered elements |
| Prop (Bar) | Type | Default | Description |
|---|---|---|---|
| radius | `'none' \| 'sm' \| 'base' \| 'md' \| 'lg'` | `'none'` | Bar corner radius |
| layout | `'vertical' \| 'horizontal'` | `'vertical'` | Bar direction |
| variant | `'solid' \| 'outline'` | `'solid'` | Fill style |
| stackPosition | `'top' \| 'bottom'` | `'top'` | Stack position |
| Prop (Line) | Type | Default | Description |
|---|---|---|---|
| type | `'linear' \| 'monotone' \| 'step' \| 'natural'` | `'monotone'` | Curve type |
| variant | `'solid' \| 'dashed'` | `'solid'` | Line style |
| dot | `boolean` | `true` | Show data points |
| activeDot | `boolean` | `true` | Show active point |
| Prop (Area) | Type | Default | Description |
|---|---|---|---|
| type | `'linear' \| 'monotone' \| 'step' \| 'natural'` | `'monotone'` | Curve type |
| variant | `'solid' \| 'gradient'` | `'solid'` | Fill style |
| fillOpacity | `number` | `0.4` | Fill opacity (0-1) |
| Prop (Pie) | Type | Default | Description |
|---|---|---|---|
| variant | `'pie' \| 'donut'` | `'pie'` | Pie or donut |
| label | `'none' \| 'outside' \| 'inside'` | `'none'` | Label display |
| labelContent | `'value' \| 'percent'` | `'value'` | Label format |
| activeShape | `boolean` | `true` | Expand on hover |
| paddingAngle | `number` | `0` | Gap between slices (degrees) |
| cornerRadius | `number` | `0` | Slice corner radius (px) |
| startAngle | `number` | `90` | Start angle (degrees, 12 o'clock = 90) |
| endAngle | `number` | `-270` | End angle (degrees, full circle = 90→-270) |
| innerRadius | `number` | — | Override donut inner radius (default auto by variant) |
**Chart Colors (CSS variables):**
`--color-chart-1` (blue), `--color-chart-2` (pink), `--color-chart-3` (lavender), `--color-chart-4` (sky), `--color-chart-5` (rose)
Each has light/dark theme variants.
**ChartConfig format:**
```tsx
type ChartConfig = {
[dataKey: string]: {
label?: ReactNode
icon?: ComponentType
color?: string // CSS color or variable
// OR theme-specific:
theme?: { light: string, dark: string }
}
}
```
---
### MetricCard
```tsx
import { MetricCard, MetricCardDescription, MetricCardHeader, MetricCardSymbol, MetricCardTitle, MetricCardTrend, MetricCardValue } from '@7onic-ui/react'
Revenue
$12,450
+12.5%
vs. last month
```
| Prop (Root) | Type | Default | Description |
|---|---|---|---|
| variant | `'default' \| 'elevated' \| 'ghost'` | `'default'` | Visual style |
| size | `'sm' \| 'default' \| 'lg'` | `'default'` | Padding scale |
| radius | `'none' \| 'sm' \| 'base' \| 'default' \| 'lg' \| 'xl' \| '2xl' \| '3xl' \| 'full'` | `'default'` | Border radius |
| Prop (Value) | Type | Default | Description |
|---|---|---|---|
| animated | `boolean` | `false` | Number count-up animation |
| Prop (Trend) | Type | Default | Description |
|---|---|---|---|
| direction | `'up' \| 'down' \| 'neutral'` | — | Trend arrow + color |
**Sub-components:** MetricCard.Header, MetricCard.Title, MetricCard.Value, MetricCard.Trend, MetricCard.Description, MetricCard.Symbol
---
# ═══ SECTION 4: COMPONENT USAGE GUIDE ═══
## Component Selection
Before creating custom UI, check if 7onic already has it:
| Need | Use This Component |
|---|---|
| Action trigger | Button, IconButton |
| Text input | Input (single line), Textarea (multi line) |
| Selection (one) | RadioGroup, Select, Segmented |
| Selection (many) | Checkbox, ToggleGroup |
| Boolean toggle | Switch, Toggle, Checkbox |
| Container | Card |
| Data table | Table |
| Tabs | Tabs |
| Collapsible | Accordion |
| Dialog | Modal |
| Side panel | Drawer |
| Hint text | Tooltip |
| Rich hint | Popover |
| Notification | Toast (imperative), Alert (inline) |
| Loading | Spinner (indeterminate), Progress (determinate), Skeleton (placeholder) |
| Navigation | Breadcrumb, Pagination, NavigationMenu |
| Data visualization | Chart (Line/Area/Bar/Pie), MetricCard |
| Metric display | MetricCard |
| Tag / chip | Badge (with `removable`) |
| Avatar | Avatar |
| Separator | Divider |
**If the component exists, use it.** Don't build custom versions with HTML + classes.
---
## Import Pattern
```tsx
// ✅ Single import path
import { Button, Card, Input, toast } from '@7onic-ui/react'
// ✅ Chart components use a separate entry point (recharts is optional)
import { ChartBar } from '@7onic-ui/react/chart'
// ❌ Never import from internal paths
import { Button } from '@7onic-ui/react/components/button' // WRONG
// ❌ Never import Radix directly
import * as Dialog from '@radix-ui/react-dialog' // WRONG → use Modal
```
---
## Compound Component Structure
Compound components have **required sub-components**. Missing them causes errors or broken UI.
**Modal — required structure:**
```tsx
...
{/* ← Required for correct z-index */}
{/* ← Required for backdrop */}
...
...
```
**Drawer — same pattern as Modal** (Portal + Overlay + Content required)
**Tooltip — Provider required:**
```tsx
{/* ← Required, wrap app once */}
...
...
```
**Toast — imperative API, no compound structure:**
```tsx
// Place Toaster once in layout
// Call toast() anywhere
toast.success('Done')
```
---
## asChild Pattern (Slot)
`asChild` replaces the component's DOM element with its child, keeping styles and behavior:
```tsx
// ❌ Double — broken HTML
About
// ✅ Button renders as with Button styles
About
// ✅ DropdownMenu item as link
Settings
// ✅ Breadcrumb as Next.js Link
Home
```
**Use `asChild` when combining 7onic components with routing ` `.**
Components that support `asChild`: Button, IconButton, Badge, Card, Modal.Trigger, Modal.Close, Drawer.Trigger, Drawer.Close, DropdownMenu.Item, Breadcrumb.Link, NavigationMenu.Link, Tooltip.Trigger, Popover.Trigger
---
## Props Usage
**Always use allowed values.** Don't pass arbitrary strings to variant/size/color props.
```tsx
// ✅ Correct
// ❌ Wrong — invalid values
// 'primary' is a color, not a variant
// Use 'md' or 'default', not 'medium'
// Use 'primary', not raw color names
```
**`className` on components = layout ONLY** (margin, width, flex positioning). All visual styling (color, size, radius, variant) must use Props.
**Style via Props, not className:**
```tsx
// ✅ Use Props
// ❌ Don't override with className
```
---
## Form Patterns
**Use Field wrapper** for labeled form elements with validation:
```tsx
import { Field, FieldCharCount, FieldError, FieldLabel, Input, Textarea } from '@7onic-ui/react'
{/* Text input with label + error */}
Email
{/* Textarea with character count */}
Bio
```
**Field context auto-connects** to Input, Textarea, Select, Checkbox, RadioGroup:
- Passes `error` state
- Passes `disabled` state
- Auto-generates matching `id` / `htmlFor` / `aria-describedby`
---
## Chart Patterns
**⚠️ recharts is required.** Auto-install when using any Chart component:
```bash
npm install recharts
```
**Always provide chartConfig:**
```tsx
const chartConfig = {
revenue: { label: 'Revenue', color: 'var(--color-chart-1)' },
expenses: { label: 'Expenses', color: 'var(--color-chart-2)' },
}
```
**Available chart colors (CSS variables, auto-adapt to light/dark):**
- `var(--color-chart-1)` — blue
- `var(--color-chart-2)` — pink
- `var(--color-chart-3)` — lavender
- `var(--color-chart-4)` — sky
- `var(--color-chart-5)` — rose
**Container height is required (layout arbitrary value — allowed):**
```tsx
```
---
## Overlay Patterns
**All overlays use Portal for correct stacking:**
```tsx
...
```
**Z-index hierarchy (automatic via tokens) — never set custom z-index:**
1. `z-dropdown` (1000) — Dropdown, Select
2. `z-overlay` (1100) — Modal/Drawer overlay
3. `z-modal` (2000) — Modal/Drawer content
4. `z-popover` (2100) — Popover
5. `z-tooltip` (2200) — Tooltip
6. `z-toast` (3000) — Toast
---
## Accessibility
**Built-in (via Radix UI):** keyboard navigation, focus trap, ARIA attributes, screen reader.
**Do NOT override:**
```tsx
// ❌ Never remove focus ring
// ✅ Focus ring is managed by the design system
```
**Always provide labels:**
```tsx
Email
```
---
## Responsive Layout
**Mobile-first with token breakpoints:**
```tsx
...
...
```
**Use component Props for sizing, not className overrides:**
```tsx
// ✅ Correct
// ❌ Wrong
```
---
## Performance
**Tree-shaking works automatically:**
```tsx
import { Button, Card, Input } from '@7onic-ui/react'
```
**Don't wrap components unnecessarily:**
```tsx
// ❌ Unnecessary
function MyButton(props) { return }
// ✅ Use directly
Submit
```
**Next.js App Router:** 7onic components have `'use client'` internally — they render in Server Components.
But if YOUR code uses React hooks (`useState`, `useEffect`) or event handlers (`onClick`, `onChange`), add `'use client'` at the top of your file. When in doubt, add `'use client'` — it's always safe.
---
# ═══ SECTION 5: COMPLETE COMPONENT SUMMARY ═══
## Quick Reference Table
> 40 entries below. 4 chart types (bar-chart, line-chart, area-chart, pie-chart) share one source — all listed as "Chart" here. Field is a form utility sub-component with no dedicated page. Total: 42 component pages on the docs site.
| Component | Type | Variants | Sizes | Colors | Key Feature |
|---|---|---|---|---|---|
| Button | Standalone | solid/outline/ghost/link | xs/sm/md/default/lg | default/primary/secondary/destructive | loading, icons, press effect |
| IconButton | Standalone | solid/outline/ghost/subtle | xs/sm/md/default/lg | default/primary/secondary/destructive | Square, icon-only |
| ButtonGroup | Container | outline/ghost | (inherits) | (inherits) | Context provider, attached |
| Input | Standalone | default/filled | xs/sm/default/lg/xl | — | leftIcon/rightIcon, error |
| Textarea | Standalone | default/filled | compact/default | — | resize options |
| Select | Compound | — | xs/sm/default/lg/xl | — | Trigger + Content + Item |
| DropdownMenu | Compound | — | sm/md/lg | — | CheckboxItem, RadioItem, Sub |
| Checkbox | Standalone | — | sm/default/lg | default/primary | indeterminate, label |
| RadioGroup | Compound | — | sm/default/lg | default/primary | Item with label |
| Switch | Standalone | — | sm/default/lg | 5 colors | label positions, icons |
| Toggle | Standalone | default/outline/ghost/outline-ghost | xs/sm/md/default/lg | — | pressed state |
| ToggleGroup | Compound | default/outline | xs/sm/md/default/lg | — | single/multiple |
| Segmented | Compound | default/outline/underline/ghost | sm/md/default/lg | — | Tab-like selection |
| Slider | Standalone | — | sm/default/lg | default/primary | tooltip, range |
| Field | Compound | — | — | — | Label, Error, CharCount |
| Avatar | Compound | — | xs/sm/default/lg/xl/2xl | — | colorized fallback, Group |
| Badge | Standalone | solid/subtle/outline | sm/default/lg | default/primary/success/warning/error/info | dot, removable |
| Card | Compound | default/outline/ghost | sm/default/lg | — | Image overlay, interactive |
| Table | Compound | default/bordered/striped | sm/default/lg | — | stickyHeader, sortable |
| Tabs | Compound | line/enclosed/pill | sm/md/default/lg | default/primary | fitted |
| Accordion | Compound | default/bordered/splitted | sm/default/lg | — | single/multiple |
| Divider | Standalone | solid/dashed/dotted | — | default/muted/strong | label |
| Modal | Compound | — | xs/sm/md/lg/xl/full | — | scrollBehavior |
| Drawer | Compound | — | sm/md/lg/xl/full | — | 4 sides |
| Tooltip | Compound | default/inverted | sm/default | — | Provider required |
| Popover | Compound | default/elevated | sm/default/lg | — | arrow, close button |
| Alert | Compound | default/outline/filled | sm/default/lg | info/success/warning/error | closable |
| Toast | Imperative | — | sm/default/lg | 6 types | promise, action |
| Progress | Standalone | default/striped | sm/default/lg | default/primary | linear/circular |
| Spinner | Standalone | ring/dots/bars/orbit | sm/default/lg | default/primary/current | 5 orbit styles |
| Skeleton | Standalone | text/circular/rectangular | — | — | pulse/wave, count |
| Breadcrumb | Compound | — | sm/default/lg | — | maxItems collapse |
| Pagination | Compound | default/outline/ghost | xs/sm/default/lg/xl | default/primary | compound or auto |
| NavigationMenu | Compound | — | sm/md/default/lg | — | horizontal/vertical, collapsed |
| Chart | Compound | — | — | chart colors | Bar/Line/Area/Pie |
| MetricCard | Compound | default/elevated/ghost | sm/default/lg | — | animated value, trend |
| TypingIndicator | Standalone | dots/cursor | sm/default/lg | default/primary/muted | speed (dots only), animate-typing-cursor, showLabel |
| QuickReply | Compound | outline/filled/ghost | sm/default/lg | default/primary | layout (scroll/wrap), radius (md/lg/full), gap, icon, asChild |
| ChatInput | Compound | outline/filled | sm/default/lg | default/primary | layout (default/inline), radius (sm/md/lg/xl/2xl/full), buttonRadius, auto-resize, showCount, loading, onStop |
| ChatMessage | Compound | bubble/flat | sm/default/lg | default/muted/primary/dark | role (assistant/user), tail, avatarSize, radius (md/lg/xl/2xl), typing, actions, Avatar/Content/Footer sub-components |
---
### TypingIndicator
```tsx
import { TypingIndicator } from '@7onic-ui/react'
{/* Default — dots, muted, default size */}
{/* Cursor variant */}
{/* Chat bubble */}
{/* AI response — fast with label */}
{/* Large cursor, primary color */}
```
| Prop | Type | Default | Description |
|---|---|---|---|
| variant | `'dots' \| 'cursor'` | `'dots'` | Animation style |
| size | `'sm' \| 'default' \| 'lg'` | `'default'` | Size |
| color | `'default' \| 'primary' \| 'muted'` | `'muted'` | Color |
| speed | `'slow' \| 'default' \| 'fast'` | `'default'` | Speed (dots only) |
| label | `string` | `'Typing'` | aria-label and showLabel text |
| showLabel | `boolean` | `false` | Show text label alongside indicator |
---
### QuickReply
```tsx
import { QuickReply, QuickReplyItem } from '@7onic-ui/react'
{/* Basic suggested replies */}
About payment
Shipping info
Return policy
{/* Primary color, filled variant */}
Payment
Shipping
{/* Wrap layout for FAQ */}
Payments
Shipping
Returns
Account
{/* With icon */}
}>Contact us
}>Track order
```
| Prop (QuickReply) | Type | Default | Description |
|---|---|---|---|
| layout | `'scroll' \| 'wrap'` | `'scroll'` | Chip layout mode |
| variant | `'outline' \| 'filled' \| 'ghost'` | `'outline'` | Visual style |
| color | `'default' \| 'primary'` | `'default'` | Color theme |
| size | `'sm' \| 'default' \| 'lg'` | `'default'` | Chip size |
| radius | `'md' \| 'lg' \| 'full'` | `'full'` | Border radius |
| gap | `'sm' \| 'default' \| 'lg'` | `'default'` | Gap between chips |
| Prop (QuickReply.Item) | Type | Default | Description |
|---|---|---|---|
| icon | `ReactNode` | — | Leading icon |
| asChild | `boolean` | `false` | Compose with custom element (Radix Slot) |
| disabled | `boolean` | `false` | Disable the chip |
| onClick | `() => void` | — | Click callback |
---
### ChatInput
```tsx
import { ChatInput, ChatInputField, ChatInputSubmit } from '@7onic-ui/react'
{/* Basic uncontrolled */}
console.log(value)}>
{/* Controlled mode */}
const [value, setValue] = useState('')
{ handleSend(v); setValue('') }}>
setValue(e.target.value)}
placeholder="Ask me anything..."
/>
{/* With loading state + stop */}
abortController.abort()}
/>
{/* Character count */}
console.log(value)}>
{/* Filled variant, large, custom radius */}
console.log(v)}>
{/* Inline layout (single-line field + button side by side) */}
console.log(value)}>
{/* Inline with custom button radius */}
```
| Prop (ChatInput) | Type | Default | Description |
|---|---|---|---|
| variant | `'outline' \| 'filled'` | `'outline'` | Visual style |
| size | `'sm' \| 'default' \| 'lg'` | `'default'` | Size scale |
| radius | `'sm' \| 'md' \| 'lg' \| 'xl' \| '2xl' \| 'full'` | `'xl'` | Corner radius (`'full'` available in inline layout) |
| color | `'default' \| 'primary'` | `'default'` | Submit button color |
| layout | `'default' \| 'inline'` | `'default'` | `'inline'` renders field and button side by side |
| disabled | `boolean` | `false` | Disable input and submit |
| onSubmit | `(value: string) => void` | — | Submit callback |
| Prop (ChatInput.Field) | Type | Default | Description |
|---|---|---|---|
| maxRows | `number` | `8` | Max rows before scrolling |
| showCount | `boolean` | `false` | Show character counter (default layout only) |
| maxLength | `number` | — | Max characters |
| placeholder | `string` | — | Placeholder text |
| Prop (ChatInput.Submit) | Type | Default | Description |
|---|---|---|---|
| loading | `boolean` | `false` | Switch to stop icon — button stays enabled |
| onStop | `() => void` | — | Called on click when loading |
| buttonRadius | `'sm' \| 'md' \| 'lg' \| 'xl' \| '2xl' \| 'full'` | — | Override button radius (default: auto from container radius) |
| children | `ReactNode` | — | Custom icon (default: send arrow) |
### ChatMessage
```tsx
import { ChatMessage, ChatMessageAvatar, ChatMessageContent, ChatMessageFooter } from '@7onic-ui/react'
{/* Assistant message */}
How can I help you today?
{/* User message with status */}
Thank you for your help!
{/* Typing animation */}
{/* Custom avatar + hover actions */}
...}
>
Response text here.
{/* User bubble with muted color (common pattern) */}
Message text
{/* History (flat) layout — full-width, no footer */}
Here is the answer.
Thanks!
```
| Prop (ChatMessage) | Type | Default | Description |
|---|---|---|---|
| role | `'assistant' \| 'user'` | `'assistant'` | Aligns left (assistant) or right (user) |
| variant | `'bubble' \| 'flat'` | `'bubble'` | Bubble style with background/border, or flat with no fill |
| color | `'default' \| 'muted' \| 'primary' \| 'dark'` | `'default'` | Bubble background color |
| size | `'sm' \| 'default' \| 'lg'` | `'default'` | Size scale affecting padding and font |
| radius | `'md' \| 'lg' \| 'xl' \| '2xl'` | `'2xl'` | Bubble corner radius |
| tail | `boolean` | `true` | Asymmetric tail corner (sharp on avatar side) — bubble only |
| avatarSize | `'sm' \| 'md' \| 'lg'` | — | Avatar size — also adjusts gap between avatar and bubble |
| typing | `boolean` | `false` | Show animated typing dots inside Content |
| actions | `ReactNode` | — | Hover-reveal action buttons (copy, react, etc.) |
| Prop (ChatMessage.Avatar) | Type | Default | Description |
|---|---|---|---|
| size | `'sm' \| 'md' \| 'lg'` | `'md'` | Avatar size: 24/28/32px |
| src | `string` | — | Avatar image URL |
| alt | `string` | `'Avatar'` | Alt text |
| initials | `string` | — | 1–2 character initials (fallback) |
| icon | `ReactNode` | — | Custom icon (fallback) |
| Prop (ChatMessage.Footer) | Type | Default | Description |
|---|---|---|---|
| timestamp | `string` | — | Pre-formatted time string |
| status | `'sending' \| 'sent' \| 'read' \| 'error' \| ReactNode` | — | Delivery status (built-in presets or custom node) |
| size | `'sm' \| 'default' \| 'lg'` | — | Size override (defaults to context value from root) |
---
## Compound Recipe (opt-in self-wrapper)
v0.3.0+ library exports Named only (``). To restore dot-notation (``) in your project, add a wrapper file. File location is flexible (`src/lib/card.tsx`, `lib/card.tsx`, `src/components/compound/card.tsx`, etc.) — pick one. Adjust the import source to match your install method:
### If installed via npm (`npm install @7onic-ui/react`)
```tsx
'use client'
import {
Card as CardBase,
CardHeader, CardTitle, CardDescription,
CardContent, CardFooter, CardImage, CardAction,
} from '@7onic-ui/react'
export const Card = Object.assign(CardBase, {
Header: CardHeader, Title: CardTitle,
Description: CardDescription, Content: CardContent,
Footer: CardFooter, Image: CardImage, Action: CardAction,
})
```
### If installed via CLI (`npx 7onic add card`)
```tsx
'use client'
import {
Card as CardBase,
CardHeader, CardTitle, CardDescription,
CardContent, CardFooter, CardImage, CardAction,
} from '@/components/ui/card'
export const Card = Object.assign(CardBase, {
Header: CardHeader, Title: CardTitle,
Description: CardDescription, Content: CardContent,
Footer: CardFooter, Image: CardImage, Action: CardAction,
})
```
Then: ``, ``, etc. — Client Components only.
**Rules**:
- Wrapper file must start with `'use client'` — Next.js Client Manifest cannot track `Object.assign` properties across RSC boundaries.
- Recipe works only in Client Components. Server Components must use Named imports (``).
- If you don't need dot-notation, skip this entirely — Named imports (``) work everywhere: RSC, Client, Vite, CRA, CJS.
- Compound namespaces (component families with sub-components): Accordion, Alert, AlertModal, Avatar, Breadcrumb, Card, Chart, ChatInput, ChatMessage, Drawer, DropdownMenu, Field, MetricCard, Modal, NavigationMenu, Pagination, Popover, QuickReply, RadioGroup, Segmented, Select, Table, Tabs, ToggleGroup, Tooltip.
---
## Links
- Documentation: https://7onic.design
- npm (tokens): https://npmjs.com/package/@7onic-ui/tokens
- npm (react): https://npmjs.com/package/@7onic-ui/react
- GitHub: https://github.com/itonys/7onic
- Tokens-only AI guide: https://7onic.design/llms.txt