@justin_evo/evo-ui 1.0.1

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 (110) hide show
  1. package/dist/Alert/Alert.d.ts +11 -0
  2. package/dist/AutoComplete/AutoComplete.d.ts +95 -0
  3. package/dist/Badge/Badge.d.ts +23 -0
  4. package/dist/Breadcrumb/Breadcrumb.d.ts +16 -0
  5. package/dist/Button/Button.d.ts +54 -0
  6. package/dist/Card/Card.d.ts +60 -0
  7. package/dist/Checkbox/Checkbox.d.ts +16 -0
  8. package/dist/CommandPalette/CommandPalette.d.ts +17 -0
  9. package/dist/Container/Container.d.ts +10 -0
  10. package/dist/Divider/Divider.d.ts +7 -0
  11. package/dist/Form/Form.d.ts +61 -0
  12. package/dist/Grid/Grid.d.ts +23 -0
  13. package/dist/ImageCropper/ImageCropper.d.ts +111 -0
  14. package/dist/Input/Input.d.ts +12 -0
  15. package/dist/Modal/Modal.d.ts +26 -0
  16. package/dist/Nav/Nav.d.ts +63 -0
  17. package/dist/Notification/Notification.d.ts +186 -0
  18. package/dist/Pagination/Pagination.d.ts +10 -0
  19. package/dist/Radio/Radio.d.ts +20 -0
  20. package/dist/RichTextArea/RichTextArea.d.ts +70 -0
  21. package/dist/Select/Select.d.ts +44 -0
  22. package/dist/Skeleton/Skeleton.d.ts +23 -0
  23. package/dist/Stack/Stack.d.ts +16 -0
  24. package/dist/Table/Table.d.ts +77 -0
  25. package/dist/Tabs/Tabs.d.ts +28 -0
  26. package/dist/Theme/ThemeProvider.d.ts +96 -0
  27. package/dist/Theme/ThemeToggle.d.ts +22 -0
  28. package/dist/Toggle/Toggle.d.ts +11 -0
  29. package/dist/Tooltip/Tooltip.d.ts +10 -0
  30. package/dist/TopNav/TopNav.d.ts +76 -0
  31. package/dist/TreeSelect/TreeSelect.d.ts +50 -0
  32. package/dist/declarations.d.ts +6 -0
  33. package/dist/evo-ui.css +1 -0
  34. package/dist/index.cjs.js +1 -0
  35. package/dist/index.d.ts +31 -0
  36. package/dist/index.es.js +5688 -0
  37. package/package.json +52 -0
  38. package/src/Alert/Alert.tsx +49 -0
  39. package/src/AutoComplete/AutoComplete.tsx +810 -0
  40. package/src/Badge/Badge.tsx +53 -0
  41. package/src/Breadcrumb/Breadcrumb.tsx +53 -0
  42. package/src/Button/Button.tsx +125 -0
  43. package/src/Card/Card.tsx +257 -0
  44. package/src/Checkbox/Checkbox.tsx +59 -0
  45. package/src/CommandPalette/CommandPalette.tsx +185 -0
  46. package/src/Container/Container.tsx +31 -0
  47. package/src/Divider/Divider.tsx +31 -0
  48. package/src/Form/Form.tsx +185 -0
  49. package/src/Grid/Grid.tsx +66 -0
  50. package/src/ImageCropper/ImageCropper.tsx +911 -0
  51. package/src/Input/Input.tsx +74 -0
  52. package/src/Modal/Modal.tsx +77 -0
  53. package/src/Nav/Nav.tsx +626 -0
  54. package/src/Notification/Notification.tsx +1503 -0
  55. package/src/Pagination/Pagination.tsx +76 -0
  56. package/src/Radio/Radio.tsx +69 -0
  57. package/src/RichTextArea/RichTextArea.tsx +869 -0
  58. package/src/Select/Select.tsx +515 -0
  59. package/src/Skeleton/Skeleton.tsx +70 -0
  60. package/src/Stack/Stack.tsx +52 -0
  61. package/src/Table/Table.tsx +335 -0
  62. package/src/Tabs/Tabs.tsx +90 -0
  63. package/src/Theme/ThemeProvider.tsx +253 -0
  64. package/src/Theme/ThemeToggle.tsx +79 -0
  65. package/src/Toggle/Toggle.tsx +48 -0
  66. package/src/Tooltip/Tooltip.tsx +38 -0
  67. package/src/TopNav/TopNav.tsx +994 -0
  68. package/src/TreeSelect/TreeSelect.tsx +825 -0
  69. package/src/css/alert.module.scss +93 -0
  70. package/src/css/autocomplete.module.scss +416 -0
  71. package/src/css/badge.module.scss +82 -0
  72. package/src/css/base/_color.scss +159 -0
  73. package/src/css/base/_theme.scss +237 -0
  74. package/src/css/base/_variables.scss +161 -0
  75. package/src/css/breadcrumb.module.scss +50 -0
  76. package/src/css/button.module.scss +385 -0
  77. package/src/css/card.module.scss +217 -0
  78. package/src/css/checkbox.module.scss +120 -0
  79. package/src/css/commandpalette.module.scss +211 -0
  80. package/src/css/container.module.scss +18 -0
  81. package/src/css/divider.module.scss +41 -0
  82. package/src/css/form.module.scss +245 -0
  83. package/src/css/imagecropper.module.scss +397 -0
  84. package/src/css/input.module.scss +89 -0
  85. package/src/css/modal.module.scss +105 -0
  86. package/src/css/nav.module.scss +339 -0
  87. package/src/css/notification.module.scss +691 -0
  88. package/src/css/pagination.module.scss +63 -0
  89. package/src/css/radio.module.scss +89 -0
  90. package/src/css/richtextarea.module.scss +307 -0
  91. package/src/css/select.module.scss +525 -0
  92. package/src/css/skeleton.module.scss +30 -0
  93. package/src/css/table.module.scss +386 -0
  94. package/src/css/tabs.module.scss +63 -0
  95. package/src/css/theme-toggle.module.scss +83 -0
  96. package/src/css/toggle.module.scss +54 -0
  97. package/src/css/tooltip.module.scss +97 -0
  98. package/src/css/topnav.module.scss +396 -0
  99. package/src/css/treeselect.module.scss +558 -0
  100. package/src/css/utilities/_borders.scss +111 -0
  101. package/src/css/utilities/_colors.scss +66 -0
  102. package/src/css/utilities/_effects.scss +216 -0
  103. package/src/css/utilities/_layout.scss +181 -0
  104. package/src/css/utilities/_position.scss +75 -0
  105. package/src/css/utilities/_sizing.scss +138 -0
  106. package/src/css/utilities/_spacing.scss +99 -0
  107. package/src/css/utilities/_typography.scss +121 -0
  108. package/src/css/utilities/index.scss +24 -0
  109. package/src/declarations.d.ts +6 -0
  110. package/src/index.ts +60 -0
@@ -0,0 +1,386 @@
1
+ @use './base/variables' as *;
2
+ @use './base/color' as *;
3
+
4
+ // ==========================================================
5
+ // EVO-UI TABLE
6
+ // ----------------------------------------------------------
7
+ // A lightweight, theme-aware data table.
8
+ // - Horizontal rules only — no busy vertical grid lines.
9
+ // - Density variants (sm/md/lg) tune padding + type scale.
10
+ // - Sticky headers, striped rows, sortable columns, and a
11
+ // loading skeleton state — all opt-in.
12
+ // - Two responsive modes for narrow viewports:
13
+ // `scroll` — thin overflow scrollbar
14
+ // `stack` — rows collapse into labelled cards
15
+ // ==========================================================
16
+
17
+ .wrapper {
18
+ width: 100%;
19
+ background-color: $color-surface-elevated;
20
+ border: 1px solid $color-border;
21
+ border-radius: $evo-border-radius-lg;
22
+ font-family: $font-sans;
23
+ color: $color-text-primary;
24
+ // Clip rounded corners against the inner scroll container.
25
+ overflow: hidden;
26
+ }
27
+
28
+ .scroll {
29
+ width: 100%;
30
+ overflow-x: auto;
31
+ -webkit-overflow-scrolling: touch;
32
+ scrollbar-color: $color-border-strong transparent;
33
+ scrollbar-width: thin;
34
+
35
+ &::-webkit-scrollbar {
36
+ height: 8px;
37
+ width: 8px;
38
+ }
39
+ &::-webkit-scrollbar-thumb {
40
+ background: $color-border-strong;
41
+ border-radius: $radius-full;
42
+ }
43
+ &::-webkit-scrollbar-track {
44
+ background: transparent;
45
+ }
46
+ }
47
+
48
+ .table {
49
+ width: 100%;
50
+ border-collapse: separate;
51
+ border-spacing: 0;
52
+ font-size: $text-sm;
53
+ font-variant-numeric: tabular-nums;
54
+ }
55
+
56
+ .caption {
57
+ caption-side: top;
58
+ text-align: left;
59
+ padding: 0.75rem 1rem 0;
60
+ color: $color-text-secondary;
61
+ font-size: $text-xs;
62
+ }
63
+
64
+ // ----- Header --------------------------------------------------
65
+ .thead {
66
+ background-color: $color-surface-sunken;
67
+ }
68
+
69
+ .th {
70
+ padding: 0.625rem 1rem;
71
+ text-align: left;
72
+ font-size: $text-xs;
73
+ font-weight: 600;
74
+ color: $color-text-secondary;
75
+ white-space: nowrap;
76
+ border-bottom: 1px solid $color-border;
77
+ vertical-align: middle;
78
+ letter-spacing: 0.01em;
79
+ user-select: none;
80
+ }
81
+
82
+ .sortBtn {
83
+ display: inline-flex;
84
+ align-items: center;
85
+ gap: 0.375rem;
86
+ background: transparent;
87
+ border: 0;
88
+ padding: 0;
89
+ margin: 0;
90
+ font: inherit;
91
+ color: inherit;
92
+ cursor: pointer;
93
+ border-radius: $radius-sm;
94
+ transition: color $transition-fast;
95
+
96
+ &:hover {
97
+ color: $color-text-primary;
98
+ }
99
+
100
+ &:focus-visible {
101
+ outline: 2px solid $evo-primary-focus;
102
+ outline-offset: 2px;
103
+ }
104
+ }
105
+
106
+ .sortIcon {
107
+ display: inline-flex;
108
+ color: $color-text-muted;
109
+ flex-shrink: 0;
110
+ transition: color $transition-fast;
111
+ }
112
+
113
+ .sortActive {
114
+ color: $color-text-primary;
115
+
116
+ .sortIcon {
117
+ color: $evo-primary-color;
118
+ }
119
+ }
120
+
121
+ // ----- Body ----------------------------------------------------
122
+ .tbody {
123
+ .tr {
124
+ transition: background-color $transition-fast;
125
+ }
126
+ }
127
+
128
+ .td {
129
+ padding: 0.75rem 1rem;
130
+ color: $color-text-primary;
131
+ vertical-align: middle;
132
+ border-bottom: 1px solid $color-border-subtle;
133
+ text-align: left;
134
+ }
135
+
136
+ // Drop the last row border so it tucks cleanly into the rounded wrapper.
137
+ .tbody .tr:last-child .td {
138
+ border-bottom: 0;
139
+ }
140
+
141
+ // ----- Alignment ----------------------------------------------
142
+ .align-left {
143
+ text-align: left;
144
+ }
145
+ .align-center {
146
+ text-align: center;
147
+ }
148
+ .align-right {
149
+ text-align: right;
150
+ }
151
+
152
+ // Sort buttons are inline-flex — `text-align` doesn't reach them.
153
+ .align-center .sortBtn {
154
+ width: 100%;
155
+ justify-content: center;
156
+ }
157
+ .align-right .sortBtn {
158
+ width: 100%;
159
+ justify-content: flex-end;
160
+ }
161
+
162
+ // ----- Density -------------------------------------------------
163
+ .size-sm {
164
+ .table {
165
+ font-size: $text-xs;
166
+ }
167
+ .th {
168
+ padding: 0.375rem 0.75rem;
169
+ }
170
+ .td {
171
+ padding: 0.5rem 0.75rem;
172
+ }
173
+ }
174
+
175
+ .size-md {
176
+ .table {
177
+ font-size: $text-sm;
178
+ }
179
+ .th {
180
+ padding: 0.625rem 1rem;
181
+ }
182
+ .td {
183
+ padding: 0.75rem 1rem;
184
+ }
185
+ }
186
+
187
+ .size-lg {
188
+ .table {
189
+ font-size: $text-base;
190
+ }
191
+ .th {
192
+ padding: 0.875rem 1.25rem;
193
+ }
194
+ .td {
195
+ padding: 1rem 1.25rem;
196
+ }
197
+ }
198
+
199
+ // ----- Modifiers ----------------------------------------------
200
+ .hoverable .tbody .tr:hover {
201
+ background-color: $color-surface-hover;
202
+ }
203
+
204
+ .striped .tbody .tr:nth-child(even) {
205
+ background-color: $color-surface-sunken;
206
+ }
207
+
208
+ // Hover wins over stripe.
209
+ .striped.hoverable .tbody .tr:nth-child(even):hover {
210
+ background-color: $color-surface-hover;
211
+ }
212
+
213
+ .bordered {
214
+ .th,
215
+ .td {
216
+ &:not(:last-child) {
217
+ border-right: 1px solid $color-border-subtle;
218
+ }
219
+ }
220
+ }
221
+
222
+ .stickyHeader {
223
+ .scroll {
224
+ max-height: 70vh;
225
+ overflow-y: auto;
226
+ }
227
+ .thead .th {
228
+ position: sticky;
229
+ top: 0;
230
+ z-index: 2;
231
+ background-color: $color-surface-sunken;
232
+ }
233
+ }
234
+
235
+ .clickable .tbody .tr {
236
+ cursor: pointer;
237
+
238
+ &:active {
239
+ background-color: $color-surface-active;
240
+ }
241
+ }
242
+
243
+ // ----- Empty + Skeleton ---------------------------------------
244
+ .empty {
245
+ padding: 3rem 1.5rem;
246
+ text-align: center;
247
+ color: $color-text-muted;
248
+ font-size: $text-sm;
249
+ }
250
+
251
+ .emptyText {
252
+ display: inline-block;
253
+ }
254
+
255
+ .skeleton {
256
+ display: block;
257
+ height: 0.75rem;
258
+ width: 70%;
259
+ border-radius: $radius-sm;
260
+ background: linear-gradient(
261
+ 90deg,
262
+ $color-skeleton-base 0%,
263
+ $color-skeleton-highlight 50%,
264
+ $color-skeleton-base 100%
265
+ );
266
+ background-size: 200% 100%;
267
+ animation: evoTableShimmer 1.4s ease-in-out infinite;
268
+ }
269
+
270
+ @keyframes evoTableShimmer {
271
+ 0% {
272
+ background-position: 200% 0;
273
+ }
274
+ 100% {
275
+ background-position: -200% 0;
276
+ }
277
+ }
278
+
279
+ @media (prefers-reduced-motion: reduce) {
280
+ .skeleton {
281
+ animation: none;
282
+ }
283
+ }
284
+
285
+ // ----- Responsive: stack mode ---------------------------------
286
+ // Below ~640px, transform rows into vertical "cards" where each
287
+ // cell becomes a labelled row. The visual header is removed
288
+ // (kept in DOM, hidden visually, for screen readers).
289
+ .responsiveStack {
290
+ @media (max-width: 640px) {
291
+ border: 0;
292
+ background: transparent;
293
+ overflow: visible;
294
+
295
+ .scroll {
296
+ overflow: visible;
297
+ }
298
+
299
+ .table,
300
+ .tbody,
301
+ .tr {
302
+ display: block;
303
+ width: 100%;
304
+ }
305
+
306
+ .thead {
307
+ // Screen-reader-only — keeps semantics while removing visuals.
308
+ position: absolute;
309
+ width: 1px;
310
+ height: 1px;
311
+ padding: 0;
312
+ margin: -1px;
313
+ overflow: hidden;
314
+ clip: rect(0, 0, 0, 0);
315
+ white-space: nowrap;
316
+ border: 0;
317
+ }
318
+
319
+ .tbody .tr {
320
+ background-color: $color-surface-elevated;
321
+ border: 1px solid $color-border;
322
+ border-radius: $evo-border-radius-lg;
323
+ padding: 0.25rem 0;
324
+ margin-bottom: 0.75rem;
325
+
326
+ &:last-child {
327
+ margin-bottom: 0;
328
+ }
329
+
330
+ // Empty-state row should look like a single full-width card, not
331
+ // a normal data row with internal padding.
332
+ &.emptyRow {
333
+ padding: 0;
334
+ margin-bottom: 0;
335
+ }
336
+ }
337
+
338
+ .td {
339
+ display: flex;
340
+ align-items: center;
341
+ justify-content: space-between;
342
+ gap: 1rem;
343
+ padding: 0.625rem 1rem;
344
+ border-bottom: 1px dashed $color-border-subtle;
345
+ text-align: right;
346
+
347
+ &:last-child {
348
+ border-bottom: 0;
349
+ }
350
+
351
+ &::before {
352
+ content: attr(data-label);
353
+ font-size: $text-xs;
354
+ font-weight: 600;
355
+ color: $color-text-secondary;
356
+ letter-spacing: 0.02em;
357
+ text-align: left;
358
+ flex-shrink: 0;
359
+ }
360
+ }
361
+
362
+ // Vertical dividers don't apply in stack mode.
363
+ &.bordered .td:not(:last-child) {
364
+ border-right: 0;
365
+ }
366
+
367
+ // Reset stripe/hover on the card layout — each row is its own card.
368
+ &.striped .tbody .tr:nth-child(even),
369
+ &.hoverable .tbody .tr:hover {
370
+ background-color: $color-surface-elevated;
371
+ }
372
+
373
+ // In stack mode the empty cell is the only td in its row.
374
+ // Reset it back to a block so the message stays centred.
375
+ .empty {
376
+ display: block;
377
+ text-align: center;
378
+ padding: 2.5rem 1rem;
379
+ border-bottom: 0;
380
+
381
+ &::before {
382
+ content: none;
383
+ }
384
+ }
385
+ }
386
+ }
@@ -0,0 +1,63 @@
1
+ @use 'base/variables' as *;
2
+ @use 'base/color' as *;
3
+
4
+ .tabs {
5
+ width: 100%;
6
+ font-family: $font-sans;
7
+ }
8
+
9
+ .tabList {
10
+ display: flex;
11
+ gap: 0.125rem;
12
+ border-bottom: 1px solid $color-border;
13
+ }
14
+
15
+ .tab {
16
+ position: relative;
17
+ padding: 0.5rem 1rem;
18
+ font-size: $text-sm;
19
+ font-weight: 500;
20
+ color: $color-text-secondary;
21
+ background: transparent;
22
+ border: none;
23
+ border-radius: $radius-sm $radius-sm 0 0;
24
+ cursor: pointer;
25
+ transition: color $transition-fast, background-color $transition-fast;
26
+ font-family: $font-sans;
27
+
28
+ &::after {
29
+ content: '';
30
+ position: absolute;
31
+ bottom: -1px;
32
+ left: 0;
33
+ right: 0;
34
+ height: 2px;
35
+ background-color: transparent;
36
+ transition: background-color $transition-fast;
37
+ border-radius: 2px 2px 0 0;
38
+ }
39
+
40
+ &:hover:not(.disabled):not(.active) {
41
+ color: $color-text-primary;
42
+ background-color: $color-surface-hover;
43
+ }
44
+
45
+ &.active {
46
+ color: $evo-primary-color;
47
+ &::after { background-color: $evo-primary-color; }
48
+ }
49
+
50
+ &.disabled {
51
+ opacity: 0.4;
52
+ cursor: not-allowed;
53
+ pointer-events: none;
54
+ }
55
+ }
56
+
57
+ .tabPanel {
58
+ padding: 1.25rem 0;
59
+ color: $color-text-secondary;
60
+ font-size: $text-sm;
61
+ line-height: 1.6;
62
+ font-family: $font-sans;
63
+ }
@@ -0,0 +1,83 @@
1
+ @use 'base/variables' as *;
2
+
3
+ // ==========================================================
4
+ // Theme toggle — animated sun/moon switch.
5
+ // All colors come from theme tokens so it auto-themes itself.
6
+ // ==========================================================
7
+
8
+ .toggle {
9
+ display: inline-flex;
10
+ align-items: center;
11
+ justify-content: center;
12
+ padding: 0;
13
+ background: transparent;
14
+ border: none;
15
+ cursor: pointer;
16
+ font: inherit;
17
+ color: inherit;
18
+ -webkit-tap-highlight-color: transparent;
19
+
20
+ &:focus-visible {
21
+ outline: 2px solid $evo-primary-focus;
22
+ outline-offset: 3px;
23
+ border-radius: $radius-full;
24
+ }
25
+ }
26
+
27
+ .track {
28
+ position: relative;
29
+ display: inline-block;
30
+ background: $color-surface-elevated;
31
+ border: 1px solid $color-border;
32
+ border-radius: $radius-full;
33
+ transition: background-color $transition-fast, border-color $transition-fast;
34
+ overflow: hidden;
35
+ }
36
+
37
+ .thumb {
38
+ position: absolute;
39
+ top: 50%;
40
+ transform: translate(0, -50%);
41
+ display: inline-flex;
42
+ align-items: center;
43
+ justify-content: center;
44
+ background-color: $color-background;
45
+ color: $evo-primary-color;
46
+ border-radius: 50%;
47
+ box-shadow: 0 2px 6px rgb(0 0 0 / 0.18);
48
+ transition: transform $transition-normal cubic-bezier(0.34, 1.56, 0.64, 1),
49
+ background-color $transition-fast;
50
+
51
+ svg {
52
+ position: absolute;
53
+ width: 60%;
54
+ height: 60%;
55
+ transition: opacity $transition-fast ease, transform $transition-normal ease;
56
+ }
57
+ }
58
+
59
+ // Sun visible in light, moon visible in dark
60
+ .sun { opacity: 1; transform: rotate(0); }
61
+ .moon { opacity: 0; transform: rotate(-90deg); }
62
+
63
+ [data-theme-state='dark'] {
64
+ .sun { opacity: 0; transform: rotate(90deg); }
65
+ .moon { opacity: 1; transform: rotate(0); }
66
+ }
67
+
68
+ // ---- Sizes ----
69
+ .sm {
70
+ .track { width: 36px; height: 20px; }
71
+ .thumb { width: 16px; height: 16px; left: 2px; }
72
+ &[data-theme-state='dark'] .thumb { transform: translate(16px, -50%); }
73
+ }
74
+ .md {
75
+ .track { width: 48px; height: 26px; }
76
+ .thumb { width: 22px; height: 22px; left: 2px; }
77
+ &[data-theme-state='dark'] .thumb { transform: translate(22px, -50%); }
78
+ }
79
+ .lg {
80
+ .track { width: 60px; height: 32px; }
81
+ .thumb { width: 28px; height: 28px; left: 2px; }
82
+ &[data-theme-state='dark'] .thumb { transform: translate(28px, -50%); }
83
+ }
@@ -0,0 +1,54 @@
1
+ @use 'base/variables' as *;
2
+ @use 'base/color' as *;
3
+
4
+ .toggleWrapper {
5
+ display: inline-flex;
6
+ align-items: center;
7
+ gap: 0.5rem;
8
+ cursor: pointer;
9
+ font-family: $font-sans;
10
+
11
+ &.disabled {
12
+ opacity: 0.5;
13
+ cursor: not-allowed;
14
+ pointer-events: none;
15
+ }
16
+ }
17
+
18
+ .hiddenInput {
19
+ position: absolute;
20
+ opacity: 0;
21
+ width: 0;
22
+ height: 0;
23
+ }
24
+
25
+ .track {
26
+ position: relative;
27
+ display: inline-block;
28
+ background-color: $color-border-strong;
29
+ border-radius: $radius-full;
30
+ transition: background-color $transition-fast;
31
+ flex-shrink: 0;
32
+
33
+ &.sm { width: 1.75rem; height: 1rem; }
34
+ &.md { width: 2.25rem; height: 1.25rem; }
35
+ &.lg { width: 2.75rem; height: 1.5rem; }
36
+
37
+ &.on { background-color: $evo-primary-color; }
38
+ }
39
+
40
+ .thumb {
41
+ position: absolute;
42
+ top: 2px;
43
+ left: 2px;
44
+ background-color: $color-background;
45
+ border-radius: 50%;
46
+ transition: transform $transition-fast;
47
+ box-shadow: 0 1px 3px rgb(0 0 0 / 0.25);
48
+ }
49
+
50
+ .label {
51
+ font-size: $text-sm;
52
+ color: $color-text-primary;
53
+ user-select: none;
54
+ }
@@ -0,0 +1,97 @@
1
+ @use 'base/variables' as *;
2
+ @use 'base/color' as *;
3
+
4
+ @keyframes tooltipFadeIn {
5
+ from { opacity: 0; transform: scale(0.95); }
6
+ to { opacity: 1; transform: scale(1); }
7
+ }
8
+
9
+ .wrapper {
10
+ position: relative;
11
+ display: inline-flex;
12
+ align-items: center;
13
+ }
14
+
15
+ .tooltip {
16
+ position: absolute;
17
+ z-index: 9000;
18
+ padding: 0.375rem 0.625rem;
19
+ background-color: $color-surface-elevated;
20
+ color: $color-text-primary;
21
+ font-size: $text-xs;
22
+ font-family: $font-sans;
23
+ border-radius: $radius-sm;
24
+ white-space: nowrap;
25
+ box-shadow: $shadow-lg;
26
+ border: 1px solid $color-border;
27
+ pointer-events: none;
28
+ animation: tooltipFadeIn 150ms ease;
29
+ line-height: 1.4;
30
+
31
+ &.top {
32
+ bottom: calc(100% + 8px);
33
+ left: 50%;
34
+ transform: translateX(-50%);
35
+ }
36
+
37
+ &.bottom {
38
+ top: calc(100% + 8px);
39
+ left: 50%;
40
+ transform: translateX(-50%);
41
+ }
42
+
43
+ &.left {
44
+ right: calc(100% + 8px);
45
+ top: 50%;
46
+ transform: translateY(-50%);
47
+ }
48
+
49
+ &.right {
50
+ left: calc(100% + 8px);
51
+ top: 50%;
52
+ transform: translateY(-50%);
53
+ }
54
+ }
55
+
56
+ .arrow {
57
+ position: absolute;
58
+ width: 0;
59
+ height: 0;
60
+ border: 5px solid transparent;
61
+
62
+ .top & {
63
+ top: 100%;
64
+ left: 50%;
65
+ transform: translateX(-50%);
66
+ border-top-color: $color-surface-elevated;
67
+ border-bottom: none;
68
+ border-top-width: 5px;
69
+ }
70
+
71
+ .bottom & {
72
+ bottom: 100%;
73
+ left: 50%;
74
+ transform: translateX(-50%);
75
+ border-bottom-color: $color-surface-elevated;
76
+ border-top: none;
77
+ border-bottom-width: 5px;
78
+ }
79
+
80
+ .left & {
81
+ left: 100%;
82
+ top: 50%;
83
+ transform: translateY(-50%);
84
+ border-left-color: $color-surface-elevated;
85
+ border-right: none;
86
+ border-left-width: 5px;
87
+ }
88
+
89
+ .right & {
90
+ right: 100%;
91
+ top: 50%;
92
+ transform: translateY(-50%);
93
+ border-right-color: $color-surface-elevated;
94
+ border-left: none;
95
+ border-right-width: 5px;
96
+ }
97
+ }