@spectrabrain/eds 0.0.3 → 0.0.4
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/AI.md +5 -1
- package/README.md +8 -3
- package/TAILWIND_V4.md +284 -0
- package/dist/components/Button/README.md +5 -5
- package/dist/components/Button/spec.json +7 -7
- package/dist/index.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +86 -16
- package/dist/index.mjs +86 -16
- package/dist/tokens.css +19 -10
- package/dist/tokens.d.mts +3 -3
- package/dist/tokens.d.ts +3 -3
- package/dist/tokens.js +86 -10
- package/dist/tokens.json +104 -10
- package/dist/tokens.mjs +86 -10
- package/llms.txt +5 -4
- package/package.json +3 -1
package/AI.md
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
- `@spectrabrain/eds/styles.css`, `@spectrabrain/eds/tokens.css`, `@spectrabrain/eds/fonts.css`를 제공합니다.
|
|
10
10
|
- `styles.css`는 Pretendard Variable font, semantic CSS custom property, Button CSS를 함께 불러옵니다. `fonts.css`는 font만 불러옵니다.
|
|
11
11
|
|
|
12
|
-
문서에 없는 API, variant, loading 동작은 추측해서 구현하지 않습니다. 공개되지 않은 토큰 원본을 직접 import하지 않습니다. dark theme
|
|
12
|
+
문서에 없는 API, variant, loading 동작은 추측해서 구현하지 않습니다. 공개되지 않은 토큰 원본을 직접 import하지 않습니다. dark theme를 지원하지 않으며, EDS가 Tailwind utility API를 직접 제공하지도 않습니다. 소비처에서 semantic token을 Tailwind CSS v4 className으로 연결해야 하면 [TAILWIND_V4.md](TAILWIND_V4.md)를 먼저 읽습니다.
|
|
13
13
|
|
|
14
14
|
## 토큰 사용
|
|
15
15
|
|
|
@@ -27,6 +27,10 @@ const color = cssVar(token); // var(--eds-color-fg-brand)
|
|
|
27
27
|
- 문서에 없는 deep import, raw 색상값, 임의 CSS variable은 사용하지 않습니다.
|
|
28
28
|
- 역할에 맞는 semantic token이 없으면 임의 값을 만들지 말고 디자인 시스템 담당자에게 요청합니다.
|
|
29
29
|
|
|
30
|
+
## Tailwind CSS v4 token 설정
|
|
31
|
+
|
|
32
|
+
소비처가 컴포넌트가 아닌 token만 Tailwind CSS v4 utility로 사용하려는 경우 [TAILWIND_V4.md](TAILWIND_V4.md)의 설치·alias·typography preset 설정을 따릅니다. 이 가이드는 공개 semantic CSS variable만 Tailwind theme alias와 custom utility로 연결하며, 내부 token 원본이나 raw 값을 소비처에 복사하지 않습니다.
|
|
33
|
+
|
|
30
34
|
## 컴포넌트 문서 읽기
|
|
31
35
|
|
|
32
36
|
컴포넌트를 사용하기 전에 해당 컴포넌트의 README와 공개 manifest를 먼저 읽습니다. 문서에는 컴포넌트의 개요, 사용 맥락, 공개 API, 접근성 계약, 금지 사례를 기록합니다.
|
package/README.md
CHANGED
|
@@ -33,7 +33,7 @@ export function SaveButton() {
|
|
|
33
33
|
}
|
|
34
34
|
~~~
|
|
35
35
|
|
|
36
|
-
아이콘만 사용하는 경우 `icon
|
|
36
|
+
아이콘만 사용하는 경우 접근성 이름을 제공하려면 `icon` 또는 `iconName`과 `aria-label`을 함께 지정합니다. `aria-label`은 필수로 강제하지 않습니다. `style`과 임의 스타일 override는 지원하지 않습니다. 전체 contract와 접근성 규칙은 설치된 버전의 `AI.md`를 확인합니다.
|
|
37
37
|
|
|
38
38
|
lucide 아이콘은 PascalCase 이름을 `iconName`, `startIconName`, `endIconName`으로 지정합니다. `ButtonIconName`이 TypeScript 자동완성을 제공하며, 같은 슬롯에 custom ReactElement와 이름을 함께 지정하지 않습니다. 이름으로 지정한 아이콘은 `lucide-react`의 기본 시각 설정을 사용하고 Button이 아이콘 영역 크기를 조정합니다.
|
|
39
39
|
|
|
@@ -70,7 +70,7 @@ lucide 아이콘은 PascalCase 이름을 `iconName`, `startIconName`, `endIconNa
|
|
|
70
70
|
| `iconName` | icon-only용 `ButtonIconName` lucide 이름입니다. |
|
|
71
71
|
| `startIcon` / `endIcon` | label 앞·뒤에 배치할 단일 custom `ReactElement` 슬롯입니다. |
|
|
72
72
|
| `startIconName` / `endIconName` | label 앞·뒤에 배치할 `ButtonIconName` lucide 이름입니다. |
|
|
73
|
-
| `aria-label` | icon-only
|
|
73
|
+
| `aria-label` | 선택적인 accessible name입니다. icon-only의 접근성 이름을 제공할 때 지정하며, text label에서도 필요할 때 사용할 수 있습니다. |
|
|
74
74
|
| `disabled` | 실행할 수 없는 상태입니다. native button은 `disabled`, link는 href 제거·`aria-disabled="true"`·`tabIndex={-1}`를 적용합니다. |
|
|
75
75
|
| `loading` | 처리 중 상태입니다. label과 아이콘 공간을 유지하고 progress circle을 표시하며 상호작용을 차단합니다. `aria-busy="true"`를 적용합니다. |
|
|
76
76
|
| `className` | 배치·컨테이너 보정용으로만 사용합니다. |
|
|
@@ -89,7 +89,7 @@ lucide 아이콘은 PascalCase 이름을 `iconName`, `startIconName`, `endIconNa
|
|
|
89
89
|
| children과 앞·뒤 아이콘을 모두 지정합니다. | `iconBoth` |
|
|
90
90
|
| children 없이 `icon` 또는 `iconName`만 지정합니다. | `iconOnly` |
|
|
91
91
|
|
|
92
|
-
잘못된 슬롯 조합, 빈 label·
|
|
92
|
+
잘못된 슬롯 조합, 빈 label·icon 또는 제공된 빈 `aria-label`은 모든 환경에서 오류로 처리합니다. Button의 개요와 사용 맥락은 설치된 패키지의 `llms.txt`에서 안내하는 Button 문서를 기준으로 합니다.
|
|
93
93
|
|
|
94
94
|
## 토큰 사용
|
|
95
95
|
|
|
@@ -107,6 +107,10 @@ const color = cssVar(token); // var(--eds-color-fg-brand-contrast)
|
|
|
107
107
|
|
|
108
108
|
필요한 역할의 token이 없으면 임의 색상값을 추가하지 말고 디자인 시스템 담당자에게 요청합니다.
|
|
109
109
|
|
|
110
|
+
## Tailwind CSS v4에서 token 사용
|
|
111
|
+
|
|
112
|
+
EDS는 Tailwind utility API를 패키지에 포함하지 않습니다. Tailwind CSS v4에서 공개 semantic token을 className으로 사용하려면 [Tailwind CSS v4 token 설정 가이드](./TAILWIND_V4.md)를 확인합니다. 가이드는 `@theme inline` color alias와 `@utility` typography preset을 설정하는 방법을 안내합니다.
|
|
113
|
+
|
|
110
114
|
## Text style 사용
|
|
111
115
|
|
|
112
116
|
하나의 text style은 다섯 속성을 함께 적용합니다.
|
|
@@ -133,6 +137,7 @@ const color = cssVar(token); // var(--eds-color-fg-brand-contrast)
|
|
|
133
137
|
| `@spectrabrain/eds/styles.css` | Pretendard font와 semantic CSS custom property를 함께 불러옵니다. |
|
|
134
138
|
| `@spectrabrain/eds/fonts.css` | Pretendard font만 불러옵니다. |
|
|
135
139
|
| `@spectrabrain/eds/tokens.json` | 도구 연동용 semantic token manifest입니다. |
|
|
140
|
+
| `@spectrabrain/eds/TAILWIND_V4.md` | Tailwind CSS v4에서 공개 token을 연결하는 설치 가이드입니다. |
|
|
136
141
|
| `@spectrabrain/eds/components/Button/README.md` | Button 개요·사용 맥락·공개 API 문서입니다. |
|
|
137
142
|
| `@spectrabrain/eds/components/Button/spec.json` | Button 공개 API와 접근성 계약을 위한 manifest입니다. |
|
|
138
143
|
| `@spectrabrain/eds/llms.txt` | AI 문서 읽기 순서입니다. |
|
package/TAILWIND_V4.md
ADDED
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
# EVA token을 Tailwind CSS v4에서 사용하는 가이드
|
|
2
|
+
|
|
3
|
+
이 문서는 소비처가 `@spectrabrain/eds`의 공개 semantic token을 Tailwind CSS v4의 `className`으로 사용하는 방법을 안내합니다. EDS는 Tailwind utility API를 패키지에 포함하지 않으며, 소비처에서 공개 CSS variable을 Tailwind theme alias와 utility로 연결해 사용합니다.
|
|
4
|
+
|
|
5
|
+
이 가이드는 token만 연결하는 경우를 다룹니다. React 컴포넌트의 구현이나 컴포넌트별 스타일을 변경하지 않습니다.
|
|
6
|
+
|
|
7
|
+
## 공개 범위
|
|
8
|
+
|
|
9
|
+
소비처는 다음 공개 경로만 사용합니다.
|
|
10
|
+
|
|
11
|
+
| 경로 | 용도 |
|
|
12
|
+
| --- | --- |
|
|
13
|
+
| `@spectrabrain/eds/tokens.css` | semantic CSS variable을 불러옵니다. |
|
|
14
|
+
| `@spectrabrain/eds/fonts.css` | Pretendard font를 불러옵니다. 선택 사항입니다. |
|
|
15
|
+
| `@spectrabrain/eds/tokens.json` | 공개 token 이름과 타입을 도구에서 확인합니다. |
|
|
16
|
+
| `@spectrabrain/eds/tokens` | TypeScript token 이름과 `cssVar()`를 사용합니다. |
|
|
17
|
+
|
|
18
|
+
공개되지 않은 내부 token 원본이나 raw 값을 소비처에 복사하지 않습니다.
|
|
19
|
+
|
|
20
|
+
## 사전 조건
|
|
21
|
+
|
|
22
|
+
- React 웹 프로젝트입니다.
|
|
23
|
+
- Tailwind CSS v4를 사용합니다.
|
|
24
|
+
- 프로젝트의 framework와 bundler가 확인되어 있습니다.
|
|
25
|
+
- 전역 CSS 진입점이 하나 지정되어 있습니다.
|
|
26
|
+
|
|
27
|
+
## 설치
|
|
28
|
+
|
|
29
|
+
기본 패키지를 설치합니다. Tailwind adapter는 프로젝트의 빌드 방식에 맞는 하나만 선택합니다.
|
|
30
|
+
|
|
31
|
+
~~~sh
|
|
32
|
+
npm install @spectrabrain/eds
|
|
33
|
+
~~~
|
|
34
|
+
|
|
35
|
+
Vite 프로젝트는 Tailwind Vite adapter를 추가합니다.
|
|
36
|
+
|
|
37
|
+
~~~sh
|
|
38
|
+
npm install -D tailwindcss @tailwindcss/vite
|
|
39
|
+
~~~
|
|
40
|
+
|
|
41
|
+
PostCSS 기반 프로젝트는 PostCSS adapter를 추가합니다.
|
|
42
|
+
|
|
43
|
+
~~~sh
|
|
44
|
+
npm install -D tailwindcss @tailwindcss/postcss postcss
|
|
45
|
+
~~~
|
|
46
|
+
|
|
47
|
+
이미 설치된 패키지는 중복 설치하지 않으며 Vite adapter와 PostCSS adapter를 동시에 추가하지 않습니다.
|
|
48
|
+
|
|
49
|
+
## 설치 시 자동화 정책
|
|
50
|
+
|
|
51
|
+
EDS는 `npm install`의 `postinstall`에서 소비처의 CSS나 설정 파일을 수정하지 않습니다. 설치 스크립트가 파일을 덮어쓰면 소비처의 기존 Tailwind 설정, CI 정책, package manager 설정과 충돌할 수 있기 때문입니다.
|
|
52
|
+
|
|
53
|
+
token alias를 EDS 버전과 함께 자동 갱신하려면 소비처 저장소가 다음 작업을 소유하는 명시적인 생성 스크립트를 둡니다.
|
|
54
|
+
|
|
55
|
+
1. `@spectrabrain/eds/tokens.json`에서 token 이름만 읽습니다.
|
|
56
|
+
2. `color-*` token을 `var(--eds-...)`로 연결하는 `@theme inline` 블록을 생성합니다.
|
|
57
|
+
3. raw `$value`나 비공개 파일 경로는 생성물에 기록하지 않습니다.
|
|
58
|
+
4. `npm run generate:eds-tailwind`처럼 명시적으로 실행하고, 필요할 때만 소비처의 `postinstall` 또는 CI에 연결합니다.
|
|
59
|
+
|
|
60
|
+
설치 스크립트를 사용하지 않는 환경에서도 동작하도록 생성된 `eds-tokens.css`는 저장소에 두거나 CI에서 재생성합니다. 현재 EDS가 제공하는 자동화 범위는 공개 token manifest와 이 설치 가이드이며, 소비처 파일을 직접 변경하는 CLI는 제공하지 않습니다.
|
|
61
|
+
|
|
62
|
+
다음은 소비처가 소유할 수 있는 color alias 생성 스크립트 예시입니다. 이 스크립트는 token의 실제 값을 읽지 않고 공개 이름만 읽습니다.
|
|
63
|
+
|
|
64
|
+
~~~js
|
|
65
|
+
// scripts/generate-eds-tailwind.mjs
|
|
66
|
+
import fs from "node:fs";
|
|
67
|
+
import path from "node:path";
|
|
68
|
+
import { createRequire } from "node:module";
|
|
69
|
+
|
|
70
|
+
const require = createRequire(import.meta.url);
|
|
71
|
+
const manifestPath = require.resolve("@spectrabrain/eds/tokens.json");
|
|
72
|
+
const manifest = JSON.parse(fs.readFileSync(manifestPath, "utf8"));
|
|
73
|
+
const colorNames = Object.keys(manifest.tokens).filter((name) => name.startsWith("color-"));
|
|
74
|
+
const aliases = colorNames
|
|
75
|
+
.map((name) => ` --color-eds-${name.slice("color-".length)}: var(--eds-${name});`)
|
|
76
|
+
.join("\n");
|
|
77
|
+
const output = `@theme inline {\n${aliases}\n}\n`;
|
|
78
|
+
const outputPath = path.resolve("src/styles/eds-tokens.css");
|
|
79
|
+
|
|
80
|
+
fs.mkdirSync(path.dirname(outputPath), { recursive: true });
|
|
81
|
+
fs.writeFileSync(outputPath, output);
|
|
82
|
+
~~~
|
|
83
|
+
|
|
84
|
+
소비처의 `package.json`에는 기존 script를 덮어쓰지 않는 범위에서 다음 명령을 추가할 수 있습니다.
|
|
85
|
+
|
|
86
|
+
~~~json
|
|
87
|
+
{
|
|
88
|
+
"scripts": {
|
|
89
|
+
"generate:eds-tailwind": "node scripts/generate-eds-tailwind.mjs"
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
~~~
|
|
93
|
+
|
|
94
|
+
`postinstall`에 연결하려면 소비처의 보안·CI 정책이 허용하는 경우에만 기존 `postinstall` 뒤에 `npm run generate:eds-tailwind`를 추가합니다. 설치 시 script 실행이 차단된 환경도 고려해 생성 파일을 커밋하거나 CI에서 `generate:eds-tailwind`를 먼저 실행합니다.
|
|
95
|
+
|
|
96
|
+
## Tailwind v4 연결
|
|
97
|
+
|
|
98
|
+
### Vite
|
|
99
|
+
|
|
100
|
+
`vite.config.ts`의 기존 plugins를 유지하면서 `tailwindcss()`를 추가합니다.
|
|
101
|
+
|
|
102
|
+
~~~ts
|
|
103
|
+
import tailwindcss from "@tailwindcss/vite";
|
|
104
|
+
import { defineConfig } from "vite";
|
|
105
|
+
|
|
106
|
+
export default defineConfig({
|
|
107
|
+
plugins: [tailwindcss()],
|
|
108
|
+
});
|
|
109
|
+
~~~
|
|
110
|
+
|
|
111
|
+
기존 React plugin 등 다른 plugin은 제거하지 않습니다.
|
|
112
|
+
|
|
113
|
+
### PostCSS
|
|
114
|
+
|
|
115
|
+
`postcss.config.mjs`의 기존 설정을 유지하면서 adapter를 추가합니다.
|
|
116
|
+
|
|
117
|
+
~~~js
|
|
118
|
+
export default {
|
|
119
|
+
plugins: {
|
|
120
|
+
"@tailwindcss/postcss": {},
|
|
121
|
+
},
|
|
122
|
+
};
|
|
123
|
+
~~~
|
|
124
|
+
|
|
125
|
+
## 전역 CSS 설정
|
|
126
|
+
|
|
127
|
+
기존 전역 CSS 파일을 사용합니다. 중복 stylesheet를 만들지 않습니다.
|
|
128
|
+
|
|
129
|
+
~~~css
|
|
130
|
+
@import "tailwindcss";
|
|
131
|
+
@import "@spectrabrain/eds/tokens.css";
|
|
132
|
+
@import "./eds-tokens.css";
|
|
133
|
+
~~~
|
|
134
|
+
|
|
135
|
+
Pretendard font도 사용하려면 `eds-tokens.css`보다 앞이나 뒤에 다음 import를 추가합니다.
|
|
136
|
+
|
|
137
|
+
~~~css
|
|
138
|
+
@import "@spectrabrain/eds/fonts.css";
|
|
139
|
+
~~~
|
|
140
|
+
|
|
141
|
+
`tokens.css`는 token variable만 제공하며 애플리케이션의 font-family를 자동으로 지정하지 않습니다.
|
|
142
|
+
|
|
143
|
+
## Color token alias
|
|
144
|
+
|
|
145
|
+
`eds-tokens.css`에 공개 semantic color variable을 Tailwind theme alias로 연결합니다. `@theme inline`을 사용해야 EDS CSS variable 참조가 유지됩니다.
|
|
146
|
+
|
|
147
|
+
~~~css
|
|
148
|
+
@theme inline {
|
|
149
|
+
--color-eds-fg-brand: var(--eds-color-fg-brand);
|
|
150
|
+
--color-eds-fg-neutral: var(--eds-color-fg-neutral);
|
|
151
|
+
--color-eds-fg-neutral-secondary: var(--eds-color-fg-neutral-secondary);
|
|
152
|
+
--color-eds-fg-neutral-inverted: var(--eds-color-fg-neutral-inverted);
|
|
153
|
+
|
|
154
|
+
--color-eds-bg-brand-primary: var(--eds-color-bg-brand-primary);
|
|
155
|
+
--color-eds-bg-brand-primary-hover: var(--eds-color-bg-brand-primary-hover);
|
|
156
|
+
--color-eds-bg-neutral-primary: var(--eds-color-bg-neutral-primary);
|
|
157
|
+
--color-eds-bg-neutral-primary-hover: var(--eds-color-bg-neutral-primary-hover);
|
|
158
|
+
--color-eds-bg-neutral-weak: var(--eds-color-bg-neutral-weak);
|
|
159
|
+
--color-eds-bg-disabled: var(--eds-color-bg-disabled);
|
|
160
|
+
|
|
161
|
+
--color-eds-stroke-neutral-secondary: var(--eds-color-stroke-neutral-secondary);
|
|
162
|
+
--color-eds-stroke-focusRing: var(--eds-color-stroke-focusRing);
|
|
163
|
+
}
|
|
164
|
+
~~~
|
|
165
|
+
|
|
166
|
+
다음 규칙으로 추가 alias를 작성합니다.
|
|
167
|
+
|
|
168
|
+
| EDS token | Tailwind alias | 생성되는 utility 예시 |
|
|
169
|
+
| --- | --- | --- |
|
|
170
|
+
| `color-fg-brand` | `--color-eds-fg-brand` | `text-eds-fg-brand` |
|
|
171
|
+
| `color-bg-brand-primary` | `--color-eds-bg-brand-primary` | `bg-eds-bg-brand-primary` |
|
|
172
|
+
| `color-stroke-neutral-secondary` | `--color-eds-stroke-neutral-secondary` | `border-eds-stroke-neutral-secondary` |
|
|
173
|
+
|
|
174
|
+
사용 예시는 다음과 같습니다.
|
|
175
|
+
|
|
176
|
+
~~~tsx
|
|
177
|
+
<div className="bg-eds-bg-neutral-primary text-eds-fg-neutral border border-eds-stroke-neutral-secondary">
|
|
178
|
+
콘텐츠입니다.
|
|
179
|
+
</div>
|
|
180
|
+
~~~
|
|
181
|
+
|
|
182
|
+
상태별 표현에는 semantic hover token을 사용합니다.
|
|
183
|
+
|
|
184
|
+
~~~tsx
|
|
185
|
+
<a className="text-eds-fg-brand hover:text-eds-fg-brand-contrast" href="/details">
|
|
186
|
+
자세히 보기
|
|
187
|
+
</a>
|
|
188
|
+
~~~
|
|
189
|
+
|
|
190
|
+
## Typography preset utility
|
|
191
|
+
|
|
192
|
+
EDS typography preset은 font family, weight, size, line height, letter spacing을 함께 적용합니다. Tailwind의 `text-*` theme variable만으로는 다섯 속성을 하나의 preset으로 묶을 수 없으므로 `@utility`를 사용합니다.
|
|
193
|
+
|
|
194
|
+
~~~css
|
|
195
|
+
@utility eds-typography-title3 {
|
|
196
|
+
font-family: var(--eds-typography-title3-fontFamily);
|
|
197
|
+
font-weight: var(--eds-typography-title3-fontWeight);
|
|
198
|
+
font-size: var(--eds-typography-title3-fontSize);
|
|
199
|
+
line-height: var(--eds-typography-title3-lineHeight);
|
|
200
|
+
letter-spacing: var(--eds-typography-title3-letterSpacing);
|
|
201
|
+
}
|
|
202
|
+
~~~
|
|
203
|
+
|
|
204
|
+
다음 preset을 같은 규칙으로 제공합니다.
|
|
205
|
+
|
|
206
|
+
~~~text
|
|
207
|
+
display1, display2
|
|
208
|
+
heading1, heading2, heading3, heading4
|
|
209
|
+
title1, title2, title3, title4
|
|
210
|
+
body1, body2, body3, body4
|
|
211
|
+
caption1, caption2, caption3
|
|
212
|
+
~~~
|
|
213
|
+
|
|
214
|
+
사용 예시는 다음과 같습니다.
|
|
215
|
+
|
|
216
|
+
~~~tsx
|
|
217
|
+
<h1 className="eds-typography-heading1 text-eds-fg-neutral">
|
|
218
|
+
제목입니다.
|
|
219
|
+
</h1>
|
|
220
|
+
|
|
221
|
+
<p className="eds-typography-body2 text-eds-fg-neutral-secondary">
|
|
222
|
+
본문입니다.
|
|
223
|
+
</p>
|
|
224
|
+
~~~
|
|
225
|
+
|
|
226
|
+
## Spacing과 radius
|
|
227
|
+
|
|
228
|
+
현재 공개 semantic token에 없는 spacing·radius 값을 소비처에서 임의로 alias로 만들지 않습니다. 공개 token이 필요한 경우 다음 정보를 디자인 시스템 담당자에게 요청합니다.
|
|
229
|
+
|
|
230
|
+
- 필요한 token 이름입니다.
|
|
231
|
+
- 사용하려는 UI 목적입니다.
|
|
232
|
+
- 필요한 상태나 variant입니다.
|
|
233
|
+
- 기존 Tailwind scale로 대체할 수 없는 이유입니다.
|
|
234
|
+
|
|
235
|
+
내부 파일 경로를 참조하거나 raw 값을 복사해 `spacing-eds-*`, `radius-eds-*` utility를 만들지 않습니다.
|
|
236
|
+
|
|
237
|
+
## TypeScript token 자동완성
|
|
238
|
+
|
|
239
|
+
CSS가 아닌 CSS-in-JS 또는 inline style에서 token을 선택해야 하면 공개 TypeScript API를 사용합니다.
|
|
240
|
+
|
|
241
|
+
~~~ts
|
|
242
|
+
import { cssVar, type SemanticTokenName } from "@spectrabrain/eds/tokens";
|
|
243
|
+
|
|
244
|
+
const token: SemanticTokenName = "color-fg-brand";
|
|
245
|
+
const color = cssVar(token);
|
|
246
|
+
// var(--eds-color-fg-brand)
|
|
247
|
+
~~~
|
|
248
|
+
|
|
249
|
+
`SemanticTokenName`은 공개 semantic token 이름 자동완성을 제공합니다. token 값 자체를 복사해 스타일에 넣지 않고 `cssVar()` 결과를 사용합니다.
|
|
250
|
+
|
|
251
|
+
## 권장 파일 구조
|
|
252
|
+
|
|
253
|
+
~~~text
|
|
254
|
+
src/styles/
|
|
255
|
+
globals.css
|
|
256
|
+
eds-tokens.css
|
|
257
|
+
~~~
|
|
258
|
+
|
|
259
|
+
`globals.css`에서 `tailwindcss`, EDS token CSS, `eds-tokens.css`를 한 번씩 import합니다. alias와 typography utility는 `eds-tokens.css`에서 관리합니다.
|
|
260
|
+
|
|
261
|
+
token 목록이 많거나 EDS 버전 변경 때 자동 갱신이 필요하면 `@spectrabrain/eds/tokens.json`의 token 이름과 CSS variable 이름만 읽어 alias 파일을 생성할 수 있습니다. 생성 스크립트에는 raw `$value`를 포함하지 않습니다.
|
|
262
|
+
|
|
263
|
+
## 금지 사항
|
|
264
|
+
|
|
265
|
+
- EDS 내부 token 원본을 import하거나 복사하지 않습니다.
|
|
266
|
+
- raw hex·px·rem 값을 EDS token 대신 작성하지 않습니다.
|
|
267
|
+
- `@theme`에 EDS token의 resolved 값을 직접 입력하지 않습니다.
|
|
268
|
+
- `@spectrabrain/eds` 패키지 내부의 비공개 경로를 deep import하지 않습니다.
|
|
269
|
+
- Tailwind class로 EDS가 관리하는 UI 스타일을 임의로 덮어쓰지 않습니다.
|
|
270
|
+
- EDS token 이름과 다른 의미의 alias를 만들어 역할을 바꾸지 않습니다.
|
|
271
|
+
|
|
272
|
+
## AI 설정 완료 조건
|
|
273
|
+
|
|
274
|
+
소비처 AI는 설정을 마친 뒤 다음을 확인합니다.
|
|
275
|
+
|
|
276
|
+
1. framework와 Tailwind v4 adapter가 현재 프로젝트에 맞게 연결되어 있습니다.
|
|
277
|
+
2. EDS token CSS가 전역에서 한 번만 import되어 있습니다.
|
|
278
|
+
3. semantic color alias가 `var(--eds-...)`를 참조합니다.
|
|
279
|
+
4. typography preset utility가 모든 공개 preset에 대해 생성되어 있습니다.
|
|
280
|
+
5. 생성 CSS에 raw 값이나 비공개 token 경로가 없습니다.
|
|
281
|
+
6. 예시 `className`이 실제 빌드 결과에 포함됩니다.
|
|
282
|
+
7. 소비처의 typecheck, lint, test, build가 통과합니다.
|
|
283
|
+
|
|
284
|
+
설정 후 변경 파일, 설치 패키지, 사용할 수 있는 `eds-*` class, 공개되지 않아 추가하지 않은 token, 검증 결과를 요약합니다.
|
|
@@ -32,7 +32,7 @@ Layout은 라벨과 아이콘의 조합으로 결정합니다. 아이콘은 행
|
|
|
32
32
|
| `iconFirst` | 라벨 앞에 아이콘을 둡니다. | 아이콘이 행동의 목적을 보조할 때 사용합니다. |
|
|
33
33
|
| `iconLast` | 라벨 뒤에 아이콘을 둡니다. | 이동 방향이나 다음 단계를 나타낼 때 사용합니다. |
|
|
34
34
|
| `iconBoth` | 라벨 양쪽에 아이콘을 둡니다. | 양쪽 아이콘이 모두 의미를 더하는 명확한 경우에만 사용합니다. |
|
|
35
|
-
| `iconOnly` | 아이콘만 제공합니다. | 아이콘만으로 행동의 의미가 충분히 명확할 때 사용하며,
|
|
35
|
+
| `iconOnly` | 아이콘만 제공합니다. | 아이콘만으로 행동의 의미가 충분히 명확할 때 사용하며, 접근성 이름을 제공하려면 `aria-label`을 지정합니다. |
|
|
36
36
|
|
|
37
37
|
### Role
|
|
38
38
|
|
|
@@ -101,7 +101,7 @@ Variant는 같은 Role 안에서 시각적 위계를 정의합니다.
|
|
|
101
101
|
| `iconName` | icon-only용 `ButtonIconName` lucide 이름입니다. |
|
|
102
102
|
| `startIcon` / `endIcon` | label 앞·뒤의 단일 custom `ReactElement` 슬롯입니다. |
|
|
103
103
|
| `startIconName` / `endIconName` | label 앞·뒤의 `ButtonIconName` lucide 이름 슬롯입니다. |
|
|
104
|
-
| `aria-label` | `string
|
|
104
|
+
| `aria-label` | 선택적인 `string`입니다. icon-only의 accessible name을 제공할 때 지정하며, 필수로 강제하지 않습니다. |
|
|
105
105
|
| `disabled` | `boolean`입니다. native button은 `disabled`, link는 href 제거·`aria-disabled="true"`·`tabIndex={-1}`를 적용합니다. |
|
|
106
106
|
| `loading` | `boolean`입니다. label·아이콘 공간을 유지한 progress circle을 표시하고 상호작용을 차단합니다. `aria-busy="true"`를 적용합니다. |
|
|
107
107
|
| `className` | `string`이며 배치·컨테이너 보정에만 허용합니다. |
|
|
@@ -120,9 +120,9 @@ Variant는 같은 Role 안에서 시각적 위계를 정의합니다.
|
|
|
120
120
|
- children과 `startIcon`이 있으면 `iconFirst`입니다.
|
|
121
121
|
- children과 `endIcon`이 있으면 `iconLast`입니다.
|
|
122
122
|
- children과 두 아이콘이 있으면 `iconBoth`입니다.
|
|
123
|
-
- children 없이 `icon`만 있으면 `iconOnly
|
|
123
|
+
- children 없이 `icon` 또는 `iconName`만 있으면 `iconOnly`입니다. 접근성 이름이 필요하면 비어 있지 않은 `aria-label`을 지정합니다.
|
|
124
124
|
|
|
125
|
-
빈 label·icon
|
|
125
|
+
빈 label·icon, 제공된 빈 `aria-label`과 잘못된 슬롯 조합은 모든 환경에서 오류로 처리합니다. label은 한 줄을 유지합니다.
|
|
126
126
|
|
|
127
127
|
`className`, native `aria-*`, `data-*`, `forwardRef`를 지원합니다. `style`과 임의 스타일 override는 공개하지 않습니다.
|
|
128
128
|
|
|
@@ -135,7 +135,7 @@ Variant는 같은 Role 안에서 시각적 위계를 정의합니다.
|
|
|
135
135
|
- hover는 CSS `:hover`로 처리합니다.
|
|
136
136
|
- 승인된 시각 상태는 enabled, hover, disabled, loading이며 focus-visible은 별도 focus ring 상태로 제공합니다. active·pressed·visited 상태는 지원하지 않습니다.
|
|
137
137
|
- focus-visible ring은 `color-stroke-focusRing` semantic token과 2px outline·offset 구조값을 사용합니다.
|
|
138
|
-
- 아이콘은 시각 장식으로 `aria-hidden="true"` 처리하며, icon-only의
|
|
138
|
+
- 아이콘은 시각 장식으로 `aria-hidden="true"` 처리하며, icon-only의 accessible name을 제공할 때 Button의 `aria-label`을 사용합니다. `aria-label`은 필수로 강제하지 않습니다.
|
|
139
139
|
- loading progress circle은 `800ms linear infinite` 회전하며 `prefers-reduced-motion: reduce`에서는 정지합니다.
|
|
140
140
|
|
|
141
141
|
## 문서와 검증
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"specVersion": 1,
|
|
3
|
-
"packageVersion": "0.0.
|
|
3
|
+
"packageVersion": "0.0.4",
|
|
4
4
|
"name": "Button",
|
|
5
5
|
"purpose": "사용자가 즉시 실행할 수 있는 행동과 탐색을 표현하는 인터랙티브 요소입니다.",
|
|
6
6
|
"usageContexts": [
|
|
@@ -8,12 +8,12 @@
|
|
|
8
8
|
"다른 페이지나 콘텐츠로 이동하는 탐색에는 neutral/link branch를 사용합니다.",
|
|
9
9
|
"brand는 화면에서 가장 중요한 행동을 강조할 때 사용합니다.",
|
|
10
10
|
"neutral은 일반적인 액션과 탐색에 사용합니다.",
|
|
11
|
-
"critical은 삭제·초기화처럼 되돌리기 어려운 행동에 사용합니다."
|
|
11
|
+
"critical은 삭제·초기화처럼 되돌리기 어려운 행동에 사용합니다.",
|
|
12
|
+
"icon-only의 접근성 이름을 제공하려면 aria-label을 지정합니다. aria-label은 필수로 강제하지 않습니다."
|
|
12
13
|
],
|
|
13
14
|
"unsupportedContexts": [
|
|
14
15
|
"문서에 없는 role·variant·상태를 className이나 inline style로 우회하지 않습니다.",
|
|
15
|
-
"상태 변경이나 일반 CTA를 neutral/link로 표현하지 않습니다."
|
|
16
|
-
"icon-only에서는 accessible name 없이 아이콘만 사용하지 않습니다."
|
|
16
|
+
"상태 변경이나 일반 CTA를 neutral/link로 표현하지 않습니다."
|
|
17
17
|
],
|
|
18
18
|
"api": {
|
|
19
19
|
"props": [
|
|
@@ -95,7 +95,7 @@
|
|
|
95
95
|
"name": "aria-label",
|
|
96
96
|
"type": "string",
|
|
97
97
|
"required": false,
|
|
98
|
-
"description": "accessible name입니다. icon-only
|
|
98
|
+
"description": "accessible name입니다. icon-only의 접근성 이름을 제공할 때 사용합니다."
|
|
99
99
|
},
|
|
100
100
|
{
|
|
101
101
|
"name": "disabled",
|
|
@@ -155,7 +155,7 @@
|
|
|
155
155
|
"iconFirst": "children과 startIcon 또는 startIconName을 제공합니다.",
|
|
156
156
|
"iconLast": "children과 endIcon 또는 endIconName을 제공합니다.",
|
|
157
157
|
"iconBoth": "children과 앞·뒤 아이콘을 모두 제공합니다.",
|
|
158
|
-
"iconOnly": "children 없이 icon 또는 iconName을
|
|
158
|
+
"iconOnly": "children 없이 icon 또는 iconName을 제공합니다. 접근성 이름이 필요하면 aria-label을 지정합니다."
|
|
159
159
|
},
|
|
160
160
|
"typeExports": [
|
|
161
161
|
"ButtonProps",
|
|
@@ -171,7 +171,7 @@
|
|
|
171
171
|
"accessibility": {
|
|
172
172
|
"nativeButtonType": "native button branch에서는 type을 필수로 지정합니다.",
|
|
173
173
|
"linkHref": "neutral/link branch에서는 href를 필수로 지정합니다.",
|
|
174
|
-
"iconOnlyName": "icon-only layout에서는 비어 있지 않은 aria-label을
|
|
174
|
+
"iconOnlyName": "icon-only layout에서는 접근성 이름을 제공할 때 비어 있지 않은 aria-label을 지정합니다. aria-label은 필수가 아닙니다.",
|
|
175
175
|
"disabledLink": "비활성 link는 href를 제거하고 aria-disabled와 tabIndex를 적용합니다.",
|
|
176
176
|
"loading": "loading 중에는 aria-busy를 적용하고 상호작용을 차단합니다.",
|
|
177
177
|
"focusVisible": "keyboard focus에는 승인된 focus ring을 표시합니다."
|
package/dist/index.d.mts
CHANGED
|
@@ -48,7 +48,7 @@ type IconOnlySlotProps = {
|
|
|
48
48
|
readonly startIconName?: never;
|
|
49
49
|
readonly endIcon?: never;
|
|
50
50
|
readonly endIconName?: never;
|
|
51
|
-
readonly "aria-label"
|
|
51
|
+
readonly "aria-label"?: string;
|
|
52
52
|
} & ({
|
|
53
53
|
readonly icon: ReactElement;
|
|
54
54
|
readonly iconName?: never;
|
package/dist/index.d.ts
CHANGED
|
@@ -48,7 +48,7 @@ type IconOnlySlotProps = {
|
|
|
48
48
|
readonly startIconName?: never;
|
|
49
49
|
readonly endIcon?: never;
|
|
50
50
|
readonly endIconName?: never;
|
|
51
|
-
readonly "aria-label"
|
|
51
|
+
readonly "aria-label"?: string;
|
|
52
52
|
} & ({
|
|
53
53
|
readonly icon: ReactElement;
|
|
54
54
|
readonly iconName?: never;
|