@orioncactuscorp/ui 1.10.0 → 1.12.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.
Files changed (87) hide show
  1. package/README.md +136 -54
  2. package/dist/components/Accordion/Accordion.css +1 -1
  3. package/dist/components/Accordion/Accordion.js +169 -177
  4. package/dist/components/ActionArea/ActionAreaLayout.js +20 -24
  5. package/dist/components/Cell/Cell.css +1 -1
  6. package/dist/components/Cell/Cell.js +57 -58
  7. package/dist/components/CheckMark/CheckMark.css +1 -1
  8. package/dist/components/Checkbox/Checkbox.css +1 -1
  9. package/dist/components/Checkbox/Checkbox.js +50 -51
  10. package/dist/components/Menu/Menu.css +1 -1
  11. package/dist/components/Menu/Menu.module.scss.js +20 -22
  12. package/dist/components/Modal/Modal.js +253 -261
  13. package/dist/components/Modal/useModalContentBlockTransition.js +49 -44
  14. package/dist/components/Radio/Radio.css +1 -1
  15. package/dist/components/ScrollArea/ScrollArea.css +1 -1
  16. package/dist/components/ScrollArea/ScrollArea.js +197 -200
  17. package/dist/components/Select/Select.js +31 -34
  18. package/dist/components/Switch/Switch.css +1 -1
  19. package/dist/components/Tabs/Tabs.css +1 -0
  20. package/dist/components/Tabs/Tabs.js +208 -0
  21. package/dist/components/Tabs/Tabs.module.scss.js +27 -0
  22. package/dist/components/Tabs.d.ts +6 -0
  23. package/dist/components/Tabs.js +8 -0
  24. package/dist/components/TextArea/TextArea.js +57 -58
  25. package/dist/components/TextInput/TextInput.js +30 -33
  26. package/dist/components/Tooltip/Tooltip.css +1 -1
  27. package/dist/foundations/color.theme.dark.css +1 -1
  28. package/dist/foundations/color.theme.light.css +1 -1
  29. package/dist/foundations/focus.css +1 -0
  30. package/dist/foundations/reset.css +1 -1
  31. package/dist/foundations.css +4 -3
  32. package/dist/index.js +69 -64
  33. package/dist/react/motion.js +31 -35
  34. package/dist/reset.css +1 -1
  35. package/dist/styles.css +14 -12
  36. package/dist/ui/src/components/Accordion/Accordion.d.ts.map +1 -1
  37. package/dist/ui/src/components/ActionArea/ActionAreaLayout.d.ts.map +1 -1
  38. package/dist/ui/src/components/Cell/Cell.d.ts.map +1 -1
  39. package/dist/ui/src/components/CheckMark/types.d.ts +10 -0
  40. package/dist/ui/src/components/CheckMark/types.d.ts.map +1 -1
  41. package/dist/ui/src/components/Checkbox/Checkbox.d.ts.map +1 -1
  42. package/dist/ui/src/components/Checkbox/types.d.ts +16 -0
  43. package/dist/ui/src/components/Checkbox/types.d.ts.map +1 -1
  44. package/dist/ui/src/components/Modal/Modal.d.ts.map +1 -1
  45. package/dist/ui/src/components/Modal/useModalContentBlockTransition.d.ts.map +1 -1
  46. package/dist/ui/src/components/Radio/types.d.ts +16 -0
  47. package/dist/ui/src/components/Radio/types.d.ts.map +1 -1
  48. package/dist/ui/src/components/ScrollArea/ScrollArea.d.ts.map +1 -1
  49. package/dist/ui/src/components/Select/Select.d.ts.map +1 -1
  50. package/dist/ui/src/components/Switch/types.d.ts +10 -0
  51. package/dist/ui/src/components/Switch/types.d.ts.map +1 -1
  52. package/dist/ui/src/components/Tabs/Tabs.d.ts +7 -0
  53. package/dist/ui/src/components/Tabs/Tabs.d.ts.map +1 -0
  54. package/dist/ui/src/components/Tabs/index.d.ts +3 -0
  55. package/dist/ui/src/components/Tabs/index.d.ts.map +1 -0
  56. package/dist/ui/src/components/Tabs/types.d.ts +26 -0
  57. package/dist/ui/src/components/Tabs/types.d.ts.map +1 -0
  58. package/dist/ui/src/components/TextArea/TextArea.d.ts.map +1 -1
  59. package/dist/ui/src/components/TextInput/TextInput.d.ts.map +1 -1
  60. package/dist/ui/src/index.d.ts +2 -0
  61. package/dist/ui/src/index.d.ts.map +1 -1
  62. package/dist/ui/src/react/motion/index.d.ts.map +1 -1
  63. package/dist/ui/src/utils/mergeRefs.d.ts +13 -0
  64. package/dist/ui/src/utils/mergeRefs.d.ts.map +1 -0
  65. package/dist/utils/mergeRefs.js +24 -0
  66. package/dist/vscode/oc-ui-vars.css +13 -0
  67. package/docs/colors.md +241 -0
  68. package/docs/editor-setup.md +42 -0
  69. package/docs/motion.md +665 -0
  70. package/docs/responsive-foundation-profile.md +230 -0
  71. package/docs/scss-helpers.md +189 -0
  72. package/docs/selector-contract.md +260 -0
  73. package/docs/spring.md +382 -0
  74. package/docs/stability.md +62 -0
  75. package/docs/tokens.md +561 -0
  76. package/docs/typography.md +115 -0
  77. package/package.json +9 -4
  78. package/src/scss/foundations/color-theme.test.ts +37 -8
  79. package/src/scss/foundations/color.theme.dark.scss +4 -1
  80. package/src/scss/foundations/color.theme.light.scss +3 -0
  81. package/src/scss/foundations/focus.scss +4 -0
  82. package/src/scss/foundations/focus.test.ts +48 -0
  83. package/src/scss/foundations/reset.scss +9 -4
  84. package/src/scss/foundations/reset.test.ts +32 -0
  85. package/src/scss/index.scss +2 -0
  86. package/src/scss/mixins/_focus.scss +11 -0
  87. package/src/scss/mixins/_focus.test.ts +58 -0
package/docs/colors.md ADDED
@@ -0,0 +1,241 @@
1
+ # Semantic Colors
2
+
3
+ oc-ui 색상 foundation은 `Global primitive → Theme semantic → Component contract`의 3단계로 사용합니다. Global primitive는 색상 램프와 opacity 숫자를 제공하고, Theme semantic은 light/dark 맥락에서 의미가 유지되는 역할 이름을 제공합니다. 컴포넌트에서는 primitive를 직접 고르기보다 semantic token을 우선하고, 컴포넌트별 상태·variant가 필요할 때 `--oc-{component}-*` contract로 한 번 더 연결합니다.
4
+
5
+ **역할 이름은 계약이고 값은 customizable 기본값입니다.** 아래 표는 패키지가 제공하는 기본 light/dark theme를 설명합니다. 제품 theme는 같은 역할 이름을 유지한 채 CSS variable 또는 SCSS theme config로 값을 바꿀 수 있습니다.
6
+
7
+ ## 역할 가이드
8
+
9
+ ### Static
10
+
11
+ `static-white`, `static-black`, `static-transparent`는 theme 전환과 무관하게 같은 물리 색을 유지해야 하는 경우에만 사용합니다. 로고 원색, 이미지 위의 고정 contrast icon처럼 의도가 명확한 표면이 대상입니다. 일반 본문이나 surface에 static 색을 쓰면 dark theme에서 역할이 뒤집히지 않으므로 피합니다.
12
+
13
+ ### Primary
14
+
15
+ `primary-normal`은 브랜드의 주 행동, 선택 상태, 핵심 강조에 사용합니다. 페이지 전체의 장식색으로 넓게 칠하기보다 사용자가 다음 행동이나 현재 선택을 식별해야 하는 지점에 제한합니다.
16
+
17
+ ### Focus ring
18
+
19
+ `focus-ring`은 `primary-normal`을 기본 alias로 삼지만 별도 리테마 지점입니다. 키보드 포커스 대비가 브랜드 primary로 충분하지 않은 제품은 이 token만 override할 수 있습니다. 컴포넌트와 커스텀 focusable 요소에서는 직접 outline을 조립하기보다 `@include oc-focus-ring`을 사용합니다.
20
+
21
+ ### Label
22
+
23
+ label 단계는 콘텐츠 중요도와 상호작용 가능성을 나타냅니다. `strong`은 가장 강한 제목·핵심 값, `normal`은 기본 본문, `neutral`은 한 단계 낮은 본문, `alternative`는 부가 설명, `assistive`는 placeholder·hint, `disable`은 비활성 텍스트에 사용합니다. 단순히 더 연한 색이 필요하다는 이유로 단계를 건너뛰지 말고 정보 위계와 상태를 먼저 정합니다.
24
+
25
+ ### Background
26
+
27
+ `background-normal-*`은 페이지 흐름의 기본 surface, `background-elevated-*`는 modal처럼 떠 있는 surface의 배경 짝입니다. 층위 구분의 기본 신호는 그림자와 dimmer이며 이는 light/dark 공통입니다 — elevated 색은 이를 대체하는 것이 아니라 **dark theme에서 추가되는 분리 신호**입니다. 어두운 배경에서는 그림자가 잘 드러나지 않으므로 떠 있는 표면을 base보다 밝은 단계로 올려 층위를 확실히 하고(iOS system background의 base/elevated 개념과 같은 접근), light 기본 theme에서는 base와 같은 값을 유지합니다(기본값 표 참조). 현행 컴포넌트의 대표 사용처는 Modal surface입니다. `normal`과 `alternative`는 인접 영역을 분리할 때 짝으로 사용합니다.
28
+
29
+ ### Interaction
30
+
31
+ `interaction-inactive`는 아직 활성화되지 않은 control 면이나 indicator에, `interaction-disable`은 조작할 수 없는 control 면에 사용합니다. 비활성 control의 글자는 `label-disable`, 면은 `interaction-disable`로 구분합니다. 두 역할을 하나의 token으로 대체하면 theme별 대비가 쉽게 무너집니다.
32
+
33
+ ### Line
34
+
35
+ `line-normal-*`은 alpha가 포함된 선으로 단일 surface 위의 구분선과 stroke에 사용합니다. 반투명 선을 중첩하면 예상보다 진해지므로 같은 위치에 여러 번 겹치지 않습니다. 중첩 가능성이 있거나 정확한 단색 경계가 필요한 layout에서는 대응하는 `line-solid-*`을 사용합니다. `strong → normal → neutral → alternative` 순서로 시각적 강도가 낮아집니다.
36
+
37
+ ### Fill
38
+
39
+ `fill-normal`은 중립 control·선택 전 surface, `fill-strong`은 더 뚜렷한 중립 강조, `fill-alternative`는 가장 약한 보조 면에 사용합니다. 텍스트 역할을 fill로 대체하거나, primary 행동을 중립 fill만으로 표현하지 않습니다.
40
+
41
+ ### Accent background
42
+
43
+ `accent-background-*`은 badge, status dot, chart mark처럼 색 자체가 면을 이루고 **텍스트 명도대비를 확보할 필요가 없는** 곳에 사용합니다. 같은 hue라도 명도대비가 필요한 텍스트·icon에는 `accent-foreground-*`을 사용합니다. 색상만으로 의미를 전달하지 말고 label, icon shape 또는 접근 가능한 이름을 함께 제공합니다.
44
+
45
+ ### Accent foreground
46
+
47
+ `accent-foreground-*`은 **텍스트 명도대비를 준수하도록 조정된** 전경색입니다. 색상 텍스트·아이콘처럼 명도 확보가 필요한 곳에 사용하고, 명도대비가 필요 없는 단순 면에는 `accent-background-*`을 사용합니다. background token을 텍스트에 쓰면 대비 준수가 보장되지 않으므로 피합니다.
48
+
49
+ ### Status
50
+
51
+ `status-positive`, `status-cautionary`, `status-negative`는 성공·주의·오류의 의미 역할이며 기본값은 대응 accent background의 alias입니다. 제품이 status palette를 별도로 운영할 때 alias 대상만 바꿀 수 있습니다. 단순 장식색에는 status token 대신 accent token을 사용합니다.
52
+
53
+ ### Inverse
54
+
55
+ inverse trio는 tooltip처럼 기본 페이지와 명암이 반전된 surface를 하나의 묶음으로 구성합니다. `inverse-background` 위에 `inverse-label`을 놓고, 행동 강조가 필요하면 `inverse-primary`를 사용합니다. 일반 dark theme surface를 inverse로 대신 만들지 않습니다.
56
+
57
+ ### Material
58
+
59
+ `material-dimmer`는 modal scrim처럼 아래 맥락을 낮추는 overlay material입니다. 콘텐츠 배경이나 disabled 면에 재사용하지 않습니다.
60
+
61
+ ## 기본 사용 규칙
62
+
63
+ 페이지의 기본 상속값은 `@include typo(body1)`, `--oc-color-theme-label-normal`, `--oc-color-theme-background-normal-normal`의 trio로 시작합니다. 하위 요소는 역할이 달라질 때만 delta를 선언합니다.
64
+
65
+ ```scss
66
+ @use '@orioncactuscorp/ui/scss/mixins/typo' as *;
67
+
68
+ .page {
69
+ @include typo(body1);
70
+
71
+ background: var(--oc-color-theme-background-normal-normal);
72
+ color: var(--oc-color-theme-label-normal);
73
+ }
74
+ ```
75
+
76
+ ## 기본값 표
77
+
78
+ <!-- prettier-ignore-start -->
79
+ <!-- generated:colors:start -->
80
+ > 아래 표는 기본 theme CSS를 기준으로 생성됩니다. 값은 고정 스펙이 아니라 기본값이며, consumer override 이후 실제 렌더 값은 달라질 수 있습니다.
81
+
82
+ ### Static
83
+
84
+ | Token | Light 기본값 | Dark 기본값 | Primitive 유도식 |
85
+ | --- | --- | --- | --- |
86
+ | `--oc-color-theme-static-white` | `white` | `white` | `var(--oc-color-global-common-100)` |
87
+ | `--oc-color-theme-static-black` | `black` | `black` | `var(--oc-color-global-common-0)` |
88
+ | `--oc-color-theme-static-transparent` | `transparent` | `transparent` | `var(--oc-color-global-common-transparent)` |
89
+
90
+ ### Primary
91
+
92
+ | Token | Light 기본값 | Dark 기본값 | Primitive 유도식 |
93
+ | --- | --- | --- | --- |
94
+ | `--oc-color-theme-primary-normal` | `#ff5e00` | `#ff7b2e` | `light: var(--oc-color-global-redOrange-50)`<br>`dark: var(--oc-color-global-redOrange-60)` |
95
+
96
+ ### Focus ring
97
+
98
+ | Token | Light 기본값 | Dark 기본값 | Primitive 유도식 |
99
+ | --- | --- | --- | --- |
100
+ | `--oc-color-theme-focus-ring` | `#ff5e00` | `#ff7b2e` | `var(--oc-color-theme-primary-normal)` |
101
+
102
+ ### Label
103
+
104
+ | Token | Light 기본값 | Dark 기본값 | Primitive 유도식 |
105
+ | --- | --- | --- | --- |
106
+ | `--oc-color-theme-label-strong` | `black` | `white` | `light: var(--oc-color-global-common-0)`<br>`dark: var(--oc-color-global-common-100)` |
107
+ | `--oc-color-theme-label-normal` | `#171719` | `#f7f7f8` | `light: var(--oc-color-global-coolNeutral-10)`<br>`dark: var(--oc-color-global-coolNeutral-99)` |
108
+ | `--oc-color-theme-label-neutral` | `rgb(46 47 51 / 88%)` | `rgb(194 196 200 / 88%)` | `light: oc-alpha(coolNeutral-22, 88)`<br>`dark: oc-alpha(coolNeutral-90, 88)` |
109
+ | `--oc-color-theme-label-alternative` | `rgb(55 56 60 / 61%)` | `rgb(174 176 182 / 61%)` | `light: oc-alpha(coolNeutral-25, 61)`<br>`dark: oc-alpha(coolNeutral-80, 61)` |
110
+ | `--oc-color-theme-label-assistive` | `rgb(55 56 60 / 28%)` | `rgb(174 176 182 / 28%)` | `light: oc-alpha(coolNeutral-25, 28)`<br>`dark: oc-alpha(coolNeutral-80, 28)` |
111
+ | `--oc-color-theme-label-disable` | `rgb(55 56 60 / 16%)` | `rgb(152 155 162 / 16%)` | `light: oc-alpha(coolNeutral-25, 16)`<br>`dark: oc-alpha(coolNeutral-70, 16)` |
112
+
113
+ ### Background
114
+
115
+ | Token | Light 기본값 | Dark 기본값 | Primitive 유도식 |
116
+ | --- | --- | --- | --- |
117
+ | `--oc-color-theme-background-normal-normal` | `white` | `#1b1c1e` | `light: var(--oc-color-global-common-100)`<br>`dark: var(--oc-color-global-coolNeutral-15)` |
118
+ | `--oc-color-theme-background-normal-alternative` | `#f7f7f8` | `#0f0f10` | `light: var(--oc-color-global-coolNeutral-99)`<br>`dark: var(--oc-color-global-coolNeutral-5)` |
119
+ | `--oc-color-theme-background-elevated-normal` | `white` | `#212225` | `light: var(--oc-color-global-common-100)`<br>`dark: var(--oc-color-global-coolNeutral-17)` |
120
+ | `--oc-color-theme-background-elevated-alternative` | `#f7f7f8` | `#141415` | `light: var(--oc-color-global-coolNeutral-99)`<br>`dark: var(--oc-color-global-coolNeutral-7)` |
121
+
122
+ ### Interaction
123
+
124
+ | Token | Light 기본값 | Dark 기본값 | Primitive 유도식 |
125
+ | --- | --- | --- | --- |
126
+ | `--oc-color-theme-interaction-inactive` | `#989ba2` | `#5a5c63` | `light: var(--oc-color-global-coolNeutral-70)`<br>`dark: var(--oc-color-global-coolNeutral-40)` |
127
+ | `--oc-color-theme-interaction-disable` | `#f4f4f5` | `#2e2f33` | `light: var(--oc-color-global-coolNeutral-98)`<br>`dark: var(--oc-color-global-coolNeutral-22)` |
128
+
129
+ ### Line
130
+
131
+ | Token | Light 기본값 | Dark 기본값 | Primitive 유도식 |
132
+ | --- | --- | --- | --- |
133
+ | `--oc-color-theme-line-normal-strong` | `rgb(112 115 124 / 52%)` | `rgb(194 196 200 / 52%)` | `light: oc-alpha(coolNeutral-50, 52)`<br>`dark: oc-alpha(coolNeutral-90, 52)` |
134
+ | `--oc-color-theme-line-normal-normal` | `rgb(112 115 124 / 22%)` | `rgb(112 115 124 / 32%)` | `light: oc-alpha(coolNeutral-50, 22)`<br>`dark: oc-alpha(coolNeutral-50, 0.32)` |
135
+ | `--oc-color-theme-line-normal-neutral` | `rgb(112 115 124 / 16%)` | `rgb(112 115 124 / 28%)` | `light: oc-alpha(coolNeutral-50, 16)`<br>`dark: oc-alpha(coolNeutral-50, 28)` |
136
+ | `--oc-color-theme-line-normal-alternative` | `rgb(112 115 124 / 8%)` | `rgb(112 115 124 / 22%)` | `light: oc-alpha(coolNeutral-50, 8)`<br>`dark: oc-alpha(coolNeutral-50, 22)` |
137
+ | `--oc-color-theme-line-solid-strong` | `#aeb0b6` | `#70737c` | `light: var(--oc-color-global-coolNeutral-80)`<br>`dark: var(--oc-color-global-coolNeutral-50)` |
138
+ | `--oc-color-theme-line-solid-normal` | `#e1e2e4` | `#37383c` | `light: var(--oc-color-global-coolNeutral-96)`<br>`dark: var(--oc-color-global-coolNeutral-25)` |
139
+ | `--oc-color-theme-line-solid-neutral` | `#eaebec` | `#333438` | `light: var(--oc-color-global-coolNeutral-97)`<br>`dark: var(--oc-color-global-coolNeutral-23)` |
140
+ | `--oc-color-theme-line-solid-alternative` | `#f4f4f5` | `#2e2f33` | `light: var(--oc-color-global-coolNeutral-98)`<br>`dark: var(--oc-color-global-coolNeutral-22)` |
141
+
142
+ ### Fill
143
+
144
+ | Token | Light 기본값 | Dark 기본값 | Primitive 유도식 |
145
+ | --- | --- | --- | --- |
146
+ | `--oc-color-theme-fill-normal` | `rgb(112 115 124 / 8%)` | `rgb(112 115 124 / 22%)` | `light: oc-alpha(coolNeutral-50, 8)`<br>`dark: oc-alpha(coolNeutral-50, 22)` |
147
+ | `--oc-color-theme-fill-strong` | `rgb(112 115 124 / 16%)` | `rgb(112 115 124 / 28%)` | `light: oc-alpha(coolNeutral-50, 16)`<br>`dark: oc-alpha(coolNeutral-50, 28)` |
148
+ | `--oc-color-theme-fill-alternative` | `rgb(112 115 124 / 5%)` | `rgb(112 115 124 / 12%)` | `light: oc-alpha(coolNeutral-50, 5)`<br>`dark: oc-alpha(coolNeutral-50, 12)` |
149
+
150
+ ### Accent background
151
+
152
+ | Token | Light 기본값 | Dark 기본값 | Primitive 유도식 |
153
+ | --- | --- | --- | --- |
154
+ | `--oc-color-theme-accent-background-red` | `#ff4242` | `#ff6363` | `light: var(--oc-color-global-red-50)`<br>`dark: var(--oc-color-global-red-60)` |
155
+ | `--oc-color-theme-accent-background-orange` | `#ff9200` | `#ffa938` | `light: var(--oc-color-global-orange-50)`<br>`dark: var(--oc-color-global-orange-60)` |
156
+ | `--oc-color-theme-accent-background-lime` | `#58cf04` | `#6be016` | `light: var(--oc-color-global-lime-50)`<br>`dark: var(--oc-color-global-lime-60)` |
157
+ | `--oc-color-theme-accent-background-green` | `#00bf40` | `#1ed45a` | `light: var(--oc-color-global-green-50)`<br>`dark: var(--oc-color-global-green-60)` |
158
+ | `--oc-color-theme-accent-background-cyan` | `#00bdde` | `#28d0ed` | `light: var(--oc-color-global-cyan-50)`<br>`dark: var(--oc-color-global-cyan-60)` |
159
+ | `--oc-color-theme-accent-background-lightBlue` | `#00aeff` | `#3dc2ff` | `light: var(--oc-color-global-lightBlue-50)`<br>`dark: var(--oc-color-global-lightBlue-60)` |
160
+ | `--oc-color-theme-accent-background-blue` | `#0066ff` | `#3385ff` | `light: var(--oc-color-global-blue-50)`<br>`dark: var(--oc-color-global-blue-60)` |
161
+ | `--oc-color-theme-accent-background-violet` | `#6541f2` | `#7d5ef7` | `light: var(--oc-color-global-violet-50)`<br>`dark: var(--oc-color-global-violet-60)` |
162
+ | `--oc-color-theme-accent-background-purple` | `#cb59ff` | `#d478ff` | `light: var(--oc-color-global-purple-50)`<br>`dark: var(--oc-color-global-purple-60)` |
163
+ | `--oc-color-theme-accent-background-pink` | `#f553da` | `#fa73e3` | `light: var(--oc-color-global-pink-50)`<br>`dark: var(--oc-color-global-pink-60)` |
164
+ | `--oc-color-theme-accent-background-redOrange` | `#ff5e00` | `#ff7b2e` | `light: var(--oc-color-global-redOrange-50)`<br>`dark: var(--oc-color-global-redOrange-60)` |
165
+
166
+ ### Accent foreground
167
+
168
+ | Token | Light 기본값 | Dark 기본값 | Primitive 유도식 |
169
+ | --- | --- | --- | --- |
170
+ | `--oc-color-theme-accent-foreground-red` | `#e52222` | `#ff6363` | `light: var(--oc-color-global-red-40)`<br>`dark: var(--oc-color-global-red-60)` |
171
+ | `--oc-color-theme-accent-foreground-redOrange` | `#f55a00` | `#ff7b2e` | `light: var(--oc-color-global-redOrange-48)`<br>`dark: var(--oc-color-global-redOrange-60)` |
172
+ | `--oc-color-theme-accent-foreground-orange` | `#d17600` | `#ff9200` | `light: var(--oc-color-global-orange-39)`<br>`dark: var(--oc-color-global-orange-50)` |
173
+ | `--oc-color-theme-accent-foreground-lime` | `#429e00` | `#58cf04` | `light: var(--oc-color-global-lime-37)`<br>`dark: var(--oc-color-global-lime-50)` |
174
+ | `--oc-color-theme-accent-foreground-green` | `#009632` | `#1ed45a` | `light: var(--oc-color-global-green-40)`<br>`dark: var(--oc-color-global-green-60)` |
175
+ | `--oc-color-theme-accent-foreground-cyan` | `#0098b2` | `#00bdde` | `light: var(--oc-color-global-cyan-40)`<br>`dark: var(--oc-color-global-cyan-50)` |
176
+ | `--oc-color-theme-accent-foreground-lightBlue` | `#008dcf` | `#00aeff` | `light: var(--oc-color-global-lightBlue-40)`<br>`dark: var(--oc-color-global-lightBlue-50)` |
177
+ | `--oc-color-theme-accent-foreground-blue` | `#005eeb` | `#4f95ff` | `light: var(--oc-color-global-blue-45)`<br>`dark: var(--oc-color-global-blue-65)` |
178
+ | `--oc-color-theme-accent-foreground-violet` | `#5b37ed` | `#9e86fc` | `light: var(--oc-color-global-violet-45)`<br>`dark: var(--oc-color-global-violet-70)` |
179
+ | `--oc-color-theme-accent-foreground-purple` | `#ad36e3` | `#d478ff` | `light: var(--oc-color-global-purple-40)`<br>`dark: var(--oc-color-global-purple-60)` |
180
+ | `--oc-color-theme-accent-foreground-pink` | `#e846cd` | `#fa73e3` | `light: var(--oc-color-global-pink-46)`<br>`dark: var(--oc-color-global-pink-60)` |
181
+
182
+ ### Status
183
+
184
+ | Token | Light 기본값 | Dark 기본값 | Primitive 유도식 |
185
+ | --- | --- | --- | --- |
186
+ | `--oc-color-theme-status-positive` | `#00bf40` | `#1ed45a` | `var(--oc-color-theme-accent-background-green)` |
187
+ | `--oc-color-theme-status-cautionary` | `#ff9200` | `#ffa938` | `var(--oc-color-theme-accent-background-orange)` |
188
+ | `--oc-color-theme-status-negative` | `#ff4242` | `#ff6363` | `var(--oc-color-theme-accent-background-red)` |
189
+
190
+ ### Inverse
191
+
192
+ | Token | Light 기본값 | Dark 기본값 | Primitive 유도식 |
193
+ | --- | --- | --- | --- |
194
+ | `--oc-color-theme-inverse-primary` | `#ff7b2e` | `#ff5e00` | `light: var(--oc-color-global-redOrange-60)`<br>`dark: var(--oc-color-global-redOrange-50)` |
195
+ | `--oc-color-theme-inverse-background` | `#1b1c1e` | `white` | `light: var(--oc-color-global-coolNeutral-15)`<br>`dark: var(--oc-color-global-common-100)` |
196
+ | `--oc-color-theme-inverse-label` | `#f7f7f8` | `#171719` | `light: var(--oc-color-global-coolNeutral-99)`<br>`dark: var(--oc-color-global-coolNeutral-10)` |
197
+
198
+ ### Material
199
+
200
+ | Token | Light 기본값 | Dark 기본값 | Primitive 유도식 |
201
+ | --- | --- | --- | --- |
202
+ | `--oc-color-theme-material-dimmer` | `rgb(23 23 25 / 52%)` | `rgb(23 23 25 / 74%)` | `light: oc-alpha(coolNeutral-10, 52)`<br>`dark: oc-alpha(coolNeutral-10, 74)` |
203
+ <!-- generated:colors:end -->
204
+ <!-- prettier-ignore-end -->
205
+
206
+ ## Customize
207
+
208
+ ### Runtime CSS variable
209
+
210
+ theme selector와 같은 scope에서 semantic token을 override합니다. Global primitive를 바꾸는 대신 역할 token을 바꾸면 컴포넌트 의미가 유지됩니다.
211
+
212
+ ```css
213
+ :root,
214
+ [data-theme='light'] {
215
+ --oc-color-theme-primary-normal: #0066ff;
216
+ --oc-color-theme-focus-ring: #0054d1;
217
+ }
218
+
219
+ [data-theme='dark'] {
220
+ --oc-color-theme-primary-normal: #69a5ff;
221
+ --oc-color-theme-focus-ring: #9ec5ff;
222
+ }
223
+ ```
224
+
225
+ Storybook의 semantic swatch는 `var(--oc-color-theme-*)`를 직접 읽으므로 consumer foundation profile이나 runtime override를 적용한 환경에서는 현재 실값으로 렌더됩니다.
226
+
227
+ ### SCSS theme config
228
+
229
+ 필요한 theme만 출력하거나 OS theme preference 연동을 끄려면 foundation을 직접 compile하면서 `color.config`를 먼저 설정합니다.
230
+
231
+ ```scss
232
+ @use '@orioncactuscorp/ui/scss/foundations/color.config' with (
233
+ $oc-color-themes: (
234
+ light,
235
+ dark,
236
+ ),
237
+ $oc-color-system-preference: false
238
+ );
239
+ ```
240
+
241
+ 전체 import 순서와 theme scope 예시는 [README Theming](../README.md#theming), responsive compile 설정은 [Responsive Foundation Profile](./responsive-foundation-profile.md)을 참조하세요.
@@ -0,0 +1,42 @@
1
+ # Editor Setup
2
+
3
+ ## VS Code CSS Variable Autocomplete
4
+
5
+ package는 VS Code CSS variable autocomplete 확장이 읽을 수 있는 foundation token index를 함께 배포합니다.
6
+
7
+ ```text
8
+ node_modules/@orioncactuscorp/ui/dist/vscode/oc-ui-vars.css
9
+ ```
10
+
11
+ consumer repository에서 `phoenisx.cssvar` 확장을 사용할 경우 `.vscode/settings.json`에 아래 설정을 추가합니다.
12
+
13
+ ```json
14
+ {
15
+ "editor.quickSuggestions": {
16
+ "other": "on",
17
+ "comments": "off",
18
+ "strings": "off"
19
+ },
20
+ "editor.suggestOnTriggerCharacters": true,
21
+ "editor.inlineSuggest.suppressSuggestions": false,
22
+ "cssvar.files": [
23
+ "./node_modules/@orioncactuscorp/ui/dist/vscode/oc-ui-vars.css"
24
+ ],
25
+ "cssvar.ignore": [],
26
+ "cssvar.extensions": ["css", "scss", "sass", "js", "jsx", "ts", "tsx"]
27
+ }
28
+ ```
29
+
30
+ 기존 `cssvar.files`가 있다면 덮어쓰지 말고 위 경로를 추가합니다. 단, oc-ui token 자동완성용으로 `@orioncactuscorp/ui/scss/foundations/*` source file을 fallback처럼 함께 추가하지 않습니다. `color.theme.light.scss`와 `color.theme.dark.scss`는 같은 `--oc-color-theme-*` semantic token 이름을 theme별 값으로 다시 선언하므로, raw source file을 같이 읽으면 completion 후보가 중복됩니다.
31
+
32
+ `phoenisx.cssvar`의 기본 `cssvar.ignore`는 `**/node_modules/**`를 제외하므로, node_modules 안의 oc-ui index를 읽으려면 `cssvar.ignore`에서 해당 제외를 제거해야 합니다. 위 예시는 oc-ui index만 명시적으로 읽는 설정이므로 빈 배열을 사용합니다.
33
+
34
+ `phoenisx.cssvar`는 빈 CSS value 위치에서 전체 token 목록을 먼저 띄우지 않습니다. `padding: --`처럼 CSS variable 이름을 직접 입력하거나 `padding: var(--`처럼 `var()` 안에서 `--`를 입력하면 oc-ui token completion이 표시됩니다.
35
+
36
+ VS Code Insiders 또는 Copilot inline suggestion이 켜진 환경에서 token이 회색 inline suggestion으로만 보이고 completion popup이 열리지 않으면, 위 예시처럼 `editor.quickSuggestions`, `editor.suggestOnTriggerCharacters`, `editor.inlineSuggest.suppressSuggestions`를 함께 설정합니다.
37
+
38
+ 이 파일은 `foundations.css`에서 생성되므로 설치된 `@orioncactuscorp/ui` package 버전의 `--oc-*` foundation token과 자동완성 목록이 함께 움직입니다. 자동완성 전용 index이므로 runtime stylesheet로 import하지 않습니다.
39
+
40
+ ## oc-ui source repository에서의 설정
41
+
42
+ oc-ui source repository에서도 `.vscode/settings.json`은 `packages/ui/dist/vscode/oc-ui-vars.css`를 읽습니다. 이 index는 `foundations.css`에서 token 이름만 dedupe해 생성한 자동완성 전용 파일입니다. source checkout에서는 extension의 default CSS scan이나 이전 cache가 compiled CSS를 다시 읽지 않도록 `packages/ui/dist/styles.css`, `packages/ui/dist/foundations.css`, `packages/ui/dist/foundations/**`, `packages/ui/src/scss/foundations/**`를 `cssvar.ignore`에 둡니다. source checkout에서 index 파일이 없다면 `bun run --cwd packages/ui build:css`를 먼저 실행합니다.