@nocobase/app-template-default 1.0.0-beta.58 → 1.0.0-beta.60

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 (72) hide show
  1. package/AGENTS.md +28 -25
  2. package/README.MD +7 -57
  3. package/client/agent-annotations-host.ts +8 -2
  4. package/client/app.ts +0 -2
  5. package/client/components/brand-loading-mark.tsx +46 -0
  6. package/client/components/brand-mark-geometry.ts +7 -0
  7. package/client/components/brand-spinner.tsx +22 -0
  8. package/client/components/brand-watermark.tsx +32 -0
  9. package/client/components/loading.tsx +4 -3
  10. package/client/components/route-overlay.tsx +15 -4
  11. package/client/components/status-badge.tsx +29 -0
  12. package/client/components/ui/alert-dialog.tsx +186 -0
  13. package/client/components/ui/card.tsx +102 -0
  14. package/client/components/ui/dialog.tsx +2 -2
  15. package/client/components/ui/radio-group.tsx +35 -0
  16. package/client/components/ui/spinner.tsx +2 -20
  17. package/client/components/ui/toast.tsx +3 -2
  18. package/client/extensions/nocobase-file-component-ui/components/file-upload-field.tsx +3 -3
  19. package/client/extensions/nocobase-inbox/inbox-item.tsx +4 -3
  20. package/client/layouts/app-layout.tsx +8 -28
  21. package/client/layouts/components/app-sidebar.tsx +4 -4
  22. package/client/layouts/components/header-actions.tsx +3 -36
  23. package/client/layouts/index.ts +0 -1
  24. package/client/lib/toaster.ts +1 -1
  25. package/client/locales/en-US.ts +8 -164
  26. package/client/locales/system/en-US.ts +344 -0
  27. package/client/locales/system/zh-CN.ts +320 -0
  28. package/client/locales/zh-CN.ts +3 -155
  29. package/client/pages/auth/login.tsx +1 -0
  30. package/client/pages/auth/shared.tsx +9 -9
  31. package/client/pages/home/capabilities.ts +52 -0
  32. package/client/pages/home/index.tsx +190 -0
  33. package/client/pages/home/prompt-dialog.tsx +122 -0
  34. package/client/pages/home/use-copy.ts +38 -0
  35. package/client/plugins.ts +2 -2
  36. package/client/routes.ts +5 -11
  37. package/client/routing/app-router.tsx +5 -55
  38. package/client/routing/route-navigation.ts +1 -1
  39. package/client/styles.css +244 -0
  40. package/client/theme/theme-settings.tsx +22 -20
  41. package/client/theme/themes/compact.css +34 -16
  42. package/client/theme/themes/default.css +34 -16
  43. package/eslint.config.js +0 -13
  44. package/index.html +48 -16
  45. package/package.json +23 -27
  46. package/tests/components/app-layout-routes.test.tsx +1 -1
  47. package/tests/components/home.test.tsx +174 -0
  48. package/tests/components/inbox.test.tsx +0 -19
  49. package/tests/components/layout-i18n.test.tsx +5 -92
  50. package/tests/components/primitive-labels.test.tsx +61 -1
  51. package/tests/fixtures/theme-tokens.html +1 -1
  52. package/tests/fixtures/theme-tokens.tsx +7 -0
  53. package/tests/logic/app-server.test.ts +0 -15
  54. package/tests/logic/client-plugin-registry.test.ts +0 -21
  55. package/tests/logic/client-routes.test.ts +2 -6
  56. package/tests/logic/client-shell.test.tsx +11 -107
  57. package/tests/logic/client-theme.test.tsx +17 -1
  58. package/tests/logic/config.test.ts +0 -1
  59. package/tests/logic/plugin-commands.test.ts +1 -1
  60. package/tsconfig.json +1 -4
  61. package/tsconfig.server.json +1 -6
  62. package/vitest.config.ts +1 -8
  63. package/client/components/inbox-badge.ts +0 -49
  64. package/client/components/inbox-button.tsx +0 -132
  65. package/client/components/inbox-header-button.tsx +0 -25
  66. package/client/layouts/components/surface-empty.tsx +0 -35
  67. package/client/layouts/settings-layout.tsx +0 -172
  68. package/client/pages/home.tsx +0 -16
  69. package/server/config/workflow.ts +0 -24
  70. package/tests/logic/client-settings.test.tsx +0 -841
  71. package/tests/logic/dev-routes-production-build.test.ts +0 -168
  72. package/tests/logic/plugin-page-authz.test.ts +0 -53
package/client/styles.css CHANGED
@@ -8,6 +8,21 @@
8
8
 
9
9
  @custom-variant dark (&:is(.dark *));
10
10
 
11
+ /* The stationary brand and a constant orbit read as loading at every size. */
12
+ @keyframes nocobase-loading-orbit {
13
+ to {
14
+ transform: rotate(360deg);
15
+ }
16
+ }
17
+ .nocobase-loading-orbit {
18
+ transform-origin: 32px 32px;
19
+ }
20
+ @media (prefers-reduced-motion: no-preference) {
21
+ .nocobase-loading-orbit {
22
+ animation: nocobase-loading-orbit 1.1s linear infinite;
23
+ }
24
+ }
25
+
11
26
  @theme {
12
27
  --font-heading: var(--font-sans);
13
28
  /* These names are implemented below as runtime-variable utilities. */
@@ -120,3 +135,232 @@
120
135
  [data-slot='toast-viewport'] {
121
136
  z-index: 100;
122
137
  }
138
+
139
+ /* Application-wide interaction and badge treatment, outside generated primitives. */
140
+ @layer base {
141
+ :is(
142
+ button,
143
+ [role='button'],
144
+ [role='menuitem'],
145
+ [role='option'],
146
+ [role='tab'],
147
+ [role='checkbox'],
148
+ [role='radio'],
149
+ [role='switch'],
150
+ [role='combobox'],
151
+ a[href]
152
+ ):not(:disabled):not([aria-disabled='true']):not([data-disabled]) {
153
+ cursor: pointer;
154
+ }
155
+ }
156
+
157
+ [data-slot='badge'] {
158
+ border-radius: var(--radius-md);
159
+ min-height: calc(var(--spacing) * 7);
160
+ height: auto;
161
+ padding-inline: calc(var(--spacing) * 2.5);
162
+ line-height: 1.4;
163
+ }
164
+
165
+ /* Shared overlay treatment lives outside generated shadcn primitives. */
166
+ :is(
167
+ [data-slot='dialog-overlay'],
168
+ [data-slot='alert-dialog-overlay'],
169
+ [data-slot='sheet-overlay']
170
+ ) {
171
+ background: var(--overlay-backdrop);
172
+ }
173
+ :is(
174
+ [data-slot='dialog-content'],
175
+ [data-slot='alert-dialog-content'],
176
+ [data-slot='route-overlay-content']
177
+ ) {
178
+ border: 1px solid var(--border);
179
+ box-shadow: var(--overlay-shadow);
180
+ }
181
+ [data-slot='route-overlay-content'][data-presentation='dialog'] {
182
+ border-radius: var(--radius-xl);
183
+ }
184
+ :is([data-slot='dialog-title'], [data-slot='alert-dialog-title']) {
185
+ font-size: var(--text-lg);
186
+ font-weight: 600;
187
+ line-height: 1.4;
188
+ }
189
+ :is([data-slot='dialog-description'], [data-slot='alert-dialog-description']) {
190
+ line-height: 1.65;
191
+ }
192
+ :is(
193
+ [data-slot='dialog-footer'],
194
+ [data-slot='alert-dialog-footer'],
195
+ [data-slot='route-overlay-footer']
196
+ )
197
+ > button {
198
+ min-height: calc(var(--spacing) * 10);
199
+ padding-inline: calc(var(--spacing) * 4);
200
+ }
201
+ [data-slot='dialog-content'] > [data-slot='dialog-close'] {
202
+ top: calc(var(--spacing) * 4);
203
+ right: calc(var(--spacing) * 4);
204
+ }
205
+ [data-slot='dialog-header'] {
206
+ padding-right: calc(var(--spacing) * 8);
207
+ }
208
+ [data-slot='alert-dialog-media'] {
209
+ border-radius: var(--radius-lg);
210
+ width: calc(var(--spacing) * 12);
211
+ height: calc(var(--spacing) * 12);
212
+ }
213
+ [data-slot='alert'] {
214
+ padding: calc(var(--spacing) * 4);
215
+ row-gap: calc(var(--spacing) * 1.5);
216
+ column-gap: calc(var(--spacing) * 3);
217
+ border-radius: var(--radius-lg);
218
+ }
219
+ [data-slot='alert'][data-tone='info'] {
220
+ background: color-mix(in srgb, var(--primary) 5%, var(--card));
221
+ border-color: color-mix(in srgb, var(--primary) 18%, var(--border));
222
+ }
223
+ [data-slot='alert'][data-tone='info'] > svg {
224
+ color: var(--primary);
225
+ }
226
+ [data-slot='alert-action'] {
227
+ top: calc(var(--spacing) * 4);
228
+ right: calc(var(--spacing) * 4);
229
+ }
230
+ [data-slot='toast'] {
231
+ border-radius: var(--radius-xl);
232
+ box-shadow: var(--shadow-lg);
233
+ }
234
+ [data-slot='toast-content'] {
235
+ padding: calc(var(--spacing) * 4);
236
+ align-items: center;
237
+ gap: calc(var(--spacing) * 3);
238
+ }
239
+ [data-slot='toast-viewport'] {
240
+ width: 22rem;
241
+ max-width: calc(100vw - 2rem);
242
+ }
243
+ [data-slot='toast-content']:has([data-slot='toast-description']:not(:empty)) {
244
+ align-items: flex-start;
245
+ }
246
+ :is([data-slot='toast-title'], [data-slot='toast-description']) {
247
+ line-height: 1.5;
248
+ overflow-wrap: anywhere;
249
+ }
250
+ [data-slot='toast-close'] {
251
+ width: calc(var(--spacing) * 6);
252
+ height: calc(var(--spacing) * 6);
253
+ opacity: 0.55;
254
+ transition:
255
+ opacity 150ms ease,
256
+ background-color 150ms ease;
257
+ }
258
+ [data-slot='toast-close']:is(:hover, :focus-visible) {
259
+ opacity: 1;
260
+ }
261
+
262
+ [data-slot='toast-icon'] {
263
+ display: inline-flex;
264
+ align-items: center;
265
+ justify-content: center;
266
+ width: calc(var(--spacing) * 7);
267
+ height: calc(var(--spacing) * 7);
268
+ border-radius: var(--radius-lg);
269
+ background: var(--accent);
270
+ color: var(--primary);
271
+ }
272
+ [data-slot='toast-icon']:has(.lucide-circle-check) {
273
+ background: var(--status-success-background);
274
+ color: var(--status-success);
275
+ }
276
+ [data-slot='toast-icon']:has(.lucide-octagon-x) {
277
+ background: color-mix(in srgb, var(--destructive) 10%, var(--popover));
278
+ color: var(--destructive);
279
+ }
280
+ [data-slot='toast-icon']:has(.lucide-triangle-alert) {
281
+ background: var(--status-warning-background);
282
+ color: var(--status-warning);
283
+ }
284
+ [data-slot='alert'].text-destructive {
285
+ background: color-mix(in srgb, var(--destructive) 5%, var(--card));
286
+ border-color: color-mix(in srgb, var(--destructive) 20%, var(--border));
287
+ }
288
+ [data-slot='alert-dialog-header']:has([data-slot='alert-dialog-media']) {
289
+ grid-template-columns: max-content minmax(0, 1fr);
290
+ column-gap: calc(var(--spacing) * 4);
291
+ align-items: start;
292
+ justify-items: start;
293
+ text-align: left;
294
+ }
295
+ [data-slot='alert-dialog-header'] > [data-slot='alert-dialog-media'] {
296
+ grid-column: 1;
297
+ grid-row: 1 / span 2;
298
+ margin-bottom: 0;
299
+ }
300
+ [data-slot='alert-dialog-header']:has([data-slot='alert-dialog-media'])
301
+ > :is(
302
+ [data-slot='alert-dialog-title'],
303
+ [data-slot='alert-dialog-description']
304
+ ) {
305
+ grid-column: 2;
306
+ }
307
+ [data-slot='alert']:has([data-slot='alert-action']) {
308
+ padding-right: calc(var(--spacing) * 24);
309
+ }
310
+
311
+ /* Compact content can stay dense while the primary navigation remains comfortable.
312
+ The primitive's important icon-mode sizes still control the collapsed rail. */
313
+ :root[data-theme='compact'] .app-navigation [data-slot='sidebar-menu-button'] {
314
+ height: calc(var(--spacing) * 12);
315
+ padding-inline: calc(var(--spacing) * 4);
316
+ }
317
+ :root[data-theme='compact'] .app-navigation [data-slot='sidebar-menu'] {
318
+ gap: calc(var(--spacing) * 1.5);
319
+ }
320
+
321
+ /* Brand tint belongs to the application shell, independent of each page's content. */
322
+ .app-brand-surface {
323
+ background-image: radial-gradient(
324
+ ellipse at 100% 0%,
325
+ color-mix(in srgb, var(--primary) 6%, transparent),
326
+ transparent 70%
327
+ );
328
+ background-size: 100% 18rem;
329
+ background-repeat: no-repeat;
330
+ }
331
+
332
+ /* Shared table hierarchy stays neutral so semantic status colors remain distinct. */
333
+ [data-slot='table-header'] {
334
+ background: color-mix(in srgb, var(--muted) 70%, var(--card));
335
+ }
336
+ [data-slot='table-header'] [data-slot='table-row']:hover {
337
+ background: transparent;
338
+ }
339
+ [data-slot='table-head'] {
340
+ height: calc(var(--spacing) * 12);
341
+ padding-inline: calc(var(--spacing) * 3);
342
+ color: color-mix(in srgb, var(--foreground) 80%, var(--muted-foreground));
343
+ font-weight: 600;
344
+ }
345
+ [data-slot='table-cell'] {
346
+ padding-inline: calc(var(--spacing) * 3);
347
+ }
348
+ [data-slot='table-head'][aria-sort]:not([aria-sort='none']) {
349
+ color: var(--primary);
350
+ }
351
+ [data-slot='table-head'] button {
352
+ font-weight: inherit;
353
+ }
354
+ [data-slot='table-head'] button:hover {
355
+ color: var(--primary);
356
+ }
357
+
358
+ /* Nested items keep a comfortable rhythm independently of compact content. */
359
+ .app-navigation [data-slot='sidebar-menu-sub-button'] {
360
+ height: calc(var(--spacing) * 10);
361
+ padding-inline: calc(var(--spacing) * 3);
362
+ }
363
+ .app-navigation [data-slot='sidebar-menu-sub'] {
364
+ gap: calc(var(--spacing) * 1.5);
365
+ padding-block: calc(var(--spacing) * 1.5);
366
+ }
@@ -3,6 +3,7 @@ import { useTheme } from 'next-themes';
3
3
  import { useTranslation } from '@nocobase/i18n/client';
4
4
  import { useId, type ReactElement } from 'react';
5
5
  import { Button } from '#components/ui/button';
6
+ import { RadioGroup, RadioGroupItem } from '#components/ui/radio-group';
6
7
  import {
7
8
  Popover,
8
9
  PopoverTrigger,
@@ -56,7 +57,13 @@ export function ThemeSettings(): ReactElement {
56
57
  <legend className='text-xs font-medium text-muted-foreground'>
57
58
  {t('appearance.mode', { defaultValue: 'Color mode' })}
58
59
  </legend>
59
- <div className='grid grid-cols-3 gap-1 rounded-lg bg-muted/70 p-1'>
60
+ <RadioGroup
61
+ name={id + '-mode'}
62
+ value={theme}
63
+ onValueChange={(value) => setTheme(String(value))}
64
+ aria-label={t('appearance.mode', { defaultValue: 'Color mode' })}
65
+ className='grid-cols-3 gap-1 rounded-lg bg-muted/70 p-1'
66
+ >
60
67
  {COLOR_MODES.map(({ id: mode, icon: ModeIcon }) => {
61
68
  const isSelected = theme === mode;
62
69
  return (
@@ -69,14 +76,7 @@ export function ThemeSettings(): ReactElement {
69
76
  : 'text-muted-foreground hover:bg-background/40 hover:text-foreground',
70
77
  )}
71
78
  >
72
- <input
73
- type='radio'
74
- name={id + '-mode'}
75
- value={mode}
76
- checked={isSelected}
77
- onChange={() => setTheme(mode)}
78
- className='sr-only'
79
- />
79
+ <RadioGroupItem value={mode} className='sr-only' />
80
80
  <ModeIcon aria-hidden='true' className='size-3.5 shrink-0' />
81
81
  <span className='whitespace-nowrap'>
82
82
  {t('appearance.' + mode, {
@@ -86,14 +86,23 @@ export function ThemeSettings(): ReactElement {
86
86
  </label>
87
87
  );
88
88
  })}
89
- </div>
89
+ </RadioGroup>
90
90
  </fieldset>
91
91
 
92
92
  <fieldset className='space-y-2'>
93
93
  <legend className='text-xs font-medium text-muted-foreground'>
94
94
  {t('appearance.preset', { defaultValue: 'Theme' })}
95
95
  </legend>
96
- <div className='grid grid-cols-2 gap-2.5'>
96
+ <RadioGroup
97
+ name={id + '-preset'}
98
+ value={preset}
99
+ onValueChange={(value) => {
100
+ const selected = themePresets.find((item) => item.id === value);
101
+ if (selected) setPreset(selected.id);
102
+ }}
103
+ aria-label={t('appearance.preset', { defaultValue: 'Theme' })}
104
+ className='grid-cols-2 gap-2.5'
105
+ >
97
106
  {themePresets.map((item) => {
98
107
  const isSelected = preset === item.id;
99
108
  return (
@@ -106,14 +115,7 @@ export function ThemeSettings(): ReactElement {
106
115
  : 'border-border/70 hover:border-border hover:bg-muted/30',
107
116
  )}
108
117
  >
109
- <input
110
- type='radio'
111
- name={id + '-preset'}
112
- value={item.id}
113
- checked={isSelected}
114
- onChange={() => setPreset(item.id)}
115
- className='sr-only'
116
- />
118
+ <RadioGroupItem value={item.id} className='sr-only' />
117
119
  <div className='mb-2 h-16 w-full'>
118
120
  <div
119
121
  aria-hidden='true'
@@ -168,7 +170,7 @@ export function ThemeSettings(): ReactElement {
168
170
  </label>
169
171
  );
170
172
  })}
171
- </div>
173
+ </RadioGroup>
172
174
  </fieldset>
173
175
  </PopoverContent>
174
176
  </Popover>
@@ -50,20 +50,31 @@
50
50
  --foreground: oklch(0.16 0 0);
51
51
  --card: oklch(1 0 0);
52
52
  --card-foreground: oklch(0.16 0 0);
53
+ --overlay-backdrop: rgb(15 23 42 / 0.28);
54
+ --overlay-shadow:
55
+ 0 24px 64px -16px rgb(15 23 42 / 0.22),
56
+ 0 8px 24px -12px rgb(15 23 42 / 0.16);
53
57
  --popover: oklch(1 0 0);
54
58
  --popover-foreground: oklch(0.16 0 0);
55
- --primary: oklch(0.18 0 0);
56
- --primary-foreground: oklch(0.985 0 0);
59
+ --primary: #002ad1;
60
+ --auth-brand-background: #101c3b;
61
+ --auth-brand-highlight: #8ca9ff;
62
+ --auth-brand-muted: #b8c4df;
63
+ --status-success: rgb(21 112 70);
64
+ --status-success-background: rgb(236 249 241);
65
+ --status-warning: rgb(150 79 10);
66
+ --status-warning-background: rgb(255 246 229);
67
+ --primary-foreground: rgb(255 255 255);
57
68
  --secondary: oklch(0.96 0 0);
58
69
  --secondary-foreground: oklch(0.22 0 0);
59
70
  --muted: oklch(0.96 0 0);
60
71
  --muted-foreground: oklch(0.52 0 0);
61
- --accent: oklch(0.94 0 0);
62
- --accent-foreground: oklch(0.22 0 0);
72
+ --accent: rgb(237 242 255);
73
+ --accent-foreground: rgb(0 42 209);
63
74
  --destructive: oklch(0.577 0.245 27.325);
64
75
  --border: oklch(0.9 0 0);
65
76
  --input: oklch(0.9 0 0);
66
- --ring: oklch(0.55 0 0);
77
+ --ring: var(--primary);
67
78
  --chart-1: oklch(0.646 0.222 41.116);
68
79
  --chart-2: oklch(0.6 0.118 184.704);
69
80
  --chart-3: oklch(0.398 0.07 227.392);
@@ -71,10 +82,10 @@
71
82
  --chart-5: oklch(0.769 0.188 70.08);
72
83
  --sidebar: var(--card);
73
84
  --sidebar-foreground: var(--card-foreground);
74
- --sidebar-primary: color-mix(in oklch, var(--primary) 10%, var(--sidebar));
85
+ --sidebar-primary: color-mix(in srgb, var(--primary) 8%, var(--sidebar));
75
86
  --sidebar-primary-foreground: var(--primary);
76
- --sidebar-accent: var(--muted);
77
- --sidebar-accent-foreground: var(--foreground);
87
+ --sidebar-accent: var(--accent);
88
+ --sidebar-accent-foreground: var(--accent-foreground);
78
89
  --sidebar-border: var(--border);
79
90
  --sidebar-ring: var(--ring);
80
91
  }
@@ -85,20 +96,27 @@
85
96
  --foreground: oklch(0.96 0 0);
86
97
  --card: oklch(0.18 0 0);
87
98
  --card-foreground: oklch(0.985 0 0);
99
+ --overlay-backdrop: rgb(0 0 0 / 0.58);
100
+ --overlay-shadow:
101
+ 0 24px 64px -16px rgb(0 0 0 / 0.6), 0 8px 24px -12px rgb(0 0 0 / 0.4);
88
102
  --popover: oklch(0.18 0 0);
89
103
  --popover-foreground: oklch(0.985 0 0);
90
- --primary: oklch(0.94 0 0);
91
- --primary-foreground: oklch(0.16 0 0);
104
+ --primary: #8ca9ff;
105
+ --status-success: rgb(119 216 160);
106
+ --status-success-background: rgb(23 49 37);
107
+ --status-warning: rgb(242 190 103);
108
+ --status-warning-background: rgb(57 43 24);
109
+ --primary-foreground: rgb(10 24 64);
92
110
  --secondary: oklch(0.24 0 0);
93
111
  --secondary-foreground: oklch(0.985 0 0);
94
112
  --muted: oklch(0.23 0 0);
95
113
  --muted-foreground: oklch(0.7 0 0);
96
- --accent: oklch(0.27 0 0);
97
- --accent-foreground: oklch(0.985 0 0);
114
+ --accent: rgb(30 42 72);
115
+ --accent-foreground: rgb(174 194 255);
98
116
  --destructive: oklch(0.704 0.191 22.216);
99
117
  --border: oklch(1 0 0 / 10%);
100
118
  --input: oklch(1 0 0 / 15%);
101
- --ring: oklch(0.62 0 0);
119
+ --ring: var(--primary);
102
120
  --chart-1: oklch(0.488 0.243 264.376);
103
121
  --chart-2: oklch(0.696 0.17 162.48);
104
122
  --chart-3: oklch(0.769 0.188 70.08);
@@ -106,10 +124,10 @@
106
124
  --chart-5: oklch(0.645 0.246 16.439);
107
125
  --sidebar: var(--card);
108
126
  --sidebar-foreground: var(--card-foreground);
109
- --sidebar-primary: color-mix(in oklch, var(--primary) 10%, var(--sidebar));
127
+ --sidebar-primary: color-mix(in srgb, var(--primary) 8%, var(--sidebar));
110
128
  --sidebar-primary-foreground: var(--primary);
111
- --sidebar-accent: var(--muted);
112
- --sidebar-accent-foreground: var(--foreground);
129
+ --sidebar-accent: var(--accent);
130
+ --sidebar-accent-foreground: var(--accent-foreground);
113
131
  --sidebar-border: var(--border);
114
132
  --sidebar-ring: var(--ring);
115
133
  }
@@ -51,20 +51,31 @@
51
51
  --foreground: oklch(0.16 0 0);
52
52
  --card: oklch(1 0 0);
53
53
  --card-foreground: oklch(0.16 0 0);
54
+ --overlay-backdrop: rgb(15 23 42 / 0.28);
55
+ --overlay-shadow:
56
+ 0 24px 64px -16px rgb(15 23 42 / 0.22),
57
+ 0 8px 24px -12px rgb(15 23 42 / 0.16);
54
58
  --popover: oklch(1 0 0);
55
59
  --popover-foreground: oklch(0.16 0 0);
56
- --primary: oklch(0.18 0 0);
57
- --primary-foreground: oklch(0.985 0 0);
60
+ --primary: #002ad1;
61
+ --auth-brand-background: #101c3b;
62
+ --auth-brand-highlight: #8ca9ff;
63
+ --auth-brand-muted: #b8c4df;
64
+ --status-success: rgb(21 112 70);
65
+ --status-success-background: rgb(236 249 241);
66
+ --status-warning: rgb(150 79 10);
67
+ --status-warning-background: rgb(255 246 229);
68
+ --primary-foreground: rgb(255 255 255);
58
69
  --secondary: oklch(0.96 0 0);
59
70
  --secondary-foreground: oklch(0.22 0 0);
60
71
  --muted: oklch(0.96 0 0);
61
72
  --muted-foreground: oklch(0.52 0 0);
62
- --accent: oklch(0.94 0 0);
63
- --accent-foreground: oklch(0.22 0 0);
73
+ --accent: rgb(237 242 255);
74
+ --accent-foreground: rgb(0 42 209);
64
75
  --destructive: oklch(0.577 0.245 27.325);
65
76
  --border: oklch(0.9 0 0);
66
77
  --input: oklch(0.9 0 0);
67
- --ring: oklch(0.55 0 0);
78
+ --ring: var(--primary);
68
79
  --chart-1: oklch(0.646 0.222 41.116);
69
80
  --chart-2: oklch(0.6 0.118 184.704);
70
81
  --chart-3: oklch(0.398 0.07 227.392);
@@ -72,10 +83,10 @@
72
83
  --chart-5: oklch(0.769 0.188 70.08);
73
84
  --sidebar: var(--card);
74
85
  --sidebar-foreground: var(--card-foreground);
75
- --sidebar-primary: color-mix(in oklch, var(--primary) 10%, var(--sidebar));
86
+ --sidebar-primary: color-mix(in srgb, var(--primary) 8%, var(--sidebar));
76
87
  --sidebar-primary-foreground: var(--primary);
77
- --sidebar-accent: var(--muted);
78
- --sidebar-accent-foreground: var(--foreground);
88
+ --sidebar-accent: var(--accent);
89
+ --sidebar-accent-foreground: var(--accent-foreground);
79
90
  --sidebar-border: var(--border);
80
91
  --sidebar-ring: var(--ring);
81
92
  }
@@ -87,20 +98,27 @@
87
98
  --foreground: oklch(0.96 0 0);
88
99
  --card: oklch(0.18 0 0);
89
100
  --card-foreground: oklch(0.985 0 0);
101
+ --overlay-backdrop: rgb(0 0 0 / 0.58);
102
+ --overlay-shadow:
103
+ 0 24px 64px -16px rgb(0 0 0 / 0.6), 0 8px 24px -12px rgb(0 0 0 / 0.4);
90
104
  --popover: oklch(0.18 0 0);
91
105
  --popover-foreground: oklch(0.985 0 0);
92
- --primary: oklch(0.94 0 0);
93
- --primary-foreground: oklch(0.16 0 0);
106
+ --primary: #8ca9ff;
107
+ --status-success: rgb(119 216 160);
108
+ --status-success-background: rgb(23 49 37);
109
+ --status-warning: rgb(242 190 103);
110
+ --status-warning-background: rgb(57 43 24);
111
+ --primary-foreground: rgb(10 24 64);
94
112
  --secondary: oklch(0.24 0 0);
95
113
  --secondary-foreground: oklch(0.985 0 0);
96
114
  --muted: oklch(0.23 0 0);
97
115
  --muted-foreground: oklch(0.7 0 0);
98
- --accent: oklch(0.27 0 0);
99
- --accent-foreground: oklch(0.985 0 0);
116
+ --accent: rgb(30 42 72);
117
+ --accent-foreground: rgb(174 194 255);
100
118
  --destructive: oklch(0.704 0.191 22.216);
101
119
  --border: oklch(1 0 0 / 10%);
102
120
  --input: oklch(1 0 0 / 15%);
103
- --ring: oklch(0.62 0 0);
121
+ --ring: var(--primary);
104
122
  --chart-1: oklch(0.488 0.243 264.376);
105
123
  --chart-2: oklch(0.696 0.17 162.48);
106
124
  --chart-3: oklch(0.769 0.188 70.08);
@@ -108,10 +126,10 @@
108
126
  --chart-5: oklch(0.645 0.246 16.439);
109
127
  --sidebar: var(--card);
110
128
  --sidebar-foreground: var(--card-foreground);
111
- --sidebar-primary: color-mix(in oklch, var(--primary) 10%, var(--sidebar));
129
+ --sidebar-primary: color-mix(in srgb, var(--primary) 8%, var(--sidebar));
112
130
  --sidebar-primary-foreground: var(--primary);
113
- --sidebar-accent: var(--muted);
114
- --sidebar-accent-foreground: var(--foreground);
131
+ --sidebar-accent: var(--accent);
132
+ --sidebar-accent-foreground: var(--accent-foreground);
115
133
  --sidebar-border: var(--border);
116
134
  --sidebar-ring: var(--ring);
117
135
  }
package/eslint.config.js CHANGED
@@ -8,17 +8,4 @@ export default createApplicationConfig({
8
8
  'public/r/**',
9
9
  'storage/**',
10
10
  ],
11
- overrides: [
12
- {
13
- // Top-level workflow definitions and handlers use the server project.
14
- files: ['workflows/**/*.ts'],
15
- ignores: ['workflows/*/client/**'],
16
- languageOptions: {
17
- parserOptions: {
18
- projectService: false,
19
- project: './tsconfig.server.json',
20
- },
21
- },
22
- },
23
- ],
24
11
  });
package/index.html CHANGED
@@ -4,7 +4,7 @@
4
4
  <meta charset="utf-8" />
5
5
  <link rel="icon" type="image/x-icon" href="/assets/favicon.ico" />
6
6
  <meta name="viewport" content="width=device-width, initial-scale=1" />
7
- <meta name="theme-color" content="#171717" />
7
+ <meta name="theme-color" content="#002ad1" />
8
8
  <meta name="description" content="NocoBase administration console" />
9
9
  <meta data-rh="true" property="og:image" content="/assets/logo-mark.png" />
10
10
  <meta data-rh="true" name="twitter:image" content="/assets/logo-mark.png" />
@@ -16,16 +16,24 @@
16
16
  align-items: center;
17
17
  justify-content: center;
18
18
  background: oklch(0.985 0 0);
19
- color: oklch(0.18 0 0);
19
+ color: #002ad1;
20
+ flex-direction: column;
21
+ gap: 0.75rem;
22
+ font:
23
+ 14px system-ui,
24
+ sans-serif;
20
25
  }
21
26
 
22
27
  .app-bootstrap-loading [data-slot='loading-indicator'] {
23
- width: 1.75rem;
24
- height: 1.75rem;
25
- opacity: 0;
26
- animation:
27
- app-bootstrap-reveal 0s 200ms forwards,
28
- app-bootstrap-spin 1s linear 200ms infinite;
28
+ width: 3rem;
29
+ height: 3rem;
30
+ }
31
+ .app-bootstrap-loading .nocobase-loading-orbit {
32
+ transform-origin: 32px 32px;
33
+ animation: app-bootstrap-spin 1.1s linear infinite;
34
+ }
35
+ .app-bootstrap-loading span {
36
+ color: oklch(0.556 0 0);
29
37
  }
30
38
 
31
39
  html,
@@ -48,14 +56,18 @@
48
56
  @media (prefers-color-scheme: dark) {
49
57
  .app-bootstrap-loading {
50
58
  background: oklch(0.145 0 0);
51
- color: oklch(0.9 0 0);
59
+ color: #8ca9ff;
52
60
  }
53
61
  }
54
62
 
63
+ @media (prefers-color-scheme: dark) {
64
+ .app-bootstrap-loading span {
65
+ color: oklch(0.708 0 0);
66
+ }
67
+ }
55
68
  @media (prefers-reduced-motion: reduce) {
56
- .app-bootstrap-loading [data-slot='loading-indicator'] {
69
+ .app-bootstrap-loading .nocobase-loading-orbit {
57
70
  animation: none;
58
- opacity: 0.65;
59
71
  }
60
72
  }
61
73
  </style>
@@ -71,18 +83,38 @@
71
83
  >
72
84
  <svg
73
85
  data-slot="loading-indicator"
74
- viewBox="0 0 24 24"
86
+ viewBox="0 0 64 64"
75
87
  fill="none"
76
88
  aria-hidden="true"
77
89
  >
78
- <path
79
- d="M21 12a9 9 0 1 1-6.219-8.56"
90
+ <circle
91
+ cx="32"
92
+ cy="32"
93
+ r="28"
80
94
  stroke="currentColor"
81
95
  stroke-width="2"
82
- stroke-linecap="round"
83
- stroke-linejoin="round"
96
+ opacity=".12"
84
97
  />
98
+ <g class="nocobase-loading-orbit">
99
+ <path
100
+ d="M32 4a28 28 0 0 1 28 28"
101
+ stroke="currentColor"
102
+ stroke-width="3"
103
+ stroke-linecap="round"
104
+ />
105
+ </g>
106
+ <g
107
+ transform="translate(15 17.176475219726562) scale(.34)"
108
+ fill="currentColor"
109
+ >
110
+ <g transform="translate(0 -6.401886463165283)">
111
+ <path
112
+ d="M99.876 55.369c-.025-.045-.076-.072-.109-.111-.066-.078-.125-.168-.217-.221l-.014-.008-.001-.002h-.001L80.368 43.648v-24.67a.92.92 0 0 0-.124-.459c-.026-.045-.075-.072-.108-.111-.066-.08-.126-.168-.218-.221l-.014-.008-.001-.002h-.002L60.286 6.531a.92.92 0 0 0-.94 0L20.099 29.834h-.002l-.001.002-.014.006c-.092.055-.151.143-.218.221-.033.041-.082.068-.108.113a.907.907 0 0 0-.124.457v1.361L.466 43.373H.465l-.001.002c-.098.055-.162.143-.23.227-.034.041-.084.068-.109.113a.898.898 0 0 0-.125.457v25.195c0 .324.171.625.45.791l39.264 23.311c.002.002.006 0 .008.002l.007.008a.924.924 0 0 0 .911 0c.003-.002.004-.006.008-.008.001-.002.005 0 .007-.002l19.161-11.377 19.162 11.377c.002.002.006 0 .008.002.004.002.004.006.007.008a.924.924 0 0 0 .911 0c.003-.002.004-.006.008-.008.002-.002.005 0 .007-.002L99.55 81.812a.916.916 0 0 0 .45-.791V55.828a.92.92 0 0 0-.124-.459zM41.104 65.867V42.812l37.424-22.219v23.055L41.104 65.867zM59.815 8.391l17.83 10.588L59.82 29.561 40.185 41.219l-17.83-10.586 37.46-22.242zM39.264 42.812V65.866L21.472 55.305V32.248l17.792 10.564z"
113
+ />
114
+ </g>
115
+ </g>
85
116
  </svg>
117
+ <span>Loading application…</span>
86
118
  </div>
87
119
  </div>
88
120
  <script type="module" src="/client/index.tsx"></script>