@iyulab/components 1.18.0 → 1.21.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 (40) hide show
  1. package/CHANGELOG.md +279 -0
  2. package/dist/_virtual/_glob-assets_raw/dark.css.e8ac080d.js +1 -1
  3. package/dist/_virtual/_glob-assets_raw/light.css.637cb2f8.js +1 -1
  4. package/dist/components/UElement.styles.js +8 -3
  5. package/dist/components/UFloatingElement.styles.js +1 -1
  6. package/dist/components/UOverlayElement.styles.js +1 -1
  7. package/dist/components/alert/UAlert.styles.js +10 -6
  8. package/dist/components/badge/UBadge.d.ts +2 -1
  9. package/dist/components/badge/UBadge.styles.js +25 -1
  10. package/dist/components/breadcrumb-item/UBreadcrumbItem.styles.js +1 -1
  11. package/dist/components/button/UButton.d.ts +22 -3
  12. package/dist/components/button/UButton.styles.js +98 -9
  13. package/dist/components/card/UCard.styles.js +3 -3
  14. package/dist/components/carousel/UCarousel.styles.js +4 -4
  15. package/dist/components/checkbox/UCheckbox.d.ts +2 -1
  16. package/dist/components/checkbox/UCheckbox.styles.js +39 -6
  17. package/dist/components/dialog/UDialog.styles.js +2 -2
  18. package/dist/components/drawer/UDrawer.styles.js +2 -2
  19. package/dist/components/input/UInput.styles.js +9 -9
  20. package/dist/components/menu-item/UMenuItem.styles.js +4 -4
  21. package/dist/components/option/UOption.styles.js +3 -3
  22. package/dist/components/progress-bar/UProgressBar.styles.js +7 -7
  23. package/dist/components/progress-ring/UProgressRing.styles.js +6 -6
  24. package/dist/components/rating/URating.styles.js +3 -3
  25. package/dist/components/select/USelect.styles.js +11 -9
  26. package/dist/components/slider/USlider.styles.js +11 -3
  27. package/dist/components/spinner/USpinner.d.ts +2 -1
  28. package/dist/components/spinner/USpinner.styles.js +8 -0
  29. package/dist/components/split-panel/USplitPanel.styles.js +2 -2
  30. package/dist/components/switch/USwitch.styles.js +13 -10
  31. package/dist/components/tab/UTab.styles.js +1 -1
  32. package/dist/components/tab-panel/UTabPanel.styles.js +1 -1
  33. package/dist/components/tag/UTag.d.ts +6 -1
  34. package/dist/components/tag/UTag.styles.js +55 -2
  35. package/dist/components/textarea/UTextarea.styles.js +7 -7
  36. package/dist/components/tooltip/UTooltip.styles.js +3 -3
  37. package/dist/components/tree-item/UTreeItem.styles.js +2 -2
  38. package/dist/styles/dark.css +107 -4
  39. package/dist/styles/light.css +140 -5
  40. package/package.json +4 -3
@@ -24,7 +24,7 @@ var styles = css`
24
24
  border: 1px solid var(--u-input-border-color, #E0E0E0);
25
25
  border-radius: 0.25em;
26
26
  background-color: var(--u-input-bg-color, #FFFFFF);
27
- transition: border-color 0.2s ease, box-shadow 0.2s ease;
27
+ transition: border-color var(--u-duration-normal, 220ms) var(--u-ease-standard, cubic-bezier(0.2, 0, 0, 1)), box-shadow var(--u-duration-normal, 220ms) var(--u-ease-standard, cubic-bezier(0.2, 0, 0, 1));
28
28
  overflow: hidden;
29
29
  user-select: none;
30
30
  cursor: pointer;
@@ -44,10 +44,10 @@ var styles = css`
44
44
  box-shadow: 0 0 0 1px var(--u-input-border-color-hover, #BDBDBD);
45
45
  }
46
46
  :host(:not([readonly]):not([disabled])) .container:focus-within {
47
- box-shadow: 0 0 0 1px var(--u-input-border-color-focus, #1976D2);
47
+ box-shadow: 0 0 0 1px var(--u-input-border-color-focus, #1565C0);
48
48
  }
49
49
  :host([invalid]:not([readonly]):not([disabled])) .container {
50
- box-shadow: 0 0 0 1px var(--u-input-border-color-invalid, #D32F2F);
50
+ box-shadow: 0 0 0 1px var(--u-input-border-color-invalid, #C62828);
51
51
  }
52
52
 
53
53
  /* ===== Variant: filled ===== */
@@ -69,11 +69,11 @@ var styles = css`
69
69
  }
70
70
  :host([variant="filled"]:not([readonly]):not([disabled])) .container:focus-within {
71
71
  box-shadow: none;
72
- border-bottom-color: var(--u-input-border-color-focus, #1976D2);
72
+ border-bottom-color: var(--u-input-border-color-focus, #1565C0);
73
73
  }
74
74
  :host([variant="filled"][invalid]:not([readonly]):not([disabled])) .container {
75
75
  box-shadow: none;
76
- border-bottom-color: var(--u-input-border-color-invalid, #D32F2F);
76
+ border-bottom-color: var(--u-input-border-color-invalid, #C62828);
77
77
  }
78
78
 
79
79
  /* ===== Variant: underlined ===== */
@@ -96,12 +96,12 @@ var styles = css`
96
96
  }
97
97
  :host([variant="underlined"]:not([readonly]):not([disabled])) .container:focus-within {
98
98
  box-shadow: none;
99
- border-bottom-color: var(--u-input-border-color-focus, #1976D2);
99
+ border-bottom-color: var(--u-input-border-color-focus, #1565C0);
100
100
  border-bottom-width: 2px;
101
101
  }
102
102
  :host([variant="underlined"][invalid]:not([readonly]):not([disabled])) .container {
103
103
  box-shadow: none;
104
- border-bottom-color: var(--u-input-border-color-invalid, #D32F2F);
104
+ border-bottom-color: var(--u-input-border-color-invalid, #C62828);
105
105
  }
106
106
 
107
107
  /* ===== Variant: borderless ===== */
@@ -120,6 +120,8 @@ var styles = css`
120
120
  .count {
121
121
  color: var(--u-txt-color-weak, #757575);
122
122
  line-height: 1.25;
123
+ /* n / m 은 제자리에서 n 이 바뀐다 — 비례폭이면 선택할 때마다 라벨 줄이 흔들린다 */
124
+ font-variant-numeric: tabular-nums;
123
125
  }
124
126
 
125
127
  .text-content {
@@ -153,7 +155,7 @@ var styles = css`
153
155
  margin-left: 0.25em;
154
156
  font-size: 1em;
155
157
  color: var(--u-icon-color, #616161);
156
- transition: color 0.2s ease;
158
+ transition: color var(--u-duration-normal, 220ms) var(--u-ease-standard, cubic-bezier(0.2, 0, 0, 1));
157
159
  cursor: pointer;
158
160
  }
159
161
  .suffix-item:hover {
@@ -173,7 +175,7 @@ var styles = css`
173
175
  border: 1px solid var(--u-border-color, #E0E0E0);
174
176
  border-radius: var(--u-radius-lg, 6px);
175
177
  background-color: var(--u-panel-bg-color, #FFFFFF);
176
- box-shadow: 0 4px 12px rgba(0, 0, 0, 0.12);
178
+ box-shadow: var(--u-shadow-lg, 0 4px 12px rgba(0, 0, 0, 0.16), 0 2px 4px rgba(0, 0, 0, 0.06));
177
179
  overflow-x: hidden;
178
180
  overflow-y: auto;
179
181
  }
@@ -21,6 +21,14 @@ var styles = css`
21
21
  font-family: var(--u-font-base);
22
22
  }
23
23
 
24
+ /* 라이브러리가 **스스로 그리는 숫자**는 고정폭 자릿수로 낸다.
25
+ 둘 다 제자리에서 값이 바뀌는 자리라 비례폭이면 드래그 중 글자가 흔들린다.
26
+ ★툴팁은 슬롯을 건너 상속으로 닿는다 — font-variant-numeric 은 상속 프로퍼티다. */
27
+ [slot="label-aside"],
28
+ u-tooltip[part="thumb-tooltip"] {
29
+ font-variant-numeric: tabular-nums;
30
+ }
31
+
24
32
  .container {
25
33
  position: relative;
26
34
  height: var(--slider-thumb-size);
@@ -67,14 +75,14 @@ var styles = css`
67
75
  border: 2px solid var(--slider-thumb-border-color);
68
76
  border-radius: var(--u-radius-circle, 50%);
69
77
  background: var(--slider-thumb-color);
70
- box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);
71
- transition: transform 0.15s ease, box-shadow 0.15s ease;
78
+ box-shadow: var(--u-shadow-sm, 0 1px 3px rgba(0, 0, 0, 0.08), 0 1px 1px rgba(0, 0, 0, 0.04));
79
+ transition: transform var(--u-duration-fast, 140ms) var(--u-ease-standard, cubic-bezier(0.2, 0, 0, 1)), box-shadow var(--u-duration-fast, 140ms) var(--u-ease-standard, cubic-bezier(0.2, 0, 0, 1));
72
80
  cursor: pointer;
73
81
  }
74
82
  .thumb:hover .thumb-content,
75
83
  .thumb:active .thumb-content {
76
84
  transform: scale(1.15);
77
- box-shadow: 0 1px 5px rgba(0, 0, 0, 0.3);
85
+ box-shadow: var(--u-shadow-md, 0 2px 8px rgba(0, 0, 0, 0.12), 0 1px 2px rgba(0, 0, 0, 0.05));
78
86
  }
79
87
  .thumb:focus-visible .thumb-content {
80
88
  box-shadow: 0 0 0 1px var(--slider-fill-color);
@@ -1,5 +1,6 @@
1
1
  import { UElement } from '../UElement.js';
2
- export type SpinnerColor = "neutral" | "blue" | "green" | "yellow" | "red" | "orange" | "teal" | "cyan" | "purple" | "pink";
2
+ /** 역할 축(`primary`…`danger`, 의미 · 리브랜딩을 따라옴)과 장식 축(`blue`…, 자체 · 면역)이 병존한다. */
3
+ export type SpinnerColor = "neutral" | "primary" | "info" | "success" | "warning" | "danger" | "blue" | "green" | "yellow" | "red" | "orange" | "teal" | "cyan" | "purple" | "pink";
3
4
  /**
4
5
  * 로딩 상태를 나타내는 회전 스피너 컴포넌트입니다.
5
6
  *
@@ -9,6 +9,14 @@ var styles = css`
9
9
  }
10
10
 
11
11
  /* Color variants */
12
+ /* 역할 축 — 스피너는 **바탕 위의 그래픽**이므로 면 단(-color)이 아니라 -strong 을
13
+ 읽는다. 다크에서 -color 는 바탕 위 3.07 까지 떨어진다(Cycle 141 실측). */
14
+ :host([color="primary"]) { --spinner-indicator-color: var(--u-primary-color-strong, #1565C0); }
15
+ :host([color="info"]) { --spinner-indicator-color: var(--u-info-color-strong, #1565C0); }
16
+ :host([color="success"]) { --spinner-indicator-color: var(--u-success-color-strong, #1B5E20); }
17
+ :host([color="warning"]) { --spinner-indicator-color: var(--u-warning-color-strong, #8A4A00); }
18
+ :host([color="danger"]) { --spinner-indicator-color: var(--u-danger-color-strong, #C62828); }
19
+
12
20
  :host([color="blue"]) { --spinner-indicator-color: var(--u-blue-600, #1E88E5); }
13
21
  :host([color="green"]) { --spinner-indicator-color: var(--u-green-600, #43A047); }
14
22
  :host([color="yellow"]) { --spinner-indicator-color: var(--u-yellow-600, #FDD835); }
@@ -5,7 +5,7 @@ var styles = css`
5
5
  --splitter-size: 4px;
6
6
  --splitter-color: var(--u-neutral-200, #EEEEEE);
7
7
  --splitter-color-hover: var(--u-primary-color-weaker, #64B5F6);
8
- --splitter-color-active: var(--u-primary-color-weak, #2196F3);
8
+ --splitter-color-active: var(--u-primary-color-strong, #1565C0);
9
9
  }
10
10
 
11
11
  :host {
@@ -36,7 +36,7 @@ var styles = css`
36
36
  align-items: center;
37
37
  justify-content: center;
38
38
  background-color: var(--splitter-color);
39
- transition: background-color 0.15s ease;
39
+ transition: background-color var(--u-duration-fast, 140ms) var(--u-ease-standard, cubic-bezier(0.2, 0, 0, 1));
40
40
  touch-action: none;
41
41
  }
42
42
  .splitter:hover {
@@ -11,7 +11,10 @@ var styles = css`
11
11
  --switch-thumb-color: #fff;
12
12
  --switch-thumb-color-checked: #fff;
13
13
  --switch-radius: 9999px;
14
- --switch-duration: 0.25s;
14
+ /* ★로컬 축이지만 **기본값은 공용 축에서 파생**한다 — 그러지 않으면
15
+ prefers-reduced-motion 이 이 컴포넌트만 비껴간다(축을 경유해야 함께 멈춘다).
16
+ 소비자가 --switch-duration 을 덮으면 그 값이 이긴다(로컬 축의 존재 이유). */
17
+ --switch-duration: var(--u-duration-normal, 220ms);
15
18
  --switch-move-width: calc(var(--switch-track-width) - var(--switch-thumb-size) - var(--switch-thumb-offset) * 2);
16
19
  }
17
20
 
@@ -56,8 +59,8 @@ var styles = css`
56
59
  }
57
60
  input:focus-visible ~ .track {
58
61
  box-shadow:
59
- 0 0 0 1px var(--u-input-border-color-focus, #1976D2),
60
- 0 0 0 3px rgba(59, 130, 246, 0.22);
62
+ 0 0 0 1px var(--u-input-border-color-focus, #1565C0),
63
+ 0 0 0 3px color-mix(in srgb, var(--u-primary-color-strong, #1565C0) 22%, transparent);
61
64
  }
62
65
 
63
66
  /* === 트랙 === */
@@ -70,7 +73,7 @@ var styles = css`
70
73
  height: var(--switch-track-height);
71
74
  border-radius: var(--switch-radius);
72
75
  background: var(--switch-track-color);
73
- transition: background var(--switch-duration) ease;
76
+ transition: background var(--switch-duration) var(--u-ease-standard, cubic-bezier(0.2, 0, 0, 1));
74
77
  }
75
78
  :host([checked]) .track {
76
79
  background: var(--switch-track-color-checked);
@@ -92,7 +95,7 @@ var styles = css`
92
95
  line-height: 1;
93
96
  white-space: nowrap;
94
97
  pointer-events: none;
95
- transition: opacity var(--switch-duration) ease;
98
+ transition: opacity var(--switch-duration) var(--u-ease-standard, cubic-bezier(0.2, 0, 0, 1));
96
99
  }
97
100
  .track-checked {
98
101
  opacity: 0;
@@ -123,11 +126,11 @@ var styles = css`
123
126
  height: var(--switch-thumb-size);
124
127
  border-radius: var(--switch-radius);
125
128
  background: var(--switch-thumb-color);
126
- box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);
129
+ box-shadow: var(--u-shadow-sm, 0 1px 3px rgba(0, 0, 0, 0.08), 0 1px 1px rgba(0, 0, 0, 0.04));
127
130
  overflow: hidden;
128
131
  transition:
129
- transform var(--switch-duration) cubic-bezier(0.4, 0, 0.2, 1),
130
- background var(--switch-duration) ease;
132
+ transform var(--switch-duration) var(--u-ease-standard, cubic-bezier(0.2, 0, 0, 1)),
133
+ background var(--switch-duration) var(--u-ease-standard, cubic-bezier(0.2, 0, 0, 1));
131
134
  }
132
135
  :host([checked]) .thumb {
133
136
  transform: translateX(var(--switch-move-width));
@@ -148,8 +151,8 @@ var styles = css`
148
151
  line-height: 1;
149
152
  pointer-events: none;
150
153
  transition:
151
- opacity var(--switch-duration) ease,
152
- transform var(--switch-duration) ease;
154
+ opacity var(--switch-duration) var(--u-ease-standard, cubic-bezier(0.2, 0, 0, 1)),
155
+ transform var(--switch-duration) var(--u-ease-standard, cubic-bezier(0.2, 0, 0, 1));
153
156
  }
154
157
  .thumb-checked {
155
158
  opacity: 0;
@@ -48,7 +48,7 @@ var styles = css`
48
48
  font-size: 0.75em;
49
49
  color: inherit;
50
50
  opacity: 0.5;
51
- transition: opacity 0.15s ease;
51
+ transition: opacity var(--u-duration-fast, 140ms) var(--u-ease-standard, cubic-bezier(0.2, 0, 0, 1));
52
52
  }
53
53
  .remove-btn:hover {
54
54
  opacity: 1;
@@ -188,7 +188,7 @@ var styles = css`
188
188
  :host([variant="pill"]) ::slotted(u-tab[active]) {
189
189
  border-color: var(--u-border-color, #E0E0E0);
190
190
  background-color: var(--u-neutral-0, #FFFFFF);
191
- box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08);
191
+ box-shadow: var(--u-shadow-sm, 0 1px 3px rgba(0, 0, 0, 0.08), 0 1px 1px rgba(0, 0, 0, 0.04));
192
192
  }
193
193
 
194
194
  /* Variant: plain */
@@ -1,6 +1,11 @@
1
1
  import { UElement } from '../UElement.js';
2
2
  export type TagVariant = "solid" | "surface" | "filled" | "outlined";
3
- export type TagColor = "neutral" | "blue" | "green" | "yellow" | "red" | "orange" | "teal" | "cyan" | "purple" | "pink";
3
+ /**
4
+ * 두 축이 병존한다 — **역할 축**(`primary`·`info`·`success`·`warning`·`danger`)은 *의미*를
5
+ * 말하고 리브랜딩을 따라오며 대비 계약을 물려받는다. **장식 축**(`blue`·`purple` …)은
6
+ * *색 자체*를 말하고 리브랜딩에 의도적으로 면역이다.
7
+ */
8
+ export type TagColor = "neutral" | "primary" | "info" | "success" | "warning" | "danger" | "blue" | "green" | "yellow" | "red" | "orange" | "teal" | "cyan" | "purple" | "pink";
4
9
  /**
5
10
  * 레이블, 카테고리, 상태 등을 표시하는 태그 컴포넌트입니다.
6
11
  *
@@ -8,6 +8,57 @@ var styles = css`
8
8
  --tag-border-color: transparent;
9
9
  }
10
10
 
11
+ /* ==========================================================================
12
+ 역할 축 — 의미 슬롯 매핑
13
+ color="danger" 는 색이 아니라 *"위험"* 을 뜻한다. 장식 축(아래)과 달리 팔레트가 아니라
14
+ **역할 토큰**을 읽으므로 리브랜딩을 따라오고, 대비 계약이 지키는 짝을 물려받는다.
15
+
16
+ 슬롯이 여섯인 이유는 자리마다 대비 요구가 다르기 때문이다(실측, 두 테마 전건 AA):
17
+ solid 면 --u-{role}-color + 그 위 글자 --u-{role}-txt-color (4.60~15.05)
18
+ surface 연한 면 --u-{role}-bg-color + 그 위 글자 --u-{role}-color-strong (4.58~7.00)
19
+ outlined 바탕 위 글자 --u-{role}-color-strong (계약 검사 대상)
20
+ ========================================================================== */
21
+ :host([color="primary"]) {
22
+ --tag-hue-solid: var(--u-primary-color, #1976D2);
23
+ --tag-hue-on-solid: var(--u-primary-txt-color, #FFFFFF);
24
+ --tag-hue-line: var(--u-primary-color-weak, #2196F3);
25
+ --tag-hue-surface: var(--u-primary-bg-color, #E3F2FD);
26
+ --tag-hue-text: var(--u-primary-color-strong, #1565C0);
27
+ --tag-hue-text-outlined: var(--u-primary-color-strong, #1565C0);
28
+ }
29
+ :host([color="info"]) {
30
+ --tag-hue-solid: var(--u-info-color, #1976D2);
31
+ --tag-hue-on-solid: var(--u-info-txt-color, #FFFFFF);
32
+ --tag-hue-line: var(--u-info-color-weak, #2196F3);
33
+ --tag-hue-surface: var(--u-info-bg-color, #E3F2FD);
34
+ --tag-hue-text: var(--u-info-color-strong, #1565C0);
35
+ --tag-hue-text-outlined: var(--u-info-color-strong, #1565C0);
36
+ }
37
+ :host([color="success"]) {
38
+ --tag-hue-solid: var(--u-success-color, #2E7D32);
39
+ --tag-hue-on-solid: var(--u-success-txt-color, #FFFFFF);
40
+ --tag-hue-line: var(--u-success-color-weak, #4CAF50);
41
+ --tag-hue-surface: var(--u-success-bg-color, #E8F5E9);
42
+ --tag-hue-text: var(--u-success-color-strong, #1B5E20);
43
+ --tag-hue-text-outlined: var(--u-success-color-strong, #1B5E20);
44
+ }
45
+ :host([color="warning"]) {
46
+ --tag-hue-solid: var(--u-warning-color, #FDD835);
47
+ --tag-hue-on-solid: var(--u-warning-txt-color, #000000);
48
+ --tag-hue-line: var(--u-warning-color-weak, #FFEB3B);
49
+ --tag-hue-surface: var(--u-warning-bg-color, #FFF59D);
50
+ --tag-hue-text: var(--u-warning-color-strong, #8A4A00);
51
+ --tag-hue-text-outlined: var(--u-warning-color-strong, #8A4A00);
52
+ }
53
+ :host([color="danger"]) {
54
+ --tag-hue-solid: var(--u-danger-color, #D32F2F);
55
+ --tag-hue-on-solid: var(--u-danger-txt-color, #FFFFFF);
56
+ --tag-hue-line: var(--u-danger-color-weak, #F44336);
57
+ --tag-hue-surface: var(--u-danger-bg-color, #FFEBEE);
58
+ --tag-hue-text: var(--u-danger-color-strong, #C62828);
59
+ --tag-hue-text-outlined: var(--u-danger-color-strong, #C62828);
60
+ }
61
+
11
62
  /* ==========================================================================
12
63
  장식 축 — 색 슬롯 매핑
13
64
  color="purple" 에는 역할 의미가 없다(장식이다). 그래서 역할 토큰이 아니라
@@ -82,7 +133,9 @@ var styles = css`
82
133
 
83
134
  /* Variant: solid (강한 채움, 색 미지정 시 --tag-fill-color = 브랜드) */
84
135
  :host([variant="solid"]) {
85
- --tag-color: var(--u-neutral-0, #FFFFFF);
136
+ /* 면 위의 글자. 장식 축은 슬롯이 비어 흰색으로 떨어진다(현행 보존) — 역할 축에서만
137
+ 갈린다. warning 이 그 이유다: 노란 면 위의 흰 글자는 읽히지 않는다. */
138
+ --tag-color: var(--tag-hue-on-solid, var(--u-neutral-0, #FFFFFF));
86
139
  --tag-bg-color: var(--tag-hue-solid, var(--tag-fill-color));
87
140
  --tag-border-color: var(--tag-hue-solid, var(--tag-fill-color));
88
141
  }
@@ -110,7 +163,7 @@ var styles = css`
110
163
 
111
164
  :host {
112
165
  display: inline-flex;
113
- font-size: 12px;
166
+ font-size: var(--u-text-caption-size, 12px);
114
167
  font-weight: 500;
115
168
  border-radius: var(--u-radius-md, 4px);
116
169
 
@@ -15,7 +15,7 @@ var styles = css`
15
15
  border: 1px solid var(--u-input-border-color, #E0E0E0);
16
16
  border-radius: 0.25em;
17
17
  background-color: var(--u-input-bg-color, #FFFFFF);
18
- transition: border-color 0.2s ease, box-shadow 0.2s ease, background-color 0.2s ease;
18
+ transition: border-color var(--u-duration-normal, 220ms) var(--u-ease-standard, cubic-bezier(0.2, 0, 0, 1)), box-shadow var(--u-duration-normal, 220ms) var(--u-ease-standard, cubic-bezier(0.2, 0, 0, 1)), background-color var(--u-duration-normal, 220ms) var(--u-ease-standard, cubic-bezier(0.2, 0, 0, 1));
19
19
  }
20
20
  :host([readonly]) .container,
21
21
  :host([disabled]) .container {
@@ -26,10 +26,10 @@ var styles = css`
26
26
  box-shadow: 0 0 0 1px var(--u-input-border-color-hover, #BDBDBD);
27
27
  }
28
28
  :host(:not([readonly]):not([disabled])) .container:focus-within {
29
- box-shadow: 0 0 0 1px var(--u-input-border-color-focus, #1976D2);
29
+ box-shadow: 0 0 0 1px var(--u-input-border-color-focus, #1565C0);
30
30
  }
31
31
  :host([invalid]:not([readonly]):not([disabled])) .container {
32
- box-shadow: 0 0 0 1px var(--u-input-border-color-invalid, #D32F2F);
32
+ box-shadow: 0 0 0 1px var(--u-input-border-color-invalid, #C62828);
33
33
  }
34
34
 
35
35
  /* ===== Variant: filled ===== */
@@ -51,11 +51,11 @@ var styles = css`
51
51
  }
52
52
  :host([variant="filled"]:not([readonly]):not([disabled])) .container:focus-within {
53
53
  box-shadow: none;
54
- border-bottom-color: var(--u-input-border-color-focus, #1976D2);
54
+ border-bottom-color: var(--u-input-border-color-focus, #1565C0);
55
55
  }
56
56
  :host([variant="filled"][invalid]:not([readonly]):not([disabled])) .container {
57
57
  box-shadow: none;
58
- border-bottom-color: var(--u-input-border-color-invalid, #D32F2F);
58
+ border-bottom-color: var(--u-input-border-color-invalid, #C62828);
59
59
  }
60
60
 
61
61
  /* ===== Variant: underlined ===== */
@@ -78,12 +78,12 @@ var styles = css`
78
78
  }
79
79
  :host([variant="underlined"]:not([readonly]):not([disabled])) .container:focus-within {
80
80
  box-shadow: none;
81
- border-bottom-color: var(--u-input-border-color-focus, #1976D2);
81
+ border-bottom-color: var(--u-input-border-color-focus, #1565C0);
82
82
  border-bottom-width: 2px;
83
83
  }
84
84
  :host([variant="underlined"][invalid]:not([readonly]):not([disabled])) .container {
85
85
  box-shadow: none;
86
- border-bottom-color: var(--u-input-border-color-invalid, #D32F2F);
86
+ border-bottom-color: var(--u-input-border-color-invalid, #C62828);
87
87
  }
88
88
 
89
89
  /* ===== Variant: borderless ===== */
@@ -8,13 +8,13 @@ var styles = css`
8
8
  :host {
9
9
  color: var(--u-tooltip-txt-color, #FFFFFF);
10
10
  font-family: var(--u-font-display, inherit);
11
- font-size: 12px;
11
+ font-size: var(--u-text-caption-size, 12px);
12
12
  line-height: 1.25;
13
13
  border-radius: var(--u-radius-md, 4px);
14
14
  background-color: var(--u-tooltip-bg-color, rgba(0, 0, 0, 0.75));
15
- box-shadow: 0 6px 18px rgba(0, 0, 0, 0.2);
15
+ box-shadow: var(--u-shadow-xl, 0 6px 18px rgba(0, 0, 0, 0.24), 0 2px 6px rgba(0, 0, 0, 0.08));
16
16
  transform: scale(0.9);
17
- transition: opacity 0.2s ease, transform 0.2s ease, visibility 0s 0.2s;
17
+ transition: opacity var(--u-duration-normal, 220ms) var(--u-ease-standard, cubic-bezier(0.2, 0, 0, 1)), transform var(--u-duration-normal, 220ms) var(--u-ease-standard, cubic-bezier(0.2, 0, 0, 1)), visibility 0s var(--u-duration-normal, 220ms);
18
18
 
19
19
  --tooltip-padding-block: var(--u-space-xs, 6px);
20
20
  --tooltip-padding-inline: var(--u-space-sm, 8px);
@@ -27,7 +27,7 @@ var styles = css`
27
27
  var(--tree-indent-size) * var(--tree-item-depth)
28
28
  + var(--tree-indent-guide-offset)
29
29
  );
30
- transition: background-color 0.15s ease, color 0.15s ease;
30
+ transition: background-color var(--u-duration-fast, 140ms) var(--u-ease-standard, cubic-bezier(0.2, 0, 0, 1)), color var(--u-duration-fast, 140ms) var(--u-ease-standard, cubic-bezier(0.2, 0, 0, 1));
31
31
  user-select: none;
32
32
  cursor: pointer;
33
33
  }
@@ -89,7 +89,7 @@ var styles = css`
89
89
  border-radius: var(--u-radius-sm, 3px);
90
90
  border: 1.5px solid var(--u-input-border-color, #E0E0E0);
91
91
  background-color: transparent;
92
- transition: background-color 0.15s ease, border-color 0.15s ease;
92
+ transition: background-color var(--u-duration-fast, 140ms) var(--u-ease-standard, cubic-bezier(0.2, 0, 0, 1)), border-color var(--u-duration-fast, 140ms) var(--u-ease-standard, cubic-bezier(0.2, 0, 0, 1));
93
93
  cursor: pointer;
94
94
  }
95
95
  .prefix-checkbox u-icon {
@@ -194,6 +194,11 @@
194
194
  --u-radius-md: 4px;
195
195
  --u-radius-lg: 6px;
196
196
  --u-radius-xl: 8px;
197
+ /* ★상단 2단은 **면(surface)용**이다 — 카드·패널·대화상자처럼 큰 사각형은 컨트롤과
198
+ 같은 반경을 쓰면 각져 보인다. 기존 5단은 **컨트롤용**이고 값을 바꾸지 않는다
199
+ (바꾸면 모든 소비자의 버튼·입력이 동시에 움직인다). */
200
+ --u-radius-2xl: 12px;
201
+ --u-radius-3xl: 16px;
197
202
  --u-radius-pill: 9999px;
198
203
  --u-radius-circle: 50%;
199
204
 
@@ -210,6 +215,16 @@
210
215
  --u-space-sm: 8px;
211
216
  --u-space-md: 12px;
212
217
  --u-space-lg: 16px;
218
+ /* ★상단 4단은 **화면 리듬**이다 — 카드 안쪽 여백(20~24)·섹션 간격(24~32)·페이지 여백
219
+ (32~40). 종전에는 이 구간이 통째로 비어 있어 소비자가 전부 리터럴로 적었고,
220
+ 그래서 앱마다 화면 밀도가 달라졌다. `lg`(16px) 이하는 **요소 사이**, `xl` 이상은
221
+ **영역 사이**로 나눠 쓴다.
222
+ ⚠`xs: 6px` 는 4px 격자에서 벗어나 있으나 **바꾸지 않는다** — 이미 배선된 컨트롤
223
+ 여백이 전부 움직인다. 신규 단은 전부 4의 배수로 둔다. */
224
+ --u-space-xl: 20px;
225
+ --u-space-2xl: 24px;
226
+ --u-space-3xl: 32px;
227
+ --u-space-4xl: 40px;
213
228
 
214
229
  /* Text Colors */
215
230
  --u-txt-color: var(--u-neutral-900);
@@ -246,10 +261,12 @@
246
261
  --u-border-color-strong: var(--u-neutral-500);
247
262
  --u-border-color-hover: var(--u-neutral-500);
248
263
 
264
+ /* ★상태 테두리는 `-strong` 단이다 — light.css 의 같은 자리 주석 참조.
265
+ 이 테마가 실제로 미달이었다: focus 2.74 · invalid 2.44 → 4.74 / 4.34. */
249
266
  --u-input-border-color: var(--u-neutral-400);
250
267
  --u-input-border-color-hover: var(--u-neutral-500);
251
- --u-input-border-color-focus: var(--u-primary-color);
252
- --u-input-border-color-invalid: var(--u-danger-color);
268
+ --u-input-border-color-focus: var(--u-primary-color-strong);
269
+ --u-input-border-color-invalid: var(--u-danger-color-strong);
253
270
 
254
271
  /* Background Colors */
255
272
  --u-bg-color: var(--u-neutral-100);
@@ -285,13 +302,99 @@
285
302
  --u-shadow-color-strong: rgba(0, 0, 0, 0.45);
286
303
  --u-shadow-color-stronger: rgba(0, 0, 0, 0.60);
287
304
 
305
+ /* Elevation Scale — 근거는 light.css 의 같은 자리 주석 참조.
306
+ ★다크는 알파가 3배 가까이 진하다 — 리터럴로 흩어져 있던 종전에는 이 차이가
307
+ 적용되지 않아 다크에서 그림자가 사실상 보이지 않았다. */
308
+ --u-shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.25), 0 1px 1px rgba(0, 0, 0, 0.14); /* = shadow-color-weak */
309
+ --u-shadow-md: 0 2px 8px rgba(0, 0, 0, 0.35), 0 1px 2px rgba(0, 0, 0, 0.18); /* = shadow-color-normal */
310
+ --u-shadow-lg: 0 4px 12px rgba(0, 0, 0, 0.45), 0 2px 4px rgba(0, 0, 0, 0.22); /* = shadow-color-strong */
311
+ --u-shadow-xl: 0 6px 18px rgba(0, 0, 0, 0.60), 0 2px 6px rgba(0, 0, 0, 0.30); /* = shadow-color-stronger */
312
+
313
+
314
+ /* ==========================================================================
315
+ Type Scale — 글자 크기·굵기·행간·자간의 **한 벌**
316
+ ★**크기만 주면 스케일이 되지 않는다.** 소비자가 크기만 받고 굵기·행간을 각자 정하면
317
+ 결국 화면마다 다른 위계가 생긴다 — 그래서 네 값을 **단 단위로 묶어** 낸다.
318
+
319
+ 단 이름은 크기가 아니라 **역할**이다(`lg`/`xl` 이 아니라 `title`/`label`). 역할로 두면
320
+ 소비자가 *"어느 크기를 쓸까"* 가 아니라 *"이 글자는 무엇인가"* 를 묻게 된다.
321
+
322
+ ★**한글 기준으로 값을 골랐다**:
323
+ ⑴ 행간은 **1.4 이상**. 라틴 관례(1.2)는 한글에서 답답하다 — 받침 때문에 글자 상자가
324
+ 세로로 꽉 차 있어 라틴과 같은 행간이면 줄이 붙어 보인다.
325
+ ⑵ 자간은 **0 이 기본**이고 큰 제목만 **음수**. 한글에 양수 자간(letter-spacing)을 주면
326
+ 가독성이 떨어진다 — 라틴 소문자 조판 관례를 그대로 옮기면 안 되는 자리다.
327
+ ⑶ `overline` 에만 양수 자간을 둔다. 그 단은 **영문·숫자 라벨**을 전제한 자리이고,
328
+ 한글을 넣을 소비자는 자간을 0 으로 덮어야 한다(문서에 명시).
329
+
330
+ ⚠**`text-transform` 은 토큰으로 내지 않는다.** 한글에는 대문자가 없어 `uppercase` 가
331
+ 아무 효과가 없고, 영문이 섞이면 그것만 커져 오히려 어수선해진다.
332
+ ========================================================================== */
333
+ --u-text-display-size: 26px;
334
+ --u-text-display-weight: 700;
335
+ --u-text-display-leading: 1.4;
336
+ --u-text-display-tracking: -0.02em;
337
+
338
+ --u-text-title-size: 20px;
339
+ --u-text-title-weight: 700;
340
+ --u-text-title-leading: 1.45;
341
+ --u-text-title-tracking: -0.01em;
342
+
343
+ --u-text-subtitle-size: 16px;
344
+ --u-text-subtitle-weight: 600;
345
+ --u-text-subtitle-leading: 1.5;
346
+ --u-text-subtitle-tracking: 0;
347
+
348
+ --u-text-body-size: 14px;
349
+ --u-text-body-weight: 400;
350
+ --u-text-body-leading: 1.6;
351
+ --u-text-body-tracking: 0;
352
+
353
+ --u-text-label-size: 13px;
354
+ --u-text-label-weight: 600;
355
+ --u-text-label-leading: 1.5;
356
+ --u-text-label-tracking: 0;
357
+
358
+ --u-text-caption-size: 12px;
359
+ --u-text-caption-weight: 400;
360
+ --u-text-caption-leading: 1.5;
361
+ --u-text-caption-tracking: 0;
362
+
363
+ --u-text-overline-size: 11px;
364
+ --u-text-overline-weight: 700;
365
+ --u-text-overline-leading: 1.45;
366
+ --u-text-overline-tracking: 0.06em;
367
+
368
+ /* ==========================================================================
369
+ Motion — 지속시간·이징
370
+ ★값이 없으면 앱마다 다른 속도가 생기고, `prefers-reduced-motion` 은 **반드시**
371
+ 빠뜨리는 앱이 나온다. 축을 여기 두고 존중 규칙은 아래 미디어 쿼리가 진다.
372
+ ========================================================================== */
373
+ --u-duration-instant: 80ms;
374
+ --u-duration-fast: 140ms;
375
+ --u-duration-normal: 220ms;
376
+ --u-duration-slow: 320ms;
377
+ --u-ease-standard: cubic-bezier(0.2, 0, 0, 1);
378
+ --u-ease-decelerate: cubic-bezier(0, 0, 0, 1);
379
+ --u-ease-accelerate: cubic-bezier(0.3, 0, 1, 1);
380
+
288
381
  /* Scrollbar Colors */
289
382
  --u-scrollbar-color: var(--u-neutral-500);
290
383
  --u-scrollbar-color-hover: var(--u-neutral-600);
291
384
  --u-scrollbar-track-color: transparent;
292
385
 
293
- /* Font Styles */
294
- --u-font-base: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Noto Sans', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji';
386
+ /* ==========================================================================
387
+ Font Styles
388
+ ★**CJK 폴백을 스택에 포함한다 — 국제화이지 취향이 아니다.**
389
+ 종전 스택(`-apple-system, Segoe UI, Noto Sans, Helvetica, Arial`)에는 **한중일 글립을
390
+ 가진 폰트가 하나도 없었다.** Windows 에서 한글은 `Segoe UI` 에 없으므로 UA 가 임의로
391
+ 맑은 고딕을 고르고, macOS 는 `-apple-system` 이 Apple SD Gothic Neo 를 준다 ⇒ **같은 앱이
392
+ OS 마다 다른 글꼴로 렌더**됐다. 폴백을 명시하면 그 선택이 결정적이 된다.
393
+ ⚠**웹폰트를 로드하지 않는다.** 라이브러리가 네트워크 요청을 만들면 소비자의 CSP·
394
+ 오프라인 환경을 깬다. 스택 맨 앞의 `Pretendard` 는 **소비자가 로드했을 때만** 잡히는
395
+ 선택적 이름이다(없으면 조용히 다음으로 넘어간다).
396
+ ========================================================================== */
397
+ --u-font-base: 'Pretendard Variable', Pretendard, -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Noto Sans', Helvetica, Arial, 'Apple SD Gothic Neo', 'Malgun Gothic', 'Noto Sans KR', 'Hiragino Sans', 'Yu Gothic UI', 'Microsoft YaHei', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji';
295
398
  --u-font-mono: ui-monospace, 'Cascadia Code', 'Source Code Pro', Menlo, Monaco, 'Courier New', monospace;
296
399
  --u-font-serif: 'Georgia', 'Times New Roman', Times, serif;
297
400
  --u-font-display: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Noto Sans', Helvetica, Arial, sans-serif;