@holaboss/ui 0.1.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.
- package/README.md +116 -0
- package/dist/index.cjs +973 -0
- package/dist/index.d.cts +643 -0
- package/dist/index.d.cts.map +1 -0
- package/dist/index.d.ts +643 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +904 -0
- package/dist/index.js.map +1 -0
- package/dist/themes/holaos.css +121 -0
- package/dist/tokens.css +446 -0
- package/package.json +72 -0
- package/src/index.ts +108 -0
- package/src/layouts/dashboard-shell.tsx +43 -0
- package/src/layouts/data-table.tsx +110 -0
- package/src/layouts/error-state.tsx +52 -0
- package/src/layouts/filter-bar.tsx +58 -0
- package/src/layouts/loading-state.tsx +67 -0
- package/src/layouts/page-header.tsx +44 -0
- package/src/layouts/section.tsx +49 -0
- package/src/layouts/stat-pill.tsx +57 -0
- package/src/lib/utils.ts +6 -0
- package/src/primitives/alert.tsx +76 -0
- package/src/primitives/badge.tsx +52 -0
- package/src/primitives/button.tsx +61 -0
- package/src/primitives/card.tsx +107 -0
- package/src/primitives/dropdown-menu.tsx +270 -0
- package/src/primitives/empty-state.tsx +112 -0
- package/src/primitives/input.tsx +20 -0
- package/src/primitives/kbd.tsx +38 -0
- package/src/primitives/label.tsx +20 -0
- package/src/primitives/popover.tsx +87 -0
- package/src/primitives/select.tsx +202 -0
- package/src/primitives/status-dot.tsx +85 -0
- package/src/primitives/switch.tsx +19 -0
- package/src/primitives/tabs.tsx +80 -0
- package/src/primitives/tooltip.tsx +64 -0
- package/src/tokens/themes/holaos.css +121 -0
- package/src/tokens/tokens.css +446 -0
package/dist/tokens.css
ADDED
|
@@ -0,0 +1,446 @@
|
|
|
1
|
+
/* Design tokens — single source of truth for color, type, radius, motion,
|
|
2
|
+
shadow, z-index. Theme files (./themes/*.css) override --background,
|
|
3
|
+
--foreground, --primary etc. by [data-theme="*"] attribute. */
|
|
4
|
+
|
|
5
|
+
@theme inline {
|
|
6
|
+
--font-heading: var(--font-sans);
|
|
7
|
+
--font-sans: "Inter Variable", sans-serif;
|
|
8
|
+
--font-mono:
|
|
9
|
+
"Geist Mono Variable", ui-monospace, SFMono-Regular, Menlo, Consolas,
|
|
10
|
+
"Liberation Mono", monospace;
|
|
11
|
+
|
|
12
|
+
/* Foreground-mix utilities — opaque tint of foreground into bg.
|
|
13
|
+
Use bg-fg-3 etc. (Distinct from bg-foreground/N alpha.) */
|
|
14
|
+
--color-fg-2: var(--fg-2);
|
|
15
|
+
--color-fg-4: var(--fg-4);
|
|
16
|
+
--color-fg-6: var(--fg-6);
|
|
17
|
+
--color-fg-8: var(--fg-8);
|
|
18
|
+
--color-fg-12: var(--fg-12);
|
|
19
|
+
--color-fg-16: var(--fg-16);
|
|
20
|
+
--color-fg-24: var(--fg-24);
|
|
21
|
+
--color-fg-32: var(--fg-32);
|
|
22
|
+
--color-fg-48: var(--fg-48);
|
|
23
|
+
--color-fg-64: var(--fg-64);
|
|
24
|
+
--color-fg-80: var(--fg-80);
|
|
25
|
+
--color-fg-92: var(--fg-92);
|
|
26
|
+
--color-sidebar-ring: var(--sidebar-ring);
|
|
27
|
+
--color-sidebar-border: var(--sidebar-border);
|
|
28
|
+
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
|
|
29
|
+
--color-sidebar-accent: var(--sidebar-accent);
|
|
30
|
+
--color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
|
|
31
|
+
--color-sidebar-primary: var(--sidebar-primary);
|
|
32
|
+
--color-sidebar-foreground: var(--sidebar-foreground);
|
|
33
|
+
--color-sidebar: var(--sidebar);
|
|
34
|
+
--color-chart-5: var(--chart-5);
|
|
35
|
+
--color-chart-4: var(--chart-4);
|
|
36
|
+
--color-chart-3: var(--chart-3);
|
|
37
|
+
--color-chart-2: var(--chart-2);
|
|
38
|
+
--color-chart-1: var(--chart-1);
|
|
39
|
+
--color-ring: var(--ring);
|
|
40
|
+
--color-input: var(--input);
|
|
41
|
+
--color-border: var(--border);
|
|
42
|
+
--color-destructive: var(--destructive);
|
|
43
|
+
--color-destructive-foreground: var(--destructive-foreground);
|
|
44
|
+
--color-success: var(--success);
|
|
45
|
+
--color-success-foreground: var(--success-foreground);
|
|
46
|
+
--color-warning: var(--warning);
|
|
47
|
+
--color-warning-foreground: var(--warning-foreground);
|
|
48
|
+
--color-info: var(--info);
|
|
49
|
+
--color-info-foreground: var(--info-foreground);
|
|
50
|
+
--color-scrim: var(--scrim);
|
|
51
|
+
--color-accent-foreground: var(--accent-foreground);
|
|
52
|
+
--color-accent: var(--accent);
|
|
53
|
+
--color-muted-foreground: var(--muted-foreground);
|
|
54
|
+
--color-muted: var(--muted);
|
|
55
|
+
--color-secondary-foreground: var(--secondary-foreground);
|
|
56
|
+
--color-secondary: var(--secondary);
|
|
57
|
+
--color-primary-foreground: var(--primary-foreground);
|
|
58
|
+
--color-primary: var(--primary);
|
|
59
|
+
--color-popover-foreground: var(--popover-foreground);
|
|
60
|
+
--color-popover: var(--popover);
|
|
61
|
+
--color-card-foreground: var(--card-foreground);
|
|
62
|
+
--color-card: var(--card);
|
|
63
|
+
--color-foreground: var(--foreground);
|
|
64
|
+
--color-background: var(--background);
|
|
65
|
+
/* Radius scale — integer px steps off base 8px. */
|
|
66
|
+
--radius-sm: calc(var(--radius) * 0.5); /* 4px */
|
|
67
|
+
--radius-md: calc(var(--radius) * 0.75); /* 6px — button/menu-item */
|
|
68
|
+
--radius-lg: var(--radius); /* 8px — card/input */
|
|
69
|
+
--radius-xl: calc(var(--radius) * 1.25); /* 10px — popover/dropdown */
|
|
70
|
+
--radius-2xl: calc(var(--radius) * 1.5); /* 12px — panel inner */
|
|
71
|
+
--radius-3xl: calc(var(--radius) * 2); /* 16px */
|
|
72
|
+
--radius-4xl: calc(var(--radius) * 2.5); /* 20px */
|
|
73
|
+
|
|
74
|
+
/* Font weights — each step ~50 lighter than Tailwind default. */
|
|
75
|
+
--font-weight-thin: 300;
|
|
76
|
+
--font-weight-extralight: 325;
|
|
77
|
+
--font-weight-light: 350;
|
|
78
|
+
--font-weight-normal: 350;
|
|
79
|
+
--font-weight-medium: 400;
|
|
80
|
+
--font-weight-semibold: 450;
|
|
81
|
+
--font-weight-bold: 500;
|
|
82
|
+
--font-weight-extrabold: 550;
|
|
83
|
+
--font-weight-black: 600;
|
|
84
|
+
|
|
85
|
+
/* Tight type scale — ~10-20% denser than Tailwind default. */
|
|
86
|
+
--text-xs: 0.725rem;
|
|
87
|
+
--text-xs--line-height: 1.2rem;
|
|
88
|
+
--text-xs--letter-spacing: 0.01em;
|
|
89
|
+
--text-sm: 0.775rem;
|
|
90
|
+
--text-sm--line-height: 1.3rem;
|
|
91
|
+
--text-sm--letter-spacing: 0.008em;
|
|
92
|
+
--text-base: 0.875rem;
|
|
93
|
+
--text-base--line-height: 1.5rem;
|
|
94
|
+
--text-lg: 0.975rem;
|
|
95
|
+
--text-lg--line-height: 1.75rem;
|
|
96
|
+
--text-xl: 1.175rem;
|
|
97
|
+
--text-xl--line-height: 1.95rem;
|
|
98
|
+
--text-2xl: 1.275rem;
|
|
99
|
+
--text-2xl--line-height: 2.25rem;
|
|
100
|
+
--text-3xl: 1.375rem;
|
|
101
|
+
--text-3xl--line-height: 2.5rem;
|
|
102
|
+
--text-4xl: 1.475rem;
|
|
103
|
+
--text-4xl--line-height: 2.75rem;
|
|
104
|
+
--text-5xl: 3.052rem;
|
|
105
|
+
|
|
106
|
+
/* Entrance animations */
|
|
107
|
+
--animate-reveal-pop: reveal-pop 0.5s cubic-bezier(0.16, 1, 0.3, 1) forwards;
|
|
108
|
+
--animate-fade-in-once: fade-in-once 0.6s ease-out forwards;
|
|
109
|
+
|
|
110
|
+
/* Brand alias — tracks whichever theme is active.
|
|
111
|
+
Use bg-brand / text-brand in new code. */
|
|
112
|
+
--color-brand: var(--primary);
|
|
113
|
+
--color-brand-foreground: var(--primary-foreground);
|
|
114
|
+
|
|
115
|
+
/* Layered shadow scale. 2xs/xs are hairline-ring + tiny drops for
|
|
116
|
+
surfaces that should read as "barely lifted" (cards, sticky toolbars).
|
|
117
|
+
sm steps up to a Linear/Stripe-style 8-layer stack for buttons +
|
|
118
|
+
popovers. md/lg/xl/2xl keep the hairline + blur scale. Dark mode
|
|
119
|
+
re-derives from --hairline-alpha / --shadow-alpha. */
|
|
120
|
+
--shadow-2xs:
|
|
121
|
+
rgba(0, 0, 0, 0.025) 0 1px 1px -0.5px, rgba(0, 0, 0, 0.05) 0 2px 2px -1px,
|
|
122
|
+
rgba(0, 0, 0, 0.05) 0 0 0 1px;
|
|
123
|
+
--shadow-xs:
|
|
124
|
+
rgba(0, 0, 0, 0.02) 0 1px 1px -0.5px, rgba(0, 0, 0, 0.04) 0 1px 1px -0.5px,
|
|
125
|
+
rgba(0, 0, 0, 0.04) 0 2px 2px -1px, rgba(0, 0, 0, 0.03) 0 0 0 0.5px;
|
|
126
|
+
--shadow-sm:
|
|
127
|
+
0 1px 1px 0.5px rgba(51, 51, 51, 0.03),
|
|
128
|
+
0 3px 3px -1.5px rgba(51, 51, 51, 0.015),
|
|
129
|
+
0 6px 6px -3px rgba(51, 51, 51, 0.03),
|
|
130
|
+
0 12px 12px -6px rgba(51, 51, 51, 0.03),
|
|
131
|
+
0 24px 24px -12px rgba(51, 51, 51, 0.03),
|
|
132
|
+
0 48px 48px -24px rgba(51, 51, 51, 0.03),
|
|
133
|
+
0 0 0 1px rgba(51, 51, 51, 0.08),
|
|
134
|
+
inset 0 -1px 1px -0.5px rgba(51, 51, 51, 0.05);
|
|
135
|
+
--shadow-md:
|
|
136
|
+
0 0 0 1px oklch(from var(--foreground) l c h / var(--hairline-alpha)),
|
|
137
|
+
0 1px 2px -1px rgba(0, 0, 0, var(--shadow-alpha)),
|
|
138
|
+
0 3px 5px -1px rgba(0, 0, 0, var(--shadow-alpha));
|
|
139
|
+
--shadow-lg:
|
|
140
|
+
0 0 0 1px oklch(from var(--foreground) l c h / var(--hairline-alpha)),
|
|
141
|
+
0 1px 2px -1px rgba(0, 0, 0, var(--shadow-alpha)),
|
|
142
|
+
0 3px 5px -1px rgba(0, 0, 0, var(--shadow-alpha)),
|
|
143
|
+
0 6px 10px -2px rgba(0, 0, 0, var(--shadow-alpha));
|
|
144
|
+
--shadow-xl:
|
|
145
|
+
0 0 0 1px oklch(from var(--foreground) l c h / var(--hairline-alpha)),
|
|
146
|
+
0 1px 2px -1px rgba(0, 0, 0, var(--shadow-alpha)),
|
|
147
|
+
0 3px 5px -1px rgba(0, 0, 0, var(--shadow-alpha)),
|
|
148
|
+
0 6px 10px -2px rgba(0, 0, 0, var(--shadow-alpha)),
|
|
149
|
+
0 14px 22px -6px rgba(0, 0, 0, calc(var(--shadow-alpha) * 0.7));
|
|
150
|
+
--shadow-2xl:
|
|
151
|
+
0 0 0 1px oklch(from var(--foreground) l c h / var(--hairline-alpha)),
|
|
152
|
+
0 1px 2px -1px rgba(0, 0, 0, var(--shadow-alpha)),
|
|
153
|
+
0 3px 5px -1px rgba(0, 0, 0, var(--shadow-alpha)),
|
|
154
|
+
0 6px 10px -2px rgba(0, 0, 0, var(--shadow-alpha)),
|
|
155
|
+
0 14px 22px -6px rgba(0, 0, 0, calc(var(--shadow-alpha) * 0.7)),
|
|
156
|
+
0 24px 36px -8px rgba(0, 0, 0, calc(var(--shadow-alpha) * 0.5));
|
|
157
|
+
|
|
158
|
+
/* Z-index — semantic app-chrome layers (Tailwind z-0..z-50 still
|
|
159
|
+
used for in-component layering). 100-step rhythm. */
|
|
160
|
+
--z-index-sticky: 100;
|
|
161
|
+
--z-index-chrome: 200;
|
|
162
|
+
--z-index-panel: 300;
|
|
163
|
+
--z-index-popover: 500;
|
|
164
|
+
--z-index-tooltip: 600;
|
|
165
|
+
--z-index-modal: 700;
|
|
166
|
+
--z-index-overlay: 800;
|
|
167
|
+
--z-index-toast: 900;
|
|
168
|
+
--z-index-splash: 1000;
|
|
169
|
+
|
|
170
|
+
/* Motion — 180ms default + custom curve. */
|
|
171
|
+
--default-transition-duration: 180ms;
|
|
172
|
+
--default-transition-timing-function: cubic-bezier(0.32, 0.08, 0.24, 1);
|
|
173
|
+
--ease-standard: cubic-bezier(0.32, 0.08, 0.24, 1);
|
|
174
|
+
--ease-out-quint: cubic-bezier(0.22, 1, 0.36, 1);
|
|
175
|
+
/* Linear-style emphasized curve — used for modals, collapses,
|
|
176
|
+
expansions, anything where the user needs to feel a deliberate
|
|
177
|
+
enter/exit. */
|
|
178
|
+
--ease-emphasized: cubic-bezier(0.32, 0.72, 0, 1);
|
|
179
|
+
/* Smooth ease-out for slide-ins where the element should decelerate
|
|
180
|
+
into rest. */
|
|
181
|
+
--ease-out-expo: cubic-bezier(0.16, 1, 0.3, 1);
|
|
182
|
+
--duration-fast: 120ms;
|
|
183
|
+
--duration-snappy: 180ms;
|
|
184
|
+
--duration-base: 220ms;
|
|
185
|
+
--duration-stride: 240ms;
|
|
186
|
+
--duration-slow: 360ms;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
@keyframes reveal-pop {
|
|
190
|
+
0% {
|
|
191
|
+
opacity: 0;
|
|
192
|
+
transform: scale(0.96) translateY(10px);
|
|
193
|
+
}
|
|
194
|
+
70% {
|
|
195
|
+
opacity: 1;
|
|
196
|
+
transform: scale(1.01) translateY(-2px);
|
|
197
|
+
}
|
|
198
|
+
100% {
|
|
199
|
+
opacity: 1;
|
|
200
|
+
transform: scale(1) translateY(0);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
@keyframes fade-in-once {
|
|
205
|
+
0% {
|
|
206
|
+
opacity: 0;
|
|
207
|
+
transform: translateY(5px);
|
|
208
|
+
}
|
|
209
|
+
100% {
|
|
210
|
+
opacity: 1;
|
|
211
|
+
transform: translateY(0);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
@keyframes holaboss-splash-halo {
|
|
216
|
+
0%,
|
|
217
|
+
100% {
|
|
218
|
+
opacity: 0.35;
|
|
219
|
+
transform: scale(1);
|
|
220
|
+
}
|
|
221
|
+
50% {
|
|
222
|
+
opacity: 0.7;
|
|
223
|
+
transform: scale(1.08);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
@keyframes holaboss-splash-dot {
|
|
228
|
+
0%,
|
|
229
|
+
100% {
|
|
230
|
+
opacity: 0.2;
|
|
231
|
+
transform: translateY(0);
|
|
232
|
+
}
|
|
233
|
+
50% {
|
|
234
|
+
opacity: 1;
|
|
235
|
+
transform: translateY(-1.5px);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/* @property — register theme colors as animatable so theme switches
|
|
240
|
+
interpolate smoothly. */
|
|
241
|
+
@property --background {
|
|
242
|
+
syntax: "<color>";
|
|
243
|
+
inherits: true;
|
|
244
|
+
initial-value: oklch(0.985 0.002 60);
|
|
245
|
+
}
|
|
246
|
+
@property --foreground {
|
|
247
|
+
syntax: "<color>";
|
|
248
|
+
inherits: true;
|
|
249
|
+
initial-value: oklch(0.18 0.015 55);
|
|
250
|
+
}
|
|
251
|
+
@property --primary {
|
|
252
|
+
syntax: "<color>";
|
|
253
|
+
inherits: true;
|
|
254
|
+
initial-value: oklch(0.68 0.21 37);
|
|
255
|
+
}
|
|
256
|
+
@property --info {
|
|
257
|
+
syntax: "<color>";
|
|
258
|
+
inherits: true;
|
|
259
|
+
initial-value: oklch(0.62 0.17 240);
|
|
260
|
+
}
|
|
261
|
+
@property --success {
|
|
262
|
+
syntax: "<color>";
|
|
263
|
+
inherits: true;
|
|
264
|
+
initial-value: oklch(0.58 0.16 148);
|
|
265
|
+
}
|
|
266
|
+
@property --destructive {
|
|
267
|
+
syntax: "<color>";
|
|
268
|
+
inherits: true;
|
|
269
|
+
initial-value: oklch(0.55 0.24 18);
|
|
270
|
+
}
|
|
271
|
+
/* Surface palette — registered so theme switches interpolate the
|
|
272
|
+
whole canvas instead of hard-cutting on most surfaces. Initial
|
|
273
|
+
values mirror the holaos-light defaults. */
|
|
274
|
+
@property --card {
|
|
275
|
+
syntax: "<color>";
|
|
276
|
+
inherits: true;
|
|
277
|
+
initial-value: oklch(0.985 0.002 250);
|
|
278
|
+
}
|
|
279
|
+
@property --popover {
|
|
280
|
+
syntax: "<color>";
|
|
281
|
+
inherits: true;
|
|
282
|
+
initial-value: oklch(1 0 0);
|
|
283
|
+
}
|
|
284
|
+
@property --muted {
|
|
285
|
+
syntax: "<color>";
|
|
286
|
+
inherits: true;
|
|
287
|
+
initial-value: oklch(0.97 0.002 250);
|
|
288
|
+
}
|
|
289
|
+
@property --muted-foreground {
|
|
290
|
+
syntax: "<color>";
|
|
291
|
+
inherits: true;
|
|
292
|
+
initial-value: oklch(0.56 0.005 250);
|
|
293
|
+
}
|
|
294
|
+
@property --accent {
|
|
295
|
+
syntax: "<color>";
|
|
296
|
+
inherits: true;
|
|
297
|
+
initial-value: oklch(0.95 0.002 250);
|
|
298
|
+
}
|
|
299
|
+
@property --secondary {
|
|
300
|
+
syntax: "<color>";
|
|
301
|
+
inherits: true;
|
|
302
|
+
initial-value: oklch(0.97 0.002 250);
|
|
303
|
+
}
|
|
304
|
+
@property --border {
|
|
305
|
+
syntax: "<color>";
|
|
306
|
+
inherits: true;
|
|
307
|
+
initial-value: oklch(0.92 0.003 250);
|
|
308
|
+
}
|
|
309
|
+
@property --ring {
|
|
310
|
+
syntax: "<color>";
|
|
311
|
+
inherits: true;
|
|
312
|
+
initial-value: oklch(0.624 0.229 32);
|
|
313
|
+
}
|
|
314
|
+
@property --sidebar {
|
|
315
|
+
syntax: "<color>";
|
|
316
|
+
inherits: true;
|
|
317
|
+
initial-value: oklch(0.97 0.002 250);
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
/* Token fallbacks — tweakcn themes override these. Anything declared here
|
|
321
|
+
keeps the app renderable during the brief frame before [data-theme] is
|
|
322
|
+
set on <html>, and during theme switches. Themes shadow these. */
|
|
323
|
+
:root {
|
|
324
|
+
--radius: 0.5rem;
|
|
325
|
+
|
|
326
|
+
/* Surface + content. Quiet near-neutral grays with a subtle cool
|
|
327
|
+
undertone; mirrors holaos-light. */
|
|
328
|
+
--background: oklch(1 0 0);
|
|
329
|
+
--foreground: oklch(0.18 0.003 250);
|
|
330
|
+
--card: oklch(0.985 0.002 250);
|
|
331
|
+
--card-foreground: oklch(0.18 0.003 250);
|
|
332
|
+
--popover: oklch(1 0 0);
|
|
333
|
+
--popover-foreground: oklch(0.18 0.003 250);
|
|
334
|
+
--primary: oklch(0.624 0.229 32);
|
|
335
|
+
--primary-foreground: oklch(0.98 0.01 32);
|
|
336
|
+
--secondary: oklch(0.97 0.002 250);
|
|
337
|
+
--secondary-foreground: oklch(0.21 0.003 250);
|
|
338
|
+
--muted: oklch(0.97 0.002 250);
|
|
339
|
+
--muted-foreground: oklch(0.56 0.005 250);
|
|
340
|
+
--accent: oklch(0.95 0.002 250);
|
|
341
|
+
--accent-foreground: oklch(0.18 0.003 250);
|
|
342
|
+
--border: oklch(0.92 0.003 250);
|
|
343
|
+
--input: oklch(0.92 0.003 250);
|
|
344
|
+
--ring: oklch(0.624 0.229 32);
|
|
345
|
+
--sidebar: oklch(0.945 0.002 250);
|
|
346
|
+
--sidebar-foreground: oklch(0.18 0.003 250);
|
|
347
|
+
--sidebar-primary: oklch(0.624 0.229 32);
|
|
348
|
+
--sidebar-primary-foreground: oklch(0.98 0.01 32);
|
|
349
|
+
--sidebar-accent: oklch(0.92 0.002 250);
|
|
350
|
+
--sidebar-accent-foreground: oklch(0.21 0.003 250);
|
|
351
|
+
--sidebar-border: oklch(0.9 0.003 250);
|
|
352
|
+
--sidebar-ring: oklch(0.624 0.229 32);
|
|
353
|
+
--chart-1: oklch(0.646 0.222 41.116);
|
|
354
|
+
--chart-2: oklch(0.6 0.118 184.704);
|
|
355
|
+
--chart-3: oklch(0.398 0.07 227.392);
|
|
356
|
+
--chart-4: oklch(0.828 0.189 84.429);
|
|
357
|
+
--chart-5: oklch(0.769 0.188 70.08);
|
|
358
|
+
|
|
359
|
+
--success: oklch(0.58 0.16 148);
|
|
360
|
+
--warning: oklch(0.82 0.17 83);
|
|
361
|
+
--info: oklch(0.62 0.17 240);
|
|
362
|
+
--scrim: oklch(0.15 0.01 240 / 0.46);
|
|
363
|
+
--destructive: oklch(0.55 0.24 18);
|
|
364
|
+
|
|
365
|
+
/* Foreground colours for tonal CTAs (text/icon on a solid tone-bg
|
|
366
|
+
button or chip). Default to `var(--background)` so contrast
|
|
367
|
+
auto-adapts to theme mode: light themes (bg ≈ white) end up
|
|
368
|
+
with white text — which reads against the typically-darker
|
|
369
|
+
light-mode tones; dark themes (bg ≈ near-black) get dark text,
|
|
370
|
+
which reads against the typically-lighter dark-mode pastels
|
|
371
|
+
most themes ship (catppuccin / nord / one-dark-pro et al.).
|
|
372
|
+
Warning stays anchored dark because amber/yellow is usually
|
|
373
|
+
light in both modes and never plays well with white text.
|
|
374
|
+
Themes that have unusual tones can still override per-tone. */
|
|
375
|
+
--destructive-foreground: var(--background);
|
|
376
|
+
--success-foreground: var(--background);
|
|
377
|
+
--warning-foreground: oklch(0.18 0 0);
|
|
378
|
+
--info-foreground: var(--background);
|
|
379
|
+
|
|
380
|
+
--hairline-alpha: 0.05;
|
|
381
|
+
--shadow-alpha: 0.07;
|
|
382
|
+
|
|
383
|
+
/* Elevated bg for unfocused panels. */
|
|
384
|
+
--background-elevated: color-mix(
|
|
385
|
+
in srgb,
|
|
386
|
+
var(--foreground) 2%,
|
|
387
|
+
var(--background)
|
|
388
|
+
);
|
|
389
|
+
|
|
390
|
+
/* Foreground-on-background opaque blends. Use --fg-N for tinted
|
|
391
|
+
surfaces; Tailwind's bg-foreground/N for transparent overlays. */
|
|
392
|
+
--fg-2: color-mix(in srgb, var(--foreground) 2%, var(--background));
|
|
393
|
+
--fg-4: color-mix(in srgb, var(--foreground) 4%, var(--background));
|
|
394
|
+
--fg-6: color-mix(in srgb, var(--foreground) 6%, var(--background));
|
|
395
|
+
--fg-8: color-mix(in srgb, var(--foreground) 8%, var(--background));
|
|
396
|
+
--fg-12: color-mix(in srgb, var(--foreground) 12%, var(--background));
|
|
397
|
+
--fg-16: color-mix(in srgb, var(--foreground) 16%, var(--background));
|
|
398
|
+
--fg-24: color-mix(in srgb, var(--foreground) 24%, var(--background));
|
|
399
|
+
--fg-32: color-mix(in srgb, var(--foreground) 32%, var(--background));
|
|
400
|
+
--fg-48: color-mix(in srgb, var(--foreground) 48%, var(--background));
|
|
401
|
+
--fg-64: color-mix(in srgb, var(--foreground) 64%, var(--background));
|
|
402
|
+
--fg-80: color-mix(in srgb, var(--foreground) 80%, var(--background));
|
|
403
|
+
--fg-92: color-mix(in srgb, var(--foreground) 92%, var(--background));
|
|
404
|
+
|
|
405
|
+
/* Status text — tinted toward foreground for labels on neutral bg. */
|
|
406
|
+
--success-text: color-mix(in oklab, var(--success) 45%, var(--foreground));
|
|
407
|
+
--destructive-text: color-mix(
|
|
408
|
+
in oklab,
|
|
409
|
+
var(--destructive) 45%,
|
|
410
|
+
var(--foreground)
|
|
411
|
+
);
|
|
412
|
+
--info-text: color-mix(in oklab, var(--info) 45%, var(--foreground));
|
|
413
|
+
|
|
414
|
+
/* Workspace identity tint — neutral gray composed with --background /
|
|
415
|
+
--foreground via color-mix, so dark mode adapts automatically without
|
|
416
|
+
a separate theme override. */
|
|
417
|
+
--workspace-color-gray: oklch(0.55 0.005 270);
|
|
418
|
+
|
|
419
|
+
--workspace-color-gray-bg: color-mix(
|
|
420
|
+
in srgb,
|
|
421
|
+
var(--workspace-color-gray) 14%,
|
|
422
|
+
var(--background)
|
|
423
|
+
);
|
|
424
|
+
--workspace-color-gray-fg: color-mix(
|
|
425
|
+
in oklab,
|
|
426
|
+
var(--workspace-color-gray) 65%,
|
|
427
|
+
var(--foreground)
|
|
428
|
+
);
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
.dark {
|
|
432
|
+
--hairline-alpha: 0.14;
|
|
433
|
+
--shadow-alpha: 0.13;
|
|
434
|
+
|
|
435
|
+
/* Black drops + white hairline ring + white top inset
|
|
436
|
+
(lit-from-above). Mirrors light stack with inverted polarity. */
|
|
437
|
+
--shadow-sm:
|
|
438
|
+
0 1px 1px 0.5px rgba(0, 0, 0, 0.32),
|
|
439
|
+
0 3px 3px -1.5px rgba(0, 0, 0, 0.16),
|
|
440
|
+
0 6px 6px -3px rgba(0, 0, 0, 0.32),
|
|
441
|
+
0 12px 12px -6px rgba(0, 0, 0, 0.32),
|
|
442
|
+
0 24px 24px -12px rgba(0, 0, 0, 0.32),
|
|
443
|
+
0 48px 48px -24px rgba(0, 0, 0, 0.32),
|
|
444
|
+
0 0 0 1px rgba(255, 255, 255, 0.08),
|
|
445
|
+
inset 0 1px 0 0 rgba(255, 255, 255, 0.05);
|
|
446
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@holaboss/ui",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"license": "Apache-2.0",
|
|
5
|
+
"description": "Shared UI library for holaOS — primitives, layouts, and tokens used by app-builder-sdk dashboards.",
|
|
6
|
+
"keywords": [
|
|
7
|
+
"holaboss",
|
|
8
|
+
"ui",
|
|
9
|
+
"design-system",
|
|
10
|
+
"react",
|
|
11
|
+
"shadcn",
|
|
12
|
+
"tailwind",
|
|
13
|
+
"components"
|
|
14
|
+
],
|
|
15
|
+
"repository": {
|
|
16
|
+
"type": "git",
|
|
17
|
+
"url": "https://github.com/holaboss-ai/holaOS.git",
|
|
18
|
+
"directory": "sdk/ui"
|
|
19
|
+
},
|
|
20
|
+
"homepage": "https://github.com/holaboss-ai/holaOS/tree/main/sdk/ui",
|
|
21
|
+
"bugs": "https://github.com/holaboss-ai/holaOS/issues",
|
|
22
|
+
"publishConfig": {
|
|
23
|
+
"access": "public"
|
|
24
|
+
},
|
|
25
|
+
"type": "module",
|
|
26
|
+
"main": "./dist/index.cjs",
|
|
27
|
+
"module": "./dist/index.js",
|
|
28
|
+
"types": "./dist/index.d.ts",
|
|
29
|
+
"exports": {
|
|
30
|
+
".": {
|
|
31
|
+
"import": {
|
|
32
|
+
"types": "./dist/index.d.ts",
|
|
33
|
+
"default": "./dist/index.js"
|
|
34
|
+
},
|
|
35
|
+
"require": {
|
|
36
|
+
"types": "./dist/index.d.cts",
|
|
37
|
+
"default": "./dist/index.cjs"
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
"./tokens.css": "./dist/tokens.css",
|
|
41
|
+
"./themes/holaos.css": "./dist/themes/holaos.css"
|
|
42
|
+
},
|
|
43
|
+
"files": [
|
|
44
|
+
"dist",
|
|
45
|
+
"src",
|
|
46
|
+
"README.md"
|
|
47
|
+
],
|
|
48
|
+
"scripts": {
|
|
49
|
+
"build": "tsdown",
|
|
50
|
+
"clean": "node ../../scripts/remove-paths.mjs dist",
|
|
51
|
+
"typecheck": "tsc --noEmit",
|
|
52
|
+
"test": "tsc --noEmit",
|
|
53
|
+
"prepublishOnly": "bun run build"
|
|
54
|
+
},
|
|
55
|
+
"dependencies": {
|
|
56
|
+
"@base-ui/react": "^1.3.0",
|
|
57
|
+
"class-variance-authority": "^0.7.1",
|
|
58
|
+
"clsx": "^2.1.1",
|
|
59
|
+
"lucide-react": "^0.542.0",
|
|
60
|
+
"tailwind-merge": "^3.5.0"
|
|
61
|
+
},
|
|
62
|
+
"peerDependencies": {
|
|
63
|
+
"react": "^19.0.0",
|
|
64
|
+
"react-dom": "^19.0.0"
|
|
65
|
+
},
|
|
66
|
+
"devDependencies": {
|
|
67
|
+
"@types/react": "^19.1.12",
|
|
68
|
+
"@types/react-dom": "^19.1.9",
|
|
69
|
+
"tsdown": "^0.21.4",
|
|
70
|
+
"typescript": "^5.9.3"
|
|
71
|
+
}
|
|
72
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
// =====================================================================
|
|
2
|
+
// Primitives — holaOS-locked shadcn-style components. Drop these in
|
|
3
|
+
// instead of redefining your own; they are guaranteed to match the
|
|
4
|
+
// workspace canvas (tokens, density, hover affordances).
|
|
5
|
+
// =====================================================================
|
|
6
|
+
|
|
7
|
+
export { Alert, AlertTitle, AlertDescription, AlertAction } from "./primitives/alert.js";
|
|
8
|
+
export { Badge, badgeVariants } from "./primitives/badge.js";
|
|
9
|
+
export { Button, buttonVariants } from "./primitives/button.js";
|
|
10
|
+
export {
|
|
11
|
+
Card,
|
|
12
|
+
CardHeader,
|
|
13
|
+
CardTitle,
|
|
14
|
+
CardDescription,
|
|
15
|
+
CardContent,
|
|
16
|
+
CardFooter,
|
|
17
|
+
CardAction,
|
|
18
|
+
} from "./primitives/card.js";
|
|
19
|
+
export {
|
|
20
|
+
DropdownMenu,
|
|
21
|
+
DropdownMenuPortal,
|
|
22
|
+
DropdownMenuTrigger,
|
|
23
|
+
DropdownMenuContent,
|
|
24
|
+
DropdownMenuGroup,
|
|
25
|
+
DropdownMenuLabel,
|
|
26
|
+
DropdownMenuItem,
|
|
27
|
+
DropdownMenuCheckboxItem,
|
|
28
|
+
DropdownMenuRadioGroup,
|
|
29
|
+
DropdownMenuRadioItem,
|
|
30
|
+
DropdownMenuSeparator,
|
|
31
|
+
DropdownMenuShortcut,
|
|
32
|
+
DropdownMenuSub,
|
|
33
|
+
DropdownMenuSubTrigger,
|
|
34
|
+
DropdownMenuSubContent,
|
|
35
|
+
} from "./primitives/dropdown-menu.js";
|
|
36
|
+
export { EmptyState } from "./primitives/empty-state.js";
|
|
37
|
+
export type { EmptyStateProps } from "./primitives/empty-state.js";
|
|
38
|
+
export { Input } from "./primitives/input.js";
|
|
39
|
+
export { Kbd } from "./primitives/kbd.js";
|
|
40
|
+
export { Label } from "./primitives/label.js";
|
|
41
|
+
export {
|
|
42
|
+
Popover,
|
|
43
|
+
PopoverContent,
|
|
44
|
+
PopoverDescription,
|
|
45
|
+
PopoverHeader,
|
|
46
|
+
PopoverTitle,
|
|
47
|
+
PopoverTrigger,
|
|
48
|
+
} from "./primitives/popover.js";
|
|
49
|
+
export {
|
|
50
|
+
Select,
|
|
51
|
+
SelectContent,
|
|
52
|
+
SelectGroup,
|
|
53
|
+
SelectItem,
|
|
54
|
+
SelectLabel,
|
|
55
|
+
SelectScrollDownButton,
|
|
56
|
+
SelectScrollUpButton,
|
|
57
|
+
SelectSeparator,
|
|
58
|
+
SelectTrigger,
|
|
59
|
+
SelectValue,
|
|
60
|
+
} from "./primitives/select.js";
|
|
61
|
+
export { StatusDot } from "./primitives/status-dot.js";
|
|
62
|
+
export { Switch } from "./primitives/switch.js";
|
|
63
|
+
export {
|
|
64
|
+
Tabs,
|
|
65
|
+
TabsList,
|
|
66
|
+
TabsTrigger,
|
|
67
|
+
TabsContent,
|
|
68
|
+
tabsListVariants,
|
|
69
|
+
} from "./primitives/tabs.js";
|
|
70
|
+
export {
|
|
71
|
+
Tooltip,
|
|
72
|
+
TooltipTrigger,
|
|
73
|
+
TooltipContent,
|
|
74
|
+
TooltipProvider,
|
|
75
|
+
} from "./primitives/tooltip.js";
|
|
76
|
+
|
|
77
|
+
// =====================================================================
|
|
78
|
+
// Layouts — composition primitives. Use these for page chrome,
|
|
79
|
+
// loading / empty / error states, and dashboard structure. The
|
|
80
|
+
// majority of visual drift between agent-built apps happens at this
|
|
81
|
+
// layer, so reach for these before hand-rolling a similar layout.
|
|
82
|
+
// =====================================================================
|
|
83
|
+
|
|
84
|
+
export { DashboardShell } from "./layouts/dashboard-shell.js";
|
|
85
|
+
export type { DashboardShellProps } from "./layouts/dashboard-shell.js";
|
|
86
|
+
export { DataTable } from "./layouts/data-table.js";
|
|
87
|
+
export type {
|
|
88
|
+
DataTableColumn,
|
|
89
|
+
DataTableProps,
|
|
90
|
+
} from "./layouts/data-table.js";
|
|
91
|
+
export { ErrorState } from "./layouts/error-state.js";
|
|
92
|
+
export type { ErrorStateProps } from "./layouts/error-state.js";
|
|
93
|
+
export { FilterBar } from "./layouts/filter-bar.js";
|
|
94
|
+
export type { FilterBarProps } from "./layouts/filter-bar.js";
|
|
95
|
+
export { LoadingState } from "./layouts/loading-state.js";
|
|
96
|
+
export type { LoadingStateProps } from "./layouts/loading-state.js";
|
|
97
|
+
export { PageHeader } from "./layouts/page-header.js";
|
|
98
|
+
export type { PageHeaderProps } from "./layouts/page-header.js";
|
|
99
|
+
export { Section } from "./layouts/section.js";
|
|
100
|
+
export type { SectionProps } from "./layouts/section.js";
|
|
101
|
+
export { StatPill } from "./layouts/stat-pill.js";
|
|
102
|
+
export type { StatPillProps } from "./layouts/stat-pill.js";
|
|
103
|
+
|
|
104
|
+
// =====================================================================
|
|
105
|
+
// Utilities
|
|
106
|
+
// =====================================================================
|
|
107
|
+
|
|
108
|
+
export { cn } from "./lib/utils.js";
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
|
|
3
|
+
import { cn } from "../lib/utils.js";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Canonical chrome for a workspace-pane dashboard. Two slots: a top bar
|
|
7
|
+
* (header, actions) and a scrollable content region underneath. Apps
|
|
8
|
+
* should wrap their dashboard root with this so density, padding, and
|
|
9
|
+
* scroll behavior stay consistent across the workspace.
|
|
10
|
+
*
|
|
11
|
+
* The shell does not manage its own width; it fills its parent (the
|
|
12
|
+
* pane). Vertical scroll lives on `content` so the header stays pinned.
|
|
13
|
+
*/
|
|
14
|
+
export interface DashboardShellProps {
|
|
15
|
+
/** Sticky top region. Typically a `<PageHeader>`. */
|
|
16
|
+
header?: ReactNode;
|
|
17
|
+
/** Main scrollable content. */
|
|
18
|
+
children: ReactNode;
|
|
19
|
+
/** Extra class on the outer flex container. */
|
|
20
|
+
className?: string;
|
|
21
|
+
/** Extra class on the scrollable content region. */
|
|
22
|
+
contentClassName?: string;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function DashboardShell({
|
|
26
|
+
header,
|
|
27
|
+
children,
|
|
28
|
+
className,
|
|
29
|
+
contentClassName,
|
|
30
|
+
}: DashboardShellProps) {
|
|
31
|
+
return (
|
|
32
|
+
<div className={cn("flex h-full min-h-0 flex-col bg-background", className)}>
|
|
33
|
+
{header ? (
|
|
34
|
+
<div className="shrink-0 border-b border-border bg-background">
|
|
35
|
+
{header}
|
|
36
|
+
</div>
|
|
37
|
+
) : null}
|
|
38
|
+
<div className={cn("min-h-0 flex-1 overflow-y-auto", contentClassName)}>
|
|
39
|
+
{children}
|
|
40
|
+
</div>
|
|
41
|
+
</div>
|
|
42
|
+
);
|
|
43
|
+
}
|