@reopt-ai/opt-ui 1.4.1 → 1.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/COMPONENT_CATALOG.md +374 -84
- package/README.md +28 -7
- package/dist/app.css +146 -0
- package/dist/core/index.cjs +164 -324
- package/dist/core/index.d.cts +3 -5
- package/dist/core/index.d.ts +3 -5
- package/dist/core/index.js +3 -323
- package/dist/docs/01-getting-started.md +25 -5
- package/dist/docs/02-components/01-core.md +192 -46
- package/dist/docs/02-components/02-visuals.md +1 -1
- package/dist/docs/02-components/03-shells.md +177 -42
- package/dist/docs/02-components/04-surfaces.md +1 -1
- package/dist/docs/02-components/index.md +1 -1
- package/dist/docs/03-recipes/03-layouts.md +20 -12
- package/dist/docs/04-theming.md +3 -1
- package/dist/docs/05-migration/01-breaking-changes.md +28 -0
- package/dist/id-registry.cjs +1899 -1872
- package/dist/id-registry.d.cts +13 -10
- package/dist/id-registry.d.cts.map +1 -0
- package/dist/id-registry.d.ts +13 -10
- package/dist/id-registry.d.ts.map +1 -0
- package/dist/id-registry.js +1897 -1871
- package/dist/id-registry.js.map +1 -0
- package/dist/id-registry.json +44 -44
- package/dist/index.cjs +8294 -9613
- package/dist/index.d.cts +1486 -1438
- package/dist/index.d.cts.map +1 -0
- package/dist/index.d.ts +1486 -1438
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +7933 -9600
- package/dist/index.js.map +1 -0
- package/dist/meta.cjs +7461 -6765
- package/dist/meta.d.cts.map +1 -0
- package/dist/meta.d.ts.map +1 -0
- package/dist/meta.js +7460 -6736
- package/dist/meta.js.map +1 -0
- package/dist/pagination-By7Ozv3U.js +3788 -0
- package/dist/pagination-By7Ozv3U.js.map +1 -0
- package/dist/pagination-Uv3CnGJz.cjs +4677 -0
- package/dist/shader-surface-BK1GMt5_.d.cts +1788 -0
- package/dist/shader-surface-BK1GMt5_.d.cts.map +1 -0
- package/dist/shader-surface-BWhO2xkk.js +3715 -0
- package/dist/shader-surface-BWhO2xkk.js.map +1 -0
- package/dist/shader-surface-DIVWtpFl.d.ts +1788 -0
- package/dist/shader-surface-DIVWtpFl.d.ts.map +1 -0
- package/dist/shader-surface-DxLLfrE6.cjs +4108 -0
- package/dist/shells/index.cjs +51 -65
- package/dist/shells/index.d.cts +4 -5
- package/dist/shells/index.d.ts +4 -5
- package/dist/shells/index.js +3 -64
- package/dist/tailwind.css +54 -5
- package/dist/theme/presets/default.css +12 -12
- package/dist/theme/server.cjs +310 -0
- package/dist/theme/server.d.cts +117 -0
- package/dist/theme/server.d.cts.map +1 -0
- package/dist/theme/server.d.ts +117 -0
- package/dist/theme/server.d.ts.map +1 -0
- package/dist/theme/server.js +287 -0
- package/dist/theme/server.js.map +1 -0
- package/dist/types-D0FlcYnM.d.cts +301 -0
- package/dist/types-D0FlcYnM.d.cts.map +1 -0
- package/dist/types-D0FlcYnM.d.ts +301 -0
- package/dist/types-D0FlcYnM.d.ts.map +1 -0
- package/dist/visuals/index.cjs +10 -4
- package/dist/visuals/index.d.cts +2 -1
- package/dist/visuals/index.d.ts +2 -1
- package/dist/visuals/index.js +1 -2
- package/dist/workflow-canvas-3Jeevkgy.cjs +2599 -0
- package/dist/workflow-canvas-BGBAcjf-.js +2403 -0
- package/dist/workflow-canvas-BGBAcjf-.js.map +1 -0
- package/dist/workflow-canvas-Bar_O2SQ.d.ts +494 -0
- package/dist/workflow-canvas-Bar_O2SQ.d.ts.map +1 -0
- package/dist/workflow-canvas-DghDRtHn.d.cts +494 -0
- package/dist/workflow-canvas-DghDRtHn.d.cts.map +1 -0
- package/package.json +24 -8
- package/dist/chunk-3GWWZKX7.js +0 -38
- package/dist/chunk-AFF2HPE5.cjs +0 -5008
- package/dist/chunk-ELWICXYY.js +0 -4745
- package/dist/chunk-N4NDU5ET.cjs +0 -4745
- package/dist/chunk-ONE3C5RV.cjs +0 -38
- package/dist/chunk-QWBHD54V.js +0 -3218
- package/dist/chunk-RBM2RNC2.js +0 -5008
- package/dist/chunk-X5WCXJAF.cjs +0 -3218
- package/dist/index-BZ_lBlO1.d.ts +0 -474
- package/dist/index-BuvxoWHf.d.cts +0 -474
- package/dist/index-DlAcuvQp.d.cts +0 -1686
- package/dist/index-Slu5hOj1.d.ts +0 -1686
- package/dist/types-D4-0lwaE.d.cts +0 -298
- package/dist/types-D4-0lwaE.d.ts +0 -298
package/README.md
CHANGED
|
@@ -2,6 +2,25 @@
|
|
|
2
2
|
|
|
3
3
|
접근성 우선 UI 컴포넌트 라이브러리. opt-ui-primitives 기반 Core, 비즈니스 Shells, Surface/block layout primitives를 제공합니다. 페이지 템플릿 Surface는 `@reopt-ai/opt-cli` registry로 설치하며, 차트와 데이터 시각화 컴포넌트는 `@reopt-ai/opt-charts`로 분리되었습니다.
|
|
4
4
|
|
|
5
|
+
## 에이전트 스킬로 설정하기 (권장)
|
|
6
|
+
|
|
7
|
+
소비자 프로젝트 루트에서 전용 스킬을 설치합니다.
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npx skills add reopt-ai/reopt-skills/opt-ui-install
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
설치 후 에이전트에게
|
|
14
|
+
`opt-ui-install 스킬로 이 프로젝트에 @reopt-ai/opt-ui를 설정하고 검증해줘`라고
|
|
15
|
+
요청하세요. 스킬은 신규 설치와 업그레이드를 구분하고, `AGENTS.md`(없으면
|
|
16
|
+
`CLAUDE.md`)의 reopt marker 블록, Tailwind v4, `OptThemeProvider`, `opt
|
|
17
|
+
doctor`, Surface 흐름을 멱등하게 설정합니다. 스킬 소스는
|
|
18
|
+
[`reopt-ai/reopt-skills`](https://github.com/reopt-ai/reopt-skills/tree/main/skills/opt-ui-install)가
|
|
19
|
+
단일 기준입니다.
|
|
20
|
+
|
|
21
|
+
아래 설치 명령은 스킬을 사용할 수 없거나 모든 단계를 직접 통제할 때의 수동
|
|
22
|
+
대안입니다.
|
|
23
|
+
|
|
5
24
|
## 설치
|
|
6
25
|
|
|
7
26
|
```bash
|
|
@@ -170,13 +189,15 @@ CSS 변수 기반 시맨틱 토큰 — `dark:` 프리픽스 없이 자동 전환
|
|
|
170
189
|
|
|
171
190
|
### 시맨틱 스페이싱
|
|
172
191
|
|
|
173
|
-
| CSS 변수 | Tailwind
|
|
174
|
-
| --------------------- |
|
|
175
|
-
| `--opt-space-section` | `gap-section` | 1.5rem (24px) |
|
|
176
|
-
| `--opt-space-group` | `gap-group`
|
|
177
|
-
| `--opt-space-element` | `gap-element` | 0.5rem (8px) |
|
|
192
|
+
| CSS 변수 | Tailwind | 값 |
|
|
193
|
+
| --------------------- | -------------------------- | ------------- |
|
|
194
|
+
| `--opt-space-section` | `gap-section`, `p-section` | 1.5rem (24px) |
|
|
195
|
+
| `--opt-space-group` | `gap-group`, `p-group` | 1rem (16px) |
|
|
196
|
+
| `--opt-space-element` | `gap-element`, `p-element` | 0.5rem (8px) |
|
|
178
197
|
|
|
179
|
-
|
|
198
|
+
Block 루트는 반드시 `BlockLayout`을 사용합니다. 페이지 콘텐츠 경계를 Block이 직접 맡을 때는
|
|
199
|
+
`inset="section"`을 지정하고, 카드나 Shell이 이미 여백을 제공하는 embedded Block에서는 inset을
|
|
200
|
+
생략합니다. `PageHeader`는 재사용 가능한 콘텐츠 헤더이므로 바깥 여백을 소유하지 않습니다.
|
|
180
201
|
|
|
181
202
|
## 접근성
|
|
182
203
|
|
|
@@ -229,7 +250,7 @@ bun run test:coverage
|
|
|
229
250
|
## Design Decisions
|
|
230
251
|
|
|
231
252
|
- **Layer metaphor**: Core → Shells는 opt-ui가 맡고, 페이지 템플릿 Surface는 opt-cli block registry로 설치
|
|
232
|
-
- **
|
|
253
|
+
- **BlockLayout 강제**: block template은 반드시 `BlockLayout` 또는 `createBlock`을 사용하고, 페이지 경계는 `inset="section"`으로 명시
|
|
233
254
|
- **Subpath exports**: `./core`, `./visuals`, `./shells` — 필요한 계층만 import 가능
|
|
234
255
|
- **Dual format**: ESM + CJS — 모든 번들러/런타임 호환
|
|
235
256
|
- **Source maps**: 디버깅을 위한 소스맵 포함
|
package/dist/app.css
ADDED
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* @reopt-ai/opt-ui — Application base layer (optional)
|
|
3
|
+
*
|
|
4
|
+
* `tailwind.css`가 토큰과 유틸리티를 준다면, 이 파일은 **앱 셸이 매번 다시 쓰는
|
|
5
|
+
* 규칙**을 준다. 실제 소비 프로젝트를 감사했을 때 아래 다섯 가지가 앱마다
|
|
6
|
+
* 손으로 재작성돼 있었고, 매번 조금씩 달랐다 — 커서 정책, opt-ui 밖 요소의
|
|
7
|
+
* 포커스 링, 사용자 모션 설정, 글자 크기 설정, 스킵 링크.
|
|
8
|
+
*
|
|
9
|
+
* Usage (consumer globals.css):
|
|
10
|
+
*
|
|
11
|
+
* @import "tailwindcss";
|
|
12
|
+
* @import "@reopt-ai/opt-ui/tailwind.css";
|
|
13
|
+
* @import "@reopt-ai/opt-ui/app.css";
|
|
14
|
+
*
|
|
15
|
+
* 선택 사항이다. 앱이 자기 규칙을 갖고 있다면 안 써도 되고, 여기 규칙은 전부
|
|
16
|
+
* `:where()`로 특이도 0이라 유틸리티 클래스가 항상 이긴다.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
@layer base {
|
|
20
|
+
/* ── Cursor ──
|
|
21
|
+
*
|
|
22
|
+
* 브라우저 기본값은 button에 `default`를 준다. 디자인 시스템을 쓰는 앱은
|
|
23
|
+
* 예외 없이 이걸 pointer로 되돌리는데, 그 목록을 손으로 관리하면 role 기반
|
|
24
|
+
* 요소(`[role="option"]`, `[role="treeitem"]`)가 빠지기 쉽다.
|
|
25
|
+
*
|
|
26
|
+
* opt-ui 컴포넌트는 자체 클래스로 커서를 지정하므로 여기 규칙과 무관하다.
|
|
27
|
+
* 이건 앱이 직접 쓰는 raw 요소를 위한 것이다. */
|
|
28
|
+
:where(
|
|
29
|
+
button:not(:disabled),
|
|
30
|
+
summary,
|
|
31
|
+
label[for],
|
|
32
|
+
select:not(:disabled),
|
|
33
|
+
a[href],
|
|
34
|
+
input:is(
|
|
35
|
+
[type="button"],
|
|
36
|
+
[type="submit"],
|
|
37
|
+
[type="reset"],
|
|
38
|
+
[type="checkbox"],
|
|
39
|
+
[type="radio"],
|
|
40
|
+
[type="file"],
|
|
41
|
+
[type="range"]
|
|
42
|
+
):not(:disabled),
|
|
43
|
+
[role="button"]:not([aria-disabled="true"]),
|
|
44
|
+
[role="tab"]:not([aria-disabled="true"]),
|
|
45
|
+
[role="menuitem"]:not([aria-disabled="true"]),
|
|
46
|
+
[role="menuitemcheckbox"]:not([aria-disabled="true"]),
|
|
47
|
+
[role="menuitemradio"]:not([aria-disabled="true"]),
|
|
48
|
+
[role="option"]:not([aria-disabled="true"]),
|
|
49
|
+
[role="switch"]:not([aria-disabled="true"]),
|
|
50
|
+
[role="checkbox"]:not([aria-disabled="true"]),
|
|
51
|
+
[role="radio"]:not([aria-disabled="true"]),
|
|
52
|
+
[role="treeitem"]:not([aria-disabled="true"])
|
|
53
|
+
) {
|
|
54
|
+
cursor: pointer;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
:where(
|
|
58
|
+
button:disabled,
|
|
59
|
+
input:disabled,
|
|
60
|
+
select:disabled,
|
|
61
|
+
textarea:disabled,
|
|
62
|
+
[aria-disabled="true"]
|
|
63
|
+
) {
|
|
64
|
+
cursor: not-allowed;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/* ── Focus ──
|
|
68
|
+
*
|
|
69
|
+
* opt-ui 컴포넌트는 `data-opt-id`를 달고 자체 포커스 링을 갖는다. 앱이 직접
|
|
70
|
+
* 쓰는 raw button/link/summary에는 아무것도 없어서, 키보드 사용자가 앱 고유
|
|
71
|
+
* 영역에 들어가는 순간 포커스가 사라지곤 한다. 같은 링을 기본값으로 준다. */
|
|
72
|
+
:where(
|
|
73
|
+
button:not([data-opt-id]),
|
|
74
|
+
a[href]:not([data-opt-id]),
|
|
75
|
+
summary:not([data-opt-id]),
|
|
76
|
+
[tabindex]:not([tabindex="-1"]):not([data-opt-id])
|
|
77
|
+
):focus-visible {
|
|
78
|
+
outline: 2px solid var(--opt-ring);
|
|
79
|
+
outline-offset: 2px;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/* ── User preference: text scale ──
|
|
83
|
+
*
|
|
84
|
+
* `<html data-text-scale="small|large">`로 루트 글자 크기를 조절한다. rem
|
|
85
|
+
* 기반 토큰이 전부 따라 움직이므로 레이아웃이 함께 확대/축소된다. */
|
|
86
|
+
html[data-text-scale="small"] {
|
|
87
|
+
font-size: 93.75%;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
html[data-text-scale="large"] {
|
|
91
|
+
font-size: 112.5%;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/* ── User preference: motion ──
|
|
95
|
+
*
|
|
96
|
+
* `tailwind.css`가 시스템 `prefers-reduced-motion`을 이미 존중한다. 이건 앱
|
|
97
|
+
* 설정에서 사용자가 **시스템과 무관하게** 끈 경우를 위한 명시적 스코프다.
|
|
98
|
+
* `<html data-motion="reduced">` 또는 앱 셸 루트에 붙인다. */
|
|
99
|
+
[data-motion="reduced"],
|
|
100
|
+
[data-motion="reduced"] :where(*, *::before, *::after) {
|
|
101
|
+
animation-duration: 0.01ms !important;
|
|
102
|
+
animation-iteration-count: 1 !important;
|
|
103
|
+
transition-duration: 0.01ms !important;
|
|
104
|
+
scroll-behavior: auto !important;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
@layer components {
|
|
109
|
+
/* ── Shortcut hints ──
|
|
110
|
+
*
|
|
111
|
+
* `<Kbd hint>`가 붙이는 클래스. 메뉴 항목 옆에 붙는 "⌘K" 같은 광고성 배지를
|
|
112
|
+
* 가리키며, 단축키 도움말 자체는 대상이 아니다.
|
|
113
|
+
*
|
|
114
|
+
* `<html data-shortcut-hints="hidden">`이면 사라진다 — 설정 값을 모든 호출
|
|
115
|
+
* 지점에 내려보내지 않고 "키보드 힌트 숨기기"를 구현하는 경로다.
|
|
116
|
+
* opt-shell의 `shortcutHints` 정책이 그 속성을 쓴다. */
|
|
117
|
+
[data-shortcut-hints="hidden"] .opt-shortcut-hint {
|
|
118
|
+
display: none;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/* ── Skip link ──
|
|
122
|
+
*
|
|
123
|
+
* 키보드 사용자가 사이드바 전체를 Tab으로 통과하지 않고 본문으로 건너뛰는
|
|
124
|
+
* 링크. 포커스 전에는 화면 밖에 있다가 포커스되면 나타난다.
|
|
125
|
+
*
|
|
126
|
+
* <a class="opt-skip-link" href="#main">본문으로 건너뛰기</a>
|
|
127
|
+
*/
|
|
128
|
+
.opt-skip-link {
|
|
129
|
+
position: fixed;
|
|
130
|
+
z-index: 100;
|
|
131
|
+
top: var(--opt-space-element);
|
|
132
|
+
left: var(--opt-space-element);
|
|
133
|
+
padding: var(--opt-space-element) var(--opt-space-group);
|
|
134
|
+
border: 1px solid var(--opt-ring);
|
|
135
|
+
border-radius: var(--opt-radius-md);
|
|
136
|
+
color: var(--opt-text);
|
|
137
|
+
background: var(--opt-surface-overlay);
|
|
138
|
+
box-shadow: var(--opt-shadow-md);
|
|
139
|
+
text-decoration: none;
|
|
140
|
+
transform: translateY(calc(-100% - var(--opt-space-section)));
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
.opt-skip-link:focus {
|
|
144
|
+
transform: translateY(0);
|
|
145
|
+
}
|
|
146
|
+
}
|