@geajs/ui
v0.1.0
Published
Accessible UI components for Gea, powered by Zag.js state machines and styled with Tailwind CSS
Maintainers
Readme
@geajs/ui
Accessible UI components for Gea, powered by Zag.js state machines and styled with Tailwind CSS.
Installation
npm install @geajs/uiPeer dependency:
npm install @geajs/coreTailwind CSS Setup
1. Add @geajs/ui to your Tailwind content paths
// tailwind.config.js
import geaPreset from '@geajs/ui/tailwind-preset'
export default {
presets: [geaPreset],
content: [
'./src/**/*.{tsx,ts,jsx,js}',
'./node_modules/@geajs/ui/dist/**/*.js',
],
}2. Import the theme CSS
In your main CSS file:
@import '@geajs/ui/style.css';Or in your entry point:
import '@geajs/ui/style.css'Components
Simple Styled Components
These components are thin wrappers with Tailwind styling and variant support.
Button
import { Button } from '@geajs/ui'
class MyApp extends Component {
template() {
return (
<div>
<Button>Default</Button>
<Button variant="destructive">Delete</Button>
<Button variant="outline">Outline</Button>
<Button variant="secondary">Secondary</Button>
<Button variant="ghost">Ghost</Button>
<Button variant="link">Link</Button>
<Button size="sm">Small</Button>
<Button size="lg">Large</Button>
<Button size="icon">🔍</Button>
</div>
)
}
}Card
import { Card, CardHeader, CardTitle, CardDescription, CardContent, CardFooter } from '@geajs/ui'
<Card>
<CardHeader>
<CardTitle>Card Title</CardTitle>
<CardDescription>Card description text.</CardDescription>
</CardHeader>
<CardContent>
<p>Card content goes here.</p>
</CardContent>
<CardFooter>
<Button>Action</Button>
</CardFooter>
</Card>Input
import { Input } from '@geajs/ui'
<Input type="email" placeholder="Email" />
<Input disabled placeholder="Disabled" />Textarea
import { Textarea } from '@geajs/ui'
<Textarea placeholder="Type your message..." rows={4} />Label
import { Label } from '@geajs/ui'
<Label htmlFor="email">Email</Label>Badge
import { Badge } from '@geajs/ui'
<Badge>Default</Badge>
<Badge variant="secondary">Secondary</Badge>
<Badge variant="destructive">Destructive</Badge>
<Badge variant="outline">Outline</Badge>Alert
import { Alert, AlertTitle, AlertDescription } from '@geajs/ui'
<Alert>
<AlertTitle>Heads up!</AlertTitle>
<AlertDescription>This is an alert description.</AlertDescription>
</Alert>
<Alert variant="destructive">
<AlertTitle>Error</AlertTitle>
<AlertDescription>Something went wrong.</AlertDescription>
</Alert>Separator
import { Separator } from '@geajs/ui'
<Separator />
<Separator orientation="vertical" />Skeleton
import { Skeleton } from '@geajs/ui'
<Skeleton class="h-4 w-[250px]" />
<Skeleton class="h-12 w-12 rounded-full" />Zag-Powered Components
These components are backed by Zag.js state machines, providing full keyboard navigation, ARIA attributes, and focus management out of the box.
Dialog
import { Dialog } from '@geajs/ui'
<Dialog
title="Confirm Action"
description="Are you sure you want to proceed?"
triggerLabel="Open Dialog"
onOpenChange={(details) => console.log(details.open)}
>
<p>Dialog body content here.</p>
</Dialog>Tabs
import { Tabs } from '@geajs/ui'
<Tabs
defaultValue="tab1"
items={[
{ value: 'tab1', label: 'Account', content: 'Account settings...' },
{ value: 'tab2', label: 'Password', content: 'Password settings...' },
{ value: 'tab3', label: 'Notifications', content: 'Notification preferences...' },
]}
/>Accordion
import { Accordion } from '@geajs/ui'
<Accordion
collapsible
items={[
{ value: 'item1', label: 'What is @geajs/ui?', content: 'A component library for Gea.' },
{ value: 'item2', label: 'Is it accessible?', content: 'Yes, powered by Zag.js.' },
]}
/>Tooltip
import { Tooltip } from '@geajs/ui'
<Tooltip content="This is a tooltip">
Hover me
</Tooltip>Popover
import { Popover } from '@geajs/ui'
<Popover title="Settings" description="Configure your preferences.">
<p>Popover content...</p>
</Popover>Menu
import { Menu } from '@geajs/ui'
<Menu
triggerLabel="Actions"
items={[
{ value: 'edit', label: 'Edit' },
{ value: 'duplicate', label: 'Duplicate' },
{ type: 'separator' },
{ value: 'delete', label: 'Delete' },
]}
onSelect={(details) => console.log(details.value)}
/>Select
import { Select } from '@geajs/ui'
<Select
label="Framework"
placeholder="Select a framework..."
items={[
{ value: 'gea', label: 'Gea' },
{ value: 'react', label: 'React' },
{ value: 'vue', label: 'Vue' },
{ value: 'solid', label: 'Solid' },
]}
onValueChange={(details) => console.log(details.value)}
/>Note: For Select and Combobox, pass a Zag collection prop for advanced usage with ListCollection.
Switch
import { Switch } from '@geajs/ui'
<Switch label="Airplane Mode" onCheckedChange={(d) => console.log(d.checked)} />Checkbox
import { Checkbox } from '@geajs/ui'
<Checkbox label="Accept terms" onCheckedChange={(d) => console.log(d.checked)} />Radio Group
import { RadioGroup } from '@geajs/ui'
<RadioGroup
label="Plan"
defaultValue="pro"
items={[
{ value: 'free', label: 'Free' },
{ value: 'pro', label: 'Pro' },
{ value: 'enterprise', label: 'Enterprise' },
]}
onValueChange={(d) => console.log(d.value)}
/>Slider
import { Slider } from '@geajs/ui'
<Slider
label="Volume"
defaultValue={[50]}
min={0}
max={100}
step={1}
/>Number Input
import { NumberInput } from '@geajs/ui'
<NumberInput label="Quantity" min={0} max={99} step={1} />Pin Input
import { PinInput } from '@geajs/ui'
<PinInput
label="Verification Code"
count={6}
type="numeric"
onValueComplete={(d) => console.log(d.valueAsString)}
/>Tags Input
import { TagsInput } from '@geajs/ui'
<TagsInput
label="Tags"
placeholder="Add tag..."
defaultValue={['gea', 'ui']}
onValueChange={(d) => console.log(d.value)}
/>Progress
import { Progress } from '@geajs/ui'
<Progress label="Upload" value={65} />Rating Group
import { RatingGroup } from '@geajs/ui'
<RatingGroup label="Rating" count={5} defaultValue={3} />Clipboard
import { Clipboard } from '@geajs/ui'
<Clipboard label="API Key" value="sk-abc123..." />Avatar
import { Avatar } from '@geajs/ui'
<Avatar src="/avatar.jpg" name="John Doe" />
<Avatar name="JD" />Toggle Group
import { ToggleGroup } from '@geajs/ui'
<ToggleGroup
items={[
{ value: 'bold', label: 'B' },
{ value: 'italic', label: 'I' },
{ value: 'underline', label: 'U' },
]}
multiple
/>Combobox
import { Combobox } from '@geajs/ui'
<Combobox
label="Country"
items={[
{ value: 'us', label: 'United States' },
{ value: 'uk', label: 'United Kingdom' },
{ value: 'de', label: 'Germany' },
]}
/>Collapsible
import { Collapsible } from '@geajs/ui'
<Collapsible label="Show more">
<p>Hidden content revealed on toggle.</p>
</Collapsible>Hover Card
import { HoverCard } from '@geajs/ui'
<HoverCard triggerLabel="@dashersw">
<p>Profile information...</p>
</HoverCard>Pagination
import { Pagination } from '@geajs/ui'
<Pagination
count={100}
defaultPageSize={10}
onPageChange={(d) => console.log(d.page)}
/>File Upload
import { FileUpload } from '@geajs/ui'
<FileUpload
label="Upload Documents"
accept={{ 'application/pdf': ['.pdf'] }}
maxFiles={5}
onFileChange={(d) => console.log(d.acceptedFiles)}
/>Toast
import { Toaster, ToastStore } from '@geajs/ui'
// Add the Toaster to your app root
class App extends Component {
template() {
return (
<div>
<Button onClick={() => ToastStore.success({ title: 'Saved!', description: 'Your changes have been saved.' })}>
Show Toast
</Button>
<Toaster />
</div>
)
}
}
// ToastStore methods: create, success, error, info, loading, dismissTree View
import { TreeView } from '@geajs/ui'
<TreeView collection={treeCollection}>
{/* Render tree nodes as children */}
</TreeView>Custom Styling
CSS Variables
Override CSS variables to customize the theme:
:root {
--primary: 222 47% 11%;
--primary-foreground: 210 40% 98%;
--radius: 0.75rem;
}Dark Mode
Add the dark class to your <html> element to enable dark mode:
<html class="dark">Component Classes
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:
[data-part="content"][data-state="open"] {
animation: custom-enter 200ms ease;
}Architecture
@geajs/ui uses a "shell component" pattern:
- Zag.js provides framework-agnostic state machines for complex UI behavior (keyboard navigation, focus traps, ARIA attributes)
- ZagComponent base class bridges Zag's vanilla adapter with Gea's reactive system
- Zag's
spreadPropsapplies dynamic attributes and event listeners imperatively after Gea's DOM patches - Gea's reactive properties drive visual state (open/closed, checked, value)
- Tailwind CSS handles all styling through utility classes and CSS custom properties
License
MIT
