Build & Operate
AI integration guide
A guide for AI agents to make effective use of opt-ui components.
reopt designUpdated
Component selection decision tree
Choose the right component based on your UI requirements.
Need selection?
- Single selection (no search) → StatusSelect, BranchSelect
- Single selection (with search) → SearchCombobox, ProjectSwitcher
- Run a command → CommandPalette
Need content navigation?
- Tab-based content switching → ContentTabs
- Collapsible content → FaqAccordion, EnvPanel
- 2D grid navigation → DashboardGrid
Need to display data?
- Table format → DomainTable
- Timeline → DeploymentTimeline
- Stat cards → StatCard, DashboardGrid
Need form input?
- Settings / preferences → SettingsForm
Intent → component mapping
| Intent / instruction | Component | Usage example |
|---|---|---|
| "Let me pick a status" | StatusSelect | <StatusSelect options={...} /> |
| "Let me pick a branch" | BranchSelect | <BranchSelect branches={...} /> |
| "Searchable selection" | SearchCombobox | <SearchCombobox items={...} /> |
| "Stat card grid" | DashboardGrid | <DashboardGrid stats={...} /> |
| "Cmd+K command palette" | CommandPalette | <CommandPalette commands={...} /> |
| "Collapsible FAQ" | FaqAccordion | <FaqAccordion items={...} /> |
| "Tabbed interface" | ContentTabs | <ContentTabs tabs={...} /> |
| "Settings form" | SettingsForm | <SettingsForm fields={...} /> |
| "Deployment timeline" | DeploymentTimeline | <DeploymentTimeline events={...} /> |
| "Environment variables panel" | EnvPanel | <EnvPanel envs={...} /> |
Data type guide
Every Block component takes a typed data array. Type definitions are exported from @reopt-ai/opt-ui.
tsx
import type {
StatCardType,
TabDef,
FaqItem,
FormFieldDef,
Command,
SelectOption,
// ... 등
} from "@reopt-ai/opt-ui";Common types → components
| Type | Component |
|---|---|
| StatCardType[] | DashboardGrid |
| TabDef[] | ContentTabs |
| FaqItem[] | FaqAccordion |
| FormFieldDef[] | SettingsForm |
| Command[] | CommandPalette |
| SelectOption[] | StatusSelect, BranchSelect |
Code generation templates
Templates AI agents can reference when generating code.
Dashboard page
tsx
"use client";
import { DashboardGrid } from "@reopt-ai/opt-ui";
import type { StatCardType } from "@reopt-ai/opt-ui";
const stats: StatCardType[] = [
{ id: "1", title: "활성 사용자", value: "1,234", trend: "+12%" },
{ id: "2", title: "총 배포", value: "567", trend: "+5%" },
// ...
];
export default function DashboardPage() {
return (
<DashboardGrid
stats={stats}
onStatClick={(stat) => console.log(stat)}
/>
);
}Tabbed page
tsx
"use client";
import { ContentTabs } from "@reopt-ai/opt-ui";
import type { TabDef } from "@reopt-ai/opt-ui";
const tabs: TabDef[] = [
{ id: "overview", label: "개요", content: <OverviewPanel /> },
{ id: "settings", label: "설정", content: <SettingsPanel /> },
{ id: "logs", label: "로그", content: <LogsPanel /> },
];
export default function TabbedPage() {
return <ContentTabs tabs={tabs} defaultTab="overview" />;
}Select component
tsx
"use client";
import { useState } from "react";
import { StatusSelect } from "@reopt-ai/opt-ui";
import type { SelectOption } from "@reopt-ai/opt-ui";
const options: SelectOption[] = [
{ id: "active", label: "활성", color: "green" },
{ id: "pending", label: "대기중", color: "yellow" },
{ id: "inactive", label: "비활성", color: "gray" },
];
export default function StatusPage() {
const [status, setStatus] = useState("active");
return (
<StatusSelect
options={options}
value={status}
onChange={setStatus}
/>
);
}Primitive vs Block
How to decide between using a Block and composing Primitives directly.
Use a Block (recommended)
- When you match a standard UI pattern
- When you only need to prepare a data array
- When you need fast prototyping
- When you want to delegate accessibility
Use Primitives directly
- When you need a custom layout
- When you need a composition Blocks don't provide
- When you need fine-grained styling control
- When you need a specialized interaction pattern
tsx
// Block 사용 (간단)
<FaqAccordion items={faqItems} />
// Primitive 조합 (세밀한 제어)
import {
DisclosureRoot,
DisclosureTrigger,
DisclosureContent,
CompositeZone,
CompositeItem,
} from "@reopt-ai/opt-ui";
<CompositeZone orientation="vertical" focusLoop>
{items.map((item) => (
<CompositeItem key={item.id} render={<DisclosureRoot />}>
<DisclosureTrigger className="custom-trigger">
{item.question}
</DisclosureTrigger>
<DisclosureContent className="custom-content">
{item.answer}
</DisclosureContent>
</CompositeItem>
))}
</CompositeZone>Implementing keyboard behavior
When implementing keyboard behavior, use the features opt-ui already provides.
| Requirement | How to implement |
|---|---|
| 2D arrow-key navigation | CompositeZone + CompositeRow + CompositeItem |
| Single Tab entry point | CompositeZone (automatic roving tabindex) |
| Close with Esc | Use Dialog |
| Select with Enter | CompositeItem or SelectItem |
| Vertical arrow-key navigation | Set orientation="vertical" |
| Horizontal arrow-key navigation | Set orientation="horizontal" |
Prompt presets
Prompt templates you can use when asking an AI agent to generate opt-ui based UI. Variables are substituted live as you type.
Generate a dashboard Surface
Build a {domain} dashboard Surface using @reopt-ai/opt-ui and @reopt-ai/opt-charts.
Requirements:
- Wrap the root with SurfaceLayout (include loading prop)
- Show 4 key metrics with SummaryRow
- Use opt-charts TrendChart for time-series trends
- DataTable for the detailed list
- FilterBar for date/status filtering
- Use semantic spacing tokens (gap-section, gap-group, gap-element)
References: /docs/opt-ui/architecture for the layer structure, /docs/opt-ui/theming for the theme systemGenerate a form Shell
Build a {feature} Shell using opt-ui's Form Core (FormInput, FormTextarea, FormSelect, FormSwitch).
Requirements:
- State management via opt-ui FormStore
- Per-field validation (validate)
- onSubmit callback on submit
- Error messages (FormError)
- Keyboard: logical Tab order, Enter to submit
Reference patterns: AuthForm (sign-in), WizardForm (multi-step), DynamicFieldForm (dynamic fields)Data visualization page
Build a {data} analytics page using @reopt-ai/opt-charts.
Available charts:
- LineChart: time-series trends
- BarChart: category comparison
- AreaChart: cumulative / area
- PieChart: ratio distribution
- ScatterChart: correlation
- FunnelChart: conversion funnel
- RetentionHeatmap: retention matrix
- SankeyChart: flow diagram
Wrap every chart in ChartContainer and include ChartTooltip and ChartLegend.
Data types: ChartDataPoint[] (name required) + ChartSeriesDef[] (dataKey, name required).CRUD management page
Build a {resource} management page with opt-ui.
Layout:
- SurfaceLayout root (loading prop)
- SummaryRow: total / active / inactive counts
- FilterBar: search + status filter + date range
- DataTable: sorting / pagination / row selection
- FloatingActionBar: bulk actions on selected rows (delete, status change)
- Dialog: create/edit form (FormInput + FormSelect)
- NotificationToast: action result notifications
Keyboard: Tab → filter → table → actions, Space to select rows, Enter to editComponent code review
Review this component against the opt-ui guidelines. Checklist: - [ ] Does the Surface use a SurfaceLayout wrapper? - [ ] Does it support the loading prop? - [ ] Does it use semantic spacing tokens (gap-section/group/element)? - [ ] Does it use semantic color tokens (bg-surface, text-text-primary, border-border)? - [ ] Does it use theme variables instead of hard-coded colors (zinc-*, gray-*)? - [ ] Is the Tab order logical? - [ ] Is every interaction reachable via the keyboard? - [ ] Does it use Core primitives directly (no raw html tags)? You can also run automatic checks via the /opt-ui-guide skill.
Theme application check
Check that this page looks correct in the site-wide Light/Black modes and opt-ui preset previews. Check points: - Site shell: only default light and default black apply globally - Component previews: Default, Minimal, Natural, Pro, and Mono Dark apply only inside local data-theme scopes - document.documentElement keeps data-theme at default/default-dark while presets change in previews If you find hard-coded colors (zinc-500, gray-200, etc.), replace them with semantic tokens.