Skip to content

Interactive Components

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.

Dialog

A modal dialog with focus trap, escape-to-close, and backdrop click to dismiss.

tsx
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>

Props

PropTypeDefaultDescription
titlestringDialog heading
descriptionstringSubheading text
triggerLabelstring'Open'Text for the trigger button
openbooleanControlled open state
defaultOpenbooleanInitial open state
modalbooleantrueWhether the dialog is modal
closeOnInteractOutsidebooleantrueClose when clicking the backdrop
closeOnEscapebooleantrueClose on Escape key
trapFocusbooleantrueTrap focus inside the dialog
preventScrollbooleantruePrevent body scroll when open
role'dialog' | 'alertdialog''dialog'ARIA role
onOpenChange(details: { open: boolean }) => voidCalled when open state changes

Tabs

Tab panels with keyboard switching (arrow keys, Home, End).

tsx
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...' },
  ]}
/>

Props

PropTypeDefaultDescription
itemsArray<{ value, label, content }>[]Tab definitions
defaultValuestringInitially active tab
valuestringControlled active tab
onValueChange(details: { value: string }) => voidCalled when active tab changes

Accordion

Expandable content sections. Supports single or multiple open panels and a collapsible mode where all panels can be closed.

tsx
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.' },
  ]}
/>

Props

PropTypeDefaultDescription
itemsArray<{ value, label, content }>[]Accordion items
collapsiblebooleanfalseAllow all panels to close
multiplebooleanfalseAllow multiple panels open at once
defaultValuestring[]Initially open panels
valuestring[]Controlled open panels
orientation'vertical' | 'horizontal''vertical'Layout direction
onValueChange(details: { value: string[] }) => voidCalled when open panels change

Tooltip

Informational popup that appears on hover with a configurable delay.

tsx
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>

Props

PropTypeDefaultDescription
contentstringTooltip text
openDelaynumberMilliseconds before showing
closeDelaynumberMilliseconds before hiding

Popover

A floating content panel anchored to a trigger button with auto-positioning.

tsx
import { Popover } from '@geajs/ui'

<Popover title="Settings" description="Configure your preferences.">
  <p>Popover content...</p>
</Popover>

Props

PropTypeDefaultDescription
titlestringPopover heading
descriptionstringSubheading text
triggerLabelstring'Open'Text for the trigger button

Dropdown menu with keyboard navigation, typeahead search, and separator support.

tsx
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)}
/>

Props

PropTypeDefaultDescription
triggerLabelstringText for the trigger button
itemsArray<{ value, label } | { type: 'separator' }>[]Menu items
onSelect(details: { value: string }) => voidCalled when an item is selected

Select

Dropdown select with keyboard navigation and auto-positioning.

tsx
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().

Props

PropTypeDefaultDescription
labelstringLabel text
placeholderstring'Select...'Placeholder when no value selected
itemsArray<{ value, label }>[]Options
collectionListCollectionAdvanced: Zag collection for custom item handling
valuestring[]Controlled selected values
defaultValuestring[]Initially selected values
multiplebooleanAllow multiple selections
disabledbooleanDisable the select
onValueChange(details: { value: string[] }) => voidCalled when selection changes
onOpenChange(details: { open: boolean }) => voidCalled when dropdown opens/closes

Combobox

Searchable dropdown with keyboard navigation and typeahead filtering.

tsx
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' },
  ]}
/>

Props

PropTypeDefaultDescription
labelstringLabel text
placeholderstringInput placeholder
itemsArray<{ value, label }>[]Options
collectionListCollectionAdvanced: Zag collection

Switch

A toggle switch.

tsx
import { Switch } from '@geajs/ui'

<Switch label="Airplane Mode" onCheckedChange={(d) => console.log(d.checked)} />

Props

PropTypeDefaultDescription
labelstringLabel text
checkedbooleanControlled checked state
defaultCheckedbooleanInitial checked state
disabledbooleanDisable the switch
namestringForm field name
onCheckedChange(details: { checked: boolean }) => voidCalled when toggled

Checkbox

A checkbox with optional indeterminate state.

tsx
import { Checkbox } from '@geajs/ui'

<Checkbox label="Accept terms" onCheckedChange={(d) => console.log(d.checked)} />

Props

PropTypeDefaultDescription
labelstringLabel text
checkedbooleanControlled checked state
defaultCheckedbooleanInitial checked state
disabledbooleanDisable the checkbox
namestringForm field name
onCheckedChange(details: { checked: boolean }) => voidCalled when toggled

Radio Group

A group of mutually exclusive radio buttons.

tsx
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)}
/>

Props

PropTypeDefaultDescription
labelstringGroup label
itemsArray<{ value, label }>[]Radio options
defaultValuestringInitially selected value
valuestringControlled selected value
onValueChange(details: { value: string }) => voidCalled when selection changes

Slider

A range slider.

tsx
import { Slider } from '@geajs/ui'

<Slider label="Volume" defaultValue={[50]} min={0} max={100} step={1} />

Props

PropTypeDefaultDescription
labelstringLabel text
defaultValuenumber[]Initial thumb positions
valuenumber[]Controlled thumb positions
minnumber0Minimum value
maxnumber100Maximum value
stepnumber1Step increment
onValueChange(details: { value: number[] }) => voidCalled when value changes

Number Input

A numeric input with increment/decrement buttons.

tsx
import { NumberInput } from '@geajs/ui'

<NumberInput label="Quantity" min={0} max={99} step={1} />

Props

PropTypeDefaultDescription
labelstringLabel text
minnumberMinimum value
maxnumberMaximum value
stepnumber1Step increment
defaultValuestringInitial value
onValueChange(details: { value: string, valueAsNumber: number }) => voidCalled when value changes

Pin Input

A multi-field input for verification codes.

tsx
import { PinInput } from '@geajs/ui'

<PinInput
  label="Verification Code"
  count={6}
  type="numeric"
  onValueComplete={(d) => console.log(d.valueAsString)}
/>

Props

PropTypeDefaultDescription
labelstringLabel text
countnumber4Number of input fields
type'alphanumeric' | 'numeric' | 'alphabetic''alphanumeric'Allowed characters
maskbooleanfalseMask the input (like a password)
onValueComplete(details: { value: string[], valueAsString: string }) => voidCalled when all fields are filled

Tags Input

A field for entering and managing tags.

tsx
import { TagsInput } from '@geajs/ui'

<TagsInput
  label="Tags"
  placeholder="Add tag..."
  defaultValue={['gea', 'ui']}
  onValueChange={(d) => console.log(d.value)}
/>

Props

PropTypeDefaultDescription
labelstringLabel text
placeholderstringInput placeholder
defaultValuestring[]Initial tags
valuestring[]Controlled tags
onValueChange(details: { value: string[] }) => voidCalled when tags change

Toggle Group

A group of toggle buttons supporting single or multiple selection.

tsx
import { ToggleGroup } from '@geajs/ui'

<ToggleGroup
  items={[
    { value: 'bold', label: 'B' },
    { value: 'italic', label: 'I' },
    { value: 'underline', label: 'U' },
  ]}
  multiple
/>

Props

PropTypeDefaultDescription
itemsArray<{ value, label }>[]Toggle options
multiplebooleanfalseAllow multiple active toggles
defaultValuestring[]Initially active values
valuestring[]Controlled active values
onValueChange(details: { value: string[] }) => voidCalled when selection changes

Progress

A progress bar.

tsx
import { Progress } from '@geajs/ui'

<Progress label="Upload" value={65} />

Props

PropTypeDefaultDescription
labelstringLabel text
valuenumber0Current progress (0–100)
maxnumber100Maximum value

Rating Group

A star rating input.

tsx
import { RatingGroup } from '@geajs/ui'

<RatingGroup label="Rating" count={5} defaultValue={3} />
<RatingGroup label="Half stars" count={5} allowHalf defaultValue={3.5} />

Props

PropTypeDefaultDescription
labelstringLabel text
countnumber5Number of stars
defaultValuenumberInitial rating
valuenumberControlled rating
allowHalfbooleanfalseEnable half-star increments
onValueChange(details: { value: number }) => voidCalled when rating changes

Clipboard

A copy-to-clipboard field with visual feedback.

tsx
import { Clipboard } from '@geajs/ui'

<Clipboard label="API Key" value="sk-abc123..." />

Props

PropTypeDefaultDescription
labelstringLabel text
valuestringText to copy

Avatar

A user avatar with image and fallback support.

tsx
import { Avatar } from '@geajs/ui'

<Avatar src="/avatar.jpg" name="John Doe" />
<Avatar name="JD" />

Props

PropTypeDefaultDescription
srcstringImage URL
namestringFallback text (initials)

Collapsible

A single expandable/collapsible section.

tsx
import { Collapsible } from '@geajs/ui'

<Collapsible label="Show more">
  <p>Hidden content revealed on toggle.</p>
</Collapsible>

Props

PropTypeDefaultDescription
labelstringTrigger button text
openbooleanControlled open state
defaultOpenbooleanInitial open state
onOpenChange(details: { open: boolean }) => voidCalled when toggled

Hover Card

A rich content preview that appears when hovering over a trigger.

tsx
import { HoverCard } from '@geajs/ui'

<HoverCard triggerLabel="@dashersw">
  <p>Profile information...</p>
</HoverCard>

Props

PropTypeDefaultDescription
triggerLabelstringTrigger text
hrefstringOptional link URL for the trigger
openDelaynumberMilliseconds before showing
closeDelaynumberMilliseconds before hiding

Pagination

Page navigation controls with previous/next buttons and page numbers.

tsx
import { Pagination } from '@geajs/ui'

<Pagination
  count={100}
  defaultPageSize={10}
  onPageChange={(d) => console.log(d.page)}
/>

Props

PropTypeDefaultDescription
countnumberTotal number of items
defaultPageSizenumber10Items per page
defaultPagenumber1Initially active page
pagenumberControlled active page
onPageChange(details: { page: number }) => voidCalled when page changes

File Upload

A file picker with drag-and-drop support and file type filtering.

tsx
import { FileUpload } from '@geajs/ui'

<FileUpload
  label="Upload Documents"
  accept={{ 'application/pdf': ['.pdf'] }}
  maxFiles={5}
  onFileChange={(d) => console.log(d.acceptedFiles)}
/>

Props

PropTypeDefaultDescription
labelstringLabel text
acceptRecord<string, string[]>Accepted MIME types and extensions
maxFilesnumberMaximum number of files
maxFileSizenumberMaximum file size in bytes
onFileChange(details: { acceptedFiles: File[], rejectedFiles: File[] }) => voidCalled when files are selected

Toast

Temporary notification messages with auto-dismiss. Unlike other components, toasts use a global store pattern.

Setup

Add the Toaster component once at your app root:

tsx
import { Component } from '@geajs/core'
import { Toaster } from '@geajs/ui'

class App extends Component {
  template() {
    return (
      <div>
        {/* Your app content */}
        <Toaster />
      </div>
    )
  }
}

Creating Toasts

Use the ToastStore singleton to create toasts from anywhere in your app:

tsx
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.' })

ToastStore Methods

MethodDescription
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

Toast Options

OptionTypeDescription
titlestringToast heading
descriptionstringBody text
type'success' | 'error' | 'info' | 'loading'Toast variant (set automatically by convenience methods)
durationnumberAuto-dismiss delay in milliseconds (default: 5000)

Tree View

A hierarchical tree for displaying nested data. Accepts a Zag tree collection for full control over the data structure.

tsx
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.

Released under the MIT License.