@svadmin/create 0.32.0 → 0.33.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/guidance/DESIGN.md +80 -27
- package/package.json +2 -2
- package/scaffold-manifest.json +21 -21
- package/template/src/App.svelte +2 -1
- package/template/src/pages/Login.svelte +192 -20
package/guidance/DESIGN.md
CHANGED
|
@@ -1,41 +1,41 @@
|
|
|
1
1
|
---
|
|
2
2
|
version: "alpha"
|
|
3
3
|
name: "svadmin Admin UI"
|
|
4
|
-
description: "A restrained, precise product interface for repeated administrative work."
|
|
4
|
+
description: "A restrained, precise Stripe-inspired product interface for repeated administrative work."
|
|
5
5
|
colors:
|
|
6
|
-
background: "
|
|
7
|
-
foreground: "
|
|
8
|
-
surface: "
|
|
9
|
-
surface-subtle: "
|
|
10
|
-
muted-foreground: "
|
|
11
|
-
border: "
|
|
12
|
-
primary: "
|
|
13
|
-
on-primary: "
|
|
6
|
+
background: "#f6f9fc"
|
|
7
|
+
foreground: "#0a2540"
|
|
8
|
+
surface: "#ffffff"
|
|
9
|
+
surface-subtle: "#f1f4f8"
|
|
10
|
+
muted-foreground: "#425466"
|
|
11
|
+
border: "#e6ebf1"
|
|
12
|
+
primary: "#635bff"
|
|
13
|
+
on-primary: "#ffffff"
|
|
14
14
|
success: "oklch(0.51 0.16 151)"
|
|
15
15
|
warning: "oklch(0.7 0.15 75)"
|
|
16
16
|
danger: "oklch(0.58 0.22 27)"
|
|
17
17
|
typography:
|
|
18
18
|
body:
|
|
19
|
-
fontFamily: "
|
|
19
|
+
fontFamily: "ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", sans-serif"
|
|
20
20
|
fontSize: "0.875rem"
|
|
21
21
|
fontWeight: 400
|
|
22
22
|
lineHeight: 1.5
|
|
23
23
|
letterSpacing: "0px"
|
|
24
24
|
label:
|
|
25
|
-
fontFamily: "
|
|
25
|
+
fontFamily: "ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", sans-serif"
|
|
26
26
|
fontSize: "0.8125rem"
|
|
27
27
|
fontWeight: 500
|
|
28
28
|
lineHeight: 1.35
|
|
29
29
|
letterSpacing: "0px"
|
|
30
30
|
heading:
|
|
31
|
-
fontFamily: "
|
|
31
|
+
fontFamily: "ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, \"Segoe UI\", sans-serif"
|
|
32
32
|
fontSize: "1.25rem"
|
|
33
33
|
fontWeight: 600
|
|
34
34
|
lineHeight: 1.3
|
|
35
35
|
letterSpacing: "0px"
|
|
36
36
|
rounded:
|
|
37
37
|
sm: "4px"
|
|
38
|
-
md: "
|
|
38
|
+
md: "8px"
|
|
39
39
|
lg: "8px"
|
|
40
40
|
spacing:
|
|
41
41
|
xs: "4px"
|
|
@@ -91,11 +91,13 @@ components:
|
|
|
91
91
|
|
|
92
92
|
## Overview
|
|
93
93
|
|
|
94
|
-
### Visual update: September
|
|
94
|
+
### Visual update: September 23, 2026
|
|
95
95
|
|
|
96
|
-
The current UI follows
|
|
97
|
-
|
|
98
|
-
|
|
96
|
+
The current UI follows a Stripe-inspired and corporate-clean visual direction:
|
|
97
|
+
neutral canvas, Stripe purple as the single action accent, hairline borders,
|
|
98
|
+
layered but restrained shadows, a subtle technical grid on the work canvas, and
|
|
99
|
+
short ease-out feedback for interactive controls. This supersedes the older
|
|
100
|
+
capability-only reference limitation below.
|
|
99
101
|
Keep SVAdmin's own branding, semantic tokens, OpenUI contracts and Bits UI behavior.
|
|
100
102
|
App chrome must use explicit anatomy hooks; never style every business `header`.
|
|
101
103
|
Package utilities live in sublayers of `utilities`, so host-authored responsive
|
|
@@ -110,7 +112,45 @@ templates.
|
|
|
110
112
|
Metronic is a capability reference only. Its page families, information
|
|
111
113
|
architecture, and scenario coverage may expose missing components or examples,
|
|
112
114
|
but its palette, decoration, card treatment, typography, and branding are not
|
|
113
|
-
visual authority.
|
|
115
|
+
visual authority. Fuse, Midone and Skote are also reference-only sources for
|
|
116
|
+
spacing and component anatomy; their template branding and decorative treatment
|
|
117
|
+
must not enter the product.
|
|
118
|
+
|
|
119
|
+
### Reference integration and precedence
|
|
120
|
+
|
|
121
|
+
The supplied references are intentionally assigned different jobs so they do
|
|
122
|
+
not become a mixed visual theme:
|
|
123
|
+
|
|
124
|
+
| Reference | Adopted responsibility | Explicitly excluded |
|
|
125
|
+
| --- | --- | --- |
|
|
126
|
+
| Stripe style prompt | `#635bff` action accent, technical grid, hairline borders, layered elevation, lift/depress feedback | Stripe brand assets, marketing gradients, oversized hero treatment |
|
|
127
|
+
| Corporate-clean prompt | neutral enterprise surfaces, readable hierarchy, generous spacing, focus-ring offset, motion capped at 200ms | blue-only palette, rigid utility-class recipes, decorative cards |
|
|
128
|
+
| Fuse / Midone / Skote | navigation anatomy, page-family coverage, toolbar/table/form composition, density observations | vendor palette, logos, fonts, CSS, copied markup or component chrome |
|
|
129
|
+
| svadmin | semantic tokens, component API, state ownership, accessibility, responsive contracts | no second visual authority |
|
|
130
|
+
|
|
131
|
+
When references conflict, svadmin semantics and accessibility win first, the
|
|
132
|
+
Stripe prompt controls the action accent and grid, and the corporate-clean
|
|
133
|
+
prompt controls restraint, spacing, and motion limits. The result is one
|
|
134
|
+
product language rather than a collage of template styles.
|
|
135
|
+
|
|
136
|
+
### Runtime integration map
|
|
137
|
+
|
|
138
|
+
The same contract is used at every delivery surface:
|
|
139
|
+
|
|
140
|
+
- `packages/ui/src/app.css` owns published semantic tokens and the
|
|
141
|
+
`clean-flat + stripe` refinement; host applications consume this stylesheet.
|
|
142
|
+
- `packages/core/src/theme.svelte.ts` owns the `stripe` color preset and mode
|
|
143
|
+
attributes; it must stay aligned with the CSS fallback values.
|
|
144
|
+
- `example/src/App.svelte` is the reference application and starts with
|
|
145
|
+
`layoutPreset: 'clean-flat'` and `colorPreset: 'stripe'`.
|
|
146
|
+
- `packages/create-svadmin/template` starts new projects with the same theme
|
|
147
|
+
and guidance document, so generated apps do not drift from the example.
|
|
148
|
+
- `design/admin-ui/preview` renders the published package CSS and uses the same
|
|
149
|
+
Stripe preset for component and state review.
|
|
150
|
+
|
|
151
|
+
Do not add page-local palettes or shadow values when a semantic token exists.
|
|
152
|
+
If a new reference suggests a different treatment, record its responsibility
|
|
153
|
+
here before changing runtime CSS.
|
|
114
154
|
|
|
115
155
|
### Design principles
|
|
116
156
|
|
|
@@ -153,6 +193,15 @@ not a page background. Success, warning, and danger are reserved for semantic
|
|
|
153
193
|
status and feedback. Consumer themes may replace the primary hue while keeping
|
|
154
194
|
the neutral hierarchy and contrast relationships intact.
|
|
155
195
|
|
|
196
|
+
The reference Stripe preset uses `#635bff`, `#0a2540`, `#f6f9fc`, and
|
|
197
|
+
`#e6ebf1`. The grid is a low-contrast canvas texture only; buttons and data
|
|
198
|
+
surfaces remain solid, and gradients are not used to communicate status. The
|
|
199
|
+
runtime names for the shared depth and motion tokens are
|
|
200
|
+
`--svadmin-shadow-control`, `--svadmin-shadow-surface`,
|
|
201
|
+
`--svadmin-shadow-surface-hover`, `--svadmin-motion-fast`,
|
|
202
|
+
`--svadmin-motion-standard`, `--svadmin-motion-slow`, and
|
|
203
|
+
`--svadmin-focus-offset`.
|
|
204
|
+
|
|
156
205
|
- **WCAG 2.2 AA Contrast**: Normal text maintains at least 4.5:1 against its
|
|
157
206
|
canvas; large text, icons, and focus rings maintain at least 3:1. Enhanced AAA
|
|
158
207
|
screens target 7:1 for normal text.
|
|
@@ -162,7 +211,7 @@ the neutral hierarchy and contrast relationships intact.
|
|
|
162
211
|
|
|
163
212
|
## Typography
|
|
164
213
|
|
|
165
|
-
Use
|
|
214
|
+
Use a compatible system sans. Product pages use compact
|
|
166
215
|
headings and normal letter spacing. Uppercase table labels, negative tracking,
|
|
167
216
|
and oversized dashboard numerals are not defaults.
|
|
168
217
|
|
|
@@ -197,14 +246,14 @@ may increase slightly for genuinely clickable items, without translation or
|
|
|
197
246
|
glow. Dialogs and menus receive stronger depth because they are floating
|
|
198
247
|
layers. Dark mode keeps the same hierarchy with low-chroma surfaces.
|
|
199
248
|
|
|
200
|
-
- **Control Shadow**: `0 1px 2px rgb(15 23 42 / 0.
|
|
201
|
-
- **Surface Shadow**: `0
|
|
202
|
-
- **Surface Hover Shadow**: `0
|
|
249
|
+
- **Control Shadow**: `0 1px 2px rgb(15 23 42 / 0.04), 0 0 0 1px rgb(15 23 42 / 0.02)`
|
|
250
|
+
- **Surface Shadow**: `0 2px 4px rgb(15 23 42 / 0.04), 0 8px 16px rgb(15 23 42 / 0.08)`
|
|
251
|
+
- **Surface Hover Shadow**: `0 4px 8px rgb(15 23 42 / 0.06), 0 16px 32px rgb(15 23 42 / 0.1)`
|
|
203
252
|
- **Overlay Shadow**: `0 20px 52px rgb(15 23 42 / 0.18), 0 6px 16px rgb(15 23 42 / 0.1)`
|
|
204
253
|
|
|
205
254
|
## Shapes
|
|
206
255
|
|
|
207
|
-
Controls use
|
|
256
|
+
Controls use 8px radii and bounded surfaces use 8px radii. Pills are limited to
|
|
208
257
|
status badges, avatar groups, and controls whose geometry carries meaning.
|
|
209
258
|
|
|
210
259
|
## Components
|
|
@@ -219,8 +268,10 @@ focus, or elevation with hard-coded values.
|
|
|
219
268
|
|
|
220
269
|
Transitions provide clear state confirmation without delaying user action:
|
|
221
270
|
|
|
222
|
-
- **Timing**: Micro-transitions use
|
|
223
|
-
|
|
271
|
+
- **Timing**: Micro-transitions use 150ms–200ms with `ease-out`; never use
|
|
272
|
+
`ease-in-out` for routine controls.
|
|
273
|
+
- **Feedback**: Buttons may lift by 2px on hover and depress to `scale(0.98)`
|
|
274
|
+
on press. Interactive cards may lift by 4px; hover never scales a card.
|
|
224
275
|
- **Focus Rings**: Operable controls declare `:focus-visible` with a 2px solid
|
|
225
276
|
ring and a 2px offset.
|
|
226
277
|
- **Accessibility**: All transitions and keyframe animations collapse to 0.01ms
|
|
@@ -320,6 +371,8 @@ Before accepting an AI-generated application page, verify all of the following:
|
|
|
320
371
|
- Don't repeat a success fact across Toast, title, description, banner, badge,
|
|
321
372
|
and table data.
|
|
322
373
|
- Don't use persistent success banners for routine mutations.
|
|
323
|
-
- Don't use gradients, glow, glassmorphism, negative letter spacing,
|
|
324
|
-
`!important` overrides as the default product language.
|
|
374
|
+
- Don't use decorative gradients, glow, glassmorphism, negative letter spacing,
|
|
375
|
+
or blanket `!important` overrides as the default product language. A subtle
|
|
376
|
+
two-line grid is allowed on the work canvas because it is part of the current
|
|
377
|
+
Stripe-inspired reference direction.
|
|
325
378
|
- Don't use cards inside cards or make every section a floating card.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@svadmin/create",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.33.0",
|
|
4
4
|
"description": "Scaffolding tool for svadmin projects",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
"@types/node": "^26.4.0",
|
|
28
28
|
"@types/prompts": "^2.4.9",
|
|
29
29
|
"typescript": "^7.0.2",
|
|
30
|
-
"@svadmin/core": "^0.
|
|
30
|
+
"@svadmin/core": "^0.57.0"
|
|
31
31
|
},
|
|
32
32
|
"keywords": [
|
|
33
33
|
"svadmin",
|
package/scaffold-manifest.json
CHANGED
|
@@ -10,10 +10,10 @@
|
|
|
10
10
|
"check": "svelte-check --tsconfig ./tsconfig.json"
|
|
11
11
|
},
|
|
12
12
|
"dependencies": {
|
|
13
|
-
"@svadmin/core": "^0.
|
|
14
|
-
"@svadmin/app": "^
|
|
15
|
-
"@svadmin/ai-elements": "^0.10.
|
|
16
|
-
"@svadmin/ui": "^0.
|
|
13
|
+
"@svadmin/core": "^0.57.0",
|
|
14
|
+
"@svadmin/app": "^0.2.0",
|
|
15
|
+
"@svadmin/ai-elements": "^0.10.2",
|
|
16
|
+
"@svadmin/ui": "^0.77.0",
|
|
17
17
|
"@sinclair/typebox": "^0.34.52",
|
|
18
18
|
"@tanstack/svelte-query": "^6.1.48",
|
|
19
19
|
"@lucide/svelte": "^1.35.0"
|
|
@@ -31,76 +31,76 @@
|
|
|
31
31
|
"@refinedev/core": "^5.0.12"
|
|
32
32
|
},
|
|
33
33
|
"simple-rest": {
|
|
34
|
-
"@svadmin/simple-rest": "^0.12.
|
|
34
|
+
"@svadmin/simple-rest": "^0.12.1",
|
|
35
35
|
"@refinedev/simple-rest": "^6.0.1"
|
|
36
36
|
},
|
|
37
37
|
"supabase": {
|
|
38
|
-
"@svadmin/supabase": "^0.17.
|
|
38
|
+
"@svadmin/supabase": "^0.17.1",
|
|
39
39
|
"@supabase/supabase-js": "^2.112.4",
|
|
40
40
|
"@refinedev/supabase": "^6.0.2"
|
|
41
41
|
},
|
|
42
42
|
"graphql": {
|
|
43
|
-
"@svadmin/graphql": "^0.12.
|
|
43
|
+
"@svadmin/graphql": "^0.12.1",
|
|
44
44
|
"@refinedev/graphql": "^8.0.1",
|
|
45
45
|
"graphql-request": "^7.4.0",
|
|
46
46
|
"graphql": "^16.8.0"
|
|
47
47
|
},
|
|
48
48
|
"rest": {
|
|
49
|
-
"@svadmin/rest": "^
|
|
49
|
+
"@svadmin/rest": "^0.2.0",
|
|
50
50
|
"@refinedev/rest": "^2.1.1",
|
|
51
51
|
"@nestjsx/crud-request": "^5.0.0-alpha.3"
|
|
52
52
|
},
|
|
53
53
|
"airtable": {
|
|
54
|
-
"@svadmin/airtable": "^0.12.
|
|
54
|
+
"@svadmin/airtable": "^0.12.1",
|
|
55
55
|
"@refinedev/airtable": "^5.0.1"
|
|
56
56
|
},
|
|
57
57
|
"appwrite": {
|
|
58
|
-
"@svadmin/appwrite": "^0.11.
|
|
58
|
+
"@svadmin/appwrite": "^0.11.1",
|
|
59
59
|
"appwrite": ">=26.2.0",
|
|
60
60
|
"@refinedev/appwrite": "^8.0.1"
|
|
61
61
|
},
|
|
62
62
|
"directus": {
|
|
63
|
-
"@svadmin/directus": "^0.11.
|
|
63
|
+
"@svadmin/directus": "^0.11.1"
|
|
64
64
|
},
|
|
65
65
|
"drizzle": {
|
|
66
|
-
"@svadmin/drizzle": "^0.13.
|
|
66
|
+
"@svadmin/drizzle": "^0.13.1",
|
|
67
67
|
"drizzle-orm": "^1.0.0-rc.1",
|
|
68
68
|
"refine-sqlx": "^0.10.3"
|
|
69
69
|
},
|
|
70
70
|
"elysia": {
|
|
71
|
-
"@svadmin/elysia": "^0.14.
|
|
71
|
+
"@svadmin/elysia": "^0.14.1",
|
|
72
72
|
"elysia": ">=1.4.30",
|
|
73
73
|
"@elysiajs/eden": ">=1.4.9"
|
|
74
74
|
},
|
|
75
75
|
"firebase": {
|
|
76
|
-
"@svadmin/firebase": "^0.12.
|
|
76
|
+
"@svadmin/firebase": "^0.12.1"
|
|
77
77
|
},
|
|
78
78
|
"hasura": {
|
|
79
|
-
"@svadmin/hasura": "^0.12.
|
|
79
|
+
"@svadmin/hasura": "^0.12.1",
|
|
80
80
|
"@refinedev/hasura": "^7.0.1",
|
|
81
81
|
"graphql-request": "^7.4.0"
|
|
82
82
|
},
|
|
83
83
|
"medusa": {
|
|
84
|
-
"@svadmin/medusa": "^0.12.
|
|
84
|
+
"@svadmin/medusa": "^0.12.1",
|
|
85
85
|
"@refinedev/medusa": "^5.0.0"
|
|
86
86
|
},
|
|
87
87
|
"nestjs-query": {
|
|
88
|
-
"@svadmin/nestjs-query": "^0.12.
|
|
88
|
+
"@svadmin/nestjs-query": "^0.12.1",
|
|
89
89
|
"@refinedev/nestjs-query": "^5.0.0"
|
|
90
90
|
},
|
|
91
91
|
"nestjsx-crud": {
|
|
92
|
-
"@svadmin/nestjsx-crud": "^0.12.
|
|
92
|
+
"@svadmin/nestjsx-crud": "^0.12.1",
|
|
93
93
|
"@refinedev/nestjsx-crud": "^6.0.1"
|
|
94
94
|
},
|
|
95
95
|
"pocketbase": {
|
|
96
|
-
"@svadmin/pocketbase": "^0.12.
|
|
96
|
+
"@svadmin/pocketbase": "^0.12.1",
|
|
97
97
|
"pocketbase": ">=0.28.0"
|
|
98
98
|
},
|
|
99
99
|
"sanity": {
|
|
100
|
-
"@svadmin/sanity": "^0.11.
|
|
100
|
+
"@svadmin/sanity": "^0.11.1"
|
|
101
101
|
},
|
|
102
102
|
"strapi": {
|
|
103
|
-
"@svadmin/strapi": "^0.12.
|
|
103
|
+
"@svadmin/strapi": "^0.12.1",
|
|
104
104
|
"@refinedev/strapi-v4": "^7.0.1"
|
|
105
105
|
}
|
|
106
106
|
},
|
package/template/src/App.svelte
CHANGED
|
@@ -15,7 +15,8 @@
|
|
|
15
15
|
resources={[...resolved.resources]}
|
|
16
16
|
title="svadmin Demo"
|
|
17
17
|
locale="en"
|
|
18
|
+
themeConfig={{ layoutPreset: 'clean-flat', colorPreset: 'stripe' }}
|
|
18
19
|
>
|
|
19
20
|
{#snippet dashboard()}<Dashboard />{/snippet}
|
|
20
21
|
{#snippet loginPage()}<Login />{/snippet}
|
|
21
|
-
</AdminApp>
|
|
22
|
+
</AdminApp>
|
|
@@ -28,58 +28,230 @@
|
|
|
28
28
|
}
|
|
29
29
|
</script>
|
|
30
30
|
|
|
31
|
-
<div class="
|
|
32
|
-
<div class="
|
|
31
|
+
<div class="scaffold-login">
|
|
32
|
+
<div class="scaffold-login__panel">
|
|
33
33
|
<!-- Logo -->
|
|
34
|
-
<div class="
|
|
35
|
-
<div class="
|
|
36
|
-
<Shield
|
|
34
|
+
<div class="scaffold-login__header">
|
|
35
|
+
<div class="scaffold-login__mark" aria-hidden="true">
|
|
36
|
+
<Shield size={28} strokeWidth={1.8} />
|
|
37
37
|
</div>
|
|
38
|
-
<h1
|
|
39
|
-
<p
|
|
38
|
+
<h1>Admin Panel</h1>
|
|
39
|
+
<p>Sign in to continue</p>
|
|
40
40
|
</div>
|
|
41
41
|
|
|
42
42
|
<!-- Error -->
|
|
43
43
|
{#if error}
|
|
44
|
-
<div role="alert" class="
|
|
44
|
+
<div role="alert" class="scaffold-login__error">
|
|
45
45
|
{error}
|
|
46
46
|
</div>
|
|
47
47
|
{/if}
|
|
48
48
|
|
|
49
49
|
<!-- Form -->
|
|
50
|
-
<form onsubmit={handleLogin} class="
|
|
51
|
-
<
|
|
52
|
-
<
|
|
50
|
+
<form onsubmit={handleLogin} class="scaffold-login__form">
|
|
51
|
+
<label>
|
|
52
|
+
<span>Email</span>
|
|
53
53
|
<input
|
|
54
54
|
id="email"
|
|
55
55
|
type="email"
|
|
56
56
|
bind:value={email}
|
|
57
57
|
required
|
|
58
|
-
class="
|
|
58
|
+
class="scaffold-login__input"
|
|
59
59
|
placeholder="admin@example.com"
|
|
60
60
|
/>
|
|
61
|
-
</
|
|
62
|
-
<
|
|
63
|
-
<
|
|
61
|
+
</label>
|
|
62
|
+
<label>
|
|
63
|
+
<span>Password</span>
|
|
64
64
|
<input
|
|
65
65
|
id="password"
|
|
66
66
|
type="password"
|
|
67
67
|
bind:value={password}
|
|
68
68
|
required
|
|
69
|
-
class="
|
|
70
|
-
placeholder="
|
|
69
|
+
class="scaffold-login__input"
|
|
70
|
+
placeholder="Enter your password"
|
|
71
71
|
/>
|
|
72
|
-
</
|
|
72
|
+
</label>
|
|
73
73
|
<button
|
|
74
74
|
type="submit"
|
|
75
75
|
disabled={loading}
|
|
76
|
-
class="
|
|
76
|
+
class="scaffold-login__submit"
|
|
77
77
|
>
|
|
78
78
|
{#if loading}
|
|
79
|
-
<
|
|
79
|
+
<span class="scaffold-login__spinner" aria-hidden="true"><Loader2 size={16} /></span>
|
|
80
80
|
{/if}
|
|
81
81
|
Sign in
|
|
82
82
|
</button>
|
|
83
83
|
</form>
|
|
84
84
|
</div>
|
|
85
85
|
</div>
|
|
86
|
+
|
|
87
|
+
<style>
|
|
88
|
+
.scaffold-login {
|
|
89
|
+
display: grid;
|
|
90
|
+
min-height: 100dvh;
|
|
91
|
+
place-items: center;
|
|
92
|
+
padding: 2rem 1rem;
|
|
93
|
+
background: var(--background);
|
|
94
|
+
background-image:
|
|
95
|
+
linear-gradient(to right, color-mix(in oklch, var(--primary) 4%, transparent) 1px, transparent 1px),
|
|
96
|
+
linear-gradient(to bottom, color-mix(in oklch, var(--primary) 4%, transparent) 1px, transparent 1px);
|
|
97
|
+
background-size: var(--svadmin-grid-size) var(--svadmin-grid-size);
|
|
98
|
+
color: var(--foreground);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
.scaffold-login__panel {
|
|
102
|
+
width: min(100%, 28rem);
|
|
103
|
+
border: 1px solid var(--border);
|
|
104
|
+
border-radius: var(--radius-lg);
|
|
105
|
+
background: var(--card);
|
|
106
|
+
padding: 2rem;
|
|
107
|
+
box-shadow: var(--shadow-surface);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
.scaffold-login__header {
|
|
111
|
+
display: grid;
|
|
112
|
+
justify-items: center;
|
|
113
|
+
gap: 0.5rem;
|
|
114
|
+
text-align: center;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
.scaffold-login__mark {
|
|
118
|
+
display: grid;
|
|
119
|
+
width: 3.5rem;
|
|
120
|
+
height: 3.5rem;
|
|
121
|
+
place-items: center;
|
|
122
|
+
border: 1px solid color-mix(in oklch, var(--primary) 20%, var(--border));
|
|
123
|
+
border-radius: var(--radius-md);
|
|
124
|
+
background: color-mix(in oklch, var(--primary) 10%, var(--card));
|
|
125
|
+
color: var(--primary);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
.scaffold-login__header h1 {
|
|
129
|
+
margin: 0.75rem 0 0;
|
|
130
|
+
color: var(--foreground);
|
|
131
|
+
font-size: 1.25rem;
|
|
132
|
+
font-weight: 650;
|
|
133
|
+
line-height: 1.3;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
.scaffold-login__header p {
|
|
137
|
+
margin: 0;
|
|
138
|
+
color: var(--muted-foreground);
|
|
139
|
+
font-size: 0.875rem;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
.scaffold-login__error {
|
|
143
|
+
margin-top: 1.5rem;
|
|
144
|
+
border: 1px solid color-mix(in oklch, var(--destructive) 28%, var(--border));
|
|
145
|
+
border-radius: var(--radius-md);
|
|
146
|
+
background: color-mix(in oklch, var(--destructive) 8%, var(--card));
|
|
147
|
+
color: var(--destructive);
|
|
148
|
+
padding: 0.75rem 1rem;
|
|
149
|
+
font-size: 0.875rem;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
.scaffold-login__form {
|
|
153
|
+
display: grid;
|
|
154
|
+
gap: 1rem;
|
|
155
|
+
margin-top: 2rem;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
.scaffold-login__form label {
|
|
159
|
+
display: grid;
|
|
160
|
+
gap: 0.5rem;
|
|
161
|
+
color: var(--foreground);
|
|
162
|
+
font-size: 0.875rem;
|
|
163
|
+
font-weight: 600;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
.scaffold-login__input {
|
|
167
|
+
min-height: 2.75rem;
|
|
168
|
+
width: 100%;
|
|
169
|
+
border: 1px solid var(--border);
|
|
170
|
+
border-radius: var(--radius-md);
|
|
171
|
+
background: var(--card);
|
|
172
|
+
color: var(--foreground);
|
|
173
|
+
padding: 0.625rem 0.75rem;
|
|
174
|
+
font: inherit;
|
|
175
|
+
font-size: 0.875rem;
|
|
176
|
+
box-shadow: var(--shadow-control);
|
|
177
|
+
transition: border-color var(--svadmin-motion-fast) ease-out, box-shadow var(--svadmin-motion-fast) ease-out;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
.scaffold-login__input::placeholder {
|
|
181
|
+
color: var(--muted-foreground);
|
|
182
|
+
opacity: 0.75;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
.scaffold-login__input:focus-visible {
|
|
186
|
+
border-color: var(--ring);
|
|
187
|
+
outline: 2px solid color-mix(in oklch, var(--ring) 42%, transparent);
|
|
188
|
+
outline-offset: var(--svadmin-focus-offset);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
.scaffold-login__submit {
|
|
192
|
+
display: inline-flex;
|
|
193
|
+
min-height: 2.75rem;
|
|
194
|
+
align-items: center;
|
|
195
|
+
justify-content: center;
|
|
196
|
+
gap: 0.5rem;
|
|
197
|
+
width: 100%;
|
|
198
|
+
border: 1px solid color-mix(in oklch, var(--primary) 70%, var(--border));
|
|
199
|
+
border-radius: var(--radius-md);
|
|
200
|
+
background: var(--primary);
|
|
201
|
+
color: var(--primary-foreground);
|
|
202
|
+
padding: 0.625rem 1rem;
|
|
203
|
+
font: inherit;
|
|
204
|
+
font-size: 0.875rem;
|
|
205
|
+
font-weight: 650;
|
|
206
|
+
box-shadow: var(--shadow-control);
|
|
207
|
+
transition: transform var(--svadmin-motion-standard) ease-out, box-shadow var(--svadmin-motion-standard) ease-out, background-color var(--svadmin-motion-standard) ease-out;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
.scaffold-login__submit:hover:not(:disabled) {
|
|
211
|
+
transform: translateY(-0.125rem);
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
.scaffold-login__submit:active:not(:disabled) {
|
|
215
|
+
transform: translateY(0) scale(0.98);
|
|
216
|
+
box-shadow: var(--shadow-control);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
.scaffold-login__submit:focus-visible {
|
|
220
|
+
outline: 2px solid color-mix(in oklch, var(--ring) 78%, transparent);
|
|
221
|
+
outline-offset: var(--svadmin-focus-offset);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
.scaffold-login__submit:disabled {
|
|
225
|
+
cursor: not-allowed;
|
|
226
|
+
opacity: 0.55;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
.scaffold-login__spinner {
|
|
230
|
+
animation: scaffold-login-spin var(--svadmin-motion-slow) linear infinite;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
@keyframes scaffold-login-spin {
|
|
234
|
+
to { transform: rotate(360deg); }
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
@media (prefers-reduced-motion: reduce) {
|
|
238
|
+
.scaffold-login__input,
|
|
239
|
+
.scaffold-login__submit {
|
|
240
|
+
transition-duration: 0.01ms;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
.scaffold-login__spinner {
|
|
244
|
+
animation-duration: 0.01ms;
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
@media (max-width: 32rem) {
|
|
249
|
+
.scaffold-login {
|
|
250
|
+
padding: 1rem;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
.scaffold-login__panel {
|
|
254
|
+
padding: 1.5rem;
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
</style>
|