These components are powered by Zag.js state machines. They handle keyboard navigation, ARIA attributes, focus management, and complex interaction patterns automatically. You get accessible behavior without writing any of it yourself.
Every interactive component accepts a class prop for additional Tailwind classes.
A modal dialog with focus trap, escape-to-close, and backdrop click to dismiss.
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>| Prop | Type | Default | Description |
|---|---|---|---|
title |
string |
— | Dialog heading |
description |
string |
— | Subheading text |
triggerLabel |
string |
'Open' |
Text for the trigger button |
open |
boolean |
— | Controlled open state |
defaultOpen |
boolean |
— | Initial open state |
modal |
boolean |
true |
Whether the dialog is modal |
closeOnInteractOutside |
boolean |
true |
Close when clicking the backdrop |
closeOnEscape |
boolean |
true |
Close on Escape key |
trapFocus |
boolean |
true |
Trap focus inside the dialog |
preventScroll |
boolean |
true |
Prevent body scroll when open |
role |
'dialog' | 'alertdialog' |
'dialog' |
ARIA role |
onOpenChange |
(details: { open: boolean }) => void |
— | Called when open state changes |
Tab panels with keyboard switching (arrow keys, Home, End).
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...' },
]}
/>| Prop | Type | Default | Description |
|---|---|---|---|
items |
Array<{ value, label, content }> |
[] |
Tab definitions |
defaultValue |
string |
— | Initially active tab |
value |
string |
— | Controlled active tab |
onValueChange |
(details: { value: string }) => void |
— | Called when active tab changes |
Expandable content sections. Supports single or multiple open panels and a collapsible mode where all panels can be closed.
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.' },
]}
/>| Prop | Type | Default | Description |
|---|---|---|---|
items |
Array<{ value, label, content }> |
[] |
Accordion items |
collapsible |
boolean |
false |
Allow all panels to close |
multiple |
boolean |
false |
Allow multiple panels open at once |
defaultValue |
string[] |
— | Initially open panels |
value |
string[] |
— | Controlled open panels |
orientation |
'vertical' | 'horizontal' |
'vertical' |
Layout direction |
onValueChange |
(details: { value: string[] }) => void |
— | Called when open panels change |
Informational popup that appears on hover with a configurable delay.
import { Tooltip } from '@geajs/ui'
<Tooltip content="Add to library">
<Button variant="outline">Hover me</Button>
</Tooltip>
<Tooltip content="Bold (Ctrl+B)" openDelay={200}>
<Button variant="outline" size="icon">B</Button>
</Tooltip>| Prop | Type | Default | Description |
|---|---|---|---|
content |
string |
— | Tooltip text |
openDelay |
number |
— | Milliseconds before showing |
closeDelay |
number |
— | Milliseconds before hiding |
A floating content panel anchored to a trigger button with auto-positioning.
import { Popover } from '@geajs/ui'
<Popover title="Settings" description="Configure your preferences.">
<p>Popover content...</p>
</Popover>| Prop | Type | Default | Description |
|---|---|---|---|
title |
string |
— | Popover heading |
description |
string |
— | Subheading text |
triggerLabel |
string |
'Open' |
Text for the trigger button |
Dropdown menu with keyboard navigation, typeahead search, and separator support.
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)}
/>| Prop | Type | Default | Description |
|---|---|---|---|
triggerLabel |
string |
— | Text for the trigger button |
items |
Array<{ value, label } | { type: 'separator' }> |
[] |
Menu items |
onSelect |
(details: { value: string }) => void |
— | Called when an item is selected |
Dropdown select with keyboard navigation and auto-positioning.
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)}
/>For advanced usage with grouped items or custom filtering, pass a Zag collection prop built with select.collection().
| Prop | Type | Default | Description |
|---|---|---|---|
label |
string |
— | Label text |
placeholder |
string |
'Select...' |
Placeholder when no value selected |
items |
Array<{ value, label }> |
[] |
Options |
collection |
ListCollection |
— | Advanced: Zag collection for custom item handling |
value |
string[] |
— | Controlled selected values |
defaultValue |
string[] |
— | Initially selected values |
multiple |
boolean |
— | Allow multiple selections |
disabled |
boolean |
— | Disable the select |
onValueChange |
(details: { value: string[] }) => void |
— | Called when selection changes |
onOpenChange |
(details: { open: boolean }) => void |
— | Called when dropdown opens/closes |
Searchable dropdown with keyboard navigation and typeahead filtering.
import { Combobox } from '@geajs/ui'
<Combobox
label="Country"
placeholder="Search..."
items={[
{ value: 'us', label: 'United States' },
{ value: 'uk', label: 'United Kingdom' },
{ value: 'de', label: 'Germany' },
]}
/>| Prop | Type | Default | Description |
|---|---|---|---|
label |
string |
— | Label text |
placeholder |
string |
— | Input placeholder |
items |
Array<{ value, label }> |
[] |
Options |
collection |
ListCollection |
— | Advanced: Zag collection |
A toggle switch.
import { Switch } from '@geajs/ui'
<Switch label="Airplane Mode" onCheckedChange={(d) => console.log(d.checked)} />| Prop | Type | Default | Description |
|---|---|---|---|
label |
string |
— | Label text |
checked |
boolean |
— | Controlled checked state |
defaultChecked |
boolean |
— | Initial checked state |
disabled |
boolean |
— | Disable the switch |
name |
string |
— | Form field name |
onCheckedChange |
(details: { checked: boolean }) => void |
— | Called when toggled |
A checkbox with optional indeterminate state.
import { Checkbox } from '@geajs/ui'
<Checkbox label="Accept terms" onCheckedChange={(d) => console.log(d.checked)} />| Prop | Type | Default | Description |
|---|---|---|---|
label |
string |
— | Label text |
checked |
boolean |
— | Controlled checked state |
defaultChecked |
boolean |
— | Initial checked state |
disabled |
boolean |
— | Disable the checkbox |
name |
string |
— | Form field name |
onCheckedChange |
(details: { checked: boolean }) => void |
— | Called when toggled |
A group of mutually exclusive radio buttons.
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)}
/>| Prop | Type | Default | Description |
|---|---|---|---|
label |
string |
— | Group label |
items |
Array<{ value, label }> |
[] |
Radio options |
defaultValue |
string |
— | Initially selected value |
value |
string |
— | Controlled selected value |
onValueChange |
(details: { value: string }) => void |
— | Called when selection changes |
A range slider.
import { Slider } from '@geajs/ui'
<Slider label="Volume" defaultValue={[50]} min={0} max={100} step={1} />| Prop | Type | Default | Description |
|---|---|---|---|
label |
string |
— | Label text |
defaultValue |
number[] |
— | Initial thumb positions |
value |
number[] |
— | Controlled thumb positions |
min |
number |
0 |
Minimum value |
max |
number |
100 |
Maximum value |
step |
number |
1 |
Step increment |
onValueChange |
(details: { value: number[] }) => void |
— | Called when value changes |
A numeric input with increment/decrement buttons.
import { NumberInput } from '@geajs/ui'
<NumberInput label="Quantity" min={0} max={99} step={1} />| Prop | Type | Default | Description |
|---|---|---|---|
label |
string |
— | Label text |
min |
number |
— | Minimum value |
max |
number |
— | Maximum value |
step |
number |
1 |
Step increment |
defaultValue |
string |
— | Initial value |
onValueChange |
(details: { value: string, valueAsNumber: number }) => void |
— | Called when value changes |
A multi-field input for verification codes.
import { PinInput } from '@geajs/ui'
<PinInput
label="Verification Code"
count={6}
type="numeric"
onValueComplete={(d) => console.log(d.valueAsString)}
/>| Prop | Type | Default | Description |
|---|---|---|---|
label |
string |
— | Label text |
count |
number |
4 |
Number of input fields |
type |
'alphanumeric' | 'numeric' | 'alphabetic' |
'alphanumeric' |
Allowed characters |
mask |
boolean |
false |
Mask the input (like a password) |
onValueComplete |
(details: { value: string[], valueAsString: string }) => void |
— | Called when all fields are filled |
A field for entering and managing tags.
import { TagsInput } from '@geajs/ui'
<TagsInput
label="Tags"
placeholder="Add tag..."
defaultValue={['gea', 'ui']}
onValueChange={(d) => console.log(d.value)}
/>| Prop | Type | Default | Description |
|---|---|---|---|
label |
string |
— | Label text |
placeholder |
string |
— | Input placeholder |
defaultValue |
string[] |
— | Initial tags |
value |
string[] |
— | Controlled tags |
onValueChange |
(details: { value: string[] }) => void |
— | Called when tags change |
A group of toggle buttons supporting single or multiple selection.
import { ToggleGroup } from '@geajs/ui'
<ToggleGroup
items={[
{ value: 'bold', label: 'B' },
{ value: 'italic', label: 'I' },
{ value: 'underline', label: 'U' },
]}
multiple
/>| Prop | Type | Default | Description |
|---|---|---|---|
items |
Array<{ value, label }> |
[] |
Toggle options |
multiple |
boolean |
false |
Allow multiple active toggles |
defaultValue |
string[] |
— | Initially active values |
value |
string[] |
— | Controlled active values |
onValueChange |
(details: { value: string[] }) => void |
— | Called when selection changes |
A progress bar.
import { Progress } from '@geajs/ui'
<Progress label="Upload" value={65} />| Prop | Type | Default | Description |
|---|---|---|---|
label |
string |
— | Label text |
value |
number |
0 |
Current progress (0–100) |
max |
number |
100 |
Maximum value |
A star rating input.
import { RatingGroup } from '@geajs/ui'
<RatingGroup label="Rating" count={5} defaultValue={3} />
<RatingGroup label="Half stars" count={5} allowHalf defaultValue={3.5} />| Prop | Type | Default | Description |
|---|---|---|---|
label |
string |
— | Label text |
count |
number |
5 |
Number of stars |
defaultValue |
number |
— | Initial rating |
value |
number |
— | Controlled rating |
allowHalf |
boolean |
false |
Enable half-star increments |
onValueChange |
(details: { value: number }) => void |
— | Called when rating changes |
A copy-to-clipboard field with visual feedback.
import { Clipboard } from '@geajs/ui'
<Clipboard label="API Key" value="sk-abc123..." />| Prop | Type | Default | Description |
|---|---|---|---|
label |
string |
— | Label text |
value |
string |
— | Text to copy |
A user avatar with image and fallback support.
import { Avatar } from '@geajs/ui'
<Avatar src="/avatar.jpg" name="John Doe" />
<Avatar name="JD" />| Prop | Type | Default | Description |
|---|---|---|---|
src |
string |
— | Image URL |
name |
string |
— | Fallback text (initials) |
A single expandable/collapsible section.
import { Collapsible } from '@geajs/ui'
<Collapsible label="Show more">
<p>Hidden content revealed on toggle.</p>
</Collapsible>| Prop | Type | Default | Description |
|---|---|---|---|
label |
string |
— | Trigger button text |
open |
boolean |
— | Controlled open state |
defaultOpen |
boolean |
— | Initial open state |
onOpenChange |
(details: { open: boolean }) => void |
— | Called when toggled |
A rich content preview that appears when hovering over a trigger.
import { HoverCard } from '@geajs/ui'
<HoverCard triggerLabel="@dashersw">
<p>Profile information...</p>
</HoverCard>| Prop | Type | Default | Description |
|---|---|---|---|
triggerLabel |
string |
— | Trigger text |
href |
string |
— | Optional link URL for the trigger |
openDelay |
number |
— | Milliseconds before showing |
closeDelay |
number |
— | Milliseconds before hiding |
Page navigation controls with previous/next buttons and page numbers.
import { Pagination } from '@geajs/ui'
<Pagination
count={100}
defaultPageSize={10}
onPageChange={(d) => console.log(d.page)}
/>| Prop | Type | Default | Description |
|---|---|---|---|
count |
number |
— | Total number of items |
defaultPageSize |
number |
10 |
Items per page |
defaultPage |
number |
1 |
Initially active page |
page |
number |
— | Controlled active page |
onPageChange |
(details: { page: number }) => void |
— | Called when page changes |
A file picker with drag-and-drop support and file type filtering.
import { FileUpload } from '@geajs/ui'
<FileUpload
label="Upload Documents"
accept={{ 'application/pdf': ['.pdf'] }}
maxFiles={5}
onFileChange={(d) => console.log(d.acceptedFiles)}
/>| Prop | Type | Default | Description |
|---|---|---|---|
label |
JSXNode |
— | Label text |
accept |
string | string[] | Record<string, string[]> |
— | Accepted MIME types and extensions |
maxFiles |
number |
— | Maximum number of files |
minFileSize |
number |
— | Minimum file size in bytes |
maxFileSize |
number |
— | Maximum file size in bytes |
allowDrop |
boolean |
true |
Allow drag&drop selection |
preventDocumentDrop |
boolean |
true |
Prevent dropping file outside the dropzone |
name |
string |
— | Input name (for usage in form) |
class |
string |
— | Class name(s) added to the root element |
disabled |
boolean |
false |
Disable interaction |
formatFileSize |
(bytes: number) => string |
localized, 2 decimal points, suffix | Function formatting file size in the file list |
onFileChange |
(details: { acceptedFiles: File[], rejectedFiles: { file: File, errors: string[] }[] }) => void |
— | Called when files are selected |
translations |
Partial<FileUploadTranslations> |
see Translations | Override UI strings |
| Key | Type | Default | Description |
|---|---|---|---|
dropzone |
string |
Drag and drop files here | Default dropzone text |
dropzoneButton |
string |
Choose Files | Button triggering file selection |
dropzoneActive |
string |
Drop your files here | Dropzone text while files are being dragged |
deleteFile |
(file: File) => string |
(file: File) => `Remove file ${file.name}` |
Button removing single file from the list |
clearAllButton |
string |
Clear all | Button removing all files from the list |
Temporary notification messages with auto-dismiss. Unlike other components, toasts use a global store pattern.
Add the Toaster component once at your app root:
import { Component } from '@geajs/core'
import { Toaster } from '@geajs/ui'
class App extends Component {
template() {
return (
<div>
{/* Your app content */}
<Toaster />
</div>
)
}
}Use the ToastStore singleton to create toasts from anywhere in your app:
import { ToastStore } from '@geajs/ui'
ToastStore.success({ title: 'Saved!', description: 'Your changes have been saved.' })
ToastStore.error({ title: 'Error', description: 'Something went wrong.' })
ToastStore.info({ title: 'Info', description: 'Here is some information.' })
ToastStore.loading({ title: 'Loading...', description: 'Please wait.' })| Method | Description |
|---|---|
create(options) |
Create a toast with full control over type and options |
success(options) |
Create a success toast |
error(options) |
Create an error toast |
info(options) |
Create an info toast |
loading(options) |
Create a loading toast |
dismiss(id?) |
Dismiss a specific toast, or all toasts if no ID given |
| Option | Type | Description |
|---|---|---|
title |
string |
Toast heading |
description |
string |
Body text |
type |
'success' | 'error' | 'info' | 'loading' |
Toast variant (set automatically by convenience methods) |
duration |
number |
Auto-dismiss delay in milliseconds (default: 5000) |
A hierarchical tree for displaying nested data. Accepts a Zag tree collection for full control over the data structure.
import { TreeView } from '@geajs/ui'
<TreeView collection={treeCollection}>
{/* Render tree nodes */}
</TreeView>See the Zag.js Tree View docs for details on building tree collections.