@zvoove/unity-ui 2.20.1 → 2.21.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/bin/generate-skills.mjs +683 -0
- package/dist/llms.txt +1185 -0
- package/dist/unity-ui.cjs.js +1 -1
- package/dist/unity-ui.css +1 -1
- package/dist/unity-ui.es.js +378 -378
- package/package.json +44 -34
package/dist/llms.txt
ADDED
|
@@ -0,0 +1,1185 @@
|
|
|
1
|
+
# Unity UI (@zvoove/unity-ui) - AI Component Reference
|
|
2
|
+
|
|
3
|
+
> This file describes all available components in the Unity UI design system.
|
|
4
|
+
> When building UIs, use ONLY these components. Do NOT create custom components for functionality already provided here.
|
|
5
|
+
|
|
6
|
+
## Setup
|
|
7
|
+
|
|
8
|
+
Install:
|
|
9
|
+
```bash
|
|
10
|
+
npm install @zvoove/unity-ui
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Import styles (required, add to your app entry point):
|
|
14
|
+
```css
|
|
15
|
+
@import '@zvoove/unity-ui/theme.css';
|
|
16
|
+
@import '@zvoove/unity-ui/unity-ui.css';
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Import components:
|
|
20
|
+
```tsx
|
|
21
|
+
import { Button, Card, TextField, Typography } from '@zvoove/unity-ui';
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Font (add to HTML head):
|
|
25
|
+
```html
|
|
26
|
+
<link href="https://fonts.googleapis.com/css2?family=Source+Sans+3:ital,wght@0,200..900;1,200..900&display=swap" rel="stylesheet" />
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Dark mode: add `data-theme="dark"` to a parent element.
|
|
30
|
+
|
|
31
|
+
## Responsive Props
|
|
32
|
+
|
|
33
|
+
Many props accept `ResponsiveType<T>`, meaning either a direct value OR a breakpoint object.
|
|
34
|
+
Breakpoints (from smallest to largest): `minimum` (0px), `mobile` (320px), `tablet` (768px), `laptop` (1024px), `desktop` (1440px).
|
|
35
|
+
Values cascade upward — setting `mobile` applies to all larger breakpoints until overridden.
|
|
36
|
+
|
|
37
|
+
```tsx
|
|
38
|
+
// Direct value — applies to all screen sizes
|
|
39
|
+
<Button size="md" />
|
|
40
|
+
|
|
41
|
+
// Responsive object — values cascade up from smallest to largest
|
|
42
|
+
<Button size={{ mobile: 'sm', tablet: 'md', desktop: 'lg' }} />
|
|
43
|
+
// mobile: sm → tablet: md → laptop: md (inherited) → desktop: lg
|
|
44
|
+
|
|
45
|
+
// Common patterns:
|
|
46
|
+
<Stack direction={{ mobile: 'column', tablet: 'row' }} /> // Stack vertically on mobile, horizontally on tablet+
|
|
47
|
+
<Grid columns={{ mobile: 1, tablet: 2, desktop: 3 }} /> // Responsive grid columns
|
|
48
|
+
<Card padding={{ mobile: 'sm', tablet: 'md', desktop: 'lg' }} /> // Responsive padding
|
|
49
|
+
<Button hideLabel={{ mobile: true, tablet: false }} icon="Plus" /> // Icon-only on mobile, label on tablet+
|
|
50
|
+
<Dialog size={{ mobile: 'fullscreen', tablet: 'md' }} /> // Fullscreen on mobile, modal on tablet+
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## LAYOUT COMPONENTS
|
|
56
|
+
|
|
57
|
+
### Stack
|
|
58
|
+
**Primary layout component.** Use Stack for ALL layout needs — arranging children in rows or columns with consistent spacing. Do NOT use Card or raw divs for layout.
|
|
59
|
+
```tsx
|
|
60
|
+
import { Stack } from '@zvoove/unity-ui';
|
|
61
|
+
|
|
62
|
+
<Stack
|
|
63
|
+
direction="column" // ResponsiveType<'row' | 'row-reverse' | 'column' | 'column-reverse'>
|
|
64
|
+
gap="md" // ResponsiveType<SpacingKeys> - none|xs2|xs|sm|md|lg|xl|xl2|xl3|xl4|xl5|xl6|xl7
|
|
65
|
+
align="center" // ResponsiveType<AlignItems> - default: 'baseline'
|
|
66
|
+
justify="space-between" // ResponsiveType<JustifyContent>
|
|
67
|
+
wrap="wrap" // ResponsiveType<FlexWrap>
|
|
68
|
+
padding="md" // ResponsiveType<Padding>
|
|
69
|
+
margin="none" // ResponsiveType<Margin>
|
|
70
|
+
width="100%" // ResponsiveType<number | string>
|
|
71
|
+
height="auto" // ResponsiveType<number | string>
|
|
72
|
+
minWidth, maxWidth, minHeight, maxHeight // ResponsiveType<number | string>
|
|
73
|
+
>
|
|
74
|
+
{children}
|
|
75
|
+
</Stack>
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Common patterns:
|
|
79
|
+
```tsx
|
|
80
|
+
// Page layout — stacks vertically on mobile, horizontally on tablet+
|
|
81
|
+
<Stack direction={{ mobile: 'column', tablet: 'row' }} gap="lg">
|
|
82
|
+
<Sidebar />
|
|
83
|
+
<MainContent />
|
|
84
|
+
</Stack>
|
|
85
|
+
|
|
86
|
+
// Form fields in a row
|
|
87
|
+
<Stack direction="row" gap="md" align="flex-end">
|
|
88
|
+
<TextField label="First name" name="first" />
|
|
89
|
+
<TextField label="Last name" name="last" />
|
|
90
|
+
</Stack>
|
|
91
|
+
|
|
92
|
+
// Action bar — right-aligned buttons
|
|
93
|
+
<Stack direction="row" gap="sm" justify="flex-end">
|
|
94
|
+
<Button variant="outlined">Cancel</Button>
|
|
95
|
+
<Button variant="filled">Save</Button>
|
|
96
|
+
</Stack>
|
|
97
|
+
|
|
98
|
+
// Centered content
|
|
99
|
+
<Stack direction="column" align="center" justify="center" gap="md" height="100%">
|
|
100
|
+
<Icon name="check-circle" size="2xl" />
|
|
101
|
+
<Typography variant="headline" size="medium">Success!</Typography>
|
|
102
|
+
</Stack>
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### Grid
|
|
106
|
+
CSS Grid container with Grid.Item children. Use Grid when you need multi-column layouts. Use Stack for simpler row/column arrangements.
|
|
107
|
+
```tsx
|
|
108
|
+
import { Grid } from '@zvoove/unity-ui';
|
|
109
|
+
|
|
110
|
+
<Grid
|
|
111
|
+
columns={3} // ResponsiveType<number | string> - default: 1
|
|
112
|
+
rows={1} // ResponsiveType<number | string> - default: 1
|
|
113
|
+
gap="md" // ResponsiveType<SpacingKeys>
|
|
114
|
+
padding="none" // ResponsiveType<Padding>
|
|
115
|
+
margin="none" // ResponsiveType<Margin>
|
|
116
|
+
width="100%" // ResponsiveType<number | string>
|
|
117
|
+
height="auto" // ResponsiveType<number | string>
|
|
118
|
+
>
|
|
119
|
+
<Grid.Item colSpan={2} rowSpan={1}>Content</Grid.Item>
|
|
120
|
+
<Grid.Item colSpan={1}>Content</Grid.Item>
|
|
121
|
+
</Grid>
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
Common patterns:
|
|
125
|
+
```tsx
|
|
126
|
+
// Responsive card grid — 1 col on mobile, 2 on tablet, 3 on desktop
|
|
127
|
+
<Grid columns={{ mobile: 1, tablet: 2, desktop: 3 }} gap="lg">
|
|
128
|
+
<Grid.Item><Card>Item 1</Card></Grid.Item>
|
|
129
|
+
<Grid.Item><Card>Item 2</Card></Grid.Item>
|
|
130
|
+
<Grid.Item><Card>Item 3</Card></Grid.Item>
|
|
131
|
+
</Grid>
|
|
132
|
+
|
|
133
|
+
// Form layout — 2 fields side by side on tablet+, stacked on mobile
|
|
134
|
+
<Grid columns={{ mobile: 1, tablet: 2 }} gap="md">
|
|
135
|
+
<Grid.Item><TextField label="First name" name="first" /></Grid.Item>
|
|
136
|
+
<Grid.Item><TextField label="Last name" name="last" /></Grid.Item>
|
|
137
|
+
</Grid>
|
|
138
|
+
|
|
139
|
+
// Wide + narrow column layout
|
|
140
|
+
<Grid columns={3} gap="md">
|
|
141
|
+
<Grid.Item colSpan={2}><Card>Main content</Card></Grid.Item>
|
|
142
|
+
<Grid.Item colSpan={1}><Card>Sidebar</Card></Grid.Item>
|
|
143
|
+
</Grid>
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
### Card
|
|
147
|
+
**Visual container** with background, elevation, and border. Use Card to group content visually (e.g., a profile card, a settings panel, a content section). Do NOT use Card for layout — use Stack or Grid instead. Card is a surface, not a layout tool.
|
|
148
|
+
```tsx
|
|
149
|
+
import { Card } from '@zvoove/unity-ui';
|
|
150
|
+
|
|
151
|
+
<Card
|
|
152
|
+
variant="filled" // 'outlined' | 'filled' (default: 'filled')
|
|
153
|
+
padding="md" // ResponsiveType<Padding> - default: 'md'. Use "none" for edge-to-edge content
|
|
154
|
+
margin="none" // ResponsiveType<Margin>
|
|
155
|
+
elevation={1} // 0 | 1 | 2 | 3 | 4 | 5 (default: 0)
|
|
156
|
+
borderRadius="md" // 'none' | 'sm' | 'md' | 'lg' | 'xl'
|
|
157
|
+
bgColor="surface" // BackgroundColors (default: 'surface')
|
|
158
|
+
overflow="visible" // ResponsiveType<Overflow>
|
|
159
|
+
width, height, minWidth, maxWidth, minHeight, maxHeight // ResponsiveType
|
|
160
|
+
>
|
|
161
|
+
{children}
|
|
162
|
+
</Card>
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
Common patterns:
|
|
166
|
+
```tsx
|
|
167
|
+
// Content card with internal layout using Stack (NOT Card for layout)
|
|
168
|
+
<Card variant="outlined" padding="lg" elevation={1}>
|
|
169
|
+
<Stack direction="column" gap="md">
|
|
170
|
+
<Typography variant="title" size="large">Profile</Typography>
|
|
171
|
+
<Typography variant="body" size="medium">User details here.</Typography>
|
|
172
|
+
</Stack>
|
|
173
|
+
</Card>
|
|
174
|
+
|
|
175
|
+
// Card with no padding — useful for full-width content like images or tables
|
|
176
|
+
<Card variant="outlined" padding="none">
|
|
177
|
+
<img src="/banner.jpg" style={{ width: '100%' }} />
|
|
178
|
+
<Stack padding="md" gap="sm">
|
|
179
|
+
<Typography variant="title" size="medium">Article title</Typography>
|
|
180
|
+
<Typography variant="body" size="medium">Article excerpt...</Typography>
|
|
181
|
+
</Stack>
|
|
182
|
+
</Card>
|
|
183
|
+
|
|
184
|
+
// Responsive padding — tighter on mobile, more spacious on desktop
|
|
185
|
+
<Card padding={{ mobile: 'sm', tablet: 'md', desktop: 'xl' }} elevation={2}>
|
|
186
|
+
{children}
|
|
187
|
+
</Card>
|
|
188
|
+
|
|
189
|
+
// WRONG: Do NOT use Card for layout. Use Stack instead.
|
|
190
|
+
// Bad: <Card><TextField /><TextField /></Card>
|
|
191
|
+
// Good: <Stack direction="column" gap="md"><TextField /><TextField /></Stack>
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
### Divider
|
|
195
|
+
Horizontal separator line.
|
|
196
|
+
```tsx
|
|
197
|
+
import { Divider } from '@zvoove/unity-ui';
|
|
198
|
+
|
|
199
|
+
<Divider variant="fullWidth" /> // 'fullWidth' | 'inset' | 'middle'
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
### Expandable
|
|
203
|
+
Animated collapsible container.
|
|
204
|
+
```tsx
|
|
205
|
+
import { Expandable } from '@zvoove/unity-ui';
|
|
206
|
+
|
|
207
|
+
<Expandable isOpen={true} as="div">
|
|
208
|
+
{children}
|
|
209
|
+
</Expandable>
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
### ContentBlock
|
|
213
|
+
Simple content wrapper.
|
|
214
|
+
```tsx
|
|
215
|
+
import { ContentBlock } from '@zvoove/unity-ui';
|
|
216
|
+
|
|
217
|
+
<ContentBlock>{children}</ContentBlock>
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
---
|
|
221
|
+
|
|
222
|
+
## TYPOGRAPHY
|
|
223
|
+
|
|
224
|
+
### Typography
|
|
225
|
+
Text rendering component with variants. Use Typography for ALL text — never use raw `<p>`, `<h1>`, `<span>` tags.
|
|
226
|
+
```tsx
|
|
227
|
+
import { Typography } from '@zvoove/unity-ui';
|
|
228
|
+
|
|
229
|
+
<Typography
|
|
230
|
+
variant="body" // 'display' | 'headline' | 'title' | 'body' | 'label'
|
|
231
|
+
size="medium" // 'small' | 'medium' | 'large'
|
|
232
|
+
as="p" // 'p' | 'span' | 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6'
|
|
233
|
+
color="on-surface" // ForegroundColors
|
|
234
|
+
textAlign="left" // 'left' | 'center' | 'right'
|
|
235
|
+
textTransform="uppercase" // 'uppercase' | 'lowercase' | 'capitalize'
|
|
236
|
+
truncate={2} // number - max lines before truncation
|
|
237
|
+
hyphenate={true} // boolean (default: true)
|
|
238
|
+
wrap={true} // boolean
|
|
239
|
+
>
|
|
240
|
+
Text content
|
|
241
|
+
</Typography>
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
Variant guide:
|
|
245
|
+
```tsx
|
|
246
|
+
// Page heading
|
|
247
|
+
<Typography variant="display" size="large" as="h1">Page Title</Typography>
|
|
248
|
+
|
|
249
|
+
// Section heading
|
|
250
|
+
<Typography variant="headline" size="medium" as="h2">Section Title</Typography>
|
|
251
|
+
|
|
252
|
+
// Card/dialog title
|
|
253
|
+
<Typography variant="title" size="large">Card Title</Typography>
|
|
254
|
+
|
|
255
|
+
// Body text (default)
|
|
256
|
+
<Typography variant="body" size="medium">Paragraph text goes here.</Typography>
|
|
257
|
+
|
|
258
|
+
// Small labels, captions
|
|
259
|
+
<Typography variant="label" size="small" color="on-surface-variant">Updated 2 hours ago</Typography>
|
|
260
|
+
|
|
261
|
+
// Truncate long text to 2 lines
|
|
262
|
+
<Typography variant="body" size="medium" truncate={2}>Very long text that will be cut off...</Typography>
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
---
|
|
266
|
+
|
|
267
|
+
## FORM COMPONENTS
|
|
268
|
+
|
|
269
|
+
### TextField
|
|
270
|
+
Text input with label, validation, and icon support.
|
|
271
|
+
```tsx
|
|
272
|
+
import { TextField } from '@zvoove/unity-ui';
|
|
273
|
+
|
|
274
|
+
<TextField
|
|
275
|
+
label="Email" // string (required)
|
|
276
|
+
name="email" // string
|
|
277
|
+
value={value} // string
|
|
278
|
+
onChange={handleChange} // (event: ChangeEvent<HTMLInputElement>) => void
|
|
279
|
+
placeholder="Enter email" // string
|
|
280
|
+
error={false} // boolean
|
|
281
|
+
errorMessage="Invalid email" // string
|
|
282
|
+
disabled={false} // boolean
|
|
283
|
+
hideLabel={false} // boolean
|
|
284
|
+
clearable={false} // boolean
|
|
285
|
+
icon="MagnifyingGlass" // CommonIconNames
|
|
286
|
+
iconPosition="right" // 'left' | 'right'
|
|
287
|
+
onIconClick={handleClick} // () => void
|
|
288
|
+
density="default" // ResponsiveType<'default' | '-2' | '-4'>
|
|
289
|
+
type="text" // standard HTML input types
|
|
290
|
+
required={false} // boolean
|
|
291
|
+
/>
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
### Textarea
|
|
295
|
+
Multi-line text input.
|
|
296
|
+
```tsx
|
|
297
|
+
import { Textarea } from '@zvoove/unity-ui';
|
|
298
|
+
|
|
299
|
+
<Textarea
|
|
300
|
+
value={value} // string
|
|
301
|
+
onChange={handleChange} // ChangeEventHandler<HTMLTextAreaElement>
|
|
302
|
+
error={false} // boolean
|
|
303
|
+
errorMessage="Too long" // string
|
|
304
|
+
maxLength={500} // number
|
|
305
|
+
actions={<Button>Save</Button>} // ReactNode
|
|
306
|
+
rows={4} // number (standard HTML)
|
|
307
|
+
placeholder="Enter text" // string
|
|
308
|
+
disabled={false} // boolean
|
|
309
|
+
/>
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
### Select
|
|
313
|
+
Dropdown select with search and multi-select support.
|
|
314
|
+
```tsx
|
|
315
|
+
import { Select } from '@zvoove/unity-ui';
|
|
316
|
+
|
|
317
|
+
<Select
|
|
318
|
+
name="country" // string (required)
|
|
319
|
+
label="Country" // string
|
|
320
|
+
options={[ // SelectOption[] (required)
|
|
321
|
+
{ value: 'de', label: 'Germany', icon: 'Flag' },
|
|
322
|
+
{ value: 'us', label: 'United States' },
|
|
323
|
+
]}
|
|
324
|
+
value="de" // string | string[]
|
|
325
|
+
onChange={handleChange} // ChangeEventHandler<HTMLSelectElement>
|
|
326
|
+
multiple={false} // boolean
|
|
327
|
+
searchable={false} // boolean
|
|
328
|
+
error={false} // boolean
|
|
329
|
+
errorMessage="Required" // string
|
|
330
|
+
disabled={false} // boolean
|
|
331
|
+
hideLabel={false} // boolean
|
|
332
|
+
/>
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
Common patterns:
|
|
336
|
+
```tsx
|
|
337
|
+
// Searchable select — for long option lists
|
|
338
|
+
<Select name="country" label="Country" searchable={true} options={countries} />
|
|
339
|
+
|
|
340
|
+
// Multi-select
|
|
341
|
+
<Select
|
|
342
|
+
name="tags"
|
|
343
|
+
label="Tags"
|
|
344
|
+
multiple={true}
|
|
345
|
+
value={['react', 'typescript']}
|
|
346
|
+
options={[
|
|
347
|
+
{ value: 'react', label: 'React' },
|
|
348
|
+
{ value: 'typescript', label: 'TypeScript' },
|
|
349
|
+
{ value: 'node', label: 'Node.js' },
|
|
350
|
+
]}
|
|
351
|
+
/>
|
|
352
|
+
|
|
353
|
+
// With icons
|
|
354
|
+
<Select
|
|
355
|
+
name="priority"
|
|
356
|
+
label="Priority"
|
|
357
|
+
options={[
|
|
358
|
+
{ value: 'high', label: 'High', icon: 'arrow-up' },
|
|
359
|
+
{ value: 'medium', label: 'Medium', icon: 'minus' },
|
|
360
|
+
{ value: 'low', label: 'Low', icon: 'arrow-down' },
|
|
361
|
+
]}
|
|
362
|
+
/>
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
### Checkbox
|
|
366
|
+
Checkbox input with label.
|
|
367
|
+
```tsx
|
|
368
|
+
import { Checkbox } from '@zvoove/unity-ui';
|
|
369
|
+
|
|
370
|
+
<Checkbox
|
|
371
|
+
label="Accept terms" // ReactNode (required)
|
|
372
|
+
name="terms" // string
|
|
373
|
+
checked={false} // boolean
|
|
374
|
+
onChange={handleChange} // ChangeEventHandler<HTMLInputElement>
|
|
375
|
+
disabled={false} // boolean
|
|
376
|
+
error={false} // boolean
|
|
377
|
+
indeterminate={false} // boolean
|
|
378
|
+
value="accepted" // string
|
|
379
|
+
/>
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
### Radio (RadioGroup + RadioButton)
|
|
383
|
+
Radio button group for single selection.
|
|
384
|
+
```tsx
|
|
385
|
+
import { RadioGroup, RadioButton } from '@zvoove/unity-ui';
|
|
386
|
+
|
|
387
|
+
<RadioGroup
|
|
388
|
+
name="size" // string (required)
|
|
389
|
+
value={selectedValue} // string
|
|
390
|
+
onChange={handleChange} // (e: ChangeEvent<HTMLInputElement>) => void
|
|
391
|
+
row={false} // boolean - horizontal layout
|
|
392
|
+
disabled={false} // boolean
|
|
393
|
+
>
|
|
394
|
+
<RadioButton label="Small" value="sm" />
|
|
395
|
+
<RadioButton label="Medium" value="md" />
|
|
396
|
+
<RadioButton label="Large" value="lg" />
|
|
397
|
+
</RadioGroup>
|
|
398
|
+
```
|
|
399
|
+
|
|
400
|
+
### Switch
|
|
401
|
+
Toggle switch input.
|
|
402
|
+
```tsx
|
|
403
|
+
import { Switch } from '@zvoove/unity-ui';
|
|
404
|
+
|
|
405
|
+
<Switch
|
|
406
|
+
checked={false} // boolean
|
|
407
|
+
onChange={handleChange} // ChangeEventHandler<HTMLInputElement>
|
|
408
|
+
label="Enable notifications" // string | { on: string; off: string }
|
|
409
|
+
labelPlacement="left" // 'left' | 'right' (default: 'left')
|
|
410
|
+
justify="space-between" // JustifyContent
|
|
411
|
+
disabled={false} // boolean
|
|
412
|
+
withIcons={false} // boolean | { on: IconName; off: IconName }
|
|
413
|
+
name="notifications" // string
|
|
414
|
+
value="enabled" // string
|
|
415
|
+
/>
|
|
416
|
+
```
|
|
417
|
+
|
|
418
|
+
### DatePicker
|
|
419
|
+
Date input with calendar popup.
|
|
420
|
+
```tsx
|
|
421
|
+
import { DatePicker } from '@zvoove/unity-ui';
|
|
422
|
+
|
|
423
|
+
<DatePicker
|
|
424
|
+
label="Start date" // string (required)
|
|
425
|
+
name="startDate" // string (required)
|
|
426
|
+
value="2024-01-15" // string (YYYY-MM-DD)
|
|
427
|
+
onChange={handleChange} // (e: ChangeEvent<HTMLInputElement>, date?: Date) => void
|
|
428
|
+
locale="en-US" // string (default: 'de-DE')
|
|
429
|
+
minDate="2024-01-01" // string (YYYY-MM-DD)
|
|
430
|
+
maxDate="2024-12-31" // string (YYYY-MM-DD)
|
|
431
|
+
openOnFocus={false} // boolean
|
|
432
|
+
closeOnSelect={false} // boolean
|
|
433
|
+
placeholder="Select date" // string
|
|
434
|
+
error={false} // boolean
|
|
435
|
+
errorMessage="Invalid date" // string
|
|
436
|
+
disabled={false} // boolean
|
|
437
|
+
buttonsTranslations={{ cancel: 'Cancel', clear: 'Clear', ok: 'OK' }}
|
|
438
|
+
/>
|
|
439
|
+
```
|
|
440
|
+
|
|
441
|
+
### Uploader
|
|
442
|
+
File upload component with drag-and-drop.
|
|
443
|
+
```tsx
|
|
444
|
+
import { Uploader } from '@zvoove/unity-ui';
|
|
445
|
+
|
|
446
|
+
<Uploader
|
|
447
|
+
accept="image/*,.pdf" // string
|
|
448
|
+
multiple={true} // boolean (default: true)
|
|
449
|
+
maxFileSize={5000000} // number (bytes)
|
|
450
|
+
maxTotalSize={20000000} // number (bytes)
|
|
451
|
+
maxCount={10} // number
|
|
452
|
+
value={files} // FileItem[]
|
|
453
|
+
onChange={handleChange} // (event: ChangeEvent) => void
|
|
454
|
+
onValidation={handleError} // (event: ValidationEvent) => void
|
|
455
|
+
disabled={false} // boolean
|
|
456
|
+
canDeleteFile={true} // boolean
|
|
457
|
+
selectionMode="append" // 'append' | 'replace' (default: 'append')
|
|
458
|
+
showFileList={true} // boolean (default: true)
|
|
459
|
+
name="files" // string
|
|
460
|
+
required={false} // boolean
|
|
461
|
+
/>
|
|
462
|
+
```
|
|
463
|
+
|
|
464
|
+
### FormLabel
|
|
465
|
+
Label for form fields.
|
|
466
|
+
```tsx
|
|
467
|
+
import { FormLabel } from '@zvoove/unity-ui';
|
|
468
|
+
|
|
469
|
+
<FormLabel value="Email address" htmlFor="email" required={true} />
|
|
470
|
+
```
|
|
471
|
+
|
|
472
|
+
---
|
|
473
|
+
|
|
474
|
+
## ACTION COMPONENTS
|
|
475
|
+
|
|
476
|
+
### Button
|
|
477
|
+
Primary action component with multiple variants.
|
|
478
|
+
```tsx
|
|
479
|
+
import { Button } from '@zvoove/unity-ui';
|
|
480
|
+
|
|
481
|
+
<Button
|
|
482
|
+
variant="filled" // ResponsiveType<'filled' | 'outlined' | 'text' | 'textSecondary' | 'elevated' | 'tonal' | 'linkPrimary' | 'linkSecondary' | 'positive' | 'negative'>
|
|
483
|
+
size="lg" // ResponsiveType<'sm' | 'md' | 'lg'> (default: 'lg')
|
|
484
|
+
icon="Plus" // CommonIconNames | Omit<IconProps, 'size' | 'color'>
|
|
485
|
+
hideLabel={false} // ResponsiveType<boolean>
|
|
486
|
+
onClick={handleClick} // (event: MouseEvent) => void
|
|
487
|
+
isLoading={false} // boolean
|
|
488
|
+
disabled={false} // boolean
|
|
489
|
+
as="button" // 'a' | 'button' | 'span' (default: 'button')
|
|
490
|
+
linkComponent={Link} // React.ElementType (for router links)
|
|
491
|
+
>
|
|
492
|
+
Click me
|
|
493
|
+
</Button>
|
|
494
|
+
```
|
|
495
|
+
|
|
496
|
+
Variant guide:
|
|
497
|
+
```tsx
|
|
498
|
+
// Primary action → filled
|
|
499
|
+
<Button variant="filled">Save</Button>
|
|
500
|
+
|
|
501
|
+
// Secondary action → outlined
|
|
502
|
+
<Button variant="outlined">Cancel</Button>
|
|
503
|
+
|
|
504
|
+
// Destructive action → negative
|
|
505
|
+
<Button variant="negative" icon="delete">Delete</Button>
|
|
506
|
+
|
|
507
|
+
// Success action → positive
|
|
508
|
+
<Button variant="positive" icon="check">Confirm</Button>
|
|
509
|
+
|
|
510
|
+
// Subtle/tertiary action → text
|
|
511
|
+
<Button variant="text">Learn more</Button>
|
|
512
|
+
|
|
513
|
+
// Link-style button → linkPrimary / linkSecondary
|
|
514
|
+
<Button variant="linkPrimary">View details</Button>
|
|
515
|
+
|
|
516
|
+
// Icon-only button (must have aria-label)
|
|
517
|
+
<Button variant="outlined" icon="edit" aria-label="Edit item" />
|
|
518
|
+
|
|
519
|
+
// Responsive: icon-only on mobile, full label on tablet+
|
|
520
|
+
<Button variant="filled" icon="add" hideLabel={{ mobile: true, tablet: false }}>
|
|
521
|
+
Add item
|
|
522
|
+
</Button>
|
|
523
|
+
|
|
524
|
+
// Loading state
|
|
525
|
+
<Button variant="filled" isLoading={true}>Saving...</Button>
|
|
526
|
+
|
|
527
|
+
// As a router link
|
|
528
|
+
<Button variant="filled" linkComponent={Link} href="/settings">Settings</Button>
|
|
529
|
+
```
|
|
530
|
+
|
|
531
|
+
### Segment (SegmentGroup + SegmentButton)
|
|
532
|
+
Segmented control for toggling between options.
|
|
533
|
+
```tsx
|
|
534
|
+
import { SegmentGroup, SegmentButton } from '@zvoove/unity-ui';
|
|
535
|
+
|
|
536
|
+
<SegmentGroup
|
|
537
|
+
activeButton="list" // V | V[]
|
|
538
|
+
onChange={handleChange} // (value: V | V[]) => void
|
|
539
|
+
stretch={false} // boolean
|
|
540
|
+
multiSelect={false} // boolean
|
|
541
|
+
disabled={false} // boolean
|
|
542
|
+
>
|
|
543
|
+
<SegmentButton value="list" label="List" icon="List" />
|
|
544
|
+
<SegmentButton value="grid" label="Grid" icon="GridFour" />
|
|
545
|
+
</SegmentGroup>
|
|
546
|
+
```
|
|
547
|
+
|
|
548
|
+
### PopUpMenu
|
|
549
|
+
Context menu / dropdown menu.
|
|
550
|
+
```tsx
|
|
551
|
+
import { PopUpMenu } from '@zvoove/unity-ui';
|
|
552
|
+
|
|
553
|
+
<PopUpMenu
|
|
554
|
+
items={[ // PopUpMenuItem[] (required)
|
|
555
|
+
{ id: '1', label: 'Edit', icon: 'Pencil' },
|
|
556
|
+
{ id: '2', label: 'Delete', icon: 'Trash', variant: 'error' },
|
|
557
|
+
{ id: 'divider', isDivider: true },
|
|
558
|
+
{ id: '3', label: 'Settings' },
|
|
559
|
+
]}
|
|
560
|
+
trigger="click" // 'hover' | 'click' | 'right-click' (default: 'click')
|
|
561
|
+
placement="bottom-left" // PopUpMenuPlacement (default: 'bottom-left')
|
|
562
|
+
selectable="none" // 'single' | 'multiple' | 'none' (default: 'none')
|
|
563
|
+
selectedItem={selected} // string | string[]
|
|
564
|
+
onItemClick={handleClick} // (item, selectedItem?) => void
|
|
565
|
+
density="default" // 'default' | '-2' | '-4'
|
|
566
|
+
showSearch={false} // boolean
|
|
567
|
+
searchPlaceholder="Search" // string
|
|
568
|
+
disabled={false} // boolean
|
|
569
|
+
>
|
|
570
|
+
<Button>Actions</Button>
|
|
571
|
+
</PopUpMenu>
|
|
572
|
+
```
|
|
573
|
+
|
|
574
|
+
---
|
|
575
|
+
|
|
576
|
+
## DATA DISPLAY COMPONENTS
|
|
577
|
+
|
|
578
|
+
### Table
|
|
579
|
+
Data table with sorting, expandable rows, and actions.
|
|
580
|
+
```tsx
|
|
581
|
+
import { Table } from '@zvoove/unity-ui';
|
|
582
|
+
|
|
583
|
+
const columns = [
|
|
584
|
+
{ id: 'name', label: 'Name', orderable: true },
|
|
585
|
+
{ id: 'email', label: 'Email' },
|
|
586
|
+
{ id: 'role', label: 'Role', align: 'right' as const },
|
|
587
|
+
] as const;
|
|
588
|
+
|
|
589
|
+
<Table
|
|
590
|
+
columns={columns} // TableColumnProps[] (required)
|
|
591
|
+
data={[ // TableRowData[] (required)
|
|
592
|
+
{ id: '1', name: 'John Doe', email: 'john@example.com', role: 'Admin' },
|
|
593
|
+
]}
|
|
594
|
+
title="Users" // string
|
|
595
|
+
subtitle="All active users" // string
|
|
596
|
+
actions={<Button>Add user</Button>} // ReactNode
|
|
597
|
+
filters={filterComponent} // ReactNode
|
|
598
|
+
loading={false} // boolean
|
|
599
|
+
orderBy={{ column: 'name', direction: 'asc' }}
|
|
600
|
+
onOrderByChange={handleSort} // ({ columnId, direction }) => void
|
|
601
|
+
hiddenColumns={['email']} // ColumnId[]
|
|
602
|
+
expandedRows={['1']} // string[]
|
|
603
|
+
emptyState="No data found" // ReactNode
|
|
604
|
+
footer={footerContent} // ReactNode
|
|
605
|
+
/>
|
|
606
|
+
```
|
|
607
|
+
|
|
608
|
+
### Tag
|
|
609
|
+
Colored label/badge for categorization.
|
|
610
|
+
```tsx
|
|
611
|
+
import { Tag } from '@zvoove/unity-ui';
|
|
612
|
+
|
|
613
|
+
<Tag
|
|
614
|
+
label="Active" // string (required)
|
|
615
|
+
variant="solid" // 'solid' | 'outlined' | 'ghost'
|
|
616
|
+
color="green" // 'green' | 'yellow' | 'pink' | 'steel-blue' | 'error' | 'primary' | 'neutral'
|
|
617
|
+
tone="dark" // 'dark' | 'light' (only with variant='solid')
|
|
618
|
+
size="medium" // 'large' | 'medium' | 'small'
|
|
619
|
+
icon="Check" // CommonIconNames
|
|
620
|
+
/>
|
|
621
|
+
```
|
|
622
|
+
|
|
623
|
+
### Chip
|
|
624
|
+
Interactive chip for filters, selections, and suggestions.
|
|
625
|
+
```tsx
|
|
626
|
+
import { Chip } from '@zvoove/unity-ui';
|
|
627
|
+
|
|
628
|
+
<Chip
|
|
629
|
+
label="React" // string (required)
|
|
630
|
+
type="filter" // 'input' | 'filter' | 'assistive' | 'suggestion' | 'choice'
|
|
631
|
+
icon="Code" // CommonIconNames
|
|
632
|
+
variant="primary" // 'primary' | 'secondary' | 'pending' | 'confirmed' | 'rejected' | 'skipped'
|
|
633
|
+
elevated={false} // boolean
|
|
634
|
+
readonly={false} // boolean
|
|
635
|
+
disabled={false} // boolean
|
|
636
|
+
size="medium" // 'medium' | 'large'
|
|
637
|
+
onDelete={handleDelete} // () => void
|
|
638
|
+
showDropdownIcon={true} // boolean
|
|
639
|
+
onToggleOpen={handleToggle} // () => void
|
|
640
|
+
/>
|
|
641
|
+
```
|
|
642
|
+
|
|
643
|
+
### Avatar & AvatarGroup
|
|
644
|
+
User avatar display.
|
|
645
|
+
```tsx
|
|
646
|
+
import { Avatar, AvatarGroup } from '@zvoove/unity-ui';
|
|
647
|
+
|
|
648
|
+
<Avatar
|
|
649
|
+
size="large" // ResponsiveType<'small' | 'medium' | 'large'>
|
|
650
|
+
type="initials" // 'initials' | 'check' | 'avatar' | 'image'
|
|
651
|
+
name="John Doe" // string
|
|
652
|
+
image="/path/to/photo.jpg" // string (for type='image')
|
|
653
|
+
initialsAmount={2} // 1 | 2
|
|
654
|
+
variant="round" // 'round' | 'square'
|
|
655
|
+
/>
|
|
656
|
+
|
|
657
|
+
<AvatarGroup maxLength={3} total={10}>
|
|
658
|
+
<Avatar name="Alice" type="initials" />
|
|
659
|
+
<Avatar name="Bob" type="initials" />
|
|
660
|
+
<Avatar name="Charlie" type="initials" />
|
|
661
|
+
</AvatarGroup>
|
|
662
|
+
```
|
|
663
|
+
|
|
664
|
+
### Badge
|
|
665
|
+
Notification badge wrapper.
|
|
666
|
+
```tsx
|
|
667
|
+
import { Badge } from '@zvoove/unity-ui';
|
|
668
|
+
|
|
669
|
+
<Badge
|
|
670
|
+
variant="primary" // 'primary' | 'secondary'
|
|
671
|
+
content={5} // ReactNode
|
|
672
|
+
dot={false} // boolean
|
|
673
|
+
>
|
|
674
|
+
<Icon name="Bell" />
|
|
675
|
+
</Badge>
|
|
676
|
+
```
|
|
677
|
+
|
|
678
|
+
### Icon
|
|
679
|
+
Phosphor icon renderer.
|
|
680
|
+
```tsx
|
|
681
|
+
import { Icon } from '@zvoove/unity-ui';
|
|
682
|
+
|
|
683
|
+
<Icon
|
|
684
|
+
name="MagnifyingGlass" // IconNames (Phosphor icon names)
|
|
685
|
+
size="lg" // '2xs' | 'xs' | 'sm' | 'md' | 'lg' | 'xl' | '2xl' (default: 'lg')
|
|
686
|
+
color="on-surface" // ForegroundColors
|
|
687
|
+
weight="regular" // IconWeight
|
|
688
|
+
featured={false} // boolean
|
|
689
|
+
/>
|
|
690
|
+
```
|
|
691
|
+
|
|
692
|
+
### Skeleton
|
|
693
|
+
Loading placeholder.
|
|
694
|
+
```tsx
|
|
695
|
+
import { Skeleton } from '@zvoove/unity-ui';
|
|
696
|
+
|
|
697
|
+
<Skeleton
|
|
698
|
+
width={200} // number | string
|
|
699
|
+
height={20} // number | string
|
|
700
|
+
animation="pulse" // 'pulse' | 'wave' | false (default: 'pulse')
|
|
701
|
+
borderRadius="xs" // 'xs' | 'sm' | 'md' | 'lg' | 'full' (default: 'xs')
|
|
702
|
+
/>
|
|
703
|
+
```
|
|
704
|
+
|
|
705
|
+
### ProgressIndicator
|
|
706
|
+
Linear or circular progress indicator.
|
|
707
|
+
```tsx
|
|
708
|
+
import { ProgressIndicator } from '@zvoove/unity-ui';
|
|
709
|
+
|
|
710
|
+
<ProgressIndicator
|
|
711
|
+
value={75} // number (0-100, default: 0)
|
|
712
|
+
variant="linear" // 'linear' | 'circular' (default: 'linear')
|
|
713
|
+
indeterminate={false} // boolean
|
|
714
|
+
/>
|
|
715
|
+
```
|
|
716
|
+
|
|
717
|
+
### CodeBlock
|
|
718
|
+
Code display with syntax highlighting.
|
|
719
|
+
```tsx
|
|
720
|
+
import { CodeBlock } from '@zvoove/unity-ui';
|
|
721
|
+
|
|
722
|
+
<CodeBlock
|
|
723
|
+
code="const x = 42;" // string (required)
|
|
724
|
+
filename="example.ts" // string
|
|
725
|
+
/>
|
|
726
|
+
```
|
|
727
|
+
|
|
728
|
+
---
|
|
729
|
+
|
|
730
|
+
## NAVIGATION COMPONENTS
|
|
731
|
+
|
|
732
|
+
### Tabs
|
|
733
|
+
Tab navigation with optional panels.
|
|
734
|
+
```tsx
|
|
735
|
+
import { Tabs } from '@zvoove/unity-ui';
|
|
736
|
+
|
|
737
|
+
<Tabs
|
|
738
|
+
items={[ // TabItem[] (required)
|
|
739
|
+
{ id: 'tab1', label: 'Overview', icon: 'House' },
|
|
740
|
+
{ id: 'tab2', label: 'Details', hasActivity: true },
|
|
741
|
+
{ id: 'tab3', label: 'Settings', icon: 'Gear', iconPosition: 'top' },
|
|
742
|
+
]}
|
|
743
|
+
activeItem="tab1" // string (required)
|
|
744
|
+
onChange={handleChange} // (item: TabItem) => void
|
|
745
|
+
panels={[ // Panel[]
|
|
746
|
+
{ id: 'tab1', children: <div>Overview content</div> },
|
|
747
|
+
{ id: 'tab2', children: <div>Details content</div> },
|
|
748
|
+
]}
|
|
749
|
+
isSticky={false} // boolean
|
|
750
|
+
hideBorder={false} // boolean
|
|
751
|
+
itemsAlignment="left" // 'left' | 'center' | 'right' | 'between' | 'around' | 'evenly'
|
|
752
|
+
linkComponent={Link} // React.ElementType
|
|
753
|
+
/>
|
|
754
|
+
```
|
|
755
|
+
|
|
756
|
+
### Breadcrumbs
|
|
757
|
+
Navigation breadcrumb trail.
|
|
758
|
+
```tsx
|
|
759
|
+
import { Breadcrumbs } from '@zvoove/unity-ui';
|
|
760
|
+
|
|
761
|
+
<Breadcrumbs
|
|
762
|
+
items={[ // BreadcrumbItem[]
|
|
763
|
+
{ label: 'Home', href: '/' },
|
|
764
|
+
{ label: 'Products', href: '/products' },
|
|
765
|
+
{ label: 'Details' },
|
|
766
|
+
]}
|
|
767
|
+
linkComponent={Link} // React.ElementType
|
|
768
|
+
/>
|
|
769
|
+
```
|
|
770
|
+
|
|
771
|
+
### SideNavigation
|
|
772
|
+
Collapsible sidebar navigation.
|
|
773
|
+
```tsx
|
|
774
|
+
import { SideNavigation } from '@zvoove/unity-ui';
|
|
775
|
+
|
|
776
|
+
<SideNavigation
|
|
777
|
+
menuItems={[ // MenuItem[] (required)
|
|
778
|
+
{ id: 'home', label: 'Home', icon: 'House' },
|
|
779
|
+
{ id: 'users', label: 'Users', icon: 'Users' },
|
|
780
|
+
]}
|
|
781
|
+
utilityItems={[ // MenuItem[]
|
|
782
|
+
{ id: 'settings', label: 'Settings', icon: 'Gear' },
|
|
783
|
+
]}
|
|
784
|
+
activeItem="home" // string
|
|
785
|
+
open={true} // boolean
|
|
786
|
+
onToggleOpen={handleToggle} // (open: boolean) => void
|
|
787
|
+
onItemClick={handleClick} // (item: MenuItem) => void
|
|
788
|
+
linkComponent={Link} // React.ElementType
|
|
789
|
+
/>
|
|
790
|
+
```
|
|
791
|
+
|
|
792
|
+
### Pagination
|
|
793
|
+
Page navigation control.
|
|
794
|
+
```tsx
|
|
795
|
+
import { Pagination } from '@zvoove/unity-ui';
|
|
796
|
+
|
|
797
|
+
<Pagination
|
|
798
|
+
currentPage={1} // number (required)
|
|
799
|
+
totalPages={10} // number (required)
|
|
800
|
+
onPageChange={handlePage} // (page: number) => void (required)
|
|
801
|
+
rowsPerPage={20} // 10 | 20 | 50 | 100 | 200
|
|
802
|
+
onRowsPerPageChange={handleRows} // (rowsPerPage: RowsPerPage) => void
|
|
803
|
+
rowsPerPageLabel="Rows per page" // string
|
|
804
|
+
pageOfPagesLabel="of" // string
|
|
805
|
+
disabled={false} // boolean
|
|
806
|
+
/>
|
|
807
|
+
```
|
|
808
|
+
|
|
809
|
+
### TopBar
|
|
810
|
+
Application top bar/header.
|
|
811
|
+
```tsx
|
|
812
|
+
import { TopBar } from '@zvoove/unity-ui';
|
|
813
|
+
|
|
814
|
+
<TopBar
|
|
815
|
+
leftTopContent={<Logo />} // ReactNode
|
|
816
|
+
rightTopContent={<Avatar />} // ReactNode
|
|
817
|
+
leftBottomContent="Dashboard" // string | ReactNode
|
|
818
|
+
rightBottomContent={actions} // ReactNode
|
|
819
|
+
subtitle="Overview" // string
|
|
820
|
+
density="default" // 'default' | '-2' | '-4'
|
|
821
|
+
/>
|
|
822
|
+
```
|
|
823
|
+
|
|
824
|
+
---
|
|
825
|
+
|
|
826
|
+
## FEEDBACK COMPONENTS
|
|
827
|
+
|
|
828
|
+
### Dialog
|
|
829
|
+
Modal dialog overlay. Use Dialog for modals — never create custom overlays.
|
|
830
|
+
```tsx
|
|
831
|
+
import { Dialog } from '@zvoove/unity-ui';
|
|
832
|
+
|
|
833
|
+
<Dialog
|
|
834
|
+
open={isOpen} // boolean (required)
|
|
835
|
+
onClose={handleClose} // () => void (required)
|
|
836
|
+
size="md" // ResponsiveType<'sm' | 'md' | 'lg' | 'none' | 'fullscreen'>
|
|
837
|
+
closeOnBackdropClick={true} // boolean
|
|
838
|
+
closeOnEsc={true} // boolean
|
|
839
|
+
padding="md" // CardProps['padding'] — use "none" for edge-to-edge content
|
|
840
|
+
zIndex={20} // number
|
|
841
|
+
>
|
|
842
|
+
<Typography variant="title" size="large">Dialog Title</Typography>
|
|
843
|
+
<Typography>Dialog content goes here.</Typography>
|
|
844
|
+
<Stack direction="row" gap="sm" justify="flex-end">
|
|
845
|
+
<Button variant="outlined" onClick={handleClose}>Cancel</Button>
|
|
846
|
+
<Button onClick={handleConfirm}>Confirm</Button>
|
|
847
|
+
</Stack>
|
|
848
|
+
</Dialog>
|
|
849
|
+
```
|
|
850
|
+
|
|
851
|
+
Common patterns:
|
|
852
|
+
```tsx
|
|
853
|
+
// Responsive: fullscreen on mobile, centered modal on tablet+
|
|
854
|
+
<Dialog
|
|
855
|
+
open={isOpen}
|
|
856
|
+
onClose={handleClose}
|
|
857
|
+
size={{ mobile: 'fullscreen', tablet: 'md' }}
|
|
858
|
+
>
|
|
859
|
+
<Stack direction="column" gap="lg">
|
|
860
|
+
<Typography variant="title" size="large">Edit Profile</Typography>
|
|
861
|
+
<TextField label="Name" name="name" value={name} onChange={setName} />
|
|
862
|
+
<TextField label="Email" name="email" value={email} onChange={setEmail} />
|
|
863
|
+
<Stack direction="row" gap="sm" justify="flex-end">
|
|
864
|
+
<Button variant="outlined" onClick={handleClose}>Cancel</Button>
|
|
865
|
+
<Button variant="filled" onClick={handleSave}>Save</Button>
|
|
866
|
+
</Stack>
|
|
867
|
+
</Stack>
|
|
868
|
+
</Dialog>
|
|
869
|
+
|
|
870
|
+
// Confirmation dialog (small)
|
|
871
|
+
<Dialog open={showConfirm} onClose={() => setShowConfirm(false)} size="sm">
|
|
872
|
+
<Stack direction="column" gap="md">
|
|
873
|
+
<Typography variant="title" size="medium">Delete item?</Typography>
|
|
874
|
+
<Typography variant="body" size="medium">This action cannot be undone.</Typography>
|
|
875
|
+
<Stack direction="row" gap="sm" justify="flex-end">
|
|
876
|
+
<Button variant="outlined" onClick={() => setShowConfirm(false)}>Cancel</Button>
|
|
877
|
+
<Button variant="negative" icon="delete" onClick={handleDelete}>Delete</Button>
|
|
878
|
+
</Stack>
|
|
879
|
+
</Stack>
|
|
880
|
+
</Dialog>
|
|
881
|
+
|
|
882
|
+
// Dialog with no padding (for full-width content like tables/images)
|
|
883
|
+
<Dialog open={isOpen} onClose={handleClose} size="lg" padding="none">
|
|
884
|
+
<Table columns={columns} data={data} />
|
|
885
|
+
</Dialog>
|
|
886
|
+
```
|
|
887
|
+
|
|
888
|
+
### Sheet
|
|
889
|
+
Bottom or side sheet overlay. Use Sheet for slide-in panels — never create custom side panels.
|
|
890
|
+
```tsx
|
|
891
|
+
import { Sheet } from '@zvoove/unity-ui';
|
|
892
|
+
|
|
893
|
+
<Sheet
|
|
894
|
+
open={isOpen} // boolean (required)
|
|
895
|
+
onClose={handleClose} // () => void (required)
|
|
896
|
+
title="Sheet Title" // string
|
|
897
|
+
subTitle="Optional subtitle" // string
|
|
898
|
+
placement="bottom" // 'bottom' | 'right' (default: 'bottom')
|
|
899
|
+
size="md" // 'sm' | 'md' | 'lg'
|
|
900
|
+
padding="lg" // SpacingKeys (default: 'lg'). Use "none" for edge-to-edge content
|
|
901
|
+
closeOnBackdropClick={true} // boolean
|
|
902
|
+
closeOnEsc={false} // boolean
|
|
903
|
+
showHandle={true} // boolean
|
|
904
|
+
showCloseButton={false} // boolean
|
|
905
|
+
showBackArrow={false} // boolean
|
|
906
|
+
stickyHeader={true} // boolean
|
|
907
|
+
stickyFooter={true} // boolean
|
|
908
|
+
headerActions={actions} // ReactNode
|
|
909
|
+
footerActions={buttons} // ReactNode
|
|
910
|
+
// Right placement extras:
|
|
911
|
+
resizable={false} // boolean
|
|
912
|
+
width={600} // number | string
|
|
913
|
+
minWidth={570} // number | string
|
|
914
|
+
maxWidth={900} // number | string
|
|
915
|
+
onResizeEnd={handleResize} // (width: number) => void
|
|
916
|
+
>
|
|
917
|
+
{children}
|
|
918
|
+
</Sheet>
|
|
919
|
+
```
|
|
920
|
+
|
|
921
|
+
Common patterns:
|
|
922
|
+
```tsx
|
|
923
|
+
// Detail panel from the right
|
|
924
|
+
<Sheet
|
|
925
|
+
open={isOpen}
|
|
926
|
+
onClose={handleClose}
|
|
927
|
+
title="User Details"
|
|
928
|
+
placement="right"
|
|
929
|
+
showCloseButton={true}
|
|
930
|
+
footerActions={
|
|
931
|
+
<Stack direction="row" gap="sm" justify="flex-end">
|
|
932
|
+
<Button variant="outlined" onClick={handleClose}>Cancel</Button>
|
|
933
|
+
<Button variant="filled" onClick={handleSave}>Save</Button>
|
|
934
|
+
</Stack>
|
|
935
|
+
}
|
|
936
|
+
>
|
|
937
|
+
<Stack direction="column" gap="md">
|
|
938
|
+
<TextField label="Name" name="name" />
|
|
939
|
+
<TextField label="Email" name="email" />
|
|
940
|
+
</Stack>
|
|
941
|
+
</Sheet>
|
|
942
|
+
|
|
943
|
+
// Mobile bottom sheet for actions
|
|
944
|
+
<Sheet
|
|
945
|
+
open={isOpen}
|
|
946
|
+
onClose={handleClose}
|
|
947
|
+
title="Sort by"
|
|
948
|
+
placement="bottom"
|
|
949
|
+
size="sm"
|
|
950
|
+
showHandle={true}
|
|
951
|
+
>
|
|
952
|
+
<Stack direction="column" gap="xs">
|
|
953
|
+
<Button variant="text" onClick={() => sort('name')}>Name</Button>
|
|
954
|
+
<Button variant="text" onClick={() => sort('date')}>Date</Button>
|
|
955
|
+
<Button variant="text" onClick={() => sort('status')}>Status</Button>
|
|
956
|
+
</Stack>
|
|
957
|
+
</Sheet>
|
|
958
|
+
```
|
|
959
|
+
|
|
960
|
+
### Snackbar
|
|
961
|
+
Toast notification system. Requires `<Snackbar />` provider in your app tree.
|
|
962
|
+
```tsx
|
|
963
|
+
import { Snackbar, useSnackbar } from '@zvoove/unity-ui';
|
|
964
|
+
|
|
965
|
+
// In your app root:
|
|
966
|
+
<Snackbar />
|
|
967
|
+
|
|
968
|
+
// In any component:
|
|
969
|
+
const { addSnackbar } = useSnackbar();
|
|
970
|
+
|
|
971
|
+
addSnackbar('Operation successful', {
|
|
972
|
+
variant: 'positive', // 'default' | 'positive' | 'warning' | 'error' | 'subtle'
|
|
973
|
+
placement: 'top-right', // 'top-left' | 'top-center' | 'top-right' | 'bottom-left' | 'bottom-center' | 'bottom-right'
|
|
974
|
+
icon: 'Check', // CommonIconNames
|
|
975
|
+
showCloseButton: true, // boolean
|
|
976
|
+
actionLabel: 'Undo', // string
|
|
977
|
+
onAction: handleUndo, // (id: string) => void
|
|
978
|
+
onClose: handleClose, // (id: string) => void
|
|
979
|
+
duration: 5000, // number (ms)
|
|
980
|
+
});
|
|
981
|
+
```
|
|
982
|
+
|
|
983
|
+
### InfoBox
|
|
984
|
+
Inline informational message.
|
|
985
|
+
```tsx
|
|
986
|
+
import { InfoBox } from '@zvoove/unity-ui';
|
|
987
|
+
|
|
988
|
+
<InfoBox
|
|
989
|
+
message="Your changes have been saved." // string (required)
|
|
990
|
+
variant="positive" // 'default' | 'positive' | 'warning' | 'error' | 'subtle' | 'neutral' | 'outlined'
|
|
991
|
+
icon="CheckCircle" // CommonIconNames
|
|
992
|
+
elevated={true} // boolean (default: true)
|
|
993
|
+
/>
|
|
994
|
+
```
|
|
995
|
+
|
|
996
|
+
### ConfirmationCard
|
|
997
|
+
Status card with actions.
|
|
998
|
+
```tsx
|
|
999
|
+
import { ConfirmationCard } from '@zvoove/unity-ui';
|
|
1000
|
+
|
|
1001
|
+
<ConfirmationCard
|
|
1002
|
+
title="Delete item?" // string (required)
|
|
1003
|
+
variant="warning" // 'info' | 'success' | 'warning' | 'error'
|
|
1004
|
+
icon="Warning" // CommonIconNames
|
|
1005
|
+
status="confirmed" // 'confirmed' | 'rejected' | 'skipped'
|
|
1006
|
+
statusLabel="Approved" // string
|
|
1007
|
+
actions={[ // ConfirmationCardAction[]
|
|
1008
|
+
{ label: 'Cancel', variant: 'outlined', onClick: handleCancel },
|
|
1009
|
+
{ label: 'Delete', variant: 'negative', icon: 'Trash', onClick: handleDelete },
|
|
1010
|
+
]}
|
|
1011
|
+
>
|
|
1012
|
+
This action cannot be undone.
|
|
1013
|
+
</ConfirmationCard>
|
|
1014
|
+
```
|
|
1015
|
+
|
|
1016
|
+
### Tooltip
|
|
1017
|
+
Hover tooltip.
|
|
1018
|
+
```tsx
|
|
1019
|
+
import { Tooltip } from '@zvoove/unity-ui';
|
|
1020
|
+
|
|
1021
|
+
<Tooltip
|
|
1022
|
+
content="Helpful description" // ReactNode (required)
|
|
1023
|
+
placement="top" // 'top' | 'bottom' | 'left' | 'right'
|
|
1024
|
+
disabled={false} // boolean
|
|
1025
|
+
isOpen={undefined} // boolean (controlled mode)
|
|
1026
|
+
>
|
|
1027
|
+
<Button>Hover me</Button>
|
|
1028
|
+
</Tooltip>
|
|
1029
|
+
```
|
|
1030
|
+
|
|
1031
|
+
---
|
|
1032
|
+
|
|
1033
|
+
## COMPOUND COMPONENTS
|
|
1034
|
+
|
|
1035
|
+
### Accordion
|
|
1036
|
+
Expandable accordion panels.
|
|
1037
|
+
```tsx
|
|
1038
|
+
import { Accordion } from '@zvoove/unity-ui';
|
|
1039
|
+
|
|
1040
|
+
<Accordion
|
|
1041
|
+
items={[ // AccordionItem[] (required)
|
|
1042
|
+
{ id: '1', title: 'Section 1', supportingText: 'Details', children: <div>Content</div> },
|
|
1043
|
+
{ id: '2', title: 'Section 2', children: <div>Content</div>, disabled: true },
|
|
1044
|
+
]}
|
|
1045
|
+
openItems={['1']} // string | string[]
|
|
1046
|
+
onToggle={handleToggle} // (item: AccordionItem) => void
|
|
1047
|
+
allowMultipleOpenItems={false} // boolean
|
|
1048
|
+
/>
|
|
1049
|
+
```
|
|
1050
|
+
|
|
1051
|
+
---
|
|
1052
|
+
|
|
1053
|
+
## HOOKS
|
|
1054
|
+
|
|
1055
|
+
### useBreakpoint
|
|
1056
|
+
Responsive breakpoint detection.
|
|
1057
|
+
```tsx
|
|
1058
|
+
import { useBreakpoint } from '@zvoove/unity-ui';
|
|
1059
|
+
|
|
1060
|
+
const { currentBreakpoint, isBiggerThan, isSmallerThan, isBetween } = useBreakpoint();
|
|
1061
|
+
|
|
1062
|
+
if (isBiggerThan('tablet')) { /* tablet and above */ }
|
|
1063
|
+
if (isSmallerThan('laptop')) { /* below laptop */ }
|
|
1064
|
+
if (isBetween('tablet', 'desktop')) { /* between tablet and desktop */ }
|
|
1065
|
+
```
|
|
1066
|
+
|
|
1067
|
+
### useClickOutside
|
|
1068
|
+
Detect clicks outside a referenced element.
|
|
1069
|
+
```tsx
|
|
1070
|
+
import { useClickOutside } from '@zvoove/unity-ui';
|
|
1071
|
+
|
|
1072
|
+
const ref = useRef(null);
|
|
1073
|
+
useClickOutside(ref, () => setOpen(false), isOpen);
|
|
1074
|
+
```
|
|
1075
|
+
|
|
1076
|
+
---
|
|
1077
|
+
|
|
1078
|
+
## SPACING SCALE
|
|
1079
|
+
|
|
1080
|
+
Use these values for gap, padding, and margin props:
|
|
1081
|
+
- `none` = 0px
|
|
1082
|
+
- `xs2` = 4px
|
|
1083
|
+
- `xs` = 8px
|
|
1084
|
+
- `sm` = 12px
|
|
1085
|
+
- `md` = 16px
|
|
1086
|
+
- `lg` = 20px
|
|
1087
|
+
- `xl` = 24px
|
|
1088
|
+
- `xl2` = 32px
|
|
1089
|
+
- `xl3` = 40px
|
|
1090
|
+
- `xl4` = 48px
|
|
1091
|
+
- `xl5` = 64px
|
|
1092
|
+
- `xl6` = 80px
|
|
1093
|
+
- `xl7` = 96px
|
|
1094
|
+
|
|
1095
|
+
---
|
|
1096
|
+
|
|
1097
|
+
## ICON NAMES
|
|
1098
|
+
|
|
1099
|
+
Unity UI uses its own semantic icon names (not raw Phosphor icon names). Pass them via `<Icon name="icon-name" />`.
|
|
1100
|
+
|
|
1101
|
+
### Common Icons
|
|
1102
|
+
|
|
1103
|
+
add, add-circle, add-file, agent, airplane, archive, arrow-back, arrow-bend, arrow-down, arrow-forward, arrow-left-right, arrow-up, article, attachment, automate, backspace, bank, bicycle, billing, binoculars, break, bus, calendar, calendar-blank, calendar-check, calendar-dot, calendar-x, camera, car, cart, cash-money, certificate, chat-bubble, chats, check, check-circle, checkbox, checkbox-empty, checkbox-indefinitely, checks, chevron-down, chevron-left, chevron-right, chevron-up, circle-notch, close, close-circle, clock-countdown, clock-person, cloud-download, cloud-upload, columns, copy, dark-mode, deactivate, delete, diagram-view, download, drag, edit, error, exclamation-mark, expand, expenses, face-id, file, filter, filters, first-page, folder, grid-view, hard-hat, help, hide, home, images, info, invoice, job, keyboard, knowledge, language, last-page, light-mode, list-view, location, location-pin, lock, menu, metadata, microphone, minus, more-horizontal, more-vertical, moped, navigation-arrow, note, notches, notifications, numpad, open-in-new-tab, order, organization, pause, phone, piggy-bank, plant, printer, privacy, qr-code, refresh, remark, save, search, send-message, settings, setup-time, shapes, show, sick, sidebar, sign-out, signature, skip-forward, smartphone, sparkle, star, start, stop, table, taxi, text-align-center, text-align-justify, text-align-left, text-align-right, text-t, time, time-sheet-download, time-sheet-upload, timer, train, translate, travel, unfold, upload, user, user-account, users, vacation, wallet, warning, wrench.
|
|
1104
|
+
|
|
1105
|
+
### File Type Icons
|
|
1106
|
+
|
|
1107
|
+
file-empty, file-pdf, file-folder, file-image, file-video, file-video-2, file-audio, file-code, file-document, file-spreadsheet, file-image-img, file-image-jpg, file-image-jpeg, file-image-png, file-image-webp, file-image-tiff, file-image-gif, file-image-svg, file-image-eps, file-document-pdf, file-document-doc, file-document-docx, file-document-txt, file-document-csv, file-document-xls, file-document-xlsx, file-document-ppt, file-document-pptx, file-design-fig, file-design-ai, file-design-psd, file-design-indd, file-design-aep, file-media-mp3, file-media-wav, file-media-mp4, file-media-mpeg, file-media-avi, file-media-mkv, file-development-html, file-development-css, file-development-rss, file-development-sql, file-development-js, file-development-json, file-development-java, file-development-xml, file-development-exe, file-development-dmg, file-archive-zip, file-archive-rar.
|
|
1108
|
+
|
|
1109
|
+
Use `getIconForFileExtension(extension)` to resolve a file extension (e.g., "pdf") to its icon name automatically.
|
|
1110
|
+
|
|
1111
|
+
---
|
|
1112
|
+
|
|
1113
|
+
## EXAMPLE: Contact Form
|
|
1114
|
+
|
|
1115
|
+
```tsx
|
|
1116
|
+
import {
|
|
1117
|
+
Card,
|
|
1118
|
+
Stack,
|
|
1119
|
+
Typography,
|
|
1120
|
+
TextField,
|
|
1121
|
+
Textarea,
|
|
1122
|
+
Select,
|
|
1123
|
+
Checkbox,
|
|
1124
|
+
Button,
|
|
1125
|
+
} from '@zvoove/unity-ui';
|
|
1126
|
+
|
|
1127
|
+
function ContactForm() {
|
|
1128
|
+
return (
|
|
1129
|
+
<Card padding="xl" elevation={1} variant="outlined" maxWidth={600}>
|
|
1130
|
+
<Stack direction="column" gap="lg">
|
|
1131
|
+
<Typography variant="headline" size="medium" as="h2">
|
|
1132
|
+
Contact Us
|
|
1133
|
+
</Typography>
|
|
1134
|
+
|
|
1135
|
+
<Grid columns={{ mobile: 1, tablet: 2 }} gap="md">
|
|
1136
|
+
<Grid.Item>
|
|
1137
|
+
<TextField label="First name" name="firstName" required />
|
|
1138
|
+
</Grid.Item>
|
|
1139
|
+
<Grid.Item>
|
|
1140
|
+
<TextField label="Last name" name="lastName" required />
|
|
1141
|
+
</Grid.Item>
|
|
1142
|
+
</Grid>
|
|
1143
|
+
|
|
1144
|
+
<TextField label="Email" name="email" type="email" icon="Envelope" required />
|
|
1145
|
+
|
|
1146
|
+
<Select
|
|
1147
|
+
name="subject"
|
|
1148
|
+
label="Subject"
|
|
1149
|
+
options={[
|
|
1150
|
+
{ value: 'general', label: 'General inquiry' },
|
|
1151
|
+
{ value: 'support', label: 'Technical support' },
|
|
1152
|
+
{ value: 'billing', label: 'Billing' },
|
|
1153
|
+
]}
|
|
1154
|
+
/>
|
|
1155
|
+
|
|
1156
|
+
<Textarea placeholder="Your message..." maxLength={1000} rows={5} />
|
|
1157
|
+
|
|
1158
|
+
<Checkbox label="I agree to the privacy policy" name="privacy" />
|
|
1159
|
+
|
|
1160
|
+
<Stack direction="row" gap="sm" justify="flex-end">
|
|
1161
|
+
<Button variant="outlined">Cancel</Button>
|
|
1162
|
+
<Button variant="filled" icon="PaperPlaneRight">Send</Button>
|
|
1163
|
+
</Stack>
|
|
1164
|
+
</Stack>
|
|
1165
|
+
</Card>
|
|
1166
|
+
);
|
|
1167
|
+
}
|
|
1168
|
+
```
|
|
1169
|
+
|
|
1170
|
+
---
|
|
1171
|
+
|
|
1172
|
+
## RULES FOR AI AGENTS
|
|
1173
|
+
|
|
1174
|
+
1. **Always import from `@zvoove/unity-ui`** - never recreate components that exist in this library
|
|
1175
|
+
2. **Use Stack and Grid for layout** - do not use Card, div, or CSS for layout. Stack is for rows/columns, Grid is for multi-column layouts
|
|
1176
|
+
3. **Card is a visual container, NOT a layout tool** - Card provides background, elevation, and border. Wrap layout content in Stack/Grid INSIDE a Card. Never use Card to arrange items
|
|
1177
|
+
4. **Use Typography for all text** - never use raw `<p>`, `<h1>`, `<span>` etc.
|
|
1178
|
+
5. **Use the spacing scale** for gap/padding/margin - never use arbitrary pixel values
|
|
1179
|
+
6. **Use Button variants** appropriately - primary actions: `filled`, secondary: `outlined`, destructive: `negative`, success: `positive`
|
|
1180
|
+
7. **Use TextField/Select/Checkbox/Radio for forms** - never create custom form inputs
|
|
1181
|
+
8. **Use Dialog for modals, Sheet for panels** - never create custom overlays
|
|
1182
|
+
9. **Use Snackbar for notifications** - never create custom toast systems
|
|
1183
|
+
10. **Use responsive props** when the UI should adapt to screen sizes. Values cascade up from smallest breakpoint. Common pattern: `{{ mobile: 'column', tablet: 'row' }}`
|
|
1184
|
+
11. **Card, Dialog, Sheet padding can be "none"** - use `padding="none"` for edge-to-edge content like images, tables, or dividers inside these components
|
|
1185
|
+
12. **Icons use semantic names** as strings (e.g., `"search"`, `"delete"`, `"edit"`) - never import Phosphor icon components directly
|