create-visualbuild-app 0.1.0 → 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 (44) hide show
  1. package/README.md +919 -58
  2. package/docs/user-guide.md +759 -0
  3. package/package.json +92 -85
  4. package/scripts/create-builder-app.mjs +513 -501
  5. package/scripts/vb-dev.mjs +41 -32
  6. package/scripts/vb-generate.mjs +332 -224
  7. package/templates/default/app/.vercelignore +6 -0
  8. package/templates/default/app/README.md +56 -21
  9. package/templates/default/app/visualbuild/components.json +3 -0
  10. package/templates/default/app/visualbuild/config.d.ts +48 -0
  11. package/templates/default/app/visualbuild.config.ts +38 -0
  12. package/templates/default/builder/README.md +37 -21
  13. package/visual-app-builder/server/parseReactPage.ts +776 -571
  14. package/visual-app-builder/shared/createReactComponentSource.d.mts +2 -0
  15. package/visual-app-builder/shared/createReactComponentSource.mjs +45 -0
  16. package/visual-app-builder/shared/generateReactSource.d.mts +57 -37
  17. package/visual-app-builder/shared/generateReactSource.mjs +608 -443
  18. package/visual-app-builder/shared/npmBuildCommand.d.mts +17 -0
  19. package/visual-app-builder/shared/npmBuildCommand.mjs +26 -0
  20. package/visual-app-builder/shared/syncCustomComponentSource.d.mts +13 -0
  21. package/visual-app-builder/shared/syncCustomComponentSource.mjs +345 -0
  22. package/visual-app-builder/shared/vercelDeployment.d.mts +31 -0
  23. package/visual-app-builder/shared/vercelDeployment.mjs +266 -0
  24. package/visual-app-builder/shared/visualbuildConfig.d.mts +144 -0
  25. package/visual-app-builder/shared/visualbuildConfig.mjs +578 -0
  26. package/visual-app-builder/src/App.tsx +1090 -874
  27. package/visual-app-builder/src/components/Canvas.tsx +1116 -1059
  28. package/visual-app-builder/src/components/CodePanel.tsx +1147 -812
  29. package/visual-app-builder/src/components/ComponentSidebar.tsx +365 -302
  30. package/visual-app-builder/src/components/DeploymentModal.tsx +295 -0
  31. package/visual-app-builder/src/components/PageSwitcher.tsx +133 -133
  32. package/visual-app-builder/src/components/ProjectExplorer.tsx +1054 -1054
  33. package/visual-app-builder/src/components/PropertiesPanel.tsx +792 -692
  34. package/visual-app-builder/src/components/Topbar.tsx +257 -128
  35. package/visual-app-builder/src/data/componentRegistry.tsx +613 -292
  36. package/visual-app-builder/src/data/tailwindClassCatalog.ts +95 -0
  37. package/visual-app-builder/src/index.css +383 -111
  38. package/visual-app-builder/src/stores/useAppStore.ts +2385 -1265
  39. package/visual-app-builder/src/theme.ts +71 -0
  40. package/visual-app-builder/src/types/index.ts +350 -261
  41. package/visual-app-builder/src/utils/codegen.ts +90 -66
  42. package/visual-app-builder/src/utils/deployment.ts +54 -0
  43. package/visual-app-builder/src/utils/projectPersistence.ts +218 -177
  44. package/visual-app-builder/vite.config.ts +1946 -1479
@@ -0,0 +1,95 @@
1
+ const colorFamilies = [
2
+ 'slate',
3
+ 'gray',
4
+ 'zinc',
5
+ 'neutral',
6
+ 'stone',
7
+ 'red',
8
+ 'orange',
9
+ 'amber',
10
+ 'yellow',
11
+ 'lime',
12
+ 'green',
13
+ 'emerald',
14
+ 'teal',
15
+ 'cyan',
16
+ 'sky',
17
+ 'blue',
18
+ 'indigo',
19
+ 'violet',
20
+ 'purple',
21
+ 'fuchsia',
22
+ 'pink',
23
+ 'rose',
24
+ ] as const
25
+
26
+ const colorShades = [
27
+ '50',
28
+ '100',
29
+ '200',
30
+ '300',
31
+ '400',
32
+ '500',
33
+ '600',
34
+ '700',
35
+ '800',
36
+ '900',
37
+ '950',
38
+ ] as const
39
+
40
+ const colorUtilityPrefixes = [
41
+ 'text',
42
+ 'bg',
43
+ 'border',
44
+ 'outline',
45
+ 'ring',
46
+ 'divide',
47
+ 'decoration',
48
+ 'placeholder',
49
+ 'caret',
50
+ 'accent',
51
+ 'fill',
52
+ 'stroke',
53
+ 'from',
54
+ 'via',
55
+ 'to',
56
+ ] as const
57
+
58
+ const semanticColors = [
59
+ 'inherit',
60
+ 'current',
61
+ 'transparent',
62
+ 'black',
63
+ 'white',
64
+ ] as const
65
+
66
+ export const tailwindColorClassNames = [
67
+ ...colorUtilityPrefixes.flatMap((utility) =>
68
+ colorFamilies.flatMap((family) =>
69
+ colorShades.map((shade) => `${utility}-${family}-${shade}`),
70
+ ),
71
+ ),
72
+ ...colorUtilityPrefixes.flatMap((utility) =>
73
+ semanticColors.map((color) => `${utility}-${color}`),
74
+ ),
75
+ ]
76
+
77
+ export function getTailwindColorClassSuggestions(
78
+ token: string,
79
+ limit = 64,
80
+ ) {
81
+ const variantSeparator = token.lastIndexOf(':')
82
+ const variantPrefix =
83
+ variantSeparator >= 0 ? token.slice(0, variantSeparator + 1) : ''
84
+ const utilityToken =
85
+ variantSeparator >= 0 ? token.slice(variantSeparator + 1) : token
86
+
87
+ if (!utilityToken) {
88
+ return []
89
+ }
90
+
91
+ return tailwindColorClassNames
92
+ .filter((className) => className.startsWith(utilityToken))
93
+ .slice(0, limit)
94
+ .map((className) => `${variantPrefix}${className}`)
95
+ }
@@ -1,111 +1,383 @@
1
- @import "tailwindcss" source(none);
2
- @source ".";
3
- @source "../.visualbuild-runtime-classes.html";
4
-
5
- *,
6
- *::before,
7
- *::after {
8
- box-sizing: border-box;
9
- }
10
-
11
- html,
12
- body,
13
- #root {
14
- width: 100%;
15
- height: 100%;
16
- overflow: hidden;
17
- }
18
-
19
- body {
20
- font-family: "Inter", system-ui, sans-serif;
21
- -webkit-font-smoothing: antialiased;
22
- }
23
-
24
- [data-vb-editor-node="true"] {
25
- cursor: pointer;
26
- }
27
-
28
- [data-vb-editor-node="true"]:hover,
29
- [data-vb-hovered="true"] {
30
- outline: 2px solid rgb(96 165 250 / 0.95) !important;
31
- outline-offset: -2px;
32
- box-shadow: 0 0 0 1px rgb(96 165 250 / 0.25);
33
- }
34
-
35
- [data-vb-selected="true"] {
36
- outline: 2px solid rgb(37 99 235) !important;
37
- outline-offset: -2px;
38
- box-shadow: 0 0 0 1px rgb(37 99 235 / 0.25);
39
- }
40
-
41
- [data-vb-drop-target="true"] {
42
- outline: 2px solid rgb(59 130 246) !important;
43
- outline-offset: -2px;
44
- }
45
-
46
- [data-vb-dragging="true"] {
47
- cursor: grabbing;
48
- }
49
-
50
- .vb-empty-node-placeholder {
51
- pointer-events: none;
52
- display: flex;
53
- min-height: 2rem;
54
- width: 100%;
55
- align-items: center;
56
- justify-content: center;
57
- border: 1px dashed rgb(147 197 253 / 0.85);
58
- border-radius: 6px;
59
- background: rgb(239 246 255 / 0.72);
60
- color: rgb(37 99 235);
61
- font-size: 11px;
62
- font-weight: 500;
63
- line-height: 1;
64
- }
65
-
66
- .vb-canvas-editor-frame {
67
- outline: 1px solid rgb(229 231 235);
68
- outline-offset: -1px;
69
- }
70
-
71
- .vb-canvas-editor-frame[data-vb-canvas-over="true"] {
72
- outline: 2px solid rgb(59 130 246);
73
- outline-offset: -2px;
74
- box-shadow: inset 0 0 0 2px rgb(147 197 253 / 0.45);
75
- }
76
-
77
- select option {
78
- color: #111827;
79
- background: #ffffff;
80
- }
81
-
82
- /* Scrollbars */
83
-
84
- ::-webkit-scrollbar {
85
- width: 4px;
86
- height: 4px;
87
- }
88
-
89
- ::-webkit-scrollbar-track {
90
- background: transparent;
91
- }
92
-
93
- ::-webkit-scrollbar-thumb {
94
- background: #2d3139;
95
- border-radius: 999px;
96
- }
97
-
98
- ::-webkit-scrollbar-thumb:hover {
99
- background: #3d4249;
100
- }
101
-
102
-
103
- @theme {
104
- --color-canvas: #f8f9fa;
105
- --color-sidebar: #1a1d23;
106
- --color-panel: #1a1d23;
107
- --color-topbar: #13151a;
108
-
109
- --color-accent: #4f6ef7;
110
- --color-accent-hover: #3d5ce0;
111
- }
1
+ @import "tailwindcss" source(none);
2
+ @source ".";
3
+ @source "../.visualbuild-runtime-classes.html";
4
+ @source inline("{text,bg,border,outline,ring,divide,decoration,placeholder,caret,accent,fill,stroke,from,via,to}-{slate,gray,zinc,neutral,stone,red,orange,amber,yellow,lime,green,emerald,teal,cyan,sky,blue,indigo,violet,purple,fuchsia,pink,rose}-{50,100,200,300,400,500,600,700,800,900,950}");
5
+ @source inline("{text,bg,border,outline,ring,divide,decoration,placeholder,caret,accent,fill,stroke,from,via,to}-{inherit,current,transparent,black,white}");
6
+
7
+ *,
8
+ *::before,
9
+ *::after {
10
+ box-sizing: border-box;
11
+ }
12
+
13
+ html,
14
+ body,
15
+ #root {
16
+ width: 100%;
17
+ height: 100%;
18
+ overflow: hidden;
19
+ }
20
+
21
+ body {
22
+ font-family: "Inter", system-ui, sans-serif;
23
+ -webkit-font-smoothing: antialiased;
24
+ }
25
+
26
+ :root,
27
+ html[data-visualbuild-theme="default"] {
28
+ color-scheme: dark;
29
+ --vb-app-bg: #030712;
30
+ --vb-topbar: #13151a;
31
+ --vb-panel: #1a1d23;
32
+ --vb-panel-alt: #101318;
33
+ --vb-code: #0b0d11;
34
+ --vb-control: rgb(255 255 255 / 0.055);
35
+ --vb-control-hover: rgb(255 255 255 / 0.1);
36
+ --vb-border: rgb(255 255 255 / 0.075);
37
+ --vb-text: #f3f4f6;
38
+ --vb-text-secondary: #c4c9d1;
39
+ --vb-text-muted: #858b96;
40
+ --vb-text-faint: #505662;
41
+ --vb-accent-theme: #4f6ef7;
42
+ --vb-selected: #111827;
43
+ --vb-selected-text: #ffffff;
44
+ --vb-workspace: #eef1f4;
45
+ --vb-toolbar: #ffffff;
46
+ --vb-toolbar-border: #e5e7eb;
47
+ --vb-toolbar-text: #6b7280;
48
+ --vb-scrollbar: #2d3139;
49
+ --vb-overlay: rgb(3 7 18 / 0.7);
50
+ --vb-success-text: #6ee7b7;
51
+ --vb-warning-text: #fde68a;
52
+ --vb-error-text: #fecaca;
53
+ --vb-link-text: #93c5fd;
54
+ }
55
+
56
+ html[data-visualbuild-theme="codex-dark"] {
57
+ color-scheme: dark;
58
+ --vb-app-bg: #171717;
59
+ --vb-topbar: #181818;
60
+ --vb-panel: #202020;
61
+ --vb-panel-alt: #1b1b1b;
62
+ --vb-code: #151515;
63
+ --vb-control: rgb(255 255 255 / 0.06);
64
+ --vb-control-hover: rgb(255 255 255 / 0.11);
65
+ --vb-border: #343434;
66
+ --vb-text: #f2f2f2;
67
+ --vb-text-secondary: #c7c7c7;
68
+ --vb-text-muted: #929292;
69
+ --vb-text-faint: #686868;
70
+ --vb-accent-theme: #8b8bff;
71
+ --vb-selected: #303030;
72
+ --vb-selected-text: #ffffff;
73
+ --vb-workspace: #252525;
74
+ --vb-toolbar: #202020;
75
+ --vb-toolbar-border: #363636;
76
+ --vb-toolbar-text: #a6a6a6;
77
+ --vb-scrollbar: #464646;
78
+ --vb-overlay: rgb(0 0 0 / 0.68);
79
+ }
80
+
81
+ html[data-visualbuild-theme="vs-dark"] {
82
+ color-scheme: dark;
83
+ --vb-app-bg: #1e1e1e;
84
+ --vb-topbar: #181818;
85
+ --vb-panel: #252526;
86
+ --vb-panel-alt: #1f1f1f;
87
+ --vb-code: #1e1e1e;
88
+ --vb-control: #313131;
89
+ --vb-control-hover: #3c3c3c;
90
+ --vb-border: #3c3c3c;
91
+ --vb-text: #cccccc;
92
+ --vb-text-secondary: #b8b8b8;
93
+ --vb-text-muted: #8b8b8b;
94
+ --vb-text-faint: #666666;
95
+ --vb-accent-theme: #007acc;
96
+ --vb-selected: #094771;
97
+ --vb-selected-text: #ffffff;
98
+ --vb-workspace: #2a2a2a;
99
+ --vb-toolbar: #252526;
100
+ --vb-toolbar-border: #3c3c3c;
101
+ --vb-toolbar-text: #b8b8b8;
102
+ --vb-scrollbar: #5a5a5a;
103
+ --vb-overlay: rgb(0 0 0 / 0.68);
104
+ }
105
+
106
+ html[data-visualbuild-theme="vs-light"] {
107
+ color-scheme: light;
108
+ --vb-app-bg: #ffffff;
109
+ --vb-topbar: #f3f3f3;
110
+ --vb-panel: #f3f3f3;
111
+ --vb-panel-alt: #f8f8f8;
112
+ --vb-code: #ffffff;
113
+ --vb-control: #ffffff;
114
+ --vb-control-hover: #e8e8e8;
115
+ --vb-border: #d4d4d4;
116
+ --vb-text: #1f1f1f;
117
+ --vb-text-secondary: #3f3f46;
118
+ --vb-text-muted: #616161;
119
+ --vb-text-faint: #8a8a8a;
120
+ --vb-accent-theme: #007acc;
121
+ --vb-selected: #007acc;
122
+ --vb-selected-text: #ffffff;
123
+ --vb-workspace: #e9eaec;
124
+ --vb-toolbar: #ffffff;
125
+ --vb-toolbar-border: #d4d4d4;
126
+ --vb-toolbar-text: #52525b;
127
+ --vb-scrollbar: #b8b8b8;
128
+ --vb-overlay: rgb(0 0 0 / 0.38);
129
+ --vb-success-text: #047857;
130
+ --vb-warning-text: #92400e;
131
+ --vb-error-text: #b91c1c;
132
+ --vb-link-text: #0369a1;
133
+ }
134
+
135
+ .vb-editor-shell {
136
+ background: var(--vb-app-bg) !important;
137
+ color: var(--vb-text) !important;
138
+ }
139
+
140
+ [data-vb-editor-chrome] {
141
+ --color-accent: var(--vb-accent-theme);
142
+ --color-accent-hover: color-mix(
143
+ in srgb,
144
+ var(--vb-accent-theme) 82%,
145
+ black
146
+ );
147
+ }
148
+
149
+ [data-vb-editor-chrome].bg-topbar,
150
+ [data-vb-editor-chrome] .bg-topbar {
151
+ background-color: var(--vb-topbar) !important;
152
+ }
153
+
154
+ [data-vb-editor-chrome].bg-panel,
155
+ [data-vb-editor-chrome] .bg-panel,
156
+ [data-vb-editor-chrome] .bg-sidebar,
157
+ [data-vb-editor-chrome] aside {
158
+ background-color: var(--vb-panel) !important;
159
+ }
160
+
161
+ [data-vb-editor-chrome] [class~="bg-[#101318]"],
162
+ [data-vb-editor-chrome][class~="bg-[#101318]"],
163
+ [data-vb-editor-chrome] [class~="bg-[#15181e]"],
164
+ [data-vb-editor-chrome] [class~="bg-[#181b21]"],
165
+ [data-vb-editor-chrome] [class~="bg-[#191d24]"],
166
+ [data-vb-editor-chrome] [class~="bg-[#171a20]"] {
167
+ background-color: var(--vb-panel-alt) !important;
168
+ }
169
+
170
+ [data-vb-editor-chrome] [class~="bg-[#0b0d11]"],
171
+ [data-vb-editor-chrome] pre,
172
+ [data-vb-editor-chrome] textarea[class*="font-mono"] {
173
+ background-color: var(--vb-code) !important;
174
+ }
175
+
176
+ [data-vb-editor-chrome] input,
177
+ [data-vb-editor-chrome] textarea,
178
+ [data-vb-editor-chrome] select,
179
+ [data-vb-editor-chrome] [class~="bg-[#11141a]"],
180
+ [data-vb-editor-chrome] [class~="bg-[#11151b]"],
181
+ [data-vb-editor-chrome] [class~="bg-[#11151c]"],
182
+ [data-vb-editor-chrome] [class~="bg-black/10"],
183
+ [data-vb-editor-chrome] [class~="bg-black/20"],
184
+ [data-vb-editor-chrome] [class~="bg-white/[0.03]"],
185
+ [data-vb-editor-chrome] [class~="bg-white/[0.04]"],
186
+ [data-vb-editor-chrome] [class~="bg-white/[0.05]"],
187
+ [data-vb-editor-chrome] [class~="bg-white/[0.06]"],
188
+ [data-vb-editor-chrome] [class~="bg-white/[0.07]"],
189
+ [data-vb-editor-chrome] [class~="bg-white/[0.08]"],
190
+ [data-vb-editor-chrome] [class~="bg-white/[0.1]"] {
191
+ background-color: var(--vb-control) !important;
192
+ }
193
+
194
+ [data-vb-editor-chrome] input,
195
+ [data-vb-editor-chrome] textarea,
196
+ [data-vb-editor-chrome] select {
197
+ color: var(--vb-text) !important;
198
+ border-color: var(--vb-border) !important;
199
+ }
200
+
201
+ [data-vb-editor-chrome] [class~="text-gray-100"],
202
+ [data-vb-editor-chrome] [class~="text-gray-200"],
203
+ [data-vb-editor-chrome] [class~="text-gray-300"] {
204
+ color: var(--vb-text-secondary) !important;
205
+ }
206
+
207
+ [data-vb-editor-chrome] [class~="text-gray-400"],
208
+ [data-vb-editor-chrome] [class~="text-gray-500"] {
209
+ color: var(--vb-text-muted) !important;
210
+ }
211
+
212
+ [data-vb-editor-chrome] [class~="text-gray-600"],
213
+ [data-vb-editor-chrome] [class~="text-gray-700"] {
214
+ color: var(--vb-text-faint) !important;
215
+ }
216
+
217
+ html[data-visualbuild-theme="vs-light"]
218
+ [data-vb-editor-chrome]
219
+ [class~="text-white"]:not([class*="bg-blue-"]):not([class*="bg-red-"]):not([class*="bg-accent"]):not([class*="bg-emerald-"]) {
220
+ color: var(--vb-text) !important;
221
+ }
222
+
223
+ [data-vb-editor-chrome] [class*="border-white/"],
224
+ [data-vb-editor-chrome][class*="border-white/"],
225
+ [data-vb-editor-chrome] [class~="border-gray-200"] {
226
+ border-color: var(--vb-border) !important;
227
+ }
228
+
229
+ [data-vb-editor-chrome] .text-accent {
230
+ color: var(--vb-accent-theme) !important;
231
+ }
232
+
233
+ [data-vb-editor-chrome] .bg-accent {
234
+ background-color: var(--vb-accent-theme) !important;
235
+ }
236
+
237
+ [data-vb-editor-chrome] .vb-deploy-success-text {
238
+ color: var(--vb-success-text) !important;
239
+ }
240
+
241
+ [data-vb-editor-chrome] .vb-deploy-warning-text {
242
+ color: var(--vb-warning-text) !important;
243
+ }
244
+
245
+ [data-vb-editor-chrome] .vb-deploy-error-text {
246
+ color: var(--vb-error-text) !important;
247
+ }
248
+
249
+ [data-vb-editor-chrome] .vb-deploy-link-text {
250
+ color: var(--vb-link-text) !important;
251
+ }
252
+
253
+ [data-vb-editor-chrome] [class~="bg-accent/20"],
254
+ [data-vb-editor-chrome] [class~="bg-accent/30"] {
255
+ background-color: color-mix(
256
+ in srgb,
257
+ var(--vb-accent-theme) 22%,
258
+ transparent
259
+ ) !important;
260
+ }
261
+
262
+ [data-vb-editor-chrome] option {
263
+ color: var(--vb-text);
264
+ background: var(--vb-panel-alt);
265
+ }
266
+
267
+ .vb-canvas-workspace {
268
+ background-color: var(--vb-workspace) !important;
269
+ }
270
+
271
+ .vb-canvas-toolbar {
272
+ background-color: var(--vb-toolbar) !important;
273
+ border-color: var(--vb-toolbar-border) !important;
274
+ color: var(--vb-toolbar-text);
275
+ }
276
+
277
+ .vb-canvas-toolbar button {
278
+ color: var(--vb-toolbar-text) !important;
279
+ }
280
+
281
+ .vb-canvas-toolbar button[data-vb-active="true"] {
282
+ color: var(--vb-selected-text) !important;
283
+ background-color: var(--vb-selected) !important;
284
+ }
285
+
286
+ .vb-editor-shell,
287
+ [data-vb-editor-chrome],
288
+ .vb-canvas-workspace,
289
+ .vb-canvas-toolbar {
290
+ transition:
291
+ background-color 140ms ease,
292
+ border-color 140ms ease,
293
+ color 140ms ease;
294
+ }
295
+
296
+ [data-vb-editor-node="true"] {
297
+ cursor: pointer;
298
+ }
299
+
300
+ [data-vb-editor-node="true"]:hover,
301
+ [data-vb-hovered="true"] {
302
+ outline: 2px solid rgb(96 165 250 / 0.95) !important;
303
+ outline-offset: -2px;
304
+ box-shadow: 0 0 0 1px rgb(96 165 250 / 0.25);
305
+ }
306
+
307
+ [data-vb-selected="true"] {
308
+ outline: 2px solid rgb(37 99 235) !important;
309
+ outline-offset: -2px;
310
+ box-shadow: 0 0 0 1px rgb(37 99 235 / 0.25);
311
+ }
312
+
313
+ [data-vb-drop-target="true"] {
314
+ outline: 2px solid rgb(59 130 246) !important;
315
+ outline-offset: -2px;
316
+ }
317
+
318
+ [data-vb-dragging="true"] {
319
+ cursor: grabbing;
320
+ }
321
+
322
+ .vb-empty-node-placeholder {
323
+ pointer-events: none;
324
+ display: flex;
325
+ min-height: 2rem;
326
+ width: 100%;
327
+ align-items: center;
328
+ justify-content: center;
329
+ border: 1px dashed rgb(147 197 253 / 0.85);
330
+ border-radius: 6px;
331
+ background: rgb(239 246 255 / 0.72);
332
+ color: rgb(37 99 235);
333
+ font-size: 11px;
334
+ font-weight: 500;
335
+ line-height: 1;
336
+ }
337
+
338
+ .vb-canvas-editor-frame {
339
+ outline: 1px solid rgb(229 231 235);
340
+ outline-offset: -1px;
341
+ }
342
+
343
+ .vb-canvas-editor-frame[data-vb-canvas-over="true"] {
344
+ outline: 2px solid rgb(59 130 246);
345
+ outline-offset: -2px;
346
+ box-shadow: inset 0 0 0 2px rgb(147 197 253 / 0.45);
347
+ }
348
+
349
+ select option {
350
+ color: #111827;
351
+ background: #ffffff;
352
+ }
353
+
354
+ /* Scrollbars */
355
+
356
+ ::-webkit-scrollbar {
357
+ width: 4px;
358
+ height: 4px;
359
+ }
360
+
361
+ ::-webkit-scrollbar-track {
362
+ background: transparent;
363
+ }
364
+
365
+ ::-webkit-scrollbar-thumb {
366
+ background: var(--vb-scrollbar);
367
+ border-radius: 999px;
368
+ }
369
+
370
+ ::-webkit-scrollbar-thumb:hover {
371
+ background: color-mix(in srgb, var(--vb-scrollbar) 78%, var(--vb-text));
372
+ }
373
+
374
+
375
+ @theme {
376
+ --color-canvas: #f8f9fa;
377
+ --color-sidebar: #1a1d23;
378
+ --color-panel: #1a1d23;
379
+ --color-topbar: #13151a;
380
+
381
+ --color-accent: #4f6ef7;
382
+ --color-accent-hover: #3d5ce0;
383
+ }