@motor-cms/ui-admin 1.0.1-alpha.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 +77 -0
- package/app/components/form/inputs/CategoryTreeInput.vue +154 -0
- package/app/components/form/inputs/CategoryTreePicker.vue +355 -0
- package/app/components/form/inputs/NestedDraggable.vue +217 -0
- package/app/components/form/inputs/QuicklinksInput.vue +186 -0
- package/app/lang/de/motor-admin/CLAUDE.md +21 -0
- package/app/lang/de/motor-admin/ai_system_prompts.json +12 -0
- package/app/lang/de/motor-admin/categories.json +12 -0
- package/app/lang/de/motor-admin/category_trees.json +14 -0
- package/app/lang/de/motor-admin/clients.json +26 -0
- package/app/lang/de/motor-admin/config_variables.json +14 -0
- package/app/lang/de/motor-admin/domains.json +19 -0
- package/app/lang/de/motor-admin/email_templates.json +38 -0
- package/app/lang/de/motor-admin/global.json +5 -0
- package/app/lang/de/motor-admin/languages.json +16 -0
- package/app/lang/de/motor-admin/permissions.json +14 -0
- package/app/lang/de/motor-admin/roles.json +15 -0
- package/app/lang/de/motor-admin/users.json +22 -0
- package/app/lang/en/motor-admin/CLAUDE.md +7 -0
- package/app/lang/en/motor-admin/ai_system_prompts.json +12 -0
- package/app/lang/en/motor-admin/categories.json +12 -0
- package/app/lang/en/motor-admin/category_trees.json +14 -0
- package/app/lang/en/motor-admin/clients.json +26 -0
- package/app/lang/en/motor-admin/config_variables.json +14 -0
- package/app/lang/en/motor-admin/domains.json +18 -0
- package/app/lang/en/motor-admin/email_templates.json +33 -0
- package/app/lang/en/motor-admin/global.json +5 -0
- package/app/lang/en/motor-admin/languages.json +16 -0
- package/app/lang/en/motor-admin/permissions.json +14 -0
- package/app/lang/en/motor-admin/roles.json +15 -0
- package/app/lang/en/motor-admin/users.json +22 -0
- package/app/pages/dashboard.vue +5 -0
- package/app/pages/index.vue +39 -0
- package/app/pages/login.vue +85 -0
- package/app/pages/motor-admin/ai-system-prompts/CLAUDE.md +7 -0
- package/app/pages/motor-admin/ai-system-prompts/[id]/edit.vue +48 -0
- package/app/pages/motor-admin/ai-system-prompts/create.vue +40 -0
- package/app/pages/motor-admin/ai-system-prompts/index.vue +68 -0
- package/app/pages/motor-admin/category-trees/CLAUDE.md +7 -0
- package/app/pages/motor-admin/category-trees/[id]/CLAUDE.md +7 -0
- package/app/pages/motor-admin/category-trees/[id]/categories/[categoryId]/edit.vue +73 -0
- package/app/pages/motor-admin/category-trees/[id]/categories/create.vue +64 -0
- package/app/pages/motor-admin/category-trees/[id]/edit.vue +45 -0
- package/app/pages/motor-admin/category-trees/[id]/index.vue +81 -0
- package/app/pages/motor-admin/category-trees/create.vue +37 -0
- package/app/pages/motor-admin/category-trees/index.vue +54 -0
- package/app/pages/motor-admin/clients/CLAUDE.md +11 -0
- package/app/pages/motor-admin/clients/[id]/CLAUDE.md +11 -0
- package/app/pages/motor-admin/clients/[id]/edit.vue +45 -0
- package/app/pages/motor-admin/clients/create.vue +37 -0
- package/app/pages/motor-admin/clients/index.vue +46 -0
- package/app/pages/motor-admin/config-variables/CLAUDE.md +11 -0
- package/app/pages/motor-admin/config-variables/[id]/edit.vue +44 -0
- package/app/pages/motor-admin/config-variables/create.vue +36 -0
- package/app/pages/motor-admin/config-variables/index.vue +66 -0
- package/app/pages/motor-admin/domains/CLAUDE.md +11 -0
- package/app/pages/motor-admin/domains/[id]/edit.vue +54 -0
- package/app/pages/motor-admin/domains/create.vue +46 -0
- package/app/pages/motor-admin/domains/index.vue +98 -0
- package/app/pages/motor-admin/email-templates/CLAUDE.md +12 -0
- package/app/pages/motor-admin/email-templates/[id]/CLAUDE.md +7 -0
- package/app/pages/motor-admin/email-templates/[id]/edit.vue +56 -0
- package/app/pages/motor-admin/email-templates/create.vue +48 -0
- package/app/pages/motor-admin/email-templates/index.vue +67 -0
- package/app/pages/motor-admin/index.vue +12 -0
- package/app/pages/motor-admin/languages/CLAUDE.md +7 -0
- package/app/pages/motor-admin/languages/[id]/edit.vue +44 -0
- package/app/pages/motor-admin/languages/create.vue +36 -0
- package/app/pages/motor-admin/languages/index.vue +44 -0
- package/app/pages/motor-admin/permission-groups/CLAUDE.md +14 -0
- package/app/pages/motor-admin/permission-groups/[id]/CLAUDE.md +11 -0
- package/app/pages/motor-admin/permission-groups/[id]/edit.vue +49 -0
- package/app/pages/motor-admin/permission-groups/create.vue +41 -0
- package/app/pages/motor-admin/permission-groups/index.vue +43 -0
- package/app/pages/motor-admin/roles/CLAUDE.md +7 -0
- package/app/pages/motor-admin/roles/[id]/edit.vue +47 -0
- package/app/pages/motor-admin/roles/create.vue +40 -0
- package/app/pages/motor-admin/roles/index.vue +45 -0
- package/app/pages/motor-admin/theme-preview/CLAUDE.md +7 -0
- package/app/pages/motor-admin/theme-preview/index.vue +4801 -0
- package/app/pages/motor-admin/theme-preview/themes/CLAUDE.md +11 -0
- package/app/pages/motor-admin/theme-preview/themes/asymmetric-brutalist.md +381 -0
- package/app/pages/motor-admin/theme-preview/themes/bold-modern.md +231 -0
- package/app/pages/motor-admin/theme-preview/themes/geometric-minimal.md +778 -0
- package/app/pages/motor-admin/theme-preview/themes/gradient-flow.md +1057 -0
- package/app/pages/motor-admin/theme-preview/themes/liquid-glass.md +823 -0
- package/app/pages/motor-admin/theme-preview/themes/neon-amber.md +1223 -0
- package/app/pages/motor-admin/theme-preview/themes/neon-terminal.md +779 -0
- package/app/pages/motor-admin/theme-preview/themes/neon-violet.md +1134 -0
- package/app/pages/motor-admin/theme-preview/themes/professional-clean.md +232 -0
- package/app/pages/motor-admin/theme-preview/themes/refined-brutalist.md +462 -0
- package/app/pages/motor-admin/theme-preview/themes/wild-card.md +263 -0
- package/app/pages/motor-admin/users/CLAUDE.md +17 -0
- package/app/pages/motor-admin/users/[id]/CLAUDE.md +11 -0
- package/app/pages/motor-admin/users/[id]/edit.vue +83 -0
- package/app/pages/motor-admin/users/create.vue +40 -0
- package/app/pages/motor-admin/users/index.vue +66 -0
- package/app/pages/profile.vue +363 -0
- package/app/pages/search.vue +91 -0
- package/app/types/generated/form-meta.ts +258 -0
- package/app/types/generated/grid-meta.ts +172 -0
- package/nuxt.config.ts +1 -0
- package/package.json +26 -0
|
@@ -0,0 +1,823 @@
|
|
|
1
|
+
# Liquid Glass Theme
|
|
2
|
+
|
|
3
|
+
**Inspired by:** Apple's Liquid Glass design language (iOS 26 / macOS Tahoe 26, WWDC 2025)
|
|
4
|
+
|
|
5
|
+
A premium, translucent admin panel theme built around frosted glass surfaces, layered depth, and subtle light refraction. Every surface feels like polished glass floating over a softly lit background -- sophisticated, airy, and unmistakably modern.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## 1. Color Palette
|
|
10
|
+
|
|
11
|
+
### Light Mode
|
|
12
|
+
|
|
13
|
+
| Token | Role | Hex | Tailwind | RGBA (glass use) |
|
|
14
|
+
|---|---|---|---|---|
|
|
15
|
+
| `--glass-bg` | Page background | `#EEF0F5` | `slate-100` | -- |
|
|
16
|
+
| `--glass-surface` | Glass panel fill | `#FFFFFF` | `white` | `rgba(255, 255, 255, 0.62)` |
|
|
17
|
+
| `--glass-surface-raised` | Raised glass fill | `#FFFFFF` | `white` | `rgba(255, 255, 255, 0.72)` |
|
|
18
|
+
| `--glass-surface-floating` | Modal / popover fill | `#FFFFFF` | `white` | `rgba(255, 255, 255, 0.80)` |
|
|
19
|
+
| `--glass-border` | Glass edge highlight | `#FFFFFF` | `white` | `rgba(255, 255, 255, 0.45)` |
|
|
20
|
+
| `--glass-border-subtle` | Secondary border | `#D1D5DB` | `gray-300` | `rgba(209, 213, 219, 0.35)` |
|
|
21
|
+
| `--glass-text-primary` | Body text | `#1C1C1E` | `gray-900` | -- |
|
|
22
|
+
| `--glass-text-secondary` | Muted text | `#636366` | `gray-500` | -- |
|
|
23
|
+
| `--glass-text-tertiary` | Placeholder text | `#AEAEB2` | `gray-400` | -- |
|
|
24
|
+
| `--glass-accent` | Primary accent | `#007AFF` | `blue-500` | `rgba(0, 122, 255, 0.15)` |
|
|
25
|
+
| `--glass-accent-hover` | Accent hover | `#0063D1` | `blue-600` | `rgba(0, 99, 209, 0.20)` |
|
|
26
|
+
| `--glass-success` | Success | `#34C759` | `green-500` | -- |
|
|
27
|
+
| `--glass-warning` | Warning | `#FF9500` | `orange-500` | -- |
|
|
28
|
+
| `--glass-error` | Error / destructive | `#FF3B30` | `red-500` | -- |
|
|
29
|
+
| `--glass-info` | Information | `#5AC8FA` | `cyan-400` | -- |
|
|
30
|
+
|
|
31
|
+
### Dark Mode
|
|
32
|
+
|
|
33
|
+
| Token | Role | Hex | Tailwind | RGBA (glass use) |
|
|
34
|
+
|---|---|---|---|---|
|
|
35
|
+
| `--glass-bg` | Page background | `#0A0A0F` | `gray-950` | -- |
|
|
36
|
+
| `--glass-surface` | Glass panel fill | `#1C1C1E` | `gray-900` | `rgba(28, 28, 30, 0.55)` |
|
|
37
|
+
| `--glass-surface-raised` | Raised glass fill | `#2C2C2E` | `gray-800` | `rgba(44, 44, 46, 0.65)` |
|
|
38
|
+
| `--glass-surface-floating` | Modal / popover fill | `#3A3A3C` | `gray-700` | `rgba(58, 58, 60, 0.75)` |
|
|
39
|
+
| `--glass-border` | Glass edge highlight | `#FFFFFF` | `white` | `rgba(255, 255, 255, 0.12)` |
|
|
40
|
+
| `--glass-border-subtle` | Secondary border | `#48484A` | `gray-600` | `rgba(72, 72, 74, 0.40)` |
|
|
41
|
+
| `--glass-text-primary` | Body text | `#F2F2F7` | `gray-100` | -- |
|
|
42
|
+
| `--glass-text-secondary` | Muted text | `#AEAEB2` | `gray-400` | -- |
|
|
43
|
+
| `--glass-text-tertiary` | Placeholder text | `#636366` | `gray-500` | -- |
|
|
44
|
+
| `--glass-accent` | Primary accent | `#0A84FF` | `blue-500` | `rgba(10, 132, 255, 0.20)` |
|
|
45
|
+
| `--glass-accent-hover` | Accent hover | `#409CFF` | `blue-400` | `rgba(64, 156, 255, 0.28)` |
|
|
46
|
+
| `--glass-success` | Success | `#30D158` | `green-400` | -- |
|
|
47
|
+
| `--glass-warning` | Warning | `#FF9F0A` | `orange-400` | -- |
|
|
48
|
+
| `--glass-error` | Error / destructive | `#FF453A` | `red-400` | -- |
|
|
49
|
+
| `--glass-info` | Information | `#64D2FF` | `cyan-300` | -- |
|
|
50
|
+
|
|
51
|
+
### NuxtUI Color Mapping
|
|
52
|
+
|
|
53
|
+
```ts
|
|
54
|
+
// nuxt.config.ts or app.config.ts
|
|
55
|
+
ui: {
|
|
56
|
+
colors: {
|
|
57
|
+
primary: 'blue', // Apple system blue
|
|
58
|
+
secondary: 'slate',
|
|
59
|
+
success: 'green',
|
|
60
|
+
warning: 'orange',
|
|
61
|
+
error: 'red',
|
|
62
|
+
info: 'cyan',
|
|
63
|
+
neutral: 'slate'
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
## 2. Glass Effect Definitions
|
|
71
|
+
|
|
72
|
+
Three tiers of glass elevation, from subtle to prominent.
|
|
73
|
+
|
|
74
|
+
### Surface Glass (cards, sidebar, table containers)
|
|
75
|
+
|
|
76
|
+
```css
|
|
77
|
+
.glass-surface {
|
|
78
|
+
background: rgba(255, 255, 255, 0.62);
|
|
79
|
+
backdrop-filter: blur(16px) saturate(180%);
|
|
80
|
+
-webkit-backdrop-filter: blur(16px) saturate(180%);
|
|
81
|
+
border: 1px solid rgba(255, 255, 255, 0.45);
|
|
82
|
+
box-shadow:
|
|
83
|
+
0 1px 3px rgba(0, 0, 0, 0.04),
|
|
84
|
+
0 4px 12px rgba(0, 0, 0, 0.03),
|
|
85
|
+
inset 0 1px 0 rgba(255, 255, 255, 0.5);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/* Dark mode */
|
|
89
|
+
.dark .glass-surface {
|
|
90
|
+
background: rgba(28, 28, 30, 0.55);
|
|
91
|
+
border: 1px solid rgba(255, 255, 255, 0.12);
|
|
92
|
+
box-shadow:
|
|
93
|
+
0 1px 3px rgba(0, 0, 0, 0.20),
|
|
94
|
+
0 4px 12px rgba(0, 0, 0, 0.15),
|
|
95
|
+
inset 0 1px 0 rgba(255, 255, 255, 0.06);
|
|
96
|
+
}
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
### Raised Glass (hovered cards, dropdowns, popovers)
|
|
100
|
+
|
|
101
|
+
```css
|
|
102
|
+
.glass-raised {
|
|
103
|
+
background: rgba(255, 255, 255, 0.72);
|
|
104
|
+
backdrop-filter: blur(24px) saturate(190%);
|
|
105
|
+
-webkit-backdrop-filter: blur(24px) saturate(190%);
|
|
106
|
+
border: 1px solid rgba(255, 255, 255, 0.50);
|
|
107
|
+
box-shadow:
|
|
108
|
+
0 2px 6px rgba(0, 0, 0, 0.05),
|
|
109
|
+
0 8px 24px rgba(0, 0, 0, 0.06),
|
|
110
|
+
inset 0 1px 0 rgba(255, 255, 255, 0.6);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/* Dark mode */
|
|
114
|
+
.dark .glass-raised {
|
|
115
|
+
background: rgba(44, 44, 46, 0.65);
|
|
116
|
+
border: 1px solid rgba(255, 255, 255, 0.15);
|
|
117
|
+
box-shadow:
|
|
118
|
+
0 2px 6px rgba(0, 0, 0, 0.25),
|
|
119
|
+
0 8px 24px rgba(0, 0, 0, 0.20),
|
|
120
|
+
inset 0 1px 0 rgba(255, 255, 255, 0.08);
|
|
121
|
+
}
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
### Floating Glass (modals, command palette, overlays)
|
|
125
|
+
|
|
126
|
+
```css
|
|
127
|
+
.glass-floating {
|
|
128
|
+
background: rgba(255, 255, 255, 0.80);
|
|
129
|
+
backdrop-filter: blur(40px) saturate(200%);
|
|
130
|
+
-webkit-backdrop-filter: blur(40px) saturate(200%);
|
|
131
|
+
border: 1px solid rgba(255, 255, 255, 0.55);
|
|
132
|
+
box-shadow:
|
|
133
|
+
0 4px 12px rgba(0, 0, 0, 0.06),
|
|
134
|
+
0 16px 48px rgba(0, 0, 0, 0.10),
|
|
135
|
+
inset 0 1px 0 rgba(255, 255, 255, 0.7);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/* Dark mode */
|
|
139
|
+
.dark .glass-floating {
|
|
140
|
+
background: rgba(58, 58, 60, 0.75);
|
|
141
|
+
border: 1px solid rgba(255, 255, 255, 0.18);
|
|
142
|
+
box-shadow:
|
|
143
|
+
0 4px 12px rgba(0, 0, 0, 0.30),
|
|
144
|
+
0 16px 48px rgba(0, 0, 0, 0.30),
|
|
145
|
+
inset 0 1px 0 rgba(255, 255, 255, 0.10);
|
|
146
|
+
}
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### Glass Tier Summary
|
|
150
|
+
|
|
151
|
+
| Tier | Blur | Saturate | Light BG Opacity | Dark BG Opacity | Use Case |
|
|
152
|
+
|---|---|---|---|---|---|
|
|
153
|
+
| Surface | `16px` | `180%` | `0.62` | `0.55` | Cards, sidebar, table wrappers |
|
|
154
|
+
| Raised | `24px` | `190%` | `0.72` | `0.65` | Hovered cards, dropdowns |
|
|
155
|
+
| Floating | `40px` | `200%` | `0.80` | `0.75` | Modals, command palette, overlays |
|
|
156
|
+
|
|
157
|
+
---
|
|
158
|
+
|
|
159
|
+
## 3. Background
|
|
160
|
+
|
|
161
|
+
The background behind the glass is critical -- it gives the glass surfaces their visual life. Without it, the translucency has nothing to refract and the effect falls flat.
|
|
162
|
+
|
|
163
|
+
### Light Mode Background
|
|
164
|
+
|
|
165
|
+
A subtle two-tone mesh gradient in cool slate tones with a hint of the accent blue. Calm and professional.
|
|
166
|
+
|
|
167
|
+
```css
|
|
168
|
+
body {
|
|
169
|
+
background-color: #EEF0F5;
|
|
170
|
+
background-image:
|
|
171
|
+
radial-gradient(ellipse at 20% 0%, rgba(0, 122, 255, 0.06) 0%, transparent 50%),
|
|
172
|
+
radial-gradient(ellipse at 80% 100%, rgba(175, 82, 222, 0.05) 0%, transparent 50%),
|
|
173
|
+
radial-gradient(ellipse at 50% 50%, rgba(90, 200, 250, 0.03) 0%, transparent 70%);
|
|
174
|
+
}
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
### Dark Mode Background
|
|
178
|
+
|
|
179
|
+
Deep near-black base with very subtle colored orbs that create gentle ambient light visible through the glass panels.
|
|
180
|
+
|
|
181
|
+
```css
|
|
182
|
+
body.dark {
|
|
183
|
+
background-color: #0A0A0F;
|
|
184
|
+
background-image:
|
|
185
|
+
radial-gradient(ellipse at 15% 10%, rgba(10, 132, 255, 0.08) 0%, transparent 45%),
|
|
186
|
+
radial-gradient(ellipse at 85% 90%, rgba(175, 82, 222, 0.06) 0%, transparent 45%),
|
|
187
|
+
radial-gradient(ellipse at 50% 50%, rgba(90, 200, 250, 0.03) 0%, transparent 60%);
|
|
188
|
+
}
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
### Tailwind Utility Approach
|
|
192
|
+
|
|
193
|
+
```html
|
|
194
|
+
<!-- Light mode wrapper -->
|
|
195
|
+
<div class="min-h-screen bg-slate-100
|
|
196
|
+
bg-[radial-gradient(ellipse_at_20%_0%,rgba(0,122,255,0.06)_0%,transparent_50%),radial-gradient(ellipse_at_80%_100%,rgba(175,82,222,0.05)_0%,transparent_50%)]">
|
|
197
|
+
</div>
|
|
198
|
+
|
|
199
|
+
<!-- Or use a CSS class in main.css for cleanliness -->
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
---
|
|
203
|
+
|
|
204
|
+
## 4. Font Pairing
|
|
205
|
+
|
|
206
|
+
Apple uses SF Pro, which is not available on the web. These alternatives closely match its geometric clarity, optical spacing, and neutral warmth.
|
|
207
|
+
|
|
208
|
+
### Primary: Inter
|
|
209
|
+
|
|
210
|
+
Clean, highly legible, designed for screens. Excellent at small sizes. Closest widely-available match to SF Pro.
|
|
211
|
+
|
|
212
|
+
### Monospace: JetBrains Mono
|
|
213
|
+
|
|
214
|
+
For code blocks, data tables, and technical content.
|
|
215
|
+
|
|
216
|
+
### Google Fonts Import
|
|
217
|
+
|
|
218
|
+
```
|
|
219
|
+
https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
### Font Scale
|
|
223
|
+
|
|
224
|
+
| Role | Weight | Size | Tracking |
|
|
225
|
+
|---|---|---|---|
|
|
226
|
+
| H1 (page title) | 700 (Bold) | 28px / 1.75rem | `-0.02em` |
|
|
227
|
+
| H2 (section title) | 600 (Semibold) | 22px / 1.375rem | `-0.01em` |
|
|
228
|
+
| H3 (card title) | 600 (Semibold) | 17px / 1.0625rem | `0` |
|
|
229
|
+
| Body | 400 (Regular) | 15px / 0.9375rem | `0` |
|
|
230
|
+
| Body small | 400 (Regular) | 13px / 0.8125rem | `0.01em` |
|
|
231
|
+
| Label / caption | 500 (Medium) | 12px / 0.75rem | `0.02em` |
|
|
232
|
+
| Code / mono | 400 (Regular) | 13px / 0.8125rem | `0` |
|
|
233
|
+
|
|
234
|
+
Apple favors tight negative letter-spacing on headings and neutral spacing on body text.
|
|
235
|
+
|
|
236
|
+
---
|
|
237
|
+
|
|
238
|
+
## 5. Shape Language
|
|
239
|
+
|
|
240
|
+
Generous, continuous rounded corners in the Apple tradition. Larger elements get larger radii.
|
|
241
|
+
|
|
242
|
+
### Border Radius Scale
|
|
243
|
+
|
|
244
|
+
| Element | Radius | Tailwind | Notes |
|
|
245
|
+
|---|---|---|---|
|
|
246
|
+
| Page-level panels (sidebar) | `20px` | `rounded-2xl` | Major structural containers |
|
|
247
|
+
| Cards | `16px` | `rounded-xl` | Content cards, table wrappers |
|
|
248
|
+
| Modals / dialogs | `20px` | `rounded-2xl` | Floating glass panels |
|
|
249
|
+
| Buttons (default) | `10px` | `rounded-[10px]` | Slightly softer than `lg` |
|
|
250
|
+
| Buttons (pill) | `9999px` | `rounded-full` | Toggle pills, tags |
|
|
251
|
+
| Inputs | `10px` | `rounded-[10px]` | Match button radius |
|
|
252
|
+
| Badges / chips | `8px` | `rounded-lg` | Small glass pills |
|
|
253
|
+
| Avatars | `9999px` | `rounded-full` | Always circular |
|
|
254
|
+
| Tooltips | `8px` | `rounded-lg` | Small floating glass |
|
|
255
|
+
| Dropdowns | `14px` | `rounded-[14px]` | Between card and button |
|
|
256
|
+
|
|
257
|
+
### Continuous Corners
|
|
258
|
+
|
|
259
|
+
Where possible, use `border-radius` with matched inner/outer radii (outer = inner + padding) to achieve Apple's "squircle" feel. CSS `border-radius` is close enough for web use.
|
|
260
|
+
|
|
261
|
+
---
|
|
262
|
+
|
|
263
|
+
## 6. Component Styling
|
|
264
|
+
|
|
265
|
+
### Sidebar
|
|
266
|
+
|
|
267
|
+
A tall glass panel pinned to the left, floating slightly above the mesh gradient background.
|
|
268
|
+
|
|
269
|
+
```css
|
|
270
|
+
.sidebar {
|
|
271
|
+
/* Surface glass */
|
|
272
|
+
background: rgba(255, 255, 255, 0.62);
|
|
273
|
+
backdrop-filter: blur(16px) saturate(180%);
|
|
274
|
+
-webkit-backdrop-filter: blur(16px) saturate(180%);
|
|
275
|
+
border-right: 1px solid rgba(255, 255, 255, 0.45);
|
|
276
|
+
box-shadow:
|
|
277
|
+
1px 0 4px rgba(0, 0, 0, 0.03),
|
|
278
|
+
inset 0 1px 0 rgba(255, 255, 255, 0.5);
|
|
279
|
+
border-radius: 0 20px 20px 0; /* rounded on the inside edge */
|
|
280
|
+
padding: 16px 12px;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
.sidebar-item {
|
|
284
|
+
padding: 8px 12px;
|
|
285
|
+
border-radius: 10px;
|
|
286
|
+
color: var(--glass-text-secondary);
|
|
287
|
+
transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
.sidebar-item:hover {
|
|
291
|
+
background: rgba(0, 122, 255, 0.08);
|
|
292
|
+
color: var(--glass-text-primary);
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
.sidebar-item.active {
|
|
296
|
+
background: rgba(0, 122, 255, 0.15);
|
|
297
|
+
color: #007AFF;
|
|
298
|
+
font-weight: 500;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
/* Dark mode */
|
|
302
|
+
.dark .sidebar {
|
|
303
|
+
background: rgba(28, 28, 30, 0.55);
|
|
304
|
+
border-right: 1px solid rgba(255, 255, 255, 0.10);
|
|
305
|
+
}
|
|
306
|
+
.dark .sidebar-item:hover {
|
|
307
|
+
background: rgba(10, 132, 255, 0.12);
|
|
308
|
+
}
|
|
309
|
+
.dark .sidebar-item.active {
|
|
310
|
+
background: rgba(10, 132, 255, 0.20);
|
|
311
|
+
color: #0A84FF;
|
|
312
|
+
}
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
### Cards
|
|
316
|
+
|
|
317
|
+
Frosted glass panels that float above the background with a subtle highlight edge on top.
|
|
318
|
+
|
|
319
|
+
```css
|
|
320
|
+
.card {
|
|
321
|
+
/* Surface glass */
|
|
322
|
+
background: rgba(255, 255, 255, 0.62);
|
|
323
|
+
backdrop-filter: blur(16px) saturate(180%);
|
|
324
|
+
-webkit-backdrop-filter: blur(16px) saturate(180%);
|
|
325
|
+
border: 1px solid rgba(255, 255, 255, 0.45);
|
|
326
|
+
border-radius: 16px;
|
|
327
|
+
padding: 20px;
|
|
328
|
+
box-shadow:
|
|
329
|
+
0 1px 3px rgba(0, 0, 0, 0.04),
|
|
330
|
+
0 4px 12px rgba(0, 0, 0, 0.03),
|
|
331
|
+
inset 0 1px 0 rgba(255, 255, 255, 0.5);
|
|
332
|
+
transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1);
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
.card:hover {
|
|
336
|
+
/* Elevated to raised glass */
|
|
337
|
+
background: rgba(255, 255, 255, 0.72);
|
|
338
|
+
backdrop-filter: blur(24px) saturate(190%);
|
|
339
|
+
box-shadow:
|
|
340
|
+
0 2px 6px rgba(0, 0, 0, 0.05),
|
|
341
|
+
0 8px 24px rgba(0, 0, 0, 0.06),
|
|
342
|
+
inset 0 1px 0 rgba(255, 255, 255, 0.6);
|
|
343
|
+
transform: translateY(-1px);
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
/* Dark mode */
|
|
347
|
+
.dark .card {
|
|
348
|
+
background: rgba(28, 28, 30, 0.55);
|
|
349
|
+
border: 1px solid rgba(255, 255, 255, 0.12);
|
|
350
|
+
}
|
|
351
|
+
.dark .card:hover {
|
|
352
|
+
background: rgba(44, 44, 46, 0.65);
|
|
353
|
+
border: 1px solid rgba(255, 255, 255, 0.15);
|
|
354
|
+
}
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
### Buttons
|
|
358
|
+
|
|
359
|
+
#### Primary Button (solid glass accent)
|
|
360
|
+
|
|
361
|
+
```css
|
|
362
|
+
.btn-primary {
|
|
363
|
+
background: rgba(0, 122, 255, 0.88);
|
|
364
|
+
backdrop-filter: blur(8px) saturate(160%);
|
|
365
|
+
-webkit-backdrop-filter: blur(8px) saturate(160%);
|
|
366
|
+
color: #FFFFFF;
|
|
367
|
+
border: 1px solid rgba(255, 255, 255, 0.20);
|
|
368
|
+
border-radius: 10px;
|
|
369
|
+
padding: 8px 18px;
|
|
370
|
+
font-weight: 500;
|
|
371
|
+
font-size: 14px;
|
|
372
|
+
box-shadow:
|
|
373
|
+
0 1px 3px rgba(0, 122, 255, 0.20),
|
|
374
|
+
inset 0 1px 0 rgba(255, 255, 255, 0.15);
|
|
375
|
+
transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
.btn-primary:hover {
|
|
379
|
+
background: rgba(0, 99, 209, 0.92);
|
|
380
|
+
box-shadow:
|
|
381
|
+
0 2px 8px rgba(0, 122, 255, 0.30),
|
|
382
|
+
inset 0 1px 0 rgba(255, 255, 255, 0.20);
|
|
383
|
+
transform: translateY(-0.5px);
|
|
384
|
+
}
|
|
385
|
+
```
|
|
386
|
+
|
|
387
|
+
#### Secondary Button (glass outline)
|
|
388
|
+
|
|
389
|
+
```css
|
|
390
|
+
.btn-secondary {
|
|
391
|
+
background: rgba(255, 255, 255, 0.40);
|
|
392
|
+
backdrop-filter: blur(12px) saturate(170%);
|
|
393
|
+
-webkit-backdrop-filter: blur(12px) saturate(170%);
|
|
394
|
+
color: #007AFF;
|
|
395
|
+
border: 1px solid rgba(0, 122, 255, 0.25);
|
|
396
|
+
border-radius: 10px;
|
|
397
|
+
padding: 8px 18px;
|
|
398
|
+
font-weight: 500;
|
|
399
|
+
font-size: 14px;
|
|
400
|
+
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.4);
|
|
401
|
+
transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
.btn-secondary:hover {
|
|
405
|
+
background: rgba(0, 122, 255, 0.10);
|
|
406
|
+
border-color: rgba(0, 122, 255, 0.40);
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
/* Dark mode */
|
|
410
|
+
.dark .btn-secondary {
|
|
411
|
+
background: rgba(255, 255, 255, 0.08);
|
|
412
|
+
color: #0A84FF;
|
|
413
|
+
border: 1px solid rgba(10, 132, 255, 0.30);
|
|
414
|
+
}
|
|
415
|
+
```
|
|
416
|
+
|
|
417
|
+
#### Ghost Button (minimal glass)
|
|
418
|
+
|
|
419
|
+
```css
|
|
420
|
+
.btn-ghost {
|
|
421
|
+
background: transparent;
|
|
422
|
+
color: var(--glass-text-secondary);
|
|
423
|
+
border: 1px solid transparent;
|
|
424
|
+
border-radius: 10px;
|
|
425
|
+
padding: 8px 18px;
|
|
426
|
+
transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
.btn-ghost:hover {
|
|
430
|
+
background: rgba(255, 255, 255, 0.35);
|
|
431
|
+
backdrop-filter: blur(8px);
|
|
432
|
+
border-color: rgba(255, 255, 255, 0.30);
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
.dark .btn-ghost:hover {
|
|
436
|
+
background: rgba(255, 255, 255, 0.06);
|
|
437
|
+
border-color: rgba(255, 255, 255, 0.10);
|
|
438
|
+
}
|
|
439
|
+
```
|
|
440
|
+
|
|
441
|
+
### Inputs
|
|
442
|
+
|
|
443
|
+
Glass input fields with a subtle inset shadow to suggest depth "into" the glass.
|
|
444
|
+
|
|
445
|
+
```css
|
|
446
|
+
.input {
|
|
447
|
+
background: rgba(255, 255, 255, 0.45);
|
|
448
|
+
backdrop-filter: blur(8px) saturate(160%);
|
|
449
|
+
-webkit-backdrop-filter: blur(8px) saturate(160%);
|
|
450
|
+
border: 1px solid rgba(209, 213, 219, 0.50);
|
|
451
|
+
border-radius: 10px;
|
|
452
|
+
padding: 10px 14px;
|
|
453
|
+
font-size: 15px;
|
|
454
|
+
color: var(--glass-text-primary);
|
|
455
|
+
box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.04);
|
|
456
|
+
transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
.input::placeholder {
|
|
460
|
+
color: var(--glass-text-tertiary);
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
.input:focus {
|
|
464
|
+
outline: none;
|
|
465
|
+
border-color: rgba(0, 122, 255, 0.50);
|
|
466
|
+
box-shadow:
|
|
467
|
+
inset 0 1px 3px rgba(0, 0, 0, 0.04),
|
|
468
|
+
0 0 0 3px rgba(0, 122, 255, 0.12);
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
/* Dark mode */
|
|
472
|
+
.dark .input {
|
|
473
|
+
background: rgba(255, 255, 255, 0.06);
|
|
474
|
+
border: 1px solid rgba(255, 255, 255, 0.12);
|
|
475
|
+
box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.15);
|
|
476
|
+
}
|
|
477
|
+
.dark .input:focus {
|
|
478
|
+
border-color: rgba(10, 132, 255, 0.50);
|
|
479
|
+
box-shadow:
|
|
480
|
+
inset 0 1px 3px rgba(0, 0, 0, 0.15),
|
|
481
|
+
0 0 0 3px rgba(10, 132, 255, 0.15);
|
|
482
|
+
}
|
|
483
|
+
```
|
|
484
|
+
|
|
485
|
+
### Modals / Dialogs
|
|
486
|
+
|
|
487
|
+
The most prominent glass tier. Heavy blur with a scrim overlay behind.
|
|
488
|
+
|
|
489
|
+
```css
|
|
490
|
+
.modal-overlay {
|
|
491
|
+
background: rgba(0, 0, 0, 0.25);
|
|
492
|
+
backdrop-filter: blur(4px);
|
|
493
|
+
-webkit-backdrop-filter: blur(4px);
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
.modal {
|
|
497
|
+
/* Floating glass */
|
|
498
|
+
background: rgba(255, 255, 255, 0.80);
|
|
499
|
+
backdrop-filter: blur(40px) saturate(200%);
|
|
500
|
+
-webkit-backdrop-filter: blur(40px) saturate(200%);
|
|
501
|
+
border: 1px solid rgba(255, 255, 255, 0.55);
|
|
502
|
+
border-radius: 20px;
|
|
503
|
+
padding: 28px;
|
|
504
|
+
box-shadow:
|
|
505
|
+
0 4px 12px rgba(0, 0, 0, 0.06),
|
|
506
|
+
0 16px 48px rgba(0, 0, 0, 0.10),
|
|
507
|
+
inset 0 1px 0 rgba(255, 255, 255, 0.7);
|
|
508
|
+
max-width: 520px;
|
|
509
|
+
width: 100%;
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
/* Dark mode */
|
|
513
|
+
.dark .modal-overlay {
|
|
514
|
+
background: rgba(0, 0, 0, 0.50);
|
|
515
|
+
}
|
|
516
|
+
.dark .modal {
|
|
517
|
+
background: rgba(58, 58, 60, 0.75);
|
|
518
|
+
border: 1px solid rgba(255, 255, 255, 0.18);
|
|
519
|
+
}
|
|
520
|
+
```
|
|
521
|
+
|
|
522
|
+
### Navigation Bar (top bar)
|
|
523
|
+
|
|
524
|
+
A horizontal glass strip across the top of the content area.
|
|
525
|
+
|
|
526
|
+
```css
|
|
527
|
+
.navbar {
|
|
528
|
+
background: rgba(255, 255, 255, 0.60);
|
|
529
|
+
backdrop-filter: blur(20px) saturate(180%);
|
|
530
|
+
-webkit-backdrop-filter: blur(20px) saturate(180%);
|
|
531
|
+
border-bottom: 1px solid rgba(255, 255, 255, 0.40);
|
|
532
|
+
box-shadow:
|
|
533
|
+
0 1px 2px rgba(0, 0, 0, 0.03),
|
|
534
|
+
inset 0 -1px 0 rgba(0, 0, 0, 0.03);
|
|
535
|
+
padding: 0 20px;
|
|
536
|
+
height: 56px;
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
.dark .navbar {
|
|
540
|
+
background: rgba(28, 28, 30, 0.50);
|
|
541
|
+
border-bottom: 1px solid rgba(255, 255, 255, 0.08);
|
|
542
|
+
}
|
|
543
|
+
```
|
|
544
|
+
|
|
545
|
+
### Badges / Chips
|
|
546
|
+
|
|
547
|
+
Small glass pills for status indicators and tags.
|
|
548
|
+
|
|
549
|
+
```css
|
|
550
|
+
.badge {
|
|
551
|
+
background: rgba(255, 255, 255, 0.50);
|
|
552
|
+
backdrop-filter: blur(8px);
|
|
553
|
+
-webkit-backdrop-filter: blur(8px);
|
|
554
|
+
border: 1px solid rgba(255, 255, 255, 0.35);
|
|
555
|
+
border-radius: 8px;
|
|
556
|
+
padding: 3px 10px;
|
|
557
|
+
font-size: 12px;
|
|
558
|
+
font-weight: 500;
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
.badge-accent {
|
|
562
|
+
background: rgba(0, 122, 255, 0.12);
|
|
563
|
+
color: #007AFF;
|
|
564
|
+
border: 1px solid rgba(0, 122, 255, 0.20);
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
.badge-success {
|
|
568
|
+
background: rgba(52, 199, 89, 0.12);
|
|
569
|
+
color: #248A3D;
|
|
570
|
+
border: 1px solid rgba(52, 199, 89, 0.20);
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
.badge-warning {
|
|
574
|
+
background: rgba(255, 149, 0, 0.12);
|
|
575
|
+
color: #C93400;
|
|
576
|
+
border: 1px solid rgba(255, 149, 0, 0.20);
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
.badge-error {
|
|
580
|
+
background: rgba(255, 59, 48, 0.12);
|
|
581
|
+
color: #D70015;
|
|
582
|
+
border: 1px solid rgba(255, 59, 48, 0.20);
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
/* Dark mode badges use lighter text */
|
|
586
|
+
.dark .badge-accent { color: #0A84FF; }
|
|
587
|
+
.dark .badge-success { color: #30D158; }
|
|
588
|
+
.dark .badge-warning { color: #FF9F0A; }
|
|
589
|
+
.dark .badge-error { color: #FF453A; }
|
|
590
|
+
```
|
|
591
|
+
|
|
592
|
+
### Data Table
|
|
593
|
+
|
|
594
|
+
```css
|
|
595
|
+
.table-wrapper {
|
|
596
|
+
/* Surface glass */
|
|
597
|
+
background: rgba(255, 255, 255, 0.62);
|
|
598
|
+
backdrop-filter: blur(16px) saturate(180%);
|
|
599
|
+
-webkit-backdrop-filter: blur(16px) saturate(180%);
|
|
600
|
+
border: 1px solid rgba(255, 255, 255, 0.45);
|
|
601
|
+
border-radius: 16px;
|
|
602
|
+
overflow: hidden;
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
.table-header {
|
|
606
|
+
background: rgba(0, 0, 0, 0.02);
|
|
607
|
+
border-bottom: 1px solid rgba(0, 0, 0, 0.06);
|
|
608
|
+
font-weight: 500;
|
|
609
|
+
font-size: 12px;
|
|
610
|
+
text-transform: uppercase;
|
|
611
|
+
letter-spacing: 0.04em;
|
|
612
|
+
color: var(--glass-text-secondary);
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
.table-row {
|
|
616
|
+
border-bottom: 1px solid rgba(0, 0, 0, 0.04);
|
|
617
|
+
transition: background 0.15s ease;
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
.table-row:hover {
|
|
621
|
+
background: rgba(0, 122, 255, 0.04);
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
.table-row:last-child {
|
|
625
|
+
border-bottom: none;
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
/* Dark mode */
|
|
629
|
+
.dark .table-header {
|
|
630
|
+
background: rgba(255, 255, 255, 0.03);
|
|
631
|
+
border-bottom: 1px solid rgba(255, 255, 255, 0.06);
|
|
632
|
+
}
|
|
633
|
+
.dark .table-row {
|
|
634
|
+
border-bottom: 1px solid rgba(255, 255, 255, 0.04);
|
|
635
|
+
}
|
|
636
|
+
.dark .table-row:hover {
|
|
637
|
+
background: rgba(10, 132, 255, 0.06);
|
|
638
|
+
}
|
|
639
|
+
```
|
|
640
|
+
|
|
641
|
+
---
|
|
642
|
+
|
|
643
|
+
## 7. Depth System
|
|
644
|
+
|
|
645
|
+
Three elevation levels that create spatial hierarchy through increasing glass intensity.
|
|
646
|
+
|
|
647
|
+
| Level | Name | Blur | BG Opacity (light) | BG Opacity (dark) | Shadow Depth | Use |
|
|
648
|
+
|---|---|---|---|---|---|---|
|
|
649
|
+
| 0 | Surface | `16px` | `0.62` | `0.55` | Subtle | Sidebar, cards, table wrappers, nav |
|
|
650
|
+
| 1 | Raised | `24px` | `0.72` | `0.65` | Medium | Hovered cards, dropdowns, popovers |
|
|
651
|
+
| 2 | Floating | `40px` | `0.80` | `0.75` | Prominent | Modals, command palette, toasts |
|
|
652
|
+
|
|
653
|
+
### Depth Transitions
|
|
654
|
+
|
|
655
|
+
When an element changes elevation (e.g., card hover), animate smoothly:
|
|
656
|
+
|
|
657
|
+
```css
|
|
658
|
+
transition: all 0.25s cubic-bezier(0.4, 0, 0.2, 1);
|
|
659
|
+
```
|
|
660
|
+
|
|
661
|
+
This cubic-bezier matches Apple's standard ease curve -- quick start, gentle deceleration.
|
|
662
|
+
|
|
663
|
+
---
|
|
664
|
+
|
|
665
|
+
## 8. Light and Dark Mode Summary
|
|
666
|
+
|
|
667
|
+
### Light Mode Personality
|
|
668
|
+
|
|
669
|
+
- **Base feel:** Bright, airy, open -- like looking through a frosted window on a clear day
|
|
670
|
+
- **Background:** Cool slate (`#EEF0F5`) with subtle blue/purple radial tints
|
|
671
|
+
- **Glass:** White at varying transparency. The `inset 0 1px 0 rgba(255,255,255,0.5)` top highlight is key -- it simulates light catching the top edge of the glass
|
|
672
|
+
- **Shadows:** Very soft, barely there. Just enough to separate layers
|
|
673
|
+
- **Text:** Near-black primary (`#1C1C1E`), true Apple system gray secondary
|
|
674
|
+
- **Accent:** Apple system blue `#007AFF` with translucent fills for active states
|
|
675
|
+
|
|
676
|
+
### Dark Mode Personality
|
|
677
|
+
|
|
678
|
+
- **Base feel:** Deep, moody, cinematic -- glass panels glow faintly against a dark void
|
|
679
|
+
- **Background:** Near-black (`#0A0A0F`) with subtle colored orbs bleeding through the glass
|
|
680
|
+
- **Glass:** Dark gray at varying transparency. The `inset` highlight becomes much subtler (`rgba(255,255,255,0.06-0.10)`) -- just a faint shimmer
|
|
681
|
+
- **Shadows:** Deeper and more diffuse. Essential for separating dark-on-dark surfaces
|
|
682
|
+
- **Text:** Off-white primary (`#F2F2F7`), muted gray secondary
|
|
683
|
+
- **Accent:** Slightly brighter Apple blue `#0A84FF` -- the dark mode variant Apple uses to maintain contrast
|
|
684
|
+
|
|
685
|
+
### Mode Transition
|
|
686
|
+
|
|
687
|
+
All glass properties should transition smoothly when switching modes:
|
|
688
|
+
|
|
689
|
+
```css
|
|
690
|
+
* {
|
|
691
|
+
transition: background 0.3s ease, border-color 0.3s ease, box-shadow 0.3s ease, color 0.3s ease;
|
|
692
|
+
}
|
|
693
|
+
```
|
|
694
|
+
|
|
695
|
+
---
|
|
696
|
+
|
|
697
|
+
## 9. Accessibility Notes
|
|
698
|
+
|
|
699
|
+
Apple's Liquid Glass has drawn criticism for contrast and legibility issues. This spec addresses those concerns for an admin panel context where readability is paramount.
|
|
700
|
+
|
|
701
|
+
- **Text contrast:** All text-on-glass combinations meet WCAG AA (4.5:1 for body, 3:1 for large text). The glass opacity values in this spec are deliberately higher than pure glassmorphism demos to ensure readable surfaces.
|
|
702
|
+
- **Focus rings:** Use a visible 3px accent-colored ring (`0 0 0 3px rgba(0, 122, 255, 0.12)`) on all interactive elements.
|
|
703
|
+
- **Reduced motion:** Respect `prefers-reduced-motion` -- disable hover transforms, simplify transitions.
|
|
704
|
+
- **Reduced transparency:** Respect `prefers-contrast: more` -- increase glass opacity to `0.90+` and remove `backdrop-filter` for users who need solid surfaces.
|
|
705
|
+
|
|
706
|
+
```css
|
|
707
|
+
@media (prefers-contrast: more) {
|
|
708
|
+
.glass-surface,
|
|
709
|
+
.glass-raised,
|
|
710
|
+
.glass-floating {
|
|
711
|
+
background: rgba(255, 255, 255, 0.95);
|
|
712
|
+
backdrop-filter: none;
|
|
713
|
+
}
|
|
714
|
+
.dark .glass-surface,
|
|
715
|
+
.dark .glass-raised,
|
|
716
|
+
.dark .glass-floating {
|
|
717
|
+
background: rgba(28, 28, 30, 0.95);
|
|
718
|
+
backdrop-filter: none;
|
|
719
|
+
}
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
@media (prefers-reduced-motion: reduce) {
|
|
723
|
+
* {
|
|
724
|
+
transition-duration: 0.01ms !important;
|
|
725
|
+
transform: none !important;
|
|
726
|
+
}
|
|
727
|
+
}
|
|
728
|
+
```
|
|
729
|
+
|
|
730
|
+
---
|
|
731
|
+
|
|
732
|
+
## 10. Performance Considerations
|
|
733
|
+
|
|
734
|
+
`backdrop-filter` is GPU-composited but can be expensive when stacked. Guidelines:
|
|
735
|
+
|
|
736
|
+
- Limit to 3-4 glass surfaces visible at once (sidebar + navbar + 1-2 cards is fine)
|
|
737
|
+
- Avoid nesting glass-on-glass (a glass card inside a glass sidebar creates double blur)
|
|
738
|
+
- Use `will-change: backdrop-filter` sparingly and only on animated elements
|
|
739
|
+
- Keep blur values under 40px for most elements (the floating tier is the maximum)
|
|
740
|
+
- Test on mid-range hardware; reduce blur or increase opacity as a fallback
|
|
741
|
+
|
|
742
|
+
---
|
|
743
|
+
|
|
744
|
+
## 11. CSS Custom Properties (full set)
|
|
745
|
+
|
|
746
|
+
For easy theming, define all values as custom properties on `:root` and `.dark`:
|
|
747
|
+
|
|
748
|
+
```css
|
|
749
|
+
:root {
|
|
750
|
+
/* Background */
|
|
751
|
+
--glass-page-bg: #EEF0F5;
|
|
752
|
+
|
|
753
|
+
/* Glass surfaces */
|
|
754
|
+
--glass-surface-bg: rgba(255, 255, 255, 0.62);
|
|
755
|
+
--glass-raised-bg: rgba(255, 255, 255, 0.72);
|
|
756
|
+
--glass-floating-bg: rgba(255, 255, 255, 0.80);
|
|
757
|
+
|
|
758
|
+
/* Blur */
|
|
759
|
+
--glass-blur-surface: blur(16px) saturate(180%);
|
|
760
|
+
--glass-blur-raised: blur(24px) saturate(190%);
|
|
761
|
+
--glass-blur-floating: blur(40px) saturate(200%);
|
|
762
|
+
|
|
763
|
+
/* Borders */
|
|
764
|
+
--glass-border: rgba(255, 255, 255, 0.45);
|
|
765
|
+
--glass-border-subtle: rgba(209, 213, 219, 0.35);
|
|
766
|
+
|
|
767
|
+
/* Inset highlight */
|
|
768
|
+
--glass-inset-highlight: inset 0 1px 0 rgba(255, 255, 255, 0.5);
|
|
769
|
+
|
|
770
|
+
/* Text */
|
|
771
|
+
--glass-text-primary: #1C1C1E;
|
|
772
|
+
--glass-text-secondary: #636366;
|
|
773
|
+
--glass-text-tertiary: #AEAEB2;
|
|
774
|
+
|
|
775
|
+
/* Accent */
|
|
776
|
+
--glass-accent: #007AFF;
|
|
777
|
+
--glass-accent-tint: rgba(0, 122, 255, 0.15);
|
|
778
|
+
--glass-accent-hover: rgba(0, 122, 255, 0.10);
|
|
779
|
+
|
|
780
|
+
/* Semantic */
|
|
781
|
+
--glass-success: #34C759;
|
|
782
|
+
--glass-warning: #FF9500;
|
|
783
|
+
--glass-error: #FF3B30;
|
|
784
|
+
--glass-info: #5AC8FA;
|
|
785
|
+
|
|
786
|
+
/* Shape */
|
|
787
|
+
--glass-radius-sm: 8px;
|
|
788
|
+
--glass-radius-md: 10px;
|
|
789
|
+
--glass-radius-lg: 14px;
|
|
790
|
+
--glass-radius-xl: 16px;
|
|
791
|
+
--glass-radius-2xl: 20px;
|
|
792
|
+
|
|
793
|
+
/* Motion */
|
|
794
|
+
--glass-ease: cubic-bezier(0.4, 0, 0.2, 1);
|
|
795
|
+
--glass-duration: 0.25s;
|
|
796
|
+
}
|
|
797
|
+
|
|
798
|
+
.dark {
|
|
799
|
+
--glass-page-bg: #0A0A0F;
|
|
800
|
+
|
|
801
|
+
--glass-surface-bg: rgba(28, 28, 30, 0.55);
|
|
802
|
+
--glass-raised-bg: rgba(44, 44, 46, 0.65);
|
|
803
|
+
--glass-floating-bg: rgba(58, 58, 60, 0.75);
|
|
804
|
+
|
|
805
|
+
--glass-border: rgba(255, 255, 255, 0.12);
|
|
806
|
+
--glass-border-subtle: rgba(72, 72, 74, 0.40);
|
|
807
|
+
|
|
808
|
+
--glass-inset-highlight: inset 0 1px 0 rgba(255, 255, 255, 0.06);
|
|
809
|
+
|
|
810
|
+
--glass-text-primary: #F2F2F7;
|
|
811
|
+
--glass-text-secondary: #AEAEB2;
|
|
812
|
+
--glass-text-tertiary: #636366;
|
|
813
|
+
|
|
814
|
+
--glass-accent: #0A84FF;
|
|
815
|
+
--glass-accent-tint: rgba(10, 132, 255, 0.20);
|
|
816
|
+
--glass-accent-hover: rgba(10, 132, 255, 0.12);
|
|
817
|
+
|
|
818
|
+
--glass-success: #30D158;
|
|
819
|
+
--glass-warning: #FF9F0A;
|
|
820
|
+
--glass-error: #FF453A;
|
|
821
|
+
--glass-info: #64D2FF;
|
|
822
|
+
}
|
|
823
|
+
```
|