tonal-ui 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,154 @@
1
+ # tonal-ui
2
+
3
+ A design system built on the principle of **Tonal Layering** — using surface color depth instead of borders to create visual hierarchy. Designed for editorial platforms that need clean, authoritative aesthetics with full dark mode and CJK typography support.
4
+
5
+ ## Design Philosophy
6
+
7
+ ### Tonal Layering
8
+
9
+ Traditional UI uses borders (1px lines) to separate elements. Tonal Layering replaces borders with **background color depth**, creating a premium feel like sheets of fine paper stacked on a surface.
10
+
11
+ ```
12
+ Level 0: surface — Page background (subtle cool white)
13
+ Level 1: surface-container-low — Section backgrounds
14
+ Level 2: surface-container-lowest — Interactive cards (pure white, "floating")
15
+ ```
16
+
17
+ Elements feel elevated not by shadows or borders, but by tonal contrast alone.
18
+
19
+ ### Core Rules
20
+
21
+ - **No-Line Rule**: Never use 1px borders to section content. Define boundaries through background color shifts.
22
+ - **Ambient Shadows**: When elements must float, use diffused shadows (blur 20px+, tinted — never pure black).
23
+ - **Ghost Border Fallback**: If accessibility requires a border, use `outline-variant` at 15% opacity.
24
+ - **Breathe Principle**: Use generous spacing (64px+) between major sections.
25
+
26
+ ## Features
27
+
28
+ - **18 components** with CVA (class-variance-authority) variants
29
+ - **Compound Pattern** for Table and Card (namespace exports)
30
+ - **CSS variable-based dark mode** — no `dark:` prefix needed
31
+ - **CJK typography** — Optimized for English, Korean, Japanese, and Chinese
32
+ - **Surface-first color tokens** — Palette → Semantic → Theme → Utility chain
33
+ - **Tailwind CSS v4** — Built CSS exported, consumers just import
34
+
35
+ ## Installation
36
+
37
+ ```bash
38
+ npm install tonal-ui
39
+ # or
40
+ pnpm add tonal-ui
41
+ ```
42
+
43
+ ## Usage
44
+
45
+ ### CSS Import (required)
46
+
47
+ ```css
48
+ /* your app's globals.css */
49
+ @import "tailwindcss";
50
+ @import "tonal-ui/styles.css";
51
+ ```
52
+
53
+ ### Components
54
+
55
+ ```tsx
56
+ import { Button, Badge, Alert } from 'tonal-ui';
57
+ import * as Card from 'tonal-ui/Card';
58
+ import * as Table from 'tonal-ui/Table';
59
+
60
+ // Simple components
61
+ <Button variant="primary" size="md">Click me</Button>
62
+ <Badge variant="success">Active</Badge>
63
+
64
+ // Compound components
65
+ <Card.Root>
66
+ <Card.Header>
67
+ <Card.Title>Title</Card.Title>
68
+ </Card.Header>
69
+ <Card.Body>Content</Card.Body>
70
+ </Card.Root>
71
+ ```
72
+
73
+ ## Components
74
+
75
+ ### Simple (named export)
76
+
77
+ | Component | Variants |
78
+ |-----------|----------|
79
+ | `Button` | primary, secondary, danger, outline, ghost × sm, md, lg |
80
+ | `Badge` | default, success, warning, danger, info |
81
+ | `Alert` | info, success, warning, error |
82
+ | `Input` | default, error × sm, md, lg |
83
+ | `Select` | default × sm, md, lg |
84
+ | `Switch` | default × sm, md |
85
+ | `Chip` | default, active |
86
+ | `IconButton` | default, ghost × sm, md, lg |
87
+ | `Modal` | sm, md, lg, xl |
88
+ | `ProgressBar` | default, success, warning, error × sm, md, lg |
89
+ | `Toast` | info, success, warning, error |
90
+ | `Container` | sm, md, lg, xl, full |
91
+ | `Divider` | horizontal, vertical |
92
+ | `HeroBadge` | — |
93
+ | `SidebarCard` | — |
94
+ | `RadioGroup` | — |
95
+
96
+ ### Compound (namespace export)
97
+
98
+ | Component | Sub-components |
99
+ |-----------|---------------|
100
+ | `Card` | Root, Header, Title, Body, Footer |
101
+ | `Table` | Root, Head, Body, Row, HeaderCell, Cell |
102
+
103
+ ## Color Tokens
104
+
105
+ ### Surface Hierarchy
106
+
107
+ | Token | Light | Dark | Use |
108
+ |-------|-------|------|-----|
109
+ | `surface` | `#faf8ff` | `#11141d` | Page background |
110
+ | `surface-container-low` | `#f3f3fe` | `#191b23` | Section background |
111
+ | `surface-container-lowest` | `#ffffff` | `#0f111a` | Cards, elevated elements |
112
+ | `surface-container-high` | `#e7e7f3` | `#282a36` | Recessed areas |
113
+
114
+ ### Semantic Colors
115
+
116
+ | Role | Token |
117
+ |------|-------|
118
+ | Primary | `primary`, `primary-container`, `on-primary` |
119
+ | Secondary | `secondary`, `secondary-container`, `on-secondary` |
120
+ | Tertiary | `tertiary`, `tertiary-container`, `on-tertiary` |
121
+ | Error | `error`, `error-container`, `on-error` |
122
+ | Success | `success`, `success-container`, `on-success` |
123
+
124
+ ## Typography
125
+
126
+ | Role | Font | Size |
127
+ |------|------|------|
128
+ | Headlines | Manrope | — |
129
+ | Body | Inter + CJK fallback | 1rem, line-height 1.75 |
130
+ | Labels | Inter | 0.75rem, uppercase, tracking 0.05em |
131
+
132
+ CJK fallback: `"Apple SD Gothic Neo", "Noto Sans KR", system-ui`
133
+
134
+ ## Tech Stack
135
+
136
+ - React 19+
137
+ - Tailwind CSS v4
138
+ - CVA (class-variance-authority)
139
+ - clsx + tailwind-merge
140
+ - tsup (JS build) + @tailwindcss/cli (CSS build)
141
+
142
+ ## Development
143
+
144
+ ```bash
145
+ pnpm install
146
+ pnpm build # Build JS + CSS
147
+ pnpm dev # Watch mode (JS only)
148
+ pnpm storybook # Component playground
149
+ pnpm typecheck # TypeScript check
150
+ ```
151
+
152
+ ## License
153
+
154
+ MIT
@@ -0,0 +1,250 @@
1
+ import { ClassValue } from 'clsx';
2
+ import * as react from 'react';
3
+ import { ButtonHTMLAttributes, HTMLAttributes, InputHTMLAttributes, SelectHTMLAttributes, ReactNode, ThHTMLAttributes, TdHTMLAttributes } from 'react';
4
+ import * as class_variance_authority_types from 'class-variance-authority/types';
5
+ import { VariantProps } from 'class-variance-authority';
6
+
7
+ declare function cn(...inputs: ClassValue[]): string;
8
+
9
+ declare const buttonVariants: (props?: ({
10
+ variant?: "primary" | "secondary" | "danger" | "outline" | "ghost" | null | undefined;
11
+ size?: "sm" | "md" | "lg" | null | undefined;
12
+ } & class_variance_authority_types.ClassProp) | undefined) => string;
13
+ interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement>, VariantProps<typeof buttonVariants> {
14
+ loading?: boolean;
15
+ }
16
+ declare const Button: react.ForwardRefExoticComponent<ButtonProps & react.RefAttributes<HTMLButtonElement>>;
17
+
18
+ declare const alertVariants: (props?: ({
19
+ variant?: "danger" | "info" | "success" | "warning" | null | undefined;
20
+ } & class_variance_authority_types.ClassProp) | undefined) => string;
21
+ interface AlertProps extends HTMLAttributes<HTMLDivElement>, VariantProps<typeof alertVariants> {
22
+ title?: string;
23
+ dismissible?: boolean;
24
+ }
25
+ declare const Alert: react.ForwardRefExoticComponent<AlertProps & react.RefAttributes<HTMLDivElement>>;
26
+
27
+ declare const badgeVariants: (props?: ({
28
+ variant?: "danger" | "info" | "success" | "warning" | "default" | null | undefined;
29
+ } & class_variance_authority_types.ClassProp) | undefined) => string;
30
+ interface BadgeProps extends HTMLAttributes<HTMLSpanElement>, VariantProps<typeof badgeVariants> {
31
+ }
32
+ declare const Badge: react.ForwardRefExoticComponent<BadgeProps & react.RefAttributes<HTMLSpanElement>>;
33
+
34
+ declare const chipVariants: (props?: ({
35
+ variant?: "outline" | "filled" | "tonal" | null | undefined;
36
+ active?: boolean | null | undefined;
37
+ } & class_variance_authority_types.ClassProp) | undefined) => string;
38
+ interface ChipProps extends HTMLAttributes<HTMLSpanElement>, VariantProps<typeof chipVariants> {
39
+ }
40
+ declare const Chip: react.ForwardRefExoticComponent<ChipProps & react.RefAttributes<HTMLSpanElement>>;
41
+
42
+ declare const containerVariants: (props?: ({
43
+ size?: "default" | "narrow" | null | undefined;
44
+ } & class_variance_authority_types.ClassProp) | undefined) => string;
45
+ interface ContainerProps extends HTMLAttributes<HTMLDivElement>, VariantProps<typeof containerVariants> {
46
+ }
47
+ declare const Container: react.ForwardRefExoticComponent<ContainerProps & react.RefAttributes<HTMLDivElement>>;
48
+
49
+ declare const dividerVariants: (props?: ({
50
+ orientation?: "horizontal" | "vertical" | null | undefined;
51
+ } & class_variance_authority_types.ClassProp) | undefined) => string;
52
+ interface DividerProps extends HTMLAttributes<HTMLDivElement>, VariantProps<typeof dividerVariants> {
53
+ }
54
+ declare const Divider: react.ForwardRefExoticComponent<DividerProps & react.RefAttributes<HTMLDivElement>>;
55
+
56
+ declare const heroBadgeVariants: (props?: ({
57
+ variant?: "primary" | "default" | "tertiary" | null | undefined;
58
+ } & class_variance_authority_types.ClassProp) | undefined) => string;
59
+ interface HeroBadgeProps extends HTMLAttributes<HTMLSpanElement>, VariantProps<typeof heroBadgeVariants> {
60
+ }
61
+ declare const HeroBadge: react.ForwardRefExoticComponent<HeroBadgeProps & react.RefAttributes<HTMLSpanElement>>;
62
+
63
+ declare const iconButtonVariants: (props?: ({
64
+ size?: "sm" | "md" | "lg" | null | undefined;
65
+ } & class_variance_authority_types.ClassProp) | undefined) => string;
66
+ interface IconButtonProps extends ButtonHTMLAttributes<HTMLButtonElement>, VariantProps<typeof iconButtonVariants> {
67
+ 'aria-label': string;
68
+ }
69
+ declare const IconButton: react.ForwardRefExoticComponent<IconButtonProps & react.RefAttributes<HTMLButtonElement>>;
70
+
71
+ declare const inputVariants: (props?: ({
72
+ variant?: "default" | "error" | null | undefined;
73
+ } & class_variance_authority_types.ClassProp) | undefined) => string;
74
+ interface InputProps extends InputHTMLAttributes<HTMLInputElement>, VariantProps<typeof inputVariants> {
75
+ label?: string;
76
+ error?: string;
77
+ }
78
+ declare const Input: react.ForwardRefExoticComponent<InputProps & react.RefAttributes<HTMLInputElement>>;
79
+
80
+ declare const modalVariants: (props?: ({
81
+ size?: "sm" | "md" | "lg" | "full" | null | undefined;
82
+ } & class_variance_authority_types.ClassProp) | undefined) => string;
83
+ interface ModalProps extends Omit<HTMLAttributes<HTMLDialogElement>, 'title'>, VariantProps<typeof modalVariants> {
84
+ open: boolean;
85
+ onClose: () => void;
86
+ title: string;
87
+ }
88
+ declare const Modal: react.ForwardRefExoticComponent<ModalProps & react.RefAttributes<HTMLDialogElement>>;
89
+
90
+ declare const progressBarVariants: (props?: ({
91
+ variant?: "primary" | "danger" | "success" | "warning" | null | undefined;
92
+ size?: "sm" | "md" | "lg" | null | undefined;
93
+ } & class_variance_authority_types.ClassProp) | undefined) => string;
94
+ interface ProgressBarProps extends HTMLAttributes<HTMLDivElement>, VariantProps<typeof progressBarVariants> {
95
+ value: number;
96
+ max?: number;
97
+ label?: string;
98
+ }
99
+ declare const ProgressBar: react.ForwardRefExoticComponent<ProgressBarProps & react.RefAttributes<HTMLDivElement>>;
100
+
101
+ declare const radioGroupVariants: (props?: ({
102
+ orientation?: "horizontal" | "vertical" | null | undefined;
103
+ } & class_variance_authority_types.ClassProp) | undefined) => string;
104
+ interface RadioOption {
105
+ value: string;
106
+ label: string;
107
+ description?: string;
108
+ }
109
+ interface RadioGroupProps extends Omit<HTMLAttributes<HTMLFieldSetElement>, 'onChange'>, VariantProps<typeof radioGroupVariants> {
110
+ name: string;
111
+ label?: string;
112
+ options: RadioOption[];
113
+ value: string;
114
+ onChange: (value: string) => void;
115
+ disabled?: boolean;
116
+ }
117
+ declare const RadioGroup: react.ForwardRefExoticComponent<RadioGroupProps & react.RefAttributes<HTMLFieldSetElement>>;
118
+
119
+ declare const selectVariants: (props?: ({
120
+ size?: "sm" | "md" | "lg" | null | undefined;
121
+ } & class_variance_authority_types.ClassProp) | undefined) => string;
122
+ interface SelectProps extends Omit<SelectHTMLAttributes<HTMLSelectElement>, 'size'>, VariantProps<typeof selectVariants> {
123
+ label?: string;
124
+ options: {
125
+ value: string;
126
+ label: string;
127
+ }[];
128
+ }
129
+ declare const Select: react.ForwardRefExoticComponent<SelectProps & react.RefAttributes<HTMLSelectElement>>;
130
+
131
+ declare const sidebarCardVariants: (props?: ({
132
+ variant?: "default" | "elevated" | null | undefined;
133
+ } & class_variance_authority_types.ClassProp) | undefined) => string;
134
+ interface SidebarCardProps extends HTMLAttributes<HTMLDivElement>, VariantProps<typeof sidebarCardVariants> {
135
+ title: string;
136
+ icon?: ReactNode;
137
+ }
138
+ declare const SidebarCard: react.ForwardRefExoticComponent<SidebarCardProps & react.RefAttributes<HTMLDivElement>>;
139
+
140
+ declare const switchVariants: (props?: ({
141
+ size?: "sm" | "md" | "lg" | null | undefined;
142
+ } & class_variance_authority_types.ClassProp) | undefined) => string;
143
+ interface SwitchProps extends Omit<HTMLAttributes<HTMLLabelElement>, 'onChange'>, VariantProps<typeof switchVariants> {
144
+ label?: string;
145
+ checked: boolean;
146
+ onChange: (checked: boolean) => void;
147
+ disabled?: boolean;
148
+ }
149
+ declare const Switch: react.ForwardRefExoticComponent<SwitchProps & react.RefAttributes<HTMLLabelElement>>;
150
+
151
+ declare const toastVariants: (props?: ({
152
+ variant?: "danger" | "info" | "success" | null | undefined;
153
+ } & class_variance_authority_types.ClassProp) | undefined) => string;
154
+ interface ToastProps extends Omit<HTMLAttributes<HTMLDivElement>, 'onClose'>, VariantProps<typeof toastVariants> {
155
+ message: string;
156
+ duration?: number;
157
+ onClose: () => void;
158
+ }
159
+ declare const Toast: react.ForwardRefExoticComponent<ToastProps & react.RefAttributes<HTMLDivElement>>;
160
+
161
+ declare const tableRootVariants: (props?: ({
162
+ density?: "default" | "compact" | "comfortable" | null | undefined;
163
+ } & class_variance_authority_types.ClassProp) | undefined) => string;
164
+ interface TableRootProps extends HTMLAttributes<HTMLTableElement>, VariantProps<typeof tableRootVariants> {
165
+ }
166
+ declare const TableRoot: react.ForwardRefExoticComponent<TableRootProps & react.RefAttributes<HTMLTableElement>>;
167
+
168
+ interface TableHeadProps extends HTMLAttributes<HTMLTableSectionElement> {
169
+ }
170
+ declare const TableHead: react.ForwardRefExoticComponent<TableHeadProps & react.RefAttributes<HTMLTableSectionElement>>;
171
+
172
+ interface TableBodyProps extends HTMLAttributes<HTMLTableSectionElement> {
173
+ }
174
+ declare const TableBody: react.ForwardRefExoticComponent<TableBodyProps & react.RefAttributes<HTMLTableSectionElement>>;
175
+
176
+ declare const tableRowVariants: (props?: ({
177
+ hoverable?: boolean | null | undefined;
178
+ selected?: boolean | null | undefined;
179
+ } & class_variance_authority_types.ClassProp) | undefined) => string;
180
+ interface TableRowProps extends HTMLAttributes<HTMLTableRowElement>, VariantProps<typeof tableRowVariants> {
181
+ }
182
+ declare const TableRow: react.ForwardRefExoticComponent<TableRowProps & react.RefAttributes<HTMLTableRowElement>>;
183
+
184
+ declare const tableHeaderCellVariants: (props?: ({
185
+ align?: "left" | "center" | "right" | null | undefined;
186
+ } & class_variance_authority_types.ClassProp) | undefined) => string;
187
+ interface TableHeaderCellProps extends Omit<ThHTMLAttributes<HTMLTableCellElement>, 'align'>, VariantProps<typeof tableHeaderCellVariants> {
188
+ }
189
+ declare const TableHeaderCell: react.ForwardRefExoticComponent<TableHeaderCellProps & react.RefAttributes<HTMLTableCellElement>>;
190
+
191
+ declare const tableCellVariants: (props?: ({
192
+ align?: "left" | "center" | "right" | null | undefined;
193
+ } & class_variance_authority_types.ClassProp) | undefined) => string;
194
+ interface TableCellProps extends Omit<TdHTMLAttributes<HTMLTableCellElement>, 'align'>, VariantProps<typeof tableCellVariants> {
195
+ }
196
+ declare const TableCell: react.ForwardRefExoticComponent<TableCellProps & react.RefAttributes<HTMLTableCellElement>>;
197
+
198
+ type index$1_TableBodyProps = TableBodyProps;
199
+ type index$1_TableCellProps = TableCellProps;
200
+ type index$1_TableHeadProps = TableHeadProps;
201
+ type index$1_TableHeaderCellProps = TableHeaderCellProps;
202
+ type index$1_TableRootProps = TableRootProps;
203
+ type index$1_TableRowProps = TableRowProps;
204
+ declare const index$1_tableCellVariants: typeof tableCellVariants;
205
+ declare const index$1_tableHeaderCellVariants: typeof tableHeaderCellVariants;
206
+ declare const index$1_tableRootVariants: typeof tableRootVariants;
207
+ declare const index$1_tableRowVariants: typeof tableRowVariants;
208
+ declare namespace index$1 {
209
+ export { TableBody as Body, TableCell as Cell, TableHead as Head, TableHeaderCell as HeaderCell, TableRoot as Root, TableRow as Row, type index$1_TableBodyProps as TableBodyProps, type index$1_TableCellProps as TableCellProps, type index$1_TableHeadProps as TableHeadProps, type index$1_TableHeaderCellProps as TableHeaderCellProps, type index$1_TableRootProps as TableRootProps, type index$1_TableRowProps as TableRowProps, index$1_tableCellVariants as tableCellVariants, index$1_tableHeaderCellVariants as tableHeaderCellVariants, index$1_tableRootVariants as tableRootVariants, index$1_tableRowVariants as tableRowVariants };
210
+ }
211
+
212
+ declare const cardRootVariants: (props?: ({
213
+ variant?: "filled" | "elevated" | "outlined" | null | undefined;
214
+ padding?: boolean | null | undefined;
215
+ } & class_variance_authority_types.ClassProp) | undefined) => string;
216
+ interface CardRootProps extends HTMLAttributes<HTMLDivElement>, VariantProps<typeof cardRootVariants> {
217
+ }
218
+ declare const CardRoot: react.ForwardRefExoticComponent<CardRootProps & react.RefAttributes<HTMLDivElement>>;
219
+
220
+ interface CardHeaderProps extends HTMLAttributes<HTMLDivElement> {
221
+ }
222
+ declare const CardHeader: react.ForwardRefExoticComponent<CardHeaderProps & react.RefAttributes<HTMLDivElement>>;
223
+
224
+ declare const cardTitleVariants: (props?: ({
225
+ size?: "sm" | "md" | "lg" | null | undefined;
226
+ } & class_variance_authority_types.ClassProp) | undefined) => string;
227
+ interface CardTitleProps extends HTMLAttributes<HTMLHeadingElement>, VariantProps<typeof cardTitleVariants> {
228
+ }
229
+ declare const CardTitle: react.ForwardRefExoticComponent<CardTitleProps & react.RefAttributes<HTMLHeadingElement>>;
230
+
231
+ interface CardBodyProps extends HTMLAttributes<HTMLDivElement> {
232
+ }
233
+ declare const CardBody: react.ForwardRefExoticComponent<CardBodyProps & react.RefAttributes<HTMLDivElement>>;
234
+
235
+ interface CardFooterProps extends HTMLAttributes<HTMLDivElement> {
236
+ }
237
+ declare const CardFooter: react.ForwardRefExoticComponent<CardFooterProps & react.RefAttributes<HTMLDivElement>>;
238
+
239
+ type index_CardBodyProps = CardBodyProps;
240
+ type index_CardFooterProps = CardFooterProps;
241
+ type index_CardHeaderProps = CardHeaderProps;
242
+ type index_CardRootProps = CardRootProps;
243
+ type index_CardTitleProps = CardTitleProps;
244
+ declare const index_cardRootVariants: typeof cardRootVariants;
245
+ declare const index_cardTitleVariants: typeof cardTitleVariants;
246
+ declare namespace index {
247
+ export { CardBody as Body, type index_CardBodyProps as CardBodyProps, type index_CardFooterProps as CardFooterProps, type index_CardHeaderProps as CardHeaderProps, type index_CardRootProps as CardRootProps, type index_CardTitleProps as CardTitleProps, CardFooter as Footer, CardHeader as Header, CardRoot as Root, CardTitle as Title, index_cardRootVariants as cardRootVariants, index_cardTitleVariants as cardTitleVariants };
248
+ }
249
+
250
+ export { Alert, type AlertProps, Badge, type BadgeProps, Button, type ButtonProps, index as Card, Chip, type ChipProps, Container, type ContainerProps, Divider, type DividerProps, HeroBadge, type HeroBadgeProps, IconButton, type IconButtonProps, Input, type InputProps, Modal, type ModalProps, ProgressBar, type ProgressBarProps, RadioGroup, type RadioGroupProps, Select, type SelectProps, SidebarCard, type SidebarCardProps, Switch, type SwitchProps, index$1 as Table, Toast, type ToastProps, alertVariants, badgeVariants, buttonVariants, chipVariants, cn, containerVariants, dividerVariants, heroBadgeVariants, iconButtonVariants, inputVariants, modalVariants, progressBarVariants, radioGroupVariants, selectVariants, sidebarCardVariants, switchVariants, toastVariants };