구축·운영
AI 통합 가이드
AI 에이전트가 opt-ui 컴포넌트를 효과적으로 활용하기 위한 가이드입니다.
reopt design업데이트
컴포넌트 선택 의사결정 트리
구현하려는 UI 요구사항에 따라 적절한 컴포넌트를 선택하세요.
선택이 필요한가?
- 단일 선택 (검색 불필요) → StatusSelect, BranchSelect
- 단일 선택 (검색 필요) → SearchCombobox, ProjectSwitcher
- 명령 실행 → CommandPalette
콘텐츠 탐색이 필요한가?
- 탭 기반 콘텐츠 전환 → ContentTabs
- 접기/펼치기 콘텐츠 → FaqAccordion, EnvPanel
- 2D 그리드 탐색 → DashboardGrid
데이터 표시가 필요한가?
- 테이블 형태 → DomainTable
- 타임라인 → DeploymentTimeline
- 통계 카드 → StatCard, DashboardGrid
폼 입력이 필요한가?
- 설정/환경설정 → SettingsForm
의도 → 컴포넌트 매핑
| 의도/지시 | 컴포넌트 | 사용 예시 |
|---|---|---|
| "상태를 선택하게 해줘" | StatusSelect | <StatusSelect options={...} /> |
| "브랜치를 선택하게 해줘" | BranchSelect | <BranchSelect branches={...} /> |
| "검색 가능한 선택" | SearchCombobox | <SearchCombobox items={...} /> |
| "통계 카드 그리드" | DashboardGrid | <DashboardGrid stats={...} /> |
| "Cmd+K 명령 팔레트" | CommandPalette | <CommandPalette commands={...} /> |
| "접기/펼치기 FAQ" | FaqAccordion | <FaqAccordion items={...} /> |
| "탭 인터페이스" | ContentTabs | <ContentTabs tabs={...} /> |
| "설정 폼" | SettingsForm | <SettingsForm fields={...} /> |
| "배포 타임라인" | DeploymentTimeline | <DeploymentTimeline events={...} /> |
| "환경변수 패널" | EnvPanel | <EnvPanel envs={...} /> |
데이터 타입 가이드
모든 Block 컴포넌트는 타입이 정의된 데이터 배열을 받습니다. 타입 정의는 @reopt-ai/opt-ui에서 export됩니다.
tsx
import type {
StatCardType,
TabDef,
FaqItem,
FormFieldDef,
Command,
SelectOption,
// ... 등
} from "@reopt-ai/opt-ui";주요 타입 → 컴포넌트 매핑
| 타입 | 컴포넌트 |
|---|---|
| StatCardType[] | DashboardGrid |
| TabDef[] | ContentTabs |
| FaqItem[] | FaqAccordion |
| FormFieldDef[] | SettingsForm |
| Command[] | CommandPalette |
| SelectOption[] | StatusSelect, BranchSelect |
코드 생성 템플릿
AI 에이전트가 코드를 생성할 때 참고할 수 있는 템플릿입니다.
대시보드 페이지
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)}
/>
);
}탭 페이지
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" />;
}선택 컴포넌트
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 선택
Block을 사용할지 Primitive를 직접 조합할지 결정하는 기준입니다.
Block 사용 (권장)
- 표준 UI 패턴에 맞을 때
- 데이터 배열만 준비하면 될 때
- 빠른 프로토타이핑이 필요할 때
- 접근성 처리를 위임하고 싶을 때
Primitive 직접 사용
- 커스텀 레이아웃이 필요할 때
- Block이 제공하지 않는 조합이 필요할 때
- 세밀한 스타일 제어가 필요할 때
- 특수한 인터랙션 패턴이 필요할 때
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>키보드 동작 구현
키보드 동작을 구현할 때 opt-ui가 제공하는 기능을 활용하세요.
| 요구사항 | 구현 방법 |
|---|---|
| 방향키로 2D 탐색 | CompositeZone + CompositeRow + CompositeItem |
| Tab 단일 진입점 | CompositeZone (roving tabindex 자동) |
| Esc로 닫기 | Dialog 사용 |
| Enter로 선택 | CompositeItem 또는 SelectItem |
| 방향키로 수직 탐색 | orientation="vertical" 설정 |
| 방향키로 수평 탐색 | orientation="horizontal" 설정 |
프롬프트 프리셋
AI 에이전트에게 opt-ui 기반 UI 생성을 요청할 때 사용할 수 있는 프롬프트 템플릿입니다. 변수를 입력하면 실시간으로 치환됩니다.
대시보드 Surface 생성
@reopt-ai/opt-ui와 @reopt-ai/opt-charts를 사용해서 {domain} 대시보드 Surface를 만들어줘.
요구사항:
- SurfaceLayout으로 루트 래핑 (loading prop 포함)
- SummaryRow로 핵심 지표 4개 표시
- opt-charts TrendChart로 시계열 추이
- DataTable로 상세 목록
- FilterBar로 날짜/상태 필터링
- 시맨틱 스페이싱 토큰 사용 (gap-section, gap-group, gap-element)
참고: /docs/opt-ui/architecture 계층 구조, /docs/opt-ui/theming 테마 시스템폼 Shell 생성
opt-ui의 Form Core (FormInput, FormTextarea, FormSelect, FormSwitch)를 사용해서
{feature} Shell을 만들어줘.
요구사항:
- opt-ui FormStore 기반 상태 관리
- 필드별 유효성 검증 (validate)
- 제출 시 onSubmit 콜백
- 에러 메시지 표시 (FormError)
- 키보드: Tab 순서 논리적, Enter로 제출
패턴 참고: AuthForm (인증), WizardForm (다단계), DynamicFieldForm (동적 필드)데이터 시각화 페이지
@reopt-ai/opt-charts를 사용해서 {data} 분석 페이지를 만들어줘.
사용 가능한 차트:
- LineChart: 시계열 추이
- BarChart: 카테고리 비교
- AreaChart: 누적/면적
- PieChart: 비율 분포
- ScatterChart: 상관관계
- FunnelChart: 전환 퍼널
- RetentionHeatmap: 리텐션 매트릭스
- SankeyChart: 흐름 다이어그램
모든 차트는 ChartContainer로 감싸고, ChartTooltip과 ChartLegend를 포함해줘.
데이터 타입은 ChartDataPoint[] (name 필수) + ChartSeriesDef[] (dataKey, name 필수).CRUD 관리 페이지
opt-ui로 {resource} 관리 페이지를 만들어줘.
구성:
- SurfaceLayout 루트 (loading prop)
- SummaryRow: 전체/활성/비활성 카운트
- FilterBar: 검색 + 상태 필터 + 날짜 범위
- DataTable: 정렬/페이지네이션/행 선택
- FloatingActionBar: 선택된 행에 대한 일괄 작업 (삭제, 상태 변경)
- Dialog: 생성/수정 폼 (FormInput + FormSelect)
- NotificationToast: 작업 결과 알림
키보드: Tab→필터→테이블→작업, Space로 행 선택, Enter로 편집컴포넌트 코드 리뷰
이 컴포넌트를 opt-ui 가이드라인에 맞게 리뷰해줘. 체크리스트: - [ ] Surface는 SurfaceLayout 래퍼 사용하는가 - [ ] loading prop 지원하는가 - [ ] 시맨틱 스페이싱 토큰 사용하는가 (gap-section/group/element) - [ ] 시맨틱 색상 토큰 사용하는가 (bg-surface, text-text-primary, border-border) - [ ] 하드코딩된 색상(zinc-*, gray-*) 대신 테마 변수 사용하는가 - [ ] Tab 순서가 논리적인가 - [ ] 키보드로 모든 인터랙션 가능한가 - [ ] Core primitive를 직접 사용하는가 (html 태그 직접 X) /opt-ui-guide 스킬로 자동 검사도 가능합니다.
테마 적용 확인
이 페이지가 사이트 전역 Light/Black 모드와 opt-ui 프리셋 프리뷰에서 모두 잘 보이는지 확인해줘. 확인 포인트: - 사이트 shell: default light와 default black만 전역 적용 - 컴포넌트 프리뷰: Default, Minimal, Natural, Pro, Mono Dark가 로컬 data-theme 범위 안에서만 적용 - 프리셋 전환 중 document.documentElement의 data-theme는 default/default-dark를 유지 하드코딩된 색상(zinc-500, gray-200 등)이 있으면 시맨틱 토큰으로 교체 필요.