airi/docs/ai/context/ui-components.md
Ryan Lei 37807b84d6
Some checks are pending
CI / Lint (push) Waiting to run
CI / Build Test (stage-tamagotchi) (push) Waiting to run
CI / Build Test (stage-tamagotchi-godot) (push) Waiting to run
CI / Build Test (stage-web) (push) Waiting to run
CI / Build Test (ui-loading-screens) (push) Waiting to run
CI / Build Test (ui-transitions) (push) Waiting to run
CI / Type Check (push) Waiting to run
CI / Check Provenance (push) Waiting to run
Cloudflare Workers / Deploy - stage-web (push) Waiting to run
fix(ui): add openOnClick prop to Combobox for reliable dropdown opening (#1795)
---------

Co-authored-by: leiyutian <leiyutian@echo.tech>
Co-authored-by-agent: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-09 22:44:27 +08:00

18 KiB
Raw Permalink Blame History

@proj-airi/ui Component Reference

Auto-maintained: When adding or updating components in packages/ui, update this document accordingly.

Standardized primitives built on reka-ui. Minimal business logic — use these instead of raw DOM elements.

Source: packages/ui/src/components/


Animations

TransitionBidirectional

Bidirectional Vue <Transition> wrapper with customizable CSS classes.

Prop Type Default Description
fromClass string? CSS class for initial state
activeClass string? CSS class during transition
toClass string? CSS class for final state

Slots: default

TransitionHorizontal

Horizontal slide/fade transition (0.5s hardcoded).

Props: None | Slots: default

TransitionVertical

Smooth vertical expand/collapse with height animation and opacity control.

Prop Type Default Description
duration number? 250 Animation duration (ms)
easingEnter string? 'ease-in-out' Enter easing function
easingLeave string? 'ease-in-out' Leave easing function
opacityClosed number? 0 Opacity when closed
opacityOpened number? 1 Opacity when opened

Slots: default


Layout

Collapsible

Expandable/collapsible container with trigger button and vertical animation.

Prop Type Default Description
default boolean? Initial visibility
label string? Trigger button label

v-model: visible: boolean Slots: trigger({ visible, setVisible }), default({ visible, setVisible })

Screen

Responsive screen component that calculates canvas dimensions based on breakpoints.

Props: None | Slots: default({ width, height })

Skeleton

Loading placeholder with animation.

Prop Type Default Description
animation 'pulse' | 'wave' | 'none' 'pulse' Animation style

Slots: default

Truncatable

Line-clamped content container that expands and collapses when the overflowing content area is clicked.

Prop Type Default Description
lineClamp number? 3 Maximum visible lines while collapsed

Slots: default


Misc

Button

Versatile button with variants, sizes, and states.

Prop Type Default Description
toggled boolean? false Toggle state
icon string? UnoCSS/Iconify icon class
label string? Button text
disabled boolean? false Disabled state
loading boolean? false Loading state
variant 'primary' | 'secondary' | 'secondary-muted' | 'danger' | 'caution' | 'pure' | 'ghost' 'primary' Visual variant
size 'sm' | 'md' | 'lg' 'md' Size
shape 'rounded' | 'pill' | 'square' 'pill' Shape
block boolean? false Full width

Slots: default (fallback when no label)

Callout

Alert/callout box with themed accent bar.

Prop Type Default Description
theme 'primary' | 'violet' | 'lime' | 'orange' 'primary' Color theme
label string? Title

Slots: label, default

ContainerError

Error display with copy/feedback buttons and scrollable stack trace.

Prop Type Default Description
error unknown? Error object
message string? Custom message
stack string? Stack trace
includeStack boolean? true Show stack
showCopyButton boolean? true Show copy button
showFeedbackButton boolean? true Show feedback button
copyButtonLabel string? 'Copy' Copy button text
copiedButtonLabel string? 'Copied' Copied state text
feedbackButtonLabel string? 'Feedback' Feedback button text
heightPreset 'sm' | 'md' | 'lg' | 'xl' | 'auto' 'md' Container height

Emits: copy(content: string), feedback()

ErrorBoundary

Catches synchronous render/setup errors in descendants via onErrorCaptured and renders a fallback (built-in ContainerError + retry button) instead of letting the error propagate. Use to wrap <RouterView> or any subtree where partial failure should not blank the host layout. Async/unhandled rejections are NOT captured — use app.config.errorHandler for those.

Prop Type Default Description
title string? Optional title shown above error details
retryable boolean? true Show built-in retry button
retryLabel string? 'Try again' Retry button label

Slots: default, fallback({ error, info, retry }) Emits: error(err, instance, info), retry() Exposed: retry(), hasError()

DoubleCheckButton

Two-stage confirmation button — click once to reveal confirm/cancel.

Prop Type Default Description
variant ButtonVariant 'danger' Confirm button variant
cancelVariant ButtonVariant 'secondary' Cancel button variant
size 'sm' | 'md' | 'lg' 'md' Size
block boolean? false Full width
disabled boolean? false Disabled
loading boolean? false Loading

Emits: confirm(), cancel() Slots: default (initial text), confirm (confirm text), cancel (cancel text)

Progress

Linear progress bar with animated shine.

Prop Type Default Description
progress number (required) Percentage 0100
barClass string? Custom bar color class

Form — Input

Input

Basic text/number input.

Prop Type Default Description
type InputType? HTML input type
variant 'primary' | 'secondary' | 'primary-dimmed' 'primary' Visual variant
size 'sm' | 'md' | 'lg' 'md' Size

v-model: modelValue: string | number

BasicInputFile

Low-level file input with drag-drop support.

Prop Type Default Description
accept string? Accepted MIME types
multiple boolean? Allow multiple files
isDraggingClasses string | string[]? Classes when dragging
isNotDraggingClasses string | string[]? Classes when not dragging

v-model: modelValue: File[] Slots: default({ isDragging, firstFile, files })

InputFile

File input with preview and drag-drop UI.

Prop Type Default Description
accept string? Accepted file types
multiple boolean? Allow multiple
placeholder string? 'Choose file' Placeholder text

v-model: modelValue: File[] | undefined

InputFileCard

Styled file upload card with drag-and-drop zone.

Prop Type Default Description
accept string? Accepted file types
multiple boolean? Allow multiple

v-model: inherits from BasicInputFile Slots: default (custom upload UI)

InputKeyValue

Two-column input for key-value pairs.

Prop Type Default Description
name string? Input name attribute
keyPlaceholder string? Key placeholder
valuePlaceholder string? Value placeholder

v-model: propertyKey: string, propertyValue: string


Form — Textarea

BasicTextarea

Auto-resizing textarea with submit and paste-file events.

Prop Type Default Description
defaultHeight string? Initial height when empty
submitOnEnter boolean? true Submit on Enter (Shift+Enter for newline)

v-model: input: string Emits: submit(message: string), pasteFile(files: File[])

Textarea

Styled textarea wrapping BasicTextarea.

v-model: modelValue: string


Form — Checkbox / Radio

Checkbox

Toggle switch using reka-ui SwitchRoot.

Prop Type Default Description
disabled boolean? Disabled state

v-model: modelValue: boolean

Radio

Single radio button for radio groups.

Prop Type Default Description
id string (required) Unique ID
name string (required) Radio group name
value string (required) Option value
title string (required) Display label
deprecated boolean? false Deprecation indicator

v-model: modelValue: string


Form — Range

Range

Horizontal slider with progress visualization.

Prop Type Default Description
min number? 0 Minimum value
max number? 100 Maximum value
step number? 1 Step increment
disabled boolean? false Disabled
thumbColor string? '#9090906e' Thumb color
trackColor string? 'gray' Track color
trackValueColor string? 'red' Filled track color

v-model: modelValue: number

ColorHueRange

HSL hue selector (0360) with rainbow gradient.

Prop Type Default Description
disabled boolean? Disabled

v-model: modelValue: number

RoundRange

Rounded-style slider.

Prop Type Default Description
min number? 0 Minimum
max number? 100 Maximum
step number? 1 Step
disabled boolean? false Disabled

v-model: modelValue: number


Form — Select

Select

Dropdown select using reka-ui with grouping and custom rendering.

Prop Type Default Description
options SelectOptionItem<T>[] | SelectOptionGroupItem<T>[] (required) Options
placeholder string? 'Select an option' Placeholder
disabled boolean? false Disabled
by string | ((a: T, b: T) => boolean)? Custom comparison
contentMinWidth string | number? 160 Dropdown min width
contentWidth string | number? Dropdown width
shape 'rounded' | 'default' 'default' Shape
variant 'blurry' | 'default' 'default' Variant

v-model: modelValue: T Slots: value({ option, value, placeholder }), option({ option })

SelectOption

Individual option item within Select.

Prop Type Default Description
option SelectOptionItem<T> (required) Option data

Slots: default


Form — Combobox

Combobox

Searchable dropdown/autocomplete using reka-ui with grouping.

Prop Type Default Description
options ComboboxOptionItem<T>[] | ComboboxOptionGroupItem<T>[] (required) Options
placeholder string? Placeholder
disabled boolean? false Disabled
openOnClick boolean? true Auto-open dropdown on click
contentMinWidth string | number? Dropdown min width
contentWidth string | number? Dropdown width

v-model: modelValue: T Slots: option({ option }), empty

ComboboxSelect

Simplified Combobox wrapper for string/number options.

Prop Type Default Description
options { label, value, description?, disabled?, icon? }[]? Options
placeholder string? Placeholder
disabled boolean? false Disabled
openOnClick boolean? true Auto-open dropdown on click
title string? Title
layout 'horizontal' | 'vertical'? Layout direction
contentMinWidth string | number? Dropdown min width
contentWidth string | number? Dropdown width

v-model: modelValue: string | number Slots: option({ option }), empty

ComboboxOption

Option item within combobox (uses provide/inject).

Prop Type Default Description
value string | number (required) Value
label string? Display text
active boolean? Active state

Slots: default


Form — SelectTab

SelectTab

Tab-like selection using radio buttons with animated indicator.

Prop Type Default Description
options SelectTabOption[] (required) Tab options { label, value, description?, icon? }
disabled boolean? false Disabled
readonly boolean? false Read-only
size 'sm' | 'md' 'md' Size

v-model: modelValue: T


Form — Field (Labeled wrappers)

All Field components wrap a base input with label, description, and consistent layout. Common slots: label, description.

FieldInput

Prop Type Default Description
label string? Label
description string? Helper text
placeholder string? Placeholder
required boolean? Required indicator
type InputType? Input type
inputClass string? Custom input class
singleLine boolean? true true = input, false = textarea

v-model: modelValue: T

FieldCheckbox

Prop Type Default Description
label string? Label
description string? Helper text
disabled boolean? Disabled
placement 'left' | 'right' 'right' Switch position

v-model: modelValue: boolean

FieldTextArea

Prop Type Default Description
label string? Label
description string? Helper text
placeholder string? Placeholder
required boolean? Required indicator
textareaClass string? Custom textarea class
rows number? 6 Rows

v-model: modelValue: string

FieldRange

Prop Type Default Description
min number? Min
max number? Max
step number? Step
label string? Label
description string? Helper text
formatValue (value: number) => string? Value formatter
as 'label' | 'div' 'label' Wrapper element

v-model: modelValue: number

FieldInputFile

Prop Type Default Description
label string? Label
description string? Helper text
accept string? Accepted types
multiple boolean? Multiple
placeholder string? Placeholder

v-model: modelValue: File[] | undefined

FieldSelect

Prop Type Default Description
label string (required) Label
description string? Helper text
options SelectOptionItem<T>[] | SelectOptionGroupItem<T>[]? Options
placeholder string? Placeholder
disabled boolean? Disabled
layout 'horizontal' | 'vertical' 'horizontal' Layout
by string | ((a, b) => boolean)? Comparison
shape 'rounded' | 'default'? Shape
variant 'blurry' | 'default'? Variant

v-model: modelValue: T Slots: label, description, value, option

FieldCombobox

Prop Type Default Description
label string (required) Label
description string? Helper text
options { label, value, description?, disabled?, icon? }[]? Options
placeholder string? Placeholder
disabled boolean? false Disabled
openOnClick boolean? true Auto-open dropdown on click
layout 'horizontal' | 'vertical' 'horizontal' Layout

v-model: modelValue: string Slots: label, description, option, empty

FieldKeyValues

Dynamic key-value pair list with add/remove.

Prop Type Default Description
label string? Label
description string? Helper text
name string? Input name
keyPlaceholder string? Key placeholder
valuePlaceholder string? Value placeholder
required boolean? Required
inputClass string? Custom input class

v-model: keyValues: { key: string, value: string }[] Emits: remove(index: number), add(key: string, value: string)

FieldValues

Dynamic string list with add/remove.

Prop Type Default Description
label string? Label
description string? Helper text
name string? Input name
valuePlaceholder string? Value placeholder
required boolean? Required
inputClass string? Custom input class

v-model: items: string[] Emits: remove(index: number), add()


Composables

Exported from packages/ui/src/composables/:

  • useDeferredMount() — Defers component mounting (useful for heavy components).
  • useTheme() — Theme management composable.