@geajs/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 +535 -0
- package/dist/index.d.mts +806 -0
- package/dist/index.mjs +3597 -0
- package/dist/index.mjs.map +1 -0
- package/dist/tailwind-preset.d.mts +51 -0
- package/dist/tailwind-preset.mjs +50 -0
- package/dist/tailwind-preset.mjs.map +1 -0
- package/dist/theme.css +215 -0
- package/package.json +99 -0
package/README.md
ADDED
|
@@ -0,0 +1,535 @@
|
|
|
1
|
+
# @geajs/ui
|
|
2
|
+
|
|
3
|
+
Accessible UI components for [Gea](https://github.com/dashersw/gea), powered by [Zag.js](https://zagjs.com/) state machines and styled with [Tailwind CSS](https://tailwindcss.com/).
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @geajs/ui
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Peer dependency:
|
|
12
|
+
```bash
|
|
13
|
+
npm install @geajs/core
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## Tailwind CSS Setup
|
|
17
|
+
|
|
18
|
+
### 1. Add @geajs/ui to your Tailwind content paths
|
|
19
|
+
|
|
20
|
+
```js
|
|
21
|
+
// tailwind.config.js
|
|
22
|
+
import geaPreset from '@geajs/ui/tailwind-preset'
|
|
23
|
+
|
|
24
|
+
export default {
|
|
25
|
+
presets: [geaPreset],
|
|
26
|
+
content: [
|
|
27
|
+
'./src/**/*.{tsx,ts,jsx,js}',
|
|
28
|
+
'./node_modules/@geajs/ui/dist/**/*.js',
|
|
29
|
+
],
|
|
30
|
+
}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### 2. Import the theme CSS
|
|
34
|
+
|
|
35
|
+
In your main CSS file:
|
|
36
|
+
|
|
37
|
+
```css
|
|
38
|
+
@import '@geajs/ui/style.css';
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Or in your entry point:
|
|
42
|
+
|
|
43
|
+
```ts
|
|
44
|
+
import '@geajs/ui/style.css'
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Components
|
|
48
|
+
|
|
49
|
+
### Simple Styled Components
|
|
50
|
+
|
|
51
|
+
These components are thin wrappers with Tailwind styling and variant support.
|
|
52
|
+
|
|
53
|
+
#### Button
|
|
54
|
+
|
|
55
|
+
```tsx
|
|
56
|
+
import { Button } from '@geajs/ui'
|
|
57
|
+
|
|
58
|
+
class MyApp extends Component {
|
|
59
|
+
template() {
|
|
60
|
+
return (
|
|
61
|
+
<div>
|
|
62
|
+
<Button>Default</Button>
|
|
63
|
+
<Button variant="destructive">Delete</Button>
|
|
64
|
+
<Button variant="outline">Outline</Button>
|
|
65
|
+
<Button variant="secondary">Secondary</Button>
|
|
66
|
+
<Button variant="ghost">Ghost</Button>
|
|
67
|
+
<Button variant="link">Link</Button>
|
|
68
|
+
<Button size="sm">Small</Button>
|
|
69
|
+
<Button size="lg">Large</Button>
|
|
70
|
+
<Button size="icon">🔍</Button>
|
|
71
|
+
</div>
|
|
72
|
+
)
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
#### Card
|
|
78
|
+
|
|
79
|
+
```tsx
|
|
80
|
+
import { Card, CardHeader, CardTitle, CardDescription, CardContent, CardFooter } from '@geajs/ui'
|
|
81
|
+
|
|
82
|
+
<Card>
|
|
83
|
+
<CardHeader>
|
|
84
|
+
<CardTitle>Card Title</CardTitle>
|
|
85
|
+
<CardDescription>Card description text.</CardDescription>
|
|
86
|
+
</CardHeader>
|
|
87
|
+
<CardContent>
|
|
88
|
+
<p>Card content goes here.</p>
|
|
89
|
+
</CardContent>
|
|
90
|
+
<CardFooter>
|
|
91
|
+
<Button>Action</Button>
|
|
92
|
+
</CardFooter>
|
|
93
|
+
</Card>
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
#### Input
|
|
97
|
+
|
|
98
|
+
```tsx
|
|
99
|
+
import { Input } from '@geajs/ui'
|
|
100
|
+
|
|
101
|
+
<Input type="email" placeholder="Email" />
|
|
102
|
+
<Input disabled placeholder="Disabled" />
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
#### Textarea
|
|
106
|
+
|
|
107
|
+
```tsx
|
|
108
|
+
import { Textarea } from '@geajs/ui'
|
|
109
|
+
|
|
110
|
+
<Textarea placeholder="Type your message..." rows={4} />
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
#### Label
|
|
114
|
+
|
|
115
|
+
```tsx
|
|
116
|
+
import { Label } from '@geajs/ui'
|
|
117
|
+
|
|
118
|
+
<Label htmlFor="email">Email</Label>
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
#### Badge
|
|
122
|
+
|
|
123
|
+
```tsx
|
|
124
|
+
import { Badge } from '@geajs/ui'
|
|
125
|
+
|
|
126
|
+
<Badge>Default</Badge>
|
|
127
|
+
<Badge variant="secondary">Secondary</Badge>
|
|
128
|
+
<Badge variant="destructive">Destructive</Badge>
|
|
129
|
+
<Badge variant="outline">Outline</Badge>
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
#### Alert
|
|
133
|
+
|
|
134
|
+
```tsx
|
|
135
|
+
import { Alert, AlertTitle, AlertDescription } from '@geajs/ui'
|
|
136
|
+
|
|
137
|
+
<Alert>
|
|
138
|
+
<AlertTitle>Heads up!</AlertTitle>
|
|
139
|
+
<AlertDescription>This is an alert description.</AlertDescription>
|
|
140
|
+
</Alert>
|
|
141
|
+
<Alert variant="destructive">
|
|
142
|
+
<AlertTitle>Error</AlertTitle>
|
|
143
|
+
<AlertDescription>Something went wrong.</AlertDescription>
|
|
144
|
+
</Alert>
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
#### Separator
|
|
148
|
+
|
|
149
|
+
```tsx
|
|
150
|
+
import { Separator } from '@geajs/ui'
|
|
151
|
+
|
|
152
|
+
<Separator />
|
|
153
|
+
<Separator orientation="vertical" />
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
#### Skeleton
|
|
157
|
+
|
|
158
|
+
```tsx
|
|
159
|
+
import { Skeleton } from '@geajs/ui'
|
|
160
|
+
|
|
161
|
+
<Skeleton class="h-4 w-[250px]" />
|
|
162
|
+
<Skeleton class="h-12 w-12 rounded-full" />
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
### Zag-Powered Components
|
|
166
|
+
|
|
167
|
+
These components are backed by Zag.js state machines, providing full keyboard navigation, ARIA attributes, and focus management out of the box.
|
|
168
|
+
|
|
169
|
+
#### Dialog
|
|
170
|
+
|
|
171
|
+
```tsx
|
|
172
|
+
import { Dialog } from '@geajs/ui'
|
|
173
|
+
|
|
174
|
+
<Dialog
|
|
175
|
+
title="Confirm Action"
|
|
176
|
+
description="Are you sure you want to proceed?"
|
|
177
|
+
triggerLabel="Open Dialog"
|
|
178
|
+
onOpenChange={(details) => console.log(details.open)}
|
|
179
|
+
>
|
|
180
|
+
<p>Dialog body content here.</p>
|
|
181
|
+
</Dialog>
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
#### Tabs
|
|
185
|
+
|
|
186
|
+
```tsx
|
|
187
|
+
import { Tabs } from '@geajs/ui'
|
|
188
|
+
|
|
189
|
+
<Tabs
|
|
190
|
+
defaultValue="tab1"
|
|
191
|
+
items={[
|
|
192
|
+
{ value: 'tab1', label: 'Account', content: 'Account settings...' },
|
|
193
|
+
{ value: 'tab2', label: 'Password', content: 'Password settings...' },
|
|
194
|
+
{ value: 'tab3', label: 'Notifications', content: 'Notification preferences...' },
|
|
195
|
+
]}
|
|
196
|
+
/>
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
#### Accordion
|
|
200
|
+
|
|
201
|
+
```tsx
|
|
202
|
+
import { Accordion } from '@geajs/ui'
|
|
203
|
+
|
|
204
|
+
<Accordion
|
|
205
|
+
collapsible
|
|
206
|
+
items={[
|
|
207
|
+
{ value: 'item1', label: 'What is @geajs/ui?', content: 'A component library for Gea.' },
|
|
208
|
+
{ value: 'item2', label: 'Is it accessible?', content: 'Yes, powered by Zag.js.' },
|
|
209
|
+
]}
|
|
210
|
+
/>
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
#### Tooltip
|
|
214
|
+
|
|
215
|
+
```tsx
|
|
216
|
+
import { Tooltip } from '@geajs/ui'
|
|
217
|
+
|
|
218
|
+
<Tooltip content="This is a tooltip">
|
|
219
|
+
Hover me
|
|
220
|
+
</Tooltip>
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
#### Popover
|
|
224
|
+
|
|
225
|
+
```tsx
|
|
226
|
+
import { Popover } from '@geajs/ui'
|
|
227
|
+
|
|
228
|
+
<Popover title="Settings" description="Configure your preferences.">
|
|
229
|
+
<p>Popover content...</p>
|
|
230
|
+
</Popover>
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
#### Menu
|
|
234
|
+
|
|
235
|
+
```tsx
|
|
236
|
+
import { Menu } from '@geajs/ui'
|
|
237
|
+
|
|
238
|
+
<Menu
|
|
239
|
+
triggerLabel="Actions"
|
|
240
|
+
items={[
|
|
241
|
+
{ value: 'edit', label: 'Edit' },
|
|
242
|
+
{ value: 'duplicate', label: 'Duplicate' },
|
|
243
|
+
{ type: 'separator' },
|
|
244
|
+
{ value: 'delete', label: 'Delete' },
|
|
245
|
+
]}
|
|
246
|
+
onSelect={(details) => console.log(details.value)}
|
|
247
|
+
/>
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
#### Select
|
|
251
|
+
|
|
252
|
+
```tsx
|
|
253
|
+
import { Select } from '@geajs/ui'
|
|
254
|
+
|
|
255
|
+
<Select
|
|
256
|
+
label="Framework"
|
|
257
|
+
placeholder="Select a framework..."
|
|
258
|
+
items={[
|
|
259
|
+
{ value: 'gea', label: 'Gea' },
|
|
260
|
+
{ value: 'react', label: 'React' },
|
|
261
|
+
{ value: 'vue', label: 'Vue' },
|
|
262
|
+
{ value: 'solid', label: 'Solid' },
|
|
263
|
+
]}
|
|
264
|
+
onValueChange={(details) => console.log(details.value)}
|
|
265
|
+
/>
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
**Note:** For Select and Combobox, pass a Zag `collection` prop for advanced usage with `ListCollection`.
|
|
269
|
+
|
|
270
|
+
#### Switch
|
|
271
|
+
|
|
272
|
+
```tsx
|
|
273
|
+
import { Switch } from '@geajs/ui'
|
|
274
|
+
|
|
275
|
+
<Switch label="Airplane Mode" onCheckedChange={(d) => console.log(d.checked)} />
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
#### Checkbox
|
|
279
|
+
|
|
280
|
+
```tsx
|
|
281
|
+
import { Checkbox } from '@geajs/ui'
|
|
282
|
+
|
|
283
|
+
<Checkbox label="Accept terms" onCheckedChange={(d) => console.log(d.checked)} />
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
#### Radio Group
|
|
287
|
+
|
|
288
|
+
```tsx
|
|
289
|
+
import { RadioGroup } from '@geajs/ui'
|
|
290
|
+
|
|
291
|
+
<RadioGroup
|
|
292
|
+
label="Plan"
|
|
293
|
+
defaultValue="pro"
|
|
294
|
+
items={[
|
|
295
|
+
{ value: 'free', label: 'Free' },
|
|
296
|
+
{ value: 'pro', label: 'Pro' },
|
|
297
|
+
{ value: 'enterprise', label: 'Enterprise' },
|
|
298
|
+
]}
|
|
299
|
+
onValueChange={(d) => console.log(d.value)}
|
|
300
|
+
/>
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
#### Slider
|
|
304
|
+
|
|
305
|
+
```tsx
|
|
306
|
+
import { Slider } from '@geajs/ui'
|
|
307
|
+
|
|
308
|
+
<Slider
|
|
309
|
+
label="Volume"
|
|
310
|
+
defaultValue={[50]}
|
|
311
|
+
min={0}
|
|
312
|
+
max={100}
|
|
313
|
+
step={1}
|
|
314
|
+
/>
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
#### Number Input
|
|
318
|
+
|
|
319
|
+
```tsx
|
|
320
|
+
import { NumberInput } from '@geajs/ui'
|
|
321
|
+
|
|
322
|
+
<NumberInput label="Quantity" min={0} max={99} step={1} />
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
#### Pin Input
|
|
326
|
+
|
|
327
|
+
```tsx
|
|
328
|
+
import { PinInput } from '@geajs/ui'
|
|
329
|
+
|
|
330
|
+
<PinInput
|
|
331
|
+
label="Verification Code"
|
|
332
|
+
count={6}
|
|
333
|
+
type="numeric"
|
|
334
|
+
onValueComplete={(d) => console.log(d.valueAsString)}
|
|
335
|
+
/>
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
#### Tags Input
|
|
339
|
+
|
|
340
|
+
```tsx
|
|
341
|
+
import { TagsInput } from '@geajs/ui'
|
|
342
|
+
|
|
343
|
+
<TagsInput
|
|
344
|
+
label="Tags"
|
|
345
|
+
placeholder="Add tag..."
|
|
346
|
+
defaultValue={['gea', 'ui']}
|
|
347
|
+
onValueChange={(d) => console.log(d.value)}
|
|
348
|
+
/>
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
#### Progress
|
|
352
|
+
|
|
353
|
+
```tsx
|
|
354
|
+
import { Progress } from '@geajs/ui'
|
|
355
|
+
|
|
356
|
+
<Progress label="Upload" value={65} />
|
|
357
|
+
```
|
|
358
|
+
|
|
359
|
+
#### Rating Group
|
|
360
|
+
|
|
361
|
+
```tsx
|
|
362
|
+
import { RatingGroup } from '@geajs/ui'
|
|
363
|
+
|
|
364
|
+
<RatingGroup label="Rating" count={5} defaultValue={3} />
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
#### Clipboard
|
|
368
|
+
|
|
369
|
+
```tsx
|
|
370
|
+
import { Clipboard } from '@geajs/ui'
|
|
371
|
+
|
|
372
|
+
<Clipboard label="API Key" value="sk-abc123..." />
|
|
373
|
+
```
|
|
374
|
+
|
|
375
|
+
#### Avatar
|
|
376
|
+
|
|
377
|
+
```tsx
|
|
378
|
+
import { Avatar } from '@geajs/ui'
|
|
379
|
+
|
|
380
|
+
<Avatar src="/avatar.jpg" name="John Doe" />
|
|
381
|
+
<Avatar name="JD" />
|
|
382
|
+
```
|
|
383
|
+
|
|
384
|
+
#### Toggle Group
|
|
385
|
+
|
|
386
|
+
```tsx
|
|
387
|
+
import { ToggleGroup } from '@geajs/ui'
|
|
388
|
+
|
|
389
|
+
<ToggleGroup
|
|
390
|
+
items={[
|
|
391
|
+
{ value: 'bold', label: 'B' },
|
|
392
|
+
{ value: 'italic', label: 'I' },
|
|
393
|
+
{ value: 'underline', label: 'U' },
|
|
394
|
+
]}
|
|
395
|
+
multiple
|
|
396
|
+
/>
|
|
397
|
+
```
|
|
398
|
+
|
|
399
|
+
#### Combobox
|
|
400
|
+
|
|
401
|
+
```tsx
|
|
402
|
+
import { Combobox } from '@geajs/ui'
|
|
403
|
+
|
|
404
|
+
<Combobox
|
|
405
|
+
label="Country"
|
|
406
|
+
items={[
|
|
407
|
+
{ value: 'us', label: 'United States' },
|
|
408
|
+
{ value: 'uk', label: 'United Kingdom' },
|
|
409
|
+
{ value: 'de', label: 'Germany' },
|
|
410
|
+
]}
|
|
411
|
+
/>
|
|
412
|
+
```
|
|
413
|
+
|
|
414
|
+
#### Collapsible
|
|
415
|
+
|
|
416
|
+
```tsx
|
|
417
|
+
import { Collapsible } from '@geajs/ui'
|
|
418
|
+
|
|
419
|
+
<Collapsible label="Show more">
|
|
420
|
+
<p>Hidden content revealed on toggle.</p>
|
|
421
|
+
</Collapsible>
|
|
422
|
+
```
|
|
423
|
+
|
|
424
|
+
#### Hover Card
|
|
425
|
+
|
|
426
|
+
```tsx
|
|
427
|
+
import { HoverCard } from '@geajs/ui'
|
|
428
|
+
|
|
429
|
+
<HoverCard triggerLabel="@dashersw">
|
|
430
|
+
<p>Profile information...</p>
|
|
431
|
+
</HoverCard>
|
|
432
|
+
```
|
|
433
|
+
|
|
434
|
+
#### Pagination
|
|
435
|
+
|
|
436
|
+
```tsx
|
|
437
|
+
import { Pagination } from '@geajs/ui'
|
|
438
|
+
|
|
439
|
+
<Pagination
|
|
440
|
+
count={100}
|
|
441
|
+
defaultPageSize={10}
|
|
442
|
+
onPageChange={(d) => console.log(d.page)}
|
|
443
|
+
/>
|
|
444
|
+
```
|
|
445
|
+
|
|
446
|
+
#### File Upload
|
|
447
|
+
|
|
448
|
+
```tsx
|
|
449
|
+
import { FileUpload } from '@geajs/ui'
|
|
450
|
+
|
|
451
|
+
<FileUpload
|
|
452
|
+
label="Upload Documents"
|
|
453
|
+
accept={{ 'application/pdf': ['.pdf'] }}
|
|
454
|
+
maxFiles={5}
|
|
455
|
+
onFileChange={(d) => console.log(d.acceptedFiles)}
|
|
456
|
+
/>
|
|
457
|
+
```
|
|
458
|
+
|
|
459
|
+
#### Toast
|
|
460
|
+
|
|
461
|
+
```tsx
|
|
462
|
+
import { Toaster, ToastStore } from '@geajs/ui'
|
|
463
|
+
|
|
464
|
+
// Add the Toaster to your app root
|
|
465
|
+
class App extends Component {
|
|
466
|
+
template() {
|
|
467
|
+
return (
|
|
468
|
+
<div>
|
|
469
|
+
<Button onClick={() => ToastStore.success({ title: 'Saved!', description: 'Your changes have been saved.' })}>
|
|
470
|
+
Show Toast
|
|
471
|
+
</Button>
|
|
472
|
+
<Toaster />
|
|
473
|
+
</div>
|
|
474
|
+
)
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
// ToastStore methods: create, success, error, info, loading, dismiss
|
|
479
|
+
```
|
|
480
|
+
|
|
481
|
+
#### Tree View
|
|
482
|
+
|
|
483
|
+
```tsx
|
|
484
|
+
import { TreeView } from '@geajs/ui'
|
|
485
|
+
|
|
486
|
+
<TreeView collection={treeCollection}>
|
|
487
|
+
{/* Render tree nodes as children */}
|
|
488
|
+
</TreeView>
|
|
489
|
+
```
|
|
490
|
+
|
|
491
|
+
## Custom Styling
|
|
492
|
+
|
|
493
|
+
### CSS Variables
|
|
494
|
+
|
|
495
|
+
Override CSS variables to customize the theme:
|
|
496
|
+
|
|
497
|
+
```css
|
|
498
|
+
:root {
|
|
499
|
+
--primary: 222 47% 11%;
|
|
500
|
+
--primary-foreground: 210 40% 98%;
|
|
501
|
+
--radius: 0.75rem;
|
|
502
|
+
}
|
|
503
|
+
```
|
|
504
|
+
|
|
505
|
+
### Dark Mode
|
|
506
|
+
|
|
507
|
+
Add the `dark` class to your `<html>` element to enable dark mode:
|
|
508
|
+
|
|
509
|
+
```html
|
|
510
|
+
<html class="dark">
|
|
511
|
+
```
|
|
512
|
+
|
|
513
|
+
### Component Classes
|
|
514
|
+
|
|
515
|
+
All components use semantic class names (e.g., `dialog-trigger`, `tabs-content`) alongside `data-part` and `data-state` attributes, making it easy to target them with custom CSS:
|
|
516
|
+
|
|
517
|
+
```css
|
|
518
|
+
[data-part="content"][data-state="open"] {
|
|
519
|
+
animation: custom-enter 200ms ease;
|
|
520
|
+
}
|
|
521
|
+
```
|
|
522
|
+
|
|
523
|
+
## Architecture
|
|
524
|
+
|
|
525
|
+
@geajs/ui uses a "shell component" pattern:
|
|
526
|
+
|
|
527
|
+
1. **Zag.js** provides framework-agnostic state machines for complex UI behavior (keyboard navigation, focus traps, ARIA attributes)
|
|
528
|
+
2. **ZagComponent** base class bridges Zag's vanilla adapter with Gea's reactive system
|
|
529
|
+
3. Zag's `spreadProps` applies dynamic attributes and event listeners imperatively after Gea's DOM patches
|
|
530
|
+
4. Gea's reactive properties drive visual state (open/closed, checked, value)
|
|
531
|
+
5. Tailwind CSS handles all styling through utility classes and CSS custom properties
|
|
532
|
+
|
|
533
|
+
## License
|
|
534
|
+
|
|
535
|
+
MIT
|