sh-ui-cli 0.52.1 → 0.52.2

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 (88) hide show
  1. package/data/changelog/versions.json +14 -0
  2. package/data/registry/react/components/_smoke/vanilla-extract.test.ts +33 -0
  3. package/data/registry/react/components/input/styles.css.ts +6 -6
  4. package/data/registry/react/registry.json +35 -852
  5. package/package.json +1 -1
  6. package/src/api.d.ts +3 -4
  7. package/src/constants.js +9 -5
  8. package/src/mcp.mjs +0 -1
  9. package/data/registry/react/components/accordion/index.vanilla-extract.tsx +0 -97
  10. package/data/registry/react/components/accordion/styles.css.ts +0 -131
  11. package/data/registry/react/components/avatar/index.vanilla-extract.tsx +0 -73
  12. package/data/registry/react/components/avatar/styles.css.ts +0 -68
  13. package/data/registry/react/components/badge/index.vanilla-extract.tsx +0 -40
  14. package/data/registry/react/components/badge/styles.css.ts +0 -71
  15. package/data/registry/react/components/breadcrumb/index.vanilla-extract.tsx +0 -152
  16. package/data/registry/react/components/breadcrumb/styles.css.ts +0 -95
  17. package/data/registry/react/components/calendar/index.vanilla-extract.tsx +0 -806
  18. package/data/registry/react/components/calendar/styles.css.ts +0 -250
  19. package/data/registry/react/components/carousel/index.vanilla-extract.tsx +0 -430
  20. package/data/registry/react/components/carousel/styles.css.ts +0 -169
  21. package/data/registry/react/components/checkbox/index.vanilla-extract.tsx +0 -96
  22. package/data/registry/react/components/checkbox/styles.css.ts +0 -74
  23. package/data/registry/react/components/code-editor/index.vanilla-extract.tsx +0 -230
  24. package/data/registry/react/components/code-editor/styles.css.ts +0 -97
  25. package/data/registry/react/components/code-panel/index.vanilla-extract.tsx +0 -191
  26. package/data/registry/react/components/code-panel/styles.css.ts +0 -151
  27. package/data/registry/react/components/color-picker/index.vanilla-extract.tsx +0 -467
  28. package/data/registry/react/components/color-picker/styles.css.ts +0 -169
  29. package/data/registry/react/components/combobox/index.vanilla-extract.tsx +0 -165
  30. package/data/registry/react/components/combobox/styles.css.ts +0 -174
  31. package/data/registry/react/components/context-menu/index.vanilla-extract.tsx +0 -251
  32. package/data/registry/react/components/context-menu/styles.css.ts +0 -167
  33. package/data/registry/react/components/date-picker/index.vanilla-extract.tsx +0 -520
  34. package/data/registry/react/components/date-picker/styles.css.ts +0 -111
  35. package/data/registry/react/components/dialog/index.vanilla-extract.tsx +0 -95
  36. package/data/registry/react/components/dialog/styles.css.ts +0 -140
  37. package/data/registry/react/components/dropdown-menu/index.vanilla-extract.tsx +0 -255
  38. package/data/registry/react/components/dropdown-menu/styles.css.ts +0 -175
  39. package/data/registry/react/components/file-upload/index.vanilla-extract.tsx +0 -487
  40. package/data/registry/react/components/file-upload/styles.css.ts +0 -193
  41. package/data/registry/react/components/form/index.vanilla-extract.tsx +0 -61
  42. package/data/registry/react/components/form/styles.css.ts +0 -56
  43. package/data/registry/react/components/header/index.vanilla-extract.tsx +0 -805
  44. package/data/registry/react/components/header/styles.css.ts +0 -413
  45. package/data/registry/react/components/label/index.vanilla-extract.tsx +0 -52
  46. package/data/registry/react/components/label/styles.css.ts +0 -141
  47. package/data/registry/react/components/markdown-editor/index.vanilla-extract.tsx +0 -119
  48. package/data/registry/react/components/markdown-editor/styles.css.ts +0 -231
  49. package/data/registry/react/components/menubar/index.vanilla-extract.tsx +0 -32
  50. package/data/registry/react/components/menubar/styles.css.ts +0 -53
  51. package/data/registry/react/components/numeric-input/index.vanilla-extract.tsx +0 -148
  52. package/data/registry/react/components/numeric-input/styles.css.ts +0 -65
  53. package/data/registry/react/components/page-toc/index.vanilla-extract.tsx +0 -174
  54. package/data/registry/react/components/page-toc/styles.css.ts +0 -97
  55. package/data/registry/react/components/pagination/index.vanilla-extract.tsx +0 -269
  56. package/data/registry/react/components/pagination/styles.css.ts +0 -113
  57. package/data/registry/react/components/popover/index.vanilla-extract.tsx +0 -113
  58. package/data/registry/react/components/popover/styles.css.ts +0 -78
  59. package/data/registry/react/components/progress/index.vanilla-extract.tsx +0 -54
  60. package/data/registry/react/components/progress/styles.css.ts +0 -53
  61. package/data/registry/react/components/radio/index.vanilla-extract.tsx +0 -65
  62. package/data/registry/react/components/radio/styles.css.ts +0 -79
  63. package/data/registry/react/components/rich-text-editor/index.vanilla-extract.tsx +0 -348
  64. package/data/registry/react/components/rich-text-editor/styles.css.ts +0 -243
  65. package/data/registry/react/components/select/index.vanilla-extract.tsx +0 -234
  66. package/data/registry/react/components/select/styles.css.ts +0 -225
  67. package/data/registry/react/components/separator/index.vanilla-extract.tsx +0 -46
  68. package/data/registry/react/components/separator/styles.css.ts +0 -24
  69. package/data/registry/react/components/sidebar/index.vanilla-extract.tsx +0 -1067
  70. package/data/registry/react/components/sidebar/styles.css.ts +0 -578
  71. package/data/registry/react/components/skeleton/index.vanilla-extract.tsx +0 -22
  72. package/data/registry/react/components/skeleton/styles.css.ts +0 -30
  73. package/data/registry/react/components/slider/index.vanilla-extract.tsx +0 -298
  74. package/data/registry/react/components/slider/styles.css.ts +0 -75
  75. package/data/registry/react/components/spinner/index.vanilla-extract.tsx +0 -38
  76. package/data/registry/react/components/spinner/styles.css.ts +0 -60
  77. package/data/registry/react/components/switch/index.vanilla-extract.tsx +0 -39
  78. package/data/registry/react/components/switch/styles.css.ts +0 -87
  79. package/data/registry/react/components/tabs/index.vanilla-extract.tsx +0 -91
  80. package/data/registry/react/components/tabs/styles.css.ts +0 -145
  81. package/data/registry/react/components/textarea/index.vanilla-extract.tsx +0 -23
  82. package/data/registry/react/components/textarea/styles.css.ts +0 -55
  83. package/data/registry/react/components/toast/index.vanilla-extract.tsx +0 -258
  84. package/data/registry/react/components/toast/styles.css.ts +0 -307
  85. package/data/registry/react/components/toggle/index.vanilla-extract.tsx +0 -131
  86. package/data/registry/react/components/toggle/styles.css.ts +0 -109
  87. package/data/registry/react/components/tooltip/index.vanilla-extract.tsx +0 -83
  88. package/data/registry/react/components/tooltip/styles.css.ts +0 -59
@@ -1,307 +0,0 @@
1
- import { style, keyframes } from "@vanilla-extract/css";
2
-
3
- export const shUiToastEnterRight = keyframes({
4
- "from": {
5
- opacity: 0,
6
- transform: "translateX(100%)",
7
- },
8
- "to": {
9
- opacity: 1,
10
- transform: "translateX(0)",
11
- },
12
- });
13
-
14
- export const shUiToastExitRight = keyframes({
15
- "from": {
16
- opacity: 1,
17
- transform: "translateX(0)",
18
- },
19
- "to": {
20
- opacity: 0,
21
- transform: "translateX(100%)",
22
- },
23
- });
24
-
25
- export const shUiToastEnterLeft = keyframes({
26
- "from": {
27
- opacity: 0,
28
- transform: "translateX(-100%)",
29
- },
30
- "to": {
31
- opacity: 1,
32
- transform: "translateX(0)",
33
- },
34
- });
35
-
36
- export const shUiToastExitLeft = keyframes({
37
- "from": {
38
- opacity: 1,
39
- transform: "translateX(0)",
40
- },
41
- "to": {
42
- opacity: 0,
43
- transform: "translateX(-100%)",
44
- },
45
- });
46
-
47
- export const shUiToastEnterBottom = keyframes({
48
- "from": {
49
- opacity: 0,
50
- transform: "translateY(100%)",
51
- },
52
- "to": {
53
- opacity: 1,
54
- transform: "translateY(0)",
55
- },
56
- });
57
-
58
- export const shUiToastExitBottom = keyframes({
59
- "from": {
60
- opacity: 1,
61
- transform: "translateY(0)",
62
- },
63
- "to": {
64
- opacity: 0,
65
- transform: "translateY(100%)",
66
- },
67
- });
68
-
69
- export const shUiToastEnterTop = keyframes({
70
- "from": {
71
- opacity: 0,
72
- transform: "translateY(-100%)",
73
- },
74
- "to": {
75
- opacity: 1,
76
- transform: "translateY(0)",
77
- },
78
- });
79
-
80
- export const shUiToastExitTop = keyframes({
81
- "from": {
82
- opacity: 1,
83
- transform: "translateY(0)",
84
- },
85
- "to": {
86
- opacity: 0,
87
- transform: "translateY(-100%)",
88
- },
89
- });
90
-
91
- export const toastViewport = style({
92
- position: "fixed",
93
- zIndex: "var(--z-toast)",
94
- display: "flex",
95
- flexDirection: "column",
96
- gap: "var(--space-2)",
97
- maxWidth: "24rem",
98
- width: "100%",
99
- pointerEvents: "none",
100
- selectors: {
101
- "&[data-position="bottom-right"]": {
102
- bottom: "var(--space-4)",
103
- right: "var(--space-4)",
104
- flexDirection: "column-reverse",
105
- },
106
- "&[data-position="bottom-left"]": {
107
- bottom: "var(--space-4)",
108
- left: "var(--space-4)",
109
- flexDirection: "column-reverse",
110
- },
111
- "&[data-position="bottom-center"]": {
112
- bottom: "var(--space-4)",
113
- left: "50%",
114
- transform: "translateX(-50%)",
115
- flexDirection: "column-reverse",
116
- },
117
- "&[data-position="top-right"]": {
118
- top: "var(--space-4)",
119
- right: "var(--space-4)",
120
- },
121
- "&[data-position="top-left"]": {
122
- top: "var(--space-4)",
123
- left: "var(--space-4)",
124
- },
125
- "&[data-position="top-center"]": {
126
- top: "var(--space-4)",
127
- left: "50%",
128
- transform: "translateX(-50%)",
129
- },
130
- },
131
- "@media": {
132
- "(max-width: 40rem)": {
133
- maxWidth: "100%",
134
- padding: "var(--space-4)",
135
- selectors: {
136
- "&[data-position="bottom-right"]": {
137
- right: 0,
138
- left: 0,
139
- bottom: 0,
140
- transform: "none",
141
- },
142
- "&[data-position="bottom-left"]": {
143
- right: 0,
144
- left: 0,
145
- bottom: 0,
146
- transform: "none",
147
- },
148
- "&[data-position="bottom-center"]": {
149
- right: 0,
150
- left: 0,
151
- bottom: 0,
152
- transform: "none",
153
- },
154
- "&[data-position="top-right"]": {
155
- right: 0,
156
- left: 0,
157
- top: 0,
158
- transform: "none",
159
- },
160
- "&[data-position="top-left"]": {
161
- right: 0,
162
- left: 0,
163
- top: 0,
164
- transform: "none",
165
- },
166
- "&[data-position="top-center"]": {
167
- right: 0,
168
- left: 0,
169
- top: 0,
170
- transform: "none",
171
- },
172
- },
173
- },
174
- },
175
- });
176
-
177
- export const toast = style({
178
- position: "relative",
179
- display: "flex",
180
- alignItems: "flex-start",
181
- gap: "0.625rem",
182
- width: "100%",
183
- padding: "var(--space-3) 2.25rem var(--space-3) var(--space-3)",
184
- background: "var(--background)",
185
- color: "var(--foreground)",
186
- border: "1px solid var(--border)",
187
- borderRadius: "var(--radius)",
188
- boxShadow: "0 4px 16px rgba(0, 0, 0, 0.12)",
189
- pointerEvents: "auto",
190
- "@media": {
191
- "(prefers-reduced-motion: reduce)": {
192
- animation: "none !important",
193
- },
194
- },
195
- });
196
-
197
- export const toast__icon = style({
198
- flexShrink: 0,
199
- display: "inline-flex",
200
- alignItems: "center",
201
- marginTop: "0.125rem",
202
- });
203
-
204
- export const toastSuccess = style({
205
- selectors: {
206
- [`& ${toast__icon}`]: {
207
- color: "var(--success, #16a34a)",
208
- },
209
- },
210
- });
211
-
212
- export const toastDanger = style({
213
- selectors: {
214
- [`& ${toast__icon}`]: {
215
- color: "var(--danger)",
216
- },
217
- },
218
- });
219
-
220
- export const toastWarning = style({
221
- selectors: {
222
- [`& ${toast__icon}`]: {
223
- color: "var(--warning, #d97706)",
224
- },
225
- },
226
- });
227
-
228
- export const toast__body = style({
229
- flex: 1,
230
- minWidth: 0,
231
- });
232
-
233
- export const toast__title = style({
234
- margin: 0,
235
- fontSize: "var(--text-sm)",
236
- fontWeight: "var(--weight-semibold)",
237
- lineHeight: 1.4,
238
- selectors: {
239
- [`& + ${toast__description}`]: {
240
- marginTop: "0.125rem",
241
- },
242
- },
243
- });
244
-
245
- export const toast__description = style({
246
- margin: 0,
247
- fontSize: "0.8125rem",
248
- lineHeight: 1.4,
249
- color: "var(--foreground-muted)",
250
- });
251
-
252
- export const toast__action = style({
253
- flexShrink: 0,
254
- display: "inline-flex",
255
- alignItems: "center",
256
- marginLeft: "auto",
257
- });
258
-
259
- export const toast__close = style({
260
- position: "absolute",
261
- top: "0.375rem",
262
- right: "0.375rem",
263
- display: "inline-flex",
264
- alignItems: "center",
265
- justifyContent: "center",
266
- width: "1.5rem",
267
- height: "1.5rem",
268
- padding: 0,
269
- border: "none",
270
- borderRadius: "calc(var(--radius) - 2px)",
271
- background: "transparent",
272
- color: "var(--foreground-muted)",
273
- fontSize: "var(--text-sm)",
274
- lineHeight: 1,
275
- cursor: "pointer",
276
- transition: "background-color var(--duration-fast), color var(--duration-fast)",
277
- selectors: {
278
- "&:hover": {
279
- background: "var(--background-muted)",
280
- color: "var(--foreground)",
281
- },
282
- "&:focus-visible": {
283
- outline: "var(--border-width-strong) solid var(--foreground)",
284
- outlineOffset: "2px",
285
- },
286
- },
287
- "@media": {
288
- "(prefers-reduced-motion: reduce)": {
289
- transition: "none",
290
- },
291
- },
292
- });
293
-
294
- /** 동적 키로 클래스 참조용 — `byKey[\`badge--${variant}\`]` 같은 패턴 지원. */
295
- export const byKey: Record<string, string> = {
296
- "toast-viewport": toastViewport,
297
- "toast": toast,
298
- "toast__icon": toast__icon,
299
- "toast--success": toastSuccess,
300
- "toast--danger": toastDanger,
301
- "toast--warning": toastWarning,
302
- "toast__body": toast__body,
303
- "toast__title": toast__title,
304
- "toast__description": toast__description,
305
- "toast__action": toast__action,
306
- "toast__close": toast__close,
307
- };
@@ -1,131 +0,0 @@
1
- "use client";
2
-
3
- import * as React from "react";
4
- import { Toggle as BaseToggle } from "@base-ui/react/toggle";
5
- import { ToggleGroup as BaseToggleGroup } from "@base-ui/react/toggle-group";
6
- import { byKey, toggle, toggleSm, toggleMd, toggleLg, toggleOutline, toggleGhost, toggleGroup } from "./styles.css";
7
-
8
-
9
- import { cn } from "@SH_UI_UTILS@";
10
- /* ───────────── Toggle ───────────── */
11
-
12
- export type ToggleVariant = "outline" | "ghost";
13
- export type ToggleSize = "sm" | "md" | "lg";
14
-
15
- export type ToggleProps = Omit<
16
- React.ComponentPropsWithoutRef<typeof BaseToggle>,
17
- "className"
18
- > & {
19
- className?: string;
20
- /**
21
- * 외형 변형.
22
- * - `ghost` — 배경 없음, 눌림 시만 강조 (기본)
23
- * - `outline` — 항상 border 표시
24
- *
25
- * @default "ghost"
26
- */
27
- variant?: ToggleVariant;
28
- /**
29
- * 크기. `sm` / `md` / `lg`.
30
- *
31
- * @default "md"
32
- */
33
- size?: ToggleSize;
34
- };
35
-
36
- /**
37
- * 눌린 상태(pressed)를 가진 버튼. 툴바의 "굵게/기울임" 같은 즉시 토글 액션에 적합.
38
- * 시각만으로 상태를 구분하지 말고 `aria-label`이나 아이콘 옆 텍스트로 의미를 명확히 할 것.
39
- */
40
- export const Toggle = React.forwardRef<HTMLButtonElement, ToggleProps>(
41
- ({ className, variant = "ghost", size = "md", ...props }, ref) => (
42
- <BaseToggle
43
- ref={ref}
44
- className={cn(
45
- toggle,
46
- byKey[`toggle--${variant}`],
47
- byKey[`toggle--${size}`],
48
- className,
49
- )}
50
- {...props}
51
- />
52
- ),
53
- );
54
- Toggle.displayName = "Toggle";
55
-
56
- /* ───────────── ToggleGroup ───────────── */
57
-
58
- export type ToggleGroupProps = Omit<
59
- React.ComponentPropsWithoutRef<typeof BaseToggleGroup>,
60
- "className"
61
- > & {
62
- className?: string;
63
- /**
64
- * 그룹 내 모든 항목에 적용될 외형. 자식 ToggleGroupItem이 자동 상속한다.
65
- * @default "ghost"
66
- */
67
- variant?: ToggleVariant;
68
- /**
69
- * 그룹 내 모든 항목에 적용될 크기. 자식 ToggleGroupItem이 자동 상속한다.
70
- * @default "md"
71
- */
72
- size?: ToggleSize;
73
- };
74
-
75
- interface ToggleGroupContextValue {
76
- variant: ToggleVariant;
77
- size: ToggleSize;
78
- }
79
-
80
- const ToggleGroupContext = React.createContext<ToggleGroupContextValue>({
81
- variant: "ghost",
82
- size: "md",
83
- });
84
-
85
- export const useToggleGroupStyle = () => React.useContext(ToggleGroupContext);
86
-
87
- /**
88
- * 여러 ToggleGroupItem을 묶는 컨테이너. `toggleMultiple` 옵션으로 단일/다중 선택을
89
- * 결정하고, 그룹 단위로 variant·size를 적용한다. 항목들은 반드시 `ToggleGroupItem`을 사용할 것.
90
- */
91
- export const ToggleGroup = React.forwardRef<HTMLDivElement, ToggleGroupProps>(
92
- ({ className, variant = "ghost", size = "md", ...props }, ref) => (
93
- <ToggleGroupContext.Provider value={{ variant, size }}>
94
- <BaseToggleGroup
95
- ref={ref}
96
- className={cn(toggleGroup, className)}
97
- {...props}
98
- />
99
- </ToggleGroupContext.Provider>
100
- ),
101
- );
102
- ToggleGroup.displayName = "ToggleGroup";
103
-
104
- /* ───────────── ToggleGroupItem ───────────── */
105
-
106
- export type ToggleGroupItemProps = Omit<
107
- React.ComponentPropsWithoutRef<typeof BaseToggle>,
108
- "className"
109
- > & {
110
- className?: string;
111
- };
112
-
113
- /** ToggleGroup의 자식 항목. 부모 그룹의 variant·size를 자동으로 상속한다. */
114
- export const ToggleGroupItem = React.forwardRef<HTMLButtonElement, ToggleGroupItemProps>(
115
- ({ className, ...props }, ref) => {
116
- const { variant, size } = useToggleGroupStyle();
117
- return (
118
- <BaseToggle
119
- ref={ref}
120
- className={cn(
121
- toggle,
122
- byKey[`toggle--${variant}`],
123
- byKey[`toggle--${size}`],
124
- className,
125
- )}
126
- {...props}
127
- />
128
- );
129
- },
130
- );
131
- ToggleGroupItem.displayName = "ToggleGroupItem";
@@ -1,109 +0,0 @@
1
- import { style } from "@vanilla-extract/css";
2
-
3
- export const toggle = style({
4
- display: "inline-flex",
5
- alignItems: "center",
6
- justifyContent: "center",
7
- gap: "0.375rem",
8
- border: "1px solid transparent",
9
- borderRadius: "var(--radius)",
10
- fontWeight: "var(--weight-medium)",
11
- lineHeight: 1,
12
- cursor: "pointer",
13
- color: "var(--foreground-muted)",
14
- background: "transparent",
15
- transition: "background-color var(--duration-fast), color var(--duration-fast), border-color var(--duration-fast)",
16
- userSelect: "none",
17
- WebkitTapHighlightColor: "transparent",
18
- selectors: {
19
- "&[data-pressed]": {
20
- background: "var(--background-muted)",
21
- color: "var(--foreground)",
22
- },
23
- "&:focus-visible": {
24
- outline: "var(--border-width-strong) solid var(--foreground)",
25
- outlineOffset: "2px",
26
- },
27
- "&:disabled": {
28
- opacity: "var(--opacity-disabled)",
29
- pointerEvents: "none",
30
- },
31
- },
32
- "@media": {
33
- "(prefers-reduced-motion: reduce)": {
34
- transition: "none",
35
- },
36
- },
37
- });
38
-
39
- export const toggleSm = style({
40
- height: "var(--control-sm)",
41
- padding: "0 0.625rem",
42
- fontSize: "var(--text-sm)",
43
- "@media": {
44
- "(hover: none) and (pointer: coarse)": {
45
- height: "2.25rem",
46
- },
47
- },
48
- });
49
-
50
- export const toggleMd = style({
51
- height: "var(--control-md)",
52
- padding: "0 var(--space-3)",
53
- fontSize: "var(--text-sm)",
54
- "@media": {
55
- "(hover: none) and (pointer: coarse)": {
56
- height: "2.75rem",
57
- },
58
- },
59
- });
60
-
61
- export const toggleLg = style({
62
- height: "var(--control-lg)",
63
- padding: "0 var(--space-4)",
64
- fontSize: "var(--text-base)",
65
- });
66
-
67
- export const toggleOutline = style({
68
- borderColor: "var(--border)",
69
- selectors: {
70
- "&:hover:not(:disabled):not([data-pressed])": {
71
- background: "var(--background-muted)",
72
- color: "var(--foreground)",
73
- },
74
- "&[data-pressed]": {
75
- borderColor: "var(--border-strong)",
76
- },
77
- },
78
- });
79
-
80
- export const toggleGhost = style({
81
- selectors: {
82
- "&:hover:not(:disabled):not([data-pressed])": {
83
- background: "var(--background-muted)",
84
- color: "var(--foreground)",
85
- },
86
- },
87
- });
88
-
89
- export const toggleGroup = style({
90
- display: "inline-flex",
91
- alignItems: "center",
92
- gap: "var(--space-1)",
93
- selectors: {
94
- "&[data-orientation="vertical"]": {
95
- flexDirection: "column",
96
- },
97
- },
98
- });
99
-
100
- /** 동적 키로 클래스 참조용 — `byKey[\`badge--${variant}\`]` 같은 패턴 지원. */
101
- export const byKey: Record<string, string> = {
102
- "toggle": toggle,
103
- "toggle--sm": toggleSm,
104
- "toggle--md": toggleMd,
105
- "toggle--lg": toggleLg,
106
- "toggle--outline": toggleOutline,
107
- "toggle--ghost": toggleGhost,
108
- "toggle-group": toggleGroup,
109
- };
@@ -1,83 +0,0 @@
1
- import * as React from "react";
2
- import { Tooltip as BaseTooltip } from "@base-ui/react/tooltip";
3
- import { byKey, tooltip__positioner, tooltip__content, tooltip__arrow } from "./styles.css";
4
-
5
- import { cn } from "@SH_UI_UTILS@";
6
- type WithStringClassName<T> = Omit<T, "className"> & { className?: string };
7
-
8
-
9
- /** 여러 Tooltip이 공통 delay를 공유하도록 묶는다. 앱 루트에 한 번 두는 것을 권장. */
10
- export const TooltipProvider = BaseTooltip.Provider;
11
-
12
- /** Tooltip 루트. Trigger + Content를 자식으로 갖는다. */
13
- export const Tooltip = BaseTooltip.Root;
14
-
15
- /** 호버/포커스로 tooltip을 표시할 엘리먼트를 감싼다. render prop으로 Button 등과 결합. */
16
- export const TooltipTrigger = BaseTooltip.Trigger;
17
-
18
- export interface TooltipContentProps
19
- extends WithStringClassName<
20
- React.ComponentPropsWithoutRef<typeof BaseTooltip.Popup>
21
- > {
22
- /**
23
- * Trigger 기준 배치 방향. 공간 부족 시 자동으로 반대편으로 뒤집힌다.
24
- * @default "top"
25
- */
26
- side?: "top" | "right" | "bottom" | "left";
27
- /**
28
- * 트리거 축에서의 정렬.
29
- * @default "center"
30
- */
31
- align?: "start" | "center" | "end";
32
- /**
33
- * Trigger와 Popup 사이 간격(px).
34
- * @default 6
35
- */
36
- sideOffset?: number;
37
- /**
38
- * Trigger를 가리키는 화살표 표시 여부.
39
- * @default false
40
- */
41
- showArrow?: boolean;
42
- /**
43
- * Portal이 마운트될 DOM 노드.
44
- * @default document.body
45
- */
46
- container?: React.ComponentPropsWithoutRef<
47
- typeof BaseTooltip.Portal
48
- >["container"];
49
- }
50
-
51
- /**
52
- * Tooltip의 본문. portal로 마운트되어 트리거 옆에 자동 위치 조정된다.
53
- * 내용은 짧게 — 긴 설명이 필요하면 Popover를 사용할 것.
54
- */
55
- export const TooltipContent = React.forwardRef<
56
- HTMLDivElement,
57
- TooltipContentProps
58
- >(function TooltipContent(
59
- { className, children, side, align, sideOffset = 6, showArrow, container, ...props },
60
- ref,
61
- ) {
62
- return (
63
- <BaseTooltip.Portal container={container}>
64
- <BaseTooltip.Positioner
65
- className={tooltip__positioner}
66
- side={side}
67
- align={align}
68
- sideOffset={sideOffset}
69
- >
70
- <BaseTooltip.Popup
71
- ref={ref}
72
- className={cn(tooltip__content, className)}
73
- {...props}
74
- >
75
- {showArrow && (
76
- <BaseTooltip.Arrow className={tooltip__arrow} />
77
- )}
78
- {children}
79
- </BaseTooltip.Popup>
80
- </BaseTooltip.Positioner>
81
- </BaseTooltip.Portal>
82
- );
83
- });
@@ -1,59 +0,0 @@
1
- import { style } from "@vanilla-extract/css";
2
-
3
- export const tooltip__positioner = style({
4
- zIndex: "var(--z-tooltip, var(--z-popover))",
5
- outline: "none",
6
- });
7
-
8
- export const tooltip__content = style({
9
- padding: "0.375rem 0.625rem",
10
- background: "var(--foreground)",
11
- color: "var(--background)",
12
- borderRadius: "calc(var(--radius) - 2px)",
13
- fontSize: "var(--text-xs)",
14
- lineHeight: 1.4,
15
- maxWidth: "20rem",
16
- boxShadow: "0 4px 12px rgba(0, 0, 0, 0.12)",
17
- transformOrigin: "var(--transform-origin)",
18
- outline: "none",
19
- transition: "opacity 120ms ease,\n transform 120ms ease",
20
- selectors: {
21
- "&[data-starting-style]": {
22
- opacity: 0,
23
- transform: "scale(0.96)",
24
- },
25
- "&[data-ending-style]": {
26
- opacity: 0,
27
- transform: "scale(0.96)",
28
- },
29
- },
30
- "@media": {
31
- "(prefers-reduced-motion: reduce)": {
32
- transition: "none",
33
- selectors: {
34
- "&[data-starting-style]": {
35
- transform: "none",
36
- },
37
- "&[data-ending-style]": {
38
- transform: "none",
39
- },
40
- },
41
- },
42
- },
43
- });
44
-
45
- export const tooltip__arrow = style({
46
- color: "var(--foreground)",
47
- selectors: {
48
- "& svg": {
49
- display: "block",
50
- },
51
- },
52
- });
53
-
54
- /** 동적 키로 클래스 참조용 — `byKey[\`badge--${variant}\`]` 같은 패턴 지원. */
55
- export const byKey: Record<string, string> = {
56
- "tooltip__positioner": tooltip__positioner,
57
- "tooltip__content": tooltip__content,
58
- "tooltip__arrow": tooltip__arrow,
59
- };