@jungherz-de/glasskit 1.3.4 → 1.4.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/CHANGELOG.md +68 -3
- package/README.md +43 -11
- package/SKILL.md +1518 -0
- package/glasskit-styles.js +2 -2
- package/glasskit.css +236 -12
- package/glasskit.min.css +1 -1
- package/package.json +4 -3
package/SKILL.md
ADDED
|
@@ -0,0 +1,1518 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: glasskit-css
|
|
3
|
+
description: GlassKit is a pure CSS glassmorphism component library (v1.4.0) with 24 components, Dark & Light mode, design tokens, and BEM-like naming. Use this reference whenever generating HTML that uses GlassKit classes to ensure correct structure, nesting, modifiers, and token usage.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# GlassKit CSS – AI Component Reference
|
|
7
|
+
|
|
8
|
+
> **Purpose:** This document is an AI-optimized reference for generating correct GlassKit HTML markup.
|
|
9
|
+
> It replaces the need to parse `docs.html` and provides copy-paste-ready structures, rules, and composition patterns.
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## 1. Setup & Boilerplate
|
|
14
|
+
|
|
15
|
+
### Including the Library
|
|
16
|
+
|
|
17
|
+
```html
|
|
18
|
+
<!-- CDN (recommended) -->
|
|
19
|
+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@jungherz-de/glasskit@1.4/glasskit.min.css">
|
|
20
|
+
|
|
21
|
+
<!-- Local -->
|
|
22
|
+
<link rel="stylesheet" href="glasskit.css">
|
|
23
|
+
|
|
24
|
+
<!-- Optional: Load custom theme after base library -->
|
|
25
|
+
<link rel="stylesheet" href="theme-override.css">
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
### Minimal Template
|
|
29
|
+
|
|
30
|
+
```html
|
|
31
|
+
<!DOCTYPE html>
|
|
32
|
+
<html lang="en" data-theme="dark">
|
|
33
|
+
<head>
|
|
34
|
+
<meta charset="UTF-8">
|
|
35
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
36
|
+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@jungherz-de/glasskit@1.4/glasskit.min.css">
|
|
37
|
+
</head>
|
|
38
|
+
<body>
|
|
39
|
+
<div class="glass-bg">
|
|
40
|
+
<!-- All content goes here -->
|
|
41
|
+
</div>
|
|
42
|
+
</body>
|
|
43
|
+
</html>
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### Naming Convention
|
|
47
|
+
|
|
48
|
+
- **Prefix:** All components use `glass-` (e.g. `glass-card`, `glass-btn`)
|
|
49
|
+
- **Utilities:** Use `gl-` (e.g. `gl-stack`, `gl-row`, `gl-mt-md`)
|
|
50
|
+
- **BEM logic:** `glass-component__element--modifier`
|
|
51
|
+
- Element: `glass-card__text`, `glass-modal__header`
|
|
52
|
+
- Modifier: `glass-btn--primary`, `glass-avatar--lg`
|
|
53
|
+
- **State classes:** `is-active`, `is-open`, `is-visible` (standalone, not BEM)
|
|
54
|
+
|
|
55
|
+
### Theming
|
|
56
|
+
|
|
57
|
+
The theme is controlled via `data-theme` on `<html>`:
|
|
58
|
+
|
|
59
|
+
```html
|
|
60
|
+
<!-- Dark Mode (default) -->
|
|
61
|
+
<html data-theme="dark">
|
|
62
|
+
|
|
63
|
+
<!-- Light Mode -->
|
|
64
|
+
<html data-theme="light">
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Toggle theme via JavaScript:
|
|
68
|
+
|
|
69
|
+
```js
|
|
70
|
+
function toggleTheme() {
|
|
71
|
+
const html = document.documentElement;
|
|
72
|
+
const current = html.getAttribute('data-theme');
|
|
73
|
+
html.setAttribute('data-theme', current === 'dark' ? 'light' : 'dark');
|
|
74
|
+
}
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
---
|
|
78
|
+
|
|
79
|
+
## 2. Design Tokens
|
|
80
|
+
|
|
81
|
+
All visual values are controlled via CSS Custom Properties. For custom theming, override them in a `theme-override.css`.
|
|
82
|
+
|
|
83
|
+
### Colors
|
|
84
|
+
|
|
85
|
+
| Token | Dark | Light | Usage |
|
|
86
|
+
|---|---|---|---|
|
|
87
|
+
| `--gl-color-primary` | `#f5a623` | `#e8852d` | Primary color, buttons, active elements |
|
|
88
|
+
| `--gl-color-primary-dark` | `#d4692a` | `#c96a1e` | Gradient end value |
|
|
89
|
+
| `--gl-color-primary-mid` | `#e07a24` | `#d97826` | Gradient midpoint |
|
|
90
|
+
| `--gl-color-text` | `#ffffff` | `#1a2a36` | Default text color |
|
|
91
|
+
| `--gl-color-text-muted` | `rgba(255,255,255,0.60)` | `rgba(26,42,54,0.55)` | Secondary text |
|
|
92
|
+
| `--gl-color-text-heading` | `#ffffff` | `#0f1f2a` | Headings |
|
|
93
|
+
| `--gl-color-success` | `#34c759` | `#28a745` | Success |
|
|
94
|
+
| `--gl-color-error` | `#ff3b30` | `#dc3545` | Error |
|
|
95
|
+
| `--gl-color-warning` | `#ffcc00` | `#e6a800` | Warning |
|
|
96
|
+
|
|
97
|
+
### Glass Surfaces
|
|
98
|
+
|
|
99
|
+
| Token | Dark | Usage |
|
|
100
|
+
|---|---|---|
|
|
101
|
+
| `--gl-surface-1` | `rgba(255,255,255, 0.08)` | Subtlest surface (status) |
|
|
102
|
+
| `--gl-surface-2` | `rgba(255,255,255, 0.10)` | Default (inputs, cards) |
|
|
103
|
+
| `--gl-surface-3` | `rgba(255,255,255, 0.14)` | Nav pills, badges |
|
|
104
|
+
| `--gl-surface-4` | `rgba(255,255,255, 0.16)` | Hover states |
|
|
105
|
+
| `--gl-surface-5` | `rgba(255,255,255, 0.22)` | Strong hover |
|
|
106
|
+
| `--gl-surface-milk` | `rgba(255,255,255, 0.55)` | Milky |
|
|
107
|
+
| `--gl-surface-milk-strong` | `rgba(255,255,255, 0.75)` | Secondary button |
|
|
108
|
+
| `--gl-surface-overlay` | `rgba(0,0,0, 0.50)` | Modal overlay |
|
|
109
|
+
|
|
110
|
+
### Borders
|
|
111
|
+
|
|
112
|
+
| Token | Value |
|
|
113
|
+
|---|---|
|
|
114
|
+
| `--gl-border-subtle` | `rgba(255,255,255, 0.18)` |
|
|
115
|
+
| `--gl-border-medium` | `rgba(255,255,255, 0.30)` |
|
|
116
|
+
| `--gl-border-strong` | `rgba(255,255,255, 0.40)` |
|
|
117
|
+
| `--gl-border-milk` | `rgba(255,255,255, 0.60)` |
|
|
118
|
+
| `--gl-border-warm` | `rgba(255,200,100, 0.35)` |
|
|
119
|
+
| `--gl-border-focus` | `rgba(245,166,35, 0.60)` |
|
|
120
|
+
|
|
121
|
+
### Blur
|
|
122
|
+
|
|
123
|
+
| Token | Value |
|
|
124
|
+
|---|---|
|
|
125
|
+
| `--gl-blur` | `24px` (default) |
|
|
126
|
+
| `--gl-blur-light` | `16px` |
|
|
127
|
+
| `--gl-blur-soft` | `12px` |
|
|
128
|
+
| `--gl-blur-heavy` | `40px` |
|
|
129
|
+
|
|
130
|
+
### Radii
|
|
131
|
+
|
|
132
|
+
| Token | Value | Usage |
|
|
133
|
+
|---|---|---|
|
|
134
|
+
| `--gl-radius-xs` | `8px` | Small elements |
|
|
135
|
+
| `--gl-radius-sm` | `12px` | Badges, small containers |
|
|
136
|
+
| `--gl-radius-input` | `14px` | Inputs, textareas |
|
|
137
|
+
| `--gl-radius-btn` | `16px` | Buttons |
|
|
138
|
+
| `--gl-radius-card` | `24px` | Cards |
|
|
139
|
+
| `--gl-radius-full` | `9999px` | Fully rounded |
|
|
140
|
+
| `--gl-radius-pill` | `50%` | Circle shape |
|
|
141
|
+
|
|
142
|
+
### Spacing
|
|
143
|
+
|
|
144
|
+
| Token | Value |
|
|
145
|
+
|---|---|
|
|
146
|
+
| `--gl-space-2xs` | `4px` |
|
|
147
|
+
| `--gl-space-xs` | `8px` |
|
|
148
|
+
| `--gl-space-sm` | `12px` |
|
|
149
|
+
| `--gl-space-md` | `16px` |
|
|
150
|
+
| `--gl-space-lg` | `20px` |
|
|
151
|
+
| `--gl-space-xl` | `24px` |
|
|
152
|
+
| `--gl-space-2xl` | `32px` |
|
|
153
|
+
| `--gl-space-3xl` | `40px` |
|
|
154
|
+
| `--gl-space-4xl` | `56px` |
|
|
155
|
+
|
|
156
|
+
### Shadows
|
|
157
|
+
|
|
158
|
+
| Token | Usage |
|
|
159
|
+
|---|---|
|
|
160
|
+
| `--gl-shadow-card` | Cards |
|
|
161
|
+
| `--gl-shadow-btn` | Default buttons |
|
|
162
|
+
| `--gl-shadow-btn-primary` | Primary button (orange glow) |
|
|
163
|
+
| `--gl-shadow-glow` | Glow effect |
|
|
164
|
+
| `--gl-shadow-modal` | Modal dialog |
|
|
165
|
+
| `--gl-shadow-toast` | Toast notifications |
|
|
166
|
+
| `--gl-shadow-focus` | Focus ring |
|
|
167
|
+
|
|
168
|
+
### Typography
|
|
169
|
+
|
|
170
|
+
| Token | Value |
|
|
171
|
+
|---|---|
|
|
172
|
+
| `--gl-font-size-xs` | `13px` |
|
|
173
|
+
| `--gl-font-size-sm` | `14px` |
|
|
174
|
+
| `--gl-font-size-base` | `15px` |
|
|
175
|
+
| `--gl-font-size-btn` | `16px` |
|
|
176
|
+
| `--gl-font-size-lg` | `18px` |
|
|
177
|
+
| `--gl-font-size-title` | `24px` |
|
|
178
|
+
| `--gl-font-size-modal` | `20px` |
|
|
179
|
+
| `--gl-font-weight-normal` | `400` |
|
|
180
|
+
| `--gl-font-weight-medium` | `500` |
|
|
181
|
+
| `--gl-font-weight-semibold` | `600` |
|
|
182
|
+
|
|
183
|
+
---
|
|
184
|
+
|
|
185
|
+
## 3. Component Catalog
|
|
186
|
+
|
|
187
|
+
### 3.1 Background
|
|
188
|
+
|
|
189
|
+
The outermost container element. Creates the aurora background with light effects. **Must always be used as the wrapper for all content.**
|
|
190
|
+
|
|
191
|
+
```html
|
|
192
|
+
<div class="glass-bg">
|
|
193
|
+
<!-- All content goes here -->
|
|
194
|
+
</div>
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
With Tab-Bar (adds bottom padding):
|
|
198
|
+
|
|
199
|
+
```html
|
|
200
|
+
<div class="glass-bg glass-bg--has-tab-bar">
|
|
201
|
+
<!-- Content -->
|
|
202
|
+
<nav class="glass-tab-bar">...</nav>
|
|
203
|
+
</div>
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
| Class | Description |
|
|
207
|
+
|---|---|
|
|
208
|
+
| `.glass-bg` | Full-screen background with aurora light effects |
|
|
209
|
+
| `.glass-bg--has-tab-bar` | Modifier: bottom padding for tab bar (82px) |
|
|
210
|
+
|
|
211
|
+
---
|
|
212
|
+
|
|
213
|
+
### 3.2 Navigation Bar
|
|
214
|
+
|
|
215
|
+
Transparent navigation bar. Typically contains `glass-pill` buttons.
|
|
216
|
+
|
|
217
|
+
```html
|
|
218
|
+
<nav class="glass-nav">
|
|
219
|
+
<button class="glass-pill">
|
|
220
|
+
<svg viewBox="0 0 24 24"><polyline points="15 18 9 12 15 6"/></svg>
|
|
221
|
+
</button>
|
|
222
|
+
<button class="glass-pill">
|
|
223
|
+
<svg viewBox="0 0 24 24"><!-- Icon --></svg>
|
|
224
|
+
</button>
|
|
225
|
+
</nav>
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
| Class | Description |
|
|
229
|
+
|---|---|
|
|
230
|
+
| `.glass-nav` | Flex container with `space-between`, padding |
|
|
231
|
+
|
|
232
|
+
---
|
|
233
|
+
|
|
234
|
+
### 3.3 Pill Button
|
|
235
|
+
|
|
236
|
+
Round glass icon buttons (46×46px). Used in nav bars and as standalone action buttons.
|
|
237
|
+
|
|
238
|
+
```html
|
|
239
|
+
<button class="glass-pill">
|
|
240
|
+
<svg viewBox="0 0 24 24"><!-- Icon SVG --></svg>
|
|
241
|
+
</button>
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
| Class | Description |
|
|
245
|
+
|---|---|
|
|
246
|
+
| `.glass-pill` | Round glass button (46×46px) |
|
|
247
|
+
| `.glass-theme-toggle` | Specialized pill with automatic moon/sun switch |
|
|
248
|
+
|
|
249
|
+
Theme Toggle (specialized pill):
|
|
250
|
+
|
|
251
|
+
```html
|
|
252
|
+
<button class="glass-theme-toggle" onclick="toggleTheme()">
|
|
253
|
+
<svg class="icon-moon" viewBox="0 0 24 24">
|
|
254
|
+
<path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"/>
|
|
255
|
+
</svg>
|
|
256
|
+
<svg class="icon-sun" viewBox="0 0 24 24">
|
|
257
|
+
<circle cx="12" cy="12" r="5"/>
|
|
258
|
+
<line x1="12" y1="1" x2="12" y2="3"/>
|
|
259
|
+
<line x1="12" y1="21" x2="12" y2="23"/>
|
|
260
|
+
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"/>
|
|
261
|
+
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"/>
|
|
262
|
+
<line x1="1" y1="12" x2="3" y2="12"/>
|
|
263
|
+
<line x1="21" y1="12" x2="23" y2="12"/>
|
|
264
|
+
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"/>
|
|
265
|
+
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"/>
|
|
266
|
+
</svg>
|
|
267
|
+
</button>
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
---
|
|
271
|
+
|
|
272
|
+
### 3.4 Tab Bar
|
|
273
|
+
|
|
274
|
+
Fixed bottom navigation with glass background. Requires `glass-bg--has-tab-bar` on the background container.
|
|
275
|
+
|
|
276
|
+
```html
|
|
277
|
+
<nav class="glass-tab-bar">
|
|
278
|
+
<button class="glass-tab-bar__item is-active">
|
|
279
|
+
<span class="glass-tab-bar__icon">
|
|
280
|
+
<svg viewBox="0 0 24 24"><!-- Icon --></svg>
|
|
281
|
+
</span>
|
|
282
|
+
<span class="glass-tab-bar__label">Home</span>
|
|
283
|
+
</button>
|
|
284
|
+
<button class="glass-tab-bar__item">
|
|
285
|
+
<span class="glass-tab-bar__icon">
|
|
286
|
+
<svg viewBox="0 0 24 24"><!-- Icon --></svg>
|
|
287
|
+
<span class="glass-tab-bar__badge">3</span>
|
|
288
|
+
</span>
|
|
289
|
+
<span class="glass-tab-bar__label">Contracts</span>
|
|
290
|
+
</button>
|
|
291
|
+
<button class="glass-tab-bar__item">
|
|
292
|
+
<span class="glass-tab-bar__icon">
|
|
293
|
+
<svg viewBox="0 0 24 24"><!-- Icon --></svg>
|
|
294
|
+
</span>
|
|
295
|
+
<span class="glass-tab-bar__label">Profile</span>
|
|
296
|
+
</button>
|
|
297
|
+
</nav>
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
| Class | Description |
|
|
301
|
+
|---|---|
|
|
302
|
+
| `.glass-tab-bar` | Container: fixed bottom, glass blur |
|
|
303
|
+
| `.glass-tab-bar__item` | Individual tab |
|
|
304
|
+
| `.glass-tab-bar__item.is-active` | Active tab (primary color) |
|
|
305
|
+
| `.glass-tab-bar__icon` | Icon wrapper |
|
|
306
|
+
| `.glass-tab-bar__badge` | Numeric badge inside icon |
|
|
307
|
+
| `.glass-tab-bar__label` | Text label below icon |
|
|
308
|
+
|
|
309
|
+
---
|
|
310
|
+
|
|
311
|
+
### 3.5 Title
|
|
312
|
+
|
|
313
|
+
Page title with text shadow effect.
|
|
314
|
+
|
|
315
|
+
```html
|
|
316
|
+
<h1 class="glass-title">Page Title</h1>
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
| Class | Description |
|
|
320
|
+
|---|---|
|
|
321
|
+
| `.glass-title` | Large title (24px, bold, text-shadow) |
|
|
322
|
+
|
|
323
|
+
---
|
|
324
|
+
|
|
325
|
+
### 3.6 Card
|
|
326
|
+
|
|
327
|
+
Glassmorphism container for content. Optionally with glow effect (frosted glass gradient + light streak).
|
|
328
|
+
|
|
329
|
+
```html
|
|
330
|
+
<!-- Standard Card -->
|
|
331
|
+
<div class="glass-card">
|
|
332
|
+
<p class="glass-card__text">Content</p>
|
|
333
|
+
</div>
|
|
334
|
+
|
|
335
|
+
<!-- Glow Card with Icon -->
|
|
336
|
+
<div class="glass-card glass-card--glow">
|
|
337
|
+
<div class="glass-card__icon">
|
|
338
|
+
<svg viewBox="0 0 64 64"><!-- Icon SVG --></svg>
|
|
339
|
+
</div>
|
|
340
|
+
<p class="glass-card__text">Description text goes here.</p>
|
|
341
|
+
</div>
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
| Class | Description |
|
|
345
|
+
|---|---|
|
|
346
|
+
| `.glass-card` | Base glass container (border-radius: 24px) |
|
|
347
|
+
| `.glass-card--glow` | Frosted glass gradient with light streak effect |
|
|
348
|
+
| `.glass-card__icon` | Centered icon wrapper (SVG, 48×48px) |
|
|
349
|
+
| `.glass-card__text` | Description text (muted) |
|
|
350
|
+
|
|
351
|
+
---
|
|
352
|
+
|
|
353
|
+
### 3.7 Buttons
|
|
354
|
+
|
|
355
|
+
Full-width buttons (56px height) with three variants and size modifiers.
|
|
356
|
+
|
|
357
|
+
```html
|
|
358
|
+
<!-- Primary: Color gradient, main action -->
|
|
359
|
+
<button class="glass-btn glass-btn--primary">
|
|
360
|
+
<svg viewBox="0 0 24 24"><!-- Optional: Icon --></svg>
|
|
361
|
+
Primary Action
|
|
362
|
+
</button>
|
|
363
|
+
|
|
364
|
+
<!-- Secondary: Milky white -->
|
|
365
|
+
<button class="glass-btn glass-btn--secondary">Secondary Action</button>
|
|
366
|
+
|
|
367
|
+
<!-- Tertiary: Subtle glass -->
|
|
368
|
+
<button class="glass-btn glass-btn--tertiary">Tertiary Action</button>
|
|
369
|
+
|
|
370
|
+
<!-- Sizes -->
|
|
371
|
+
<button class="glass-btn glass-btn--primary glass-btn--sm">Small (44px)</button>
|
|
372
|
+
<button class="glass-btn glass-btn--primary glass-btn--lg">Large (64px)</button>
|
|
373
|
+
|
|
374
|
+
<!-- Auto-width (instead of full-width) -->
|
|
375
|
+
<button class="glass-btn glass-btn--primary glass-btn--auto">Auto</button>
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
| Class | Description |
|
|
379
|
+
|---|---|
|
|
380
|
+
| `.glass-btn` | Base (56px height, width: 100%) |
|
|
381
|
+
| `.glass-btn--primary` | Color gradient (orange) |
|
|
382
|
+
| `.glass-btn--secondary` | Milky white, dark text |
|
|
383
|
+
| `.glass-btn--tertiary` | Subtle glass, more transparent |
|
|
384
|
+
| `.glass-btn--sm` | 44px height |
|
|
385
|
+
| `.glass-btn--lg` | 64px height |
|
|
386
|
+
| `.glass-btn--auto` | Width: auto instead of 100% |
|
|
387
|
+
|
|
388
|
+
**Important:** Buttons default to `width: 100%`. Use `--auto` for inline/auto-width buttons.
|
|
389
|
+
|
|
390
|
+
---
|
|
391
|
+
|
|
392
|
+
### 3.8 Badge
|
|
393
|
+
|
|
394
|
+
Tags and labels.
|
|
395
|
+
|
|
396
|
+
```html
|
|
397
|
+
<span class="glass-badge">Default</span>
|
|
398
|
+
<span class="glass-badge glass-badge--primary">Active</span>
|
|
399
|
+
<span class="glass-badge glass-badge--success">Done</span>
|
|
400
|
+
<span class="glass-badge glass-badge--error">Error</span>
|
|
401
|
+
```
|
|
402
|
+
|
|
403
|
+
| Class | Description |
|
|
404
|
+
|---|---|
|
|
405
|
+
| `.glass-badge` | Default (subtle glass) |
|
|
406
|
+
| `.glass-badge--primary` | Primary color |
|
|
407
|
+
| `.glass-badge--success` | Green |
|
|
408
|
+
| `.glass-badge--error` | Red |
|
|
409
|
+
|
|
410
|
+
---
|
|
411
|
+
|
|
412
|
+
### 3.9 Avatar
|
|
413
|
+
|
|
414
|
+
Glass circles in three sizes. For initials, icons, or images.
|
|
415
|
+
|
|
416
|
+
```html
|
|
417
|
+
<div class="glass-avatar glass-avatar--sm">S</div>
|
|
418
|
+
<div class="glass-avatar">M</div>
|
|
419
|
+
<div class="glass-avatar glass-avatar--lg">L</div>
|
|
420
|
+
```
|
|
421
|
+
|
|
422
|
+
| Class | Description |
|
|
423
|
+
|---|---|
|
|
424
|
+
| `.glass-avatar` | Default size (medium) |
|
|
425
|
+
| `.glass-avatar--sm` | Small |
|
|
426
|
+
| `.glass-avatar--lg` | Large |
|
|
427
|
+
|
|
428
|
+
---
|
|
429
|
+
|
|
430
|
+
### 3.10 Divider
|
|
431
|
+
|
|
432
|
+
Horizontal separator line with fade effect.
|
|
433
|
+
|
|
434
|
+
```html
|
|
435
|
+
<hr class="glass-divider">
|
|
436
|
+
```
|
|
437
|
+
|
|
438
|
+
---
|
|
439
|
+
|
|
440
|
+
### 3.11 Status Notice
|
|
441
|
+
|
|
442
|
+
Info/notice card with icon and text.
|
|
443
|
+
|
|
444
|
+
```html
|
|
445
|
+
<div class="glass-status">
|
|
446
|
+
<svg viewBox="0 0 24 24">
|
|
447
|
+
<circle cx="12" cy="12" r="10"/>
|
|
448
|
+
<line x1="12" y1="16" x2="12" y2="12"/>
|
|
449
|
+
<line x1="12" y1="8" x2="12" y2="8"/>
|
|
450
|
+
</svg>
|
|
451
|
+
<p>No documents captured yet.</p>
|
|
452
|
+
</div>
|
|
453
|
+
```
|
|
454
|
+
|
|
455
|
+
| Class | Description |
|
|
456
|
+
|---|---|
|
|
457
|
+
| `.glass-status` | Container with subtle glass surface |
|
|
458
|
+
|
|
459
|
+
---
|
|
460
|
+
|
|
461
|
+
### 3.12 Modal
|
|
462
|
+
|
|
463
|
+
Centered dialog with blur overlay. Controlled via the `is-active` state class on the overlay.
|
|
464
|
+
|
|
465
|
+
```html
|
|
466
|
+
<div class="glass-modal-overlay is-active">
|
|
467
|
+
<div class="glass-modal">
|
|
468
|
+
<div class="glass-modal__header">
|
|
469
|
+
<h2 class="glass-modal__title">Delete contract?</h2>
|
|
470
|
+
</div>
|
|
471
|
+
<div class="glass-modal__body">
|
|
472
|
+
<p>This action cannot be undone.</p>
|
|
473
|
+
</div>
|
|
474
|
+
<div class="glass-modal__footer">
|
|
475
|
+
<button class="glass-modal__action">Cancel</button>
|
|
476
|
+
<button class="glass-modal__action glass-modal__action--primary">Confirm</button>
|
|
477
|
+
</div>
|
|
478
|
+
</div>
|
|
479
|
+
</div>
|
|
480
|
+
```
|
|
481
|
+
|
|
482
|
+
Danger variant:
|
|
483
|
+
|
|
484
|
+
```html
|
|
485
|
+
<button class="glass-modal__action glass-modal__action--danger">Delete</button>
|
|
486
|
+
```
|
|
487
|
+
|
|
488
|
+
| Class | Description |
|
|
489
|
+
|---|---|
|
|
490
|
+
| `.glass-modal-overlay` | Fullscreen container with blur |
|
|
491
|
+
| `.glass-modal-overlay.is-active` | Visible + animated |
|
|
492
|
+
| `.glass-modal` | Dialog box |
|
|
493
|
+
| `.glass-modal__header` | Header area |
|
|
494
|
+
| `.glass-modal__title` | Title (20px, bold) |
|
|
495
|
+
| `.glass-modal__body` | Content area |
|
|
496
|
+
| `.glass-modal__footer` | Action bar |
|
|
497
|
+
| `.glass-modal__action` | Action button in footer |
|
|
498
|
+
| `.glass-modal__action--primary` | Primary action (colored) |
|
|
499
|
+
| `.glass-modal__action--danger` | Dangerous action (red) |
|
|
500
|
+
|
|
501
|
+
**Important:** `is-active` goes on `.glass-modal-overlay`, **not** on `.glass-modal`.
|
|
502
|
+
|
|
503
|
+
JavaScript to open/close:
|
|
504
|
+
|
|
505
|
+
```js
|
|
506
|
+
// Open
|
|
507
|
+
document.querySelector('.glass-modal-overlay').classList.add('is-active');
|
|
508
|
+
// Close
|
|
509
|
+
document.querySelector('.glass-modal-overlay').classList.remove('is-active');
|
|
510
|
+
```
|
|
511
|
+
|
|
512
|
+
---
|
|
513
|
+
|
|
514
|
+
### 3.13 Toast
|
|
515
|
+
|
|
516
|
+
Temporary notification. Visible via `is-visible`. Three variants.
|
|
517
|
+
|
|
518
|
+
```html
|
|
519
|
+
<div class="glass-toast glass-toast--success is-visible">
|
|
520
|
+
<svg class="glass-toast__icon" viewBox="0 0 24 24"><!-- Icon --></svg>
|
|
521
|
+
<span class="glass-toast__text">Saved successfully!</span>
|
|
522
|
+
</div>
|
|
523
|
+
```
|
|
524
|
+
|
|
525
|
+
| Class | Description |
|
|
526
|
+
|---|---|
|
|
527
|
+
| `.glass-toast` | Base container |
|
|
528
|
+
| `.glass-toast--success` | Green accent |
|
|
529
|
+
| `.glass-toast--error` | Red accent |
|
|
530
|
+
| `.glass-toast--warning` | Yellow accent |
|
|
531
|
+
| `.glass-toast.is-visible` | Visible + faded in |
|
|
532
|
+
| `.glass-toast__icon` | Icon (SVG) |
|
|
533
|
+
| `.glass-toast__text` | Message text |
|
|
534
|
+
|
|
535
|
+
---
|
|
536
|
+
|
|
537
|
+
### 3.14 Input
|
|
538
|
+
|
|
539
|
+
Text fields with glass background. Wrapped in a `glass-input-group` with label and optional hint.
|
|
540
|
+
|
|
541
|
+
```html
|
|
542
|
+
<div class="glass-input-group">
|
|
543
|
+
<label class="glass-label">Contract Name</label>
|
|
544
|
+
<input class="glass-input" type="text" placeholder="e.g. Rental Agreement">
|
|
545
|
+
<span class="glass-hint">Optional help text</span>
|
|
546
|
+
</div>
|
|
547
|
+
```
|
|
548
|
+
|
|
549
|
+
Error state:
|
|
550
|
+
|
|
551
|
+
```html
|
|
552
|
+
<div class="glass-input-group">
|
|
553
|
+
<label class="glass-label">Email</label>
|
|
554
|
+
<input class="glass-input glass-input--error" type="email" value="invalid@">
|
|
555
|
+
<span class="glass-hint glass-hint--error">Please enter a valid email address</span>
|
|
556
|
+
</div>
|
|
557
|
+
```
|
|
558
|
+
|
|
559
|
+
Disabled:
|
|
560
|
+
|
|
561
|
+
```html
|
|
562
|
+
<input class="glass-input" type="text" disabled>
|
|
563
|
+
```
|
|
564
|
+
|
|
565
|
+
| Class | Description |
|
|
566
|
+
|---|---|
|
|
567
|
+
| `.glass-input-group` | Wrapper for label + input + hint |
|
|
568
|
+
| `.glass-label` | Label (small, muted, uppercase) |
|
|
569
|
+
| `.glass-input` | Text input (glass background) |
|
|
570
|
+
| `.glass-input--error` | Red border for error state |
|
|
571
|
+
| `.glass-hint` | Help text below input |
|
|
572
|
+
| `.glass-hint--error` | Red help text |
|
|
573
|
+
|
|
574
|
+
---
|
|
575
|
+
|
|
576
|
+
### 3.15 Textarea
|
|
577
|
+
|
|
578
|
+
Multi-line text field.
|
|
579
|
+
|
|
580
|
+
```html
|
|
581
|
+
<textarea class="glass-textarea" placeholder="Optional notes…"></textarea>
|
|
582
|
+
```
|
|
583
|
+
|
|
584
|
+
| Class | Description |
|
|
585
|
+
|---|---|
|
|
586
|
+
| `.glass-textarea` | Multi-line glass input |
|
|
587
|
+
|
|
588
|
+
---
|
|
589
|
+
|
|
590
|
+
### 3.16 Select
|
|
591
|
+
|
|
592
|
+
Dropdown with glass styling and custom chevron.
|
|
593
|
+
|
|
594
|
+
```html
|
|
595
|
+
<select class="glass-select">
|
|
596
|
+
<option>Please select…</option>
|
|
597
|
+
<option>Insurance</option>
|
|
598
|
+
<option>Rental Agreement</option>
|
|
599
|
+
</select>
|
|
600
|
+
```
|
|
601
|
+
|
|
602
|
+
| Class | Description |
|
|
603
|
+
|---|---|
|
|
604
|
+
| `.glass-select` | Styled dropdown |
|
|
605
|
+
|
|
606
|
+
---
|
|
607
|
+
|
|
608
|
+
### 3.17 Search
|
|
609
|
+
|
|
610
|
+
Search field with embedded search icon.
|
|
611
|
+
|
|
612
|
+
```html
|
|
613
|
+
<div class="glass-search">
|
|
614
|
+
<svg class="glass-search__icon" viewBox="0 0 24 24">
|
|
615
|
+
<circle cx="11" cy="11" r="8"/>
|
|
616
|
+
<line x1="21" y1="21" x2="16.65" y2="16.65"/>
|
|
617
|
+
</svg>
|
|
618
|
+
<input class="glass-input" type="search" placeholder="Search contracts…">
|
|
619
|
+
</div>
|
|
620
|
+
```
|
|
621
|
+
|
|
622
|
+
| Class | Description |
|
|
623
|
+
|---|---|
|
|
624
|
+
| `.glass-search` | Wrapper (position: relative) |
|
|
625
|
+
| `.glass-search__icon` | Positioned search icon (left) |
|
|
626
|
+
|
|
627
|
+
**Important:** The input inside `.glass-search` uses the regular `.glass-input` class.
|
|
628
|
+
|
|
629
|
+
---
|
|
630
|
+
|
|
631
|
+
### 3.18 Toggle Switch
|
|
632
|
+
|
|
633
|
+
iOS-style switch.
|
|
634
|
+
|
|
635
|
+
```html
|
|
636
|
+
<label class="glass-toggle">
|
|
637
|
+
<input class="glass-toggle__input" type="checkbox" checked>
|
|
638
|
+
<span class="glass-toggle__track">
|
|
639
|
+
<span class="glass-toggle__thumb"></span>
|
|
640
|
+
</span>
|
|
641
|
+
<span class="glass-toggle__label">Notifications</span>
|
|
642
|
+
</label>
|
|
643
|
+
```
|
|
644
|
+
|
|
645
|
+
| Class | Description |
|
|
646
|
+
|---|---|
|
|
647
|
+
| `.glass-toggle` | Outer label (flex container) |
|
|
648
|
+
| `.glass-toggle__input` | Hidden checkbox input |
|
|
649
|
+
| `.glass-toggle__track` | Visible track |
|
|
650
|
+
| `.glass-toggle__thumb` | Movable thumb |
|
|
651
|
+
| `.glass-toggle__label` | Text label |
|
|
652
|
+
|
|
653
|
+
**State:** `:checked` on the input activates the toggle visually.
|
|
654
|
+
|
|
655
|
+
---
|
|
656
|
+
|
|
657
|
+
### 3.19 Checkbox
|
|
658
|
+
|
|
659
|
+
Animated checkbox with checkmark SVG.
|
|
660
|
+
|
|
661
|
+
```html
|
|
662
|
+
<label class="glass-checkbox">
|
|
663
|
+
<input class="glass-checkbox__input" type="checkbox" checked>
|
|
664
|
+
<span class="glass-checkbox__box">
|
|
665
|
+
<svg viewBox="0 0 24 24"><polyline points="20 6 9 17 4 12"/></svg>
|
|
666
|
+
</span>
|
|
667
|
+
<span class="glass-checkbox__label">Accept terms of service</span>
|
|
668
|
+
</label>
|
|
669
|
+
```
|
|
670
|
+
|
|
671
|
+
| Class | Description |
|
|
672
|
+
|---|---|
|
|
673
|
+
| `.glass-checkbox` | Outer label |
|
|
674
|
+
| `.glass-checkbox__input` | Hidden checkbox input |
|
|
675
|
+
| `.glass-checkbox__box` | Visible box with checkmark SVG |
|
|
676
|
+
| `.glass-checkbox__label` | Text label |
|
|
677
|
+
|
|
678
|
+
---
|
|
679
|
+
|
|
680
|
+
### 3.20 Radio Button
|
|
681
|
+
|
|
682
|
+
Animated radio button with dot.
|
|
683
|
+
|
|
684
|
+
```html
|
|
685
|
+
<label class="glass-radio">
|
|
686
|
+
<input class="glass-radio__input" type="radio" name="group" checked>
|
|
687
|
+
<span class="glass-radio__circle">
|
|
688
|
+
<span class="glass-radio__dot"></span>
|
|
689
|
+
</span>
|
|
690
|
+
<span class="glass-radio__label">Option A</span>
|
|
691
|
+
</label>
|
|
692
|
+
|
|
693
|
+
<label class="glass-radio">
|
|
694
|
+
<input class="glass-radio__input" type="radio" name="group">
|
|
695
|
+
<span class="glass-radio__circle">
|
|
696
|
+
<span class="glass-radio__dot"></span>
|
|
697
|
+
</span>
|
|
698
|
+
<span class="glass-radio__label">Option B</span>
|
|
699
|
+
</label>
|
|
700
|
+
```
|
|
701
|
+
|
|
702
|
+
| Class | Description |
|
|
703
|
+
|---|---|
|
|
704
|
+
| `.glass-radio` | Outer label |
|
|
705
|
+
| `.glass-radio__input` | Hidden radio input |
|
|
706
|
+
| `.glass-radio__circle` | Visible circle |
|
|
707
|
+
| `.glass-radio__dot` | Inner dot (visible on :checked) |
|
|
708
|
+
| `.glass-radio__label` | Text label |
|
|
709
|
+
|
|
710
|
+
**Important:** Radio buttons in the same group need the same `name` attribute value.
|
|
711
|
+
|
|
712
|
+
---
|
|
713
|
+
|
|
714
|
+
### 3.21 Range Slider
|
|
715
|
+
|
|
716
|
+
Slider with gradient thumb. Used in a group with header and value display.
|
|
717
|
+
|
|
718
|
+
```html
|
|
719
|
+
<div class="glass-range-group">
|
|
720
|
+
<div class="glass-range-header">
|
|
721
|
+
<label class="glass-label">Image Quality</label>
|
|
722
|
+
<span class="glass-range-value" id="range-val">75%</span>
|
|
723
|
+
</div>
|
|
724
|
+
<input class="glass-range" type="range" min="0" max="100" value="75"
|
|
725
|
+
oninput="document.getElementById('range-val').textContent = this.value + '%'">
|
|
726
|
+
</div>
|
|
727
|
+
```
|
|
728
|
+
|
|
729
|
+
| Class | Description |
|
|
730
|
+
|---|---|
|
|
731
|
+
| `.glass-range-group` | Wrapper |
|
|
732
|
+
| `.glass-range-header` | Flex container for label + value |
|
|
733
|
+
| `.glass-range-value` | Value display (right) |
|
|
734
|
+
| `.glass-range` | The actual slider |
|
|
735
|
+
|
|
736
|
+
---
|
|
737
|
+
|
|
738
|
+
### 3.22 Progress Bar
|
|
739
|
+
|
|
740
|
+
Progress bar with optional shimmer effect.
|
|
741
|
+
|
|
742
|
+
```html
|
|
743
|
+
<div class="glass-progress">
|
|
744
|
+
<div class="glass-progress__header">
|
|
745
|
+
<span class="glass-progress__label">Upload</span>
|
|
746
|
+
<span class="glass-progress__value">68%</span>
|
|
747
|
+
</div>
|
|
748
|
+
<div class="glass-progress__track">
|
|
749
|
+
<div class="glass-progress__fill" style="width: 68%"></div>
|
|
750
|
+
</div>
|
|
751
|
+
</div>
|
|
752
|
+
```
|
|
753
|
+
|
|
754
|
+
| Class | Description |
|
|
755
|
+
|---|---|
|
|
756
|
+
| `.glass-progress` | Base container |
|
|
757
|
+
| `.glass-progress--sm` | Narrow track (4px) |
|
|
758
|
+
| `.glass-progress--lg` | Wide track (12px) |
|
|
759
|
+
| `.glass-progress--success` | Green bar |
|
|
760
|
+
| `.glass-progress--error` | Red bar |
|
|
761
|
+
| `.glass-progress__header` | Flex container for label + value |
|
|
762
|
+
| `.glass-progress__label` | Label (left) |
|
|
763
|
+
| `.glass-progress__value` | Percentage value (right) |
|
|
764
|
+
| `.glass-progress__track` | Background track |
|
|
765
|
+
| `.glass-progress__fill` | Filled area (width via `style="width: X%"`) |
|
|
766
|
+
|
|
767
|
+
**Important:** Progress width is controlled via inline `style="width: X%"` on `.glass-progress__fill`.
|
|
768
|
+
|
|
769
|
+
---
|
|
770
|
+
|
|
771
|
+
### 3.23 Accordion
|
|
772
|
+
|
|
773
|
+
Collapsible content sections. Controlled via `is-open` on items.
|
|
774
|
+
|
|
775
|
+
```html
|
|
776
|
+
<div class="glass-accordion">
|
|
777
|
+
<div class="glass-accordion__item is-open">
|
|
778
|
+
<button class="glass-accordion__trigger" onclick="this.parentElement.classList.toggle('is-open')">
|
|
779
|
+
<span>Question one?</span>
|
|
780
|
+
<span class="glass-accordion__trigger-icon">
|
|
781
|
+
<svg viewBox="0 0 24 24"><polyline points="6 9 12 15 18 9"/></svg>
|
|
782
|
+
</span>
|
|
783
|
+
</button>
|
|
784
|
+
<div class="glass-accordion__content">
|
|
785
|
+
<div class="glass-accordion__body">
|
|
786
|
+
The answer to question one.
|
|
787
|
+
</div>
|
|
788
|
+
</div>
|
|
789
|
+
</div>
|
|
790
|
+
|
|
791
|
+
<div class="glass-accordion__item">
|
|
792
|
+
<button class="glass-accordion__trigger" onclick="this.parentElement.classList.toggle('is-open')">
|
|
793
|
+
<span>Question two?</span>
|
|
794
|
+
<span class="glass-accordion__trigger-icon">
|
|
795
|
+
<svg viewBox="0 0 24 24"><polyline points="6 9 12 15 18 9"/></svg>
|
|
796
|
+
</span>
|
|
797
|
+
</button>
|
|
798
|
+
<div class="glass-accordion__content">
|
|
799
|
+
<div class="glass-accordion__body">
|
|
800
|
+
The answer to question two.
|
|
801
|
+
</div>
|
|
802
|
+
</div>
|
|
803
|
+
</div>
|
|
804
|
+
</div>
|
|
805
|
+
```
|
|
806
|
+
|
|
807
|
+
| Class | Description |
|
|
808
|
+
|---|---|
|
|
809
|
+
| `.glass-accordion` | Container |
|
|
810
|
+
| `.glass-accordion__item` | Individual item |
|
|
811
|
+
| `.glass-accordion__item.is-open` | Expanded item |
|
|
812
|
+
| `.glass-accordion__trigger` | Clickable header button |
|
|
813
|
+
| `.glass-accordion__trigger-icon` | Chevron icon (rotates on open) |
|
|
814
|
+
| `.glass-accordion__content` | Wrapper for animated height |
|
|
815
|
+
| `.glass-accordion__body` | Actual content |
|
|
816
|
+
|
|
817
|
+
---
|
|
818
|
+
|
|
819
|
+
### 3.24 List
|
|
820
|
+
|
|
821
|
+
iOS-style grouped settings list. Items can carry a leading icon, a title with optional subtitle, and a trailing element (chevron, value, button). Dividers between items are drawn automatically via `::after` — **never add divider markup manually**.
|
|
822
|
+
|
|
823
|
+
```html
|
|
824
|
+
<!-- Settings-style list with icons + subtitles + trailing -->
|
|
825
|
+
<ul class="glass-list">
|
|
826
|
+
<li class="glass-list__item glass-list__item--interactive">
|
|
827
|
+
<span class="glass-list__leading">
|
|
828
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
829
|
+
<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/>
|
|
830
|
+
<polyline points="7 10 12 15 17 10"/>
|
|
831
|
+
<line x1="12" y1="15" x2="12" y2="3"/>
|
|
832
|
+
</svg>
|
|
833
|
+
</span>
|
|
834
|
+
<div class="glass-list__content">
|
|
835
|
+
<div class="glass-list__title">iOS 26.4 Update</div>
|
|
836
|
+
<div class="glass-list__subtitle">2.1 GB · Available now</div>
|
|
837
|
+
</div>
|
|
838
|
+
<div class="glass-list__trailing">
|
|
839
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
840
|
+
<polyline points="9 18 15 12 9 6"/>
|
|
841
|
+
</svg>
|
|
842
|
+
</div>
|
|
843
|
+
</li>
|
|
844
|
+
|
|
845
|
+
<li class="glass-list__item glass-list__item--interactive">
|
|
846
|
+
<span class="glass-list__leading">
|
|
847
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
848
|
+
<rect x="2" y="5" width="20" height="14" rx="2"/>
|
|
849
|
+
<line x1="2" y1="10" x2="22" y2="10"/>
|
|
850
|
+
</svg>
|
|
851
|
+
</span>
|
|
852
|
+
<div class="glass-list__content">
|
|
853
|
+
<div class="glass-list__title">Apple One</div>
|
|
854
|
+
<div class="glass-list__subtitle">Family — renews Apr 28</div>
|
|
855
|
+
</div>
|
|
856
|
+
<div class="glass-list__trailing">$22.95</div>
|
|
857
|
+
</li>
|
|
858
|
+
|
|
859
|
+
<li class="glass-list__item glass-list__item--center glass-list__item--interactive">
|
|
860
|
+
View all subscriptions
|
|
861
|
+
</li>
|
|
862
|
+
</ul>
|
|
863
|
+
```
|
|
864
|
+
|
|
865
|
+
```html
|
|
866
|
+
<!-- Compact menu (centered text only, no icons) -->
|
|
867
|
+
<ul class="glass-list">
|
|
868
|
+
<li class="glass-list__item glass-list__item--center glass-list__item--interactive">Share</li>
|
|
869
|
+
<li class="glass-list__item glass-list__item--center glass-list__item--interactive">Duplicate</li>
|
|
870
|
+
<li class="glass-list__item glass-list__item--center glass-list__item--interactive">Delete</li>
|
|
871
|
+
</ul>
|
|
872
|
+
```
|
|
873
|
+
|
|
874
|
+
| Class | Description |
|
|
875
|
+
|---|---|
|
|
876
|
+
| `.glass-list` | Grouped surface container |
|
|
877
|
+
| `.glass-list--flush` | Edge-to-edge variant (no side margin / radius). Assumes parent has `--gl-space-lg` horizontal padding. |
|
|
878
|
+
| `.glass-list--bare` | Strips background, border & shadow — for embedding inside `.glass-popover` or `.glass-card`. |
|
|
879
|
+
| `.glass-list__item` | List row (use `<li>`, `<a>`, or `<button>`) |
|
|
880
|
+
| `.glass-list__item--interactive` | Adds hover / focus / active states |
|
|
881
|
+
| `.glass-list__item--center` | Centered single-text variant with ellipsis truncation |
|
|
882
|
+
| `.glass-list__leading` | Leading slot (28×28, holds an icon SVG) |
|
|
883
|
+
| `.glass-list__content` | Flexible middle slot — takes remaining width, enables truncation |
|
|
884
|
+
| `.glass-list__title` | Primary text (medium weight, ellipsis) |
|
|
885
|
+
| `.glass-list__subtitle` | Secondary text (small, muted, ellipsis) |
|
|
886
|
+
| `.glass-list__trailing` | Trailing slot — chevron, value, button, badge |
|
|
887
|
+
|
|
888
|
+
**Notes:**
|
|
889
|
+
- Dividers are auto-rendered via `::after`. The last item never has a divider.
|
|
890
|
+
- Items **with** a `__leading` slot get an icon-aligned divider inset; items **without** a leading slot get a standard left/right padding inset (handled via `:has()`).
|
|
891
|
+
- SVG icon convention: `24px` for leading, `18px` for trailing, `stroke: currentColor`, `stroke-width: 2`.
|
|
892
|
+
- Use `<ul>` + `<li>` for semantic lists. For interactive rows wrap in `<a>` or `<button>` instead of `<li>` if a single-row list is needed.
|
|
893
|
+
|
|
894
|
+
---
|
|
895
|
+
|
|
896
|
+
### 3.25 Popover
|
|
897
|
+
|
|
898
|
+
Anchored dropdown / menu container. Wrap a trigger button and a `.glass-popover` inside a `.glass-popover-anchor`. Visibility is controlled via `.is-open` — toggling requires a tiny bit of JavaScript.
|
|
899
|
+
|
|
900
|
+
```html
|
|
901
|
+
<div class="glass-popover-anchor">
|
|
902
|
+
<button class="glass-btn glass-btn--secondary glass-btn--auto"
|
|
903
|
+
onclick="gkTogglePopover(this, event)">
|
|
904
|
+
Open menu
|
|
905
|
+
</button>
|
|
906
|
+
<div class="glass-popover">
|
|
907
|
+
<ul class="glass-list glass-list--bare">
|
|
908
|
+
<li class="glass-list__item glass-list__item--interactive">
|
|
909
|
+
<span class="glass-list__leading">
|
|
910
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
911
|
+
<path d="M4 12v8a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-8"/>
|
|
912
|
+
<polyline points="16 6 12 2 8 6"/>
|
|
913
|
+
<line x1="12" y1="2" x2="12" y2="15"/>
|
|
914
|
+
</svg>
|
|
915
|
+
</span>
|
|
916
|
+
<div class="glass-list__content"><div class="glass-list__title">Share</div></div>
|
|
917
|
+
</li>
|
|
918
|
+
<li class="glass-list__item glass-list__item--interactive">
|
|
919
|
+
<div class="glass-list__content"><div class="glass-list__title">Duplicate</div></div>
|
|
920
|
+
</li>
|
|
921
|
+
<li class="glass-list__item glass-list__item--interactive">
|
|
922
|
+
<div class="glass-list__content"><div class="glass-list__title">Delete</div></div>
|
|
923
|
+
</li>
|
|
924
|
+
</ul>
|
|
925
|
+
</div>
|
|
926
|
+
</div>
|
|
927
|
+
|
|
928
|
+
<script>
|
|
929
|
+
// ⚠️ Do NOT name this function `togglePopover` — it collides with the
|
|
930
|
+
// native HTMLElement.togglePopover() method from the HTML Popover API.
|
|
931
|
+
function gkTogglePopover(btn, e) {
|
|
932
|
+
const popover = btn.nextElementSibling;
|
|
933
|
+
const wasOpen = popover.classList.contains('is-open');
|
|
934
|
+
document.querySelectorAll('.glass-popover.is-open')
|
|
935
|
+
.forEach(p => p.classList.remove('is-open'));
|
|
936
|
+
if (!wasOpen) popover.classList.add('is-open');
|
|
937
|
+
if (e) e.stopPropagation();
|
|
938
|
+
}
|
|
939
|
+
document.addEventListener('click', e => {
|
|
940
|
+
if (!e.target.closest('.glass-popover-anchor')) {
|
|
941
|
+
document.querySelectorAll('.glass-popover.is-open')
|
|
942
|
+
.forEach(p => p.classList.remove('is-open'));
|
|
943
|
+
}
|
|
944
|
+
});
|
|
945
|
+
</script>
|
|
946
|
+
```
|
|
947
|
+
|
|
948
|
+
| Class | Description |
|
|
949
|
+
|---|---|
|
|
950
|
+
| `.glass-popover-anchor` | Positioning context — wraps trigger + popover |
|
|
951
|
+
| `.glass-popover` | Floating glass surface, hidden until `.is-open` |
|
|
952
|
+
| `.glass-popover.is-open` | Visible state — fade + scale animation |
|
|
953
|
+
| `.glass-popover--top` | Opens upward (above the trigger) |
|
|
954
|
+
| `.glass-popover--start` | Aligns left edge with trigger |
|
|
955
|
+
| `.glass-popover--end` | Aligns right edge with trigger |
|
|
956
|
+
|
|
957
|
+
**Note:** name your toggle function anything except `togglePopover` — that name collides with the native `HTMLElement.togglePopover()` method (HTML Popover API) and inline `onclick` handlers will throw `NotSupportedError`. Use a prefix like `gkTogglePopover` or `myToggle`.
|
|
958
|
+
|
|
959
|
+
---
|
|
960
|
+
|
|
961
|
+
## 4. Utility Classes
|
|
962
|
+
|
|
963
|
+
### Stack (Vertical)
|
|
964
|
+
|
|
965
|
+
Flexbox column with gap.
|
|
966
|
+
|
|
967
|
+
```html
|
|
968
|
+
<div class="gl-stack gl-stack--md">
|
|
969
|
+
<div>Item 1</div>
|
|
970
|
+
<div>Item 2</div>
|
|
971
|
+
</div>
|
|
972
|
+
```
|
|
973
|
+
|
|
974
|
+
| Class | Gap |
|
|
975
|
+
|---|---|
|
|
976
|
+
| `.gl-stack` | Default |
|
|
977
|
+
| `.gl-stack--2xs` | 4px |
|
|
978
|
+
| `.gl-stack--xs` | 8px |
|
|
979
|
+
| `.gl-stack--sm` | 12px |
|
|
980
|
+
| `.gl-stack--md` | 16px |
|
|
981
|
+
| `.gl-stack--lg` | 20px |
|
|
982
|
+
| `.gl-stack--xl` | 24px |
|
|
983
|
+
|
|
984
|
+
### Row (Horizontal)
|
|
985
|
+
|
|
986
|
+
Flexbox row with gap.
|
|
987
|
+
|
|
988
|
+
```html
|
|
989
|
+
<div class="gl-row gl-row--sm">
|
|
990
|
+
<span class="glass-badge">Tag 1</span>
|
|
991
|
+
<span class="glass-badge">Tag 2</span>
|
|
992
|
+
</div>
|
|
993
|
+
```
|
|
994
|
+
|
|
995
|
+
| Class | Gap |
|
|
996
|
+
|---|---|
|
|
997
|
+
| `.gl-row` | Default |
|
|
998
|
+
| `.gl-row--xs` | 8px |
|
|
999
|
+
| `.gl-row--sm` | 12px |
|
|
1000
|
+
| `.gl-row--md` | 16px |
|
|
1001
|
+
|
|
1002
|
+
### Margin
|
|
1003
|
+
|
|
1004
|
+
| Class | Value |
|
|
1005
|
+
|---|---|
|
|
1006
|
+
| `.gl-mt-sm` | margin-top: 12px |
|
|
1007
|
+
| `.gl-mt-md` | margin-top: 16px |
|
|
1008
|
+
| `.gl-mt-lg` | margin-top: 20px |
|
|
1009
|
+
| `.gl-mt-xl` | margin-top: 24px |
|
|
1010
|
+
| `.gl-mb-sm` | margin-bottom: 12px |
|
|
1011
|
+
| `.gl-mb-md` | margin-bottom: 16px |
|
|
1012
|
+
| `.gl-mb-lg` | margin-bottom: 20px |
|
|
1013
|
+
| `.gl-mb-xl` | margin-bottom: 24px |
|
|
1014
|
+
|
|
1015
|
+
### Text
|
|
1016
|
+
|
|
1017
|
+
| Class | Description |
|
|
1018
|
+
|---|---|
|
|
1019
|
+
| `.gl-text-center` | text-align: center |
|
|
1020
|
+
| `.gl-text-muted` | Muted text color |
|
|
1021
|
+
| `.gl-text-sm` | Smaller font size |
|
|
1022
|
+
|
|
1023
|
+
### Layout
|
|
1024
|
+
|
|
1025
|
+
| Class | Description |
|
|
1026
|
+
|---|---|
|
|
1027
|
+
| `.gl-px` | Horizontal padding |
|
|
1028
|
+
| `.gl-w-full` | width: 100% |
|
|
1029
|
+
| `.gl-flex-1` | flex: 1 |
|
|
1030
|
+
|
|
1031
|
+
---
|
|
1032
|
+
|
|
1033
|
+
## 5. State Classes Overview
|
|
1034
|
+
|
|
1035
|
+
| State Class | Used on | Description |
|
|
1036
|
+
|---|---|---|
|
|
1037
|
+
| `.is-active` | `.glass-modal-overlay`, `.glass-tab-bar__item` | Element is active/visible |
|
|
1038
|
+
| `.is-open` | `.glass-accordion__item`, `.glass-popover` | Accordion item expanded / popover visible |
|
|
1039
|
+
| `.is-visible` | `.glass-toast` | Toast is visible |
|
|
1040
|
+
| `:checked` | Toggle, Checkbox, Radio (on the input) | Native checked state |
|
|
1041
|
+
| `:focus` | Input, Textarea, Select, Range | Focus ring |
|
|
1042
|
+
| `:disabled` | `.glass-input` | Disabled input |
|
|
1043
|
+
|
|
1044
|
+
---
|
|
1045
|
+
|
|
1046
|
+
## 6. Composition Patterns
|
|
1047
|
+
|
|
1048
|
+
### Login Screen
|
|
1049
|
+
|
|
1050
|
+
```html
|
|
1051
|
+
<div class="glass-bg">
|
|
1052
|
+
<nav class="glass-nav">
|
|
1053
|
+
<button class="glass-pill">
|
|
1054
|
+
<svg viewBox="0 0 24 24"><polyline points="15 18 9 12 15 6"/></svg>
|
|
1055
|
+
</button>
|
|
1056
|
+
<button class="glass-theme-toggle" onclick="toggleTheme()">
|
|
1057
|
+
<svg class="icon-moon" viewBox="0 0 24 24"><path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"/></svg>
|
|
1058
|
+
<svg class="icon-sun" viewBox="0 0 24 24"><circle cx="12" cy="12" r="5"/></svg>
|
|
1059
|
+
</button>
|
|
1060
|
+
</nav>
|
|
1061
|
+
|
|
1062
|
+
<h1 class="glass-title">Sign In</h1>
|
|
1063
|
+
|
|
1064
|
+
<div class="gl-stack gl-stack--md">
|
|
1065
|
+
<div class="glass-input-group">
|
|
1066
|
+
<label class="glass-label">Email</label>
|
|
1067
|
+
<input class="glass-input" type="email" placeholder="name@example.com">
|
|
1068
|
+
</div>
|
|
1069
|
+
<div class="glass-input-group">
|
|
1070
|
+
<label class="glass-label">Password</label>
|
|
1071
|
+
<input class="glass-input" type="password" placeholder="••••••••">
|
|
1072
|
+
</div>
|
|
1073
|
+
</div>
|
|
1074
|
+
|
|
1075
|
+
<div class="gl-stack gl-stack--sm gl-mt-lg">
|
|
1076
|
+
<button class="glass-btn glass-btn--primary">Log In</button>
|
|
1077
|
+
<button class="glass-btn glass-btn--tertiary">Forgot password?</button>
|
|
1078
|
+
</div>
|
|
1079
|
+
</div>
|
|
1080
|
+
```
|
|
1081
|
+
|
|
1082
|
+
### Dashboard with Cards
|
|
1083
|
+
|
|
1084
|
+
```html
|
|
1085
|
+
<div class="glass-bg glass-bg--has-tab-bar">
|
|
1086
|
+
<nav class="glass-nav">
|
|
1087
|
+
<h1 class="glass-title">Dashboard</h1>
|
|
1088
|
+
<button class="glass-pill">
|
|
1089
|
+
<svg viewBox="0 0 24 24"><!-- Settings Icon --></svg>
|
|
1090
|
+
</button>
|
|
1091
|
+
</nav>
|
|
1092
|
+
|
|
1093
|
+
<div class="gl-stack gl-stack--md">
|
|
1094
|
+
<div class="glass-card glass-card--glow">
|
|
1095
|
+
<div class="glass-card__icon">
|
|
1096
|
+
<svg viewBox="0 0 64 64"><!-- Icon --></svg>
|
|
1097
|
+
</div>
|
|
1098
|
+
<p class="glass-card__text">Capture and upload documents.</p>
|
|
1099
|
+
</div>
|
|
1100
|
+
|
|
1101
|
+
<div class="glass-card glass-card--glow">
|
|
1102
|
+
<div class="glass-card__icon">
|
|
1103
|
+
<svg viewBox="0 0 64 64"><!-- Icon --></svg>
|
|
1104
|
+
</div>
|
|
1105
|
+
<p class="glass-card__text">Manage and archive contracts.</p>
|
|
1106
|
+
</div>
|
|
1107
|
+
</div>
|
|
1108
|
+
|
|
1109
|
+
<nav class="glass-tab-bar">
|
|
1110
|
+
<button class="glass-tab-bar__item is-active">
|
|
1111
|
+
<span class="glass-tab-bar__icon"><svg viewBox="0 0 24 24"><!-- Home --></svg></span>
|
|
1112
|
+
<span class="glass-tab-bar__label">Home</span>
|
|
1113
|
+
</button>
|
|
1114
|
+
<button class="glass-tab-bar__item">
|
|
1115
|
+
<span class="glass-tab-bar__icon"><svg viewBox="0 0 24 24"><!-- Docs --></svg></span>
|
|
1116
|
+
<span class="glass-tab-bar__label">Contracts</span>
|
|
1117
|
+
</button>
|
|
1118
|
+
<button class="glass-tab-bar__item">
|
|
1119
|
+
<span class="glass-tab-bar__icon"><svg viewBox="0 0 24 24"><!-- Profile --></svg></span>
|
|
1120
|
+
<span class="glass-tab-bar__label">Profile</span>
|
|
1121
|
+
</button>
|
|
1122
|
+
</nav>
|
|
1123
|
+
</div>
|
|
1124
|
+
```
|
|
1125
|
+
|
|
1126
|
+
### Form Page
|
|
1127
|
+
|
|
1128
|
+
```html
|
|
1129
|
+
<div class="glass-bg">
|
|
1130
|
+
<nav class="glass-nav">
|
|
1131
|
+
<button class="glass-pill">
|
|
1132
|
+
<svg viewBox="0 0 24 24"><polyline points="15 18 9 12 15 6"/></svg>
|
|
1133
|
+
</button>
|
|
1134
|
+
</nav>
|
|
1135
|
+
|
|
1136
|
+
<h1 class="glass-title">New Contract</h1>
|
|
1137
|
+
|
|
1138
|
+
<div class="gl-stack gl-stack--md">
|
|
1139
|
+
<div class="glass-input-group">
|
|
1140
|
+
<label class="glass-label">Contract Name</label>
|
|
1141
|
+
<input class="glass-input" type="text" placeholder="e.g. Rental Agreement">
|
|
1142
|
+
</div>
|
|
1143
|
+
|
|
1144
|
+
<div class="glass-input-group">
|
|
1145
|
+
<label class="glass-label">Category</label>
|
|
1146
|
+
<select class="glass-select">
|
|
1147
|
+
<option>Please select…</option>
|
|
1148
|
+
<option>Insurance</option>
|
|
1149
|
+
<option>Rental Agreement</option>
|
|
1150
|
+
<option>Employment Contract</option>
|
|
1151
|
+
</select>
|
|
1152
|
+
</div>
|
|
1153
|
+
|
|
1154
|
+
<div class="glass-input-group">
|
|
1155
|
+
<label class="glass-label">Notes</label>
|
|
1156
|
+
<textarea class="glass-textarea" placeholder="Optional notes…"></textarea>
|
|
1157
|
+
</div>
|
|
1158
|
+
|
|
1159
|
+
<label class="glass-toggle">
|
|
1160
|
+
<input class="glass-toggle__input" type="checkbox">
|
|
1161
|
+
<span class="glass-toggle__track"><span class="glass-toggle__thumb"></span></span>
|
|
1162
|
+
<span class="glass-toggle__label">Enable reminder</span>
|
|
1163
|
+
</label>
|
|
1164
|
+
|
|
1165
|
+
<hr class="glass-divider">
|
|
1166
|
+
|
|
1167
|
+
<button class="glass-btn glass-btn--primary">Save</button>
|
|
1168
|
+
<button class="glass-btn glass-btn--tertiary">Cancel</button>
|
|
1169
|
+
</div>
|
|
1170
|
+
</div>
|
|
1171
|
+
```
|
|
1172
|
+
|
|
1173
|
+
### Delete Confirmation (Modal)
|
|
1174
|
+
|
|
1175
|
+
```html
|
|
1176
|
+
<div class="glass-modal-overlay is-active">
|
|
1177
|
+
<div class="glass-modal">
|
|
1178
|
+
<div class="glass-modal__header">
|
|
1179
|
+
<h2 class="glass-modal__title">Delete contract?</h2>
|
|
1180
|
+
</div>
|
|
1181
|
+
<div class="glass-modal__body">
|
|
1182
|
+
<p>Do you want to permanently delete this contract? This action cannot be undone.</p>
|
|
1183
|
+
</div>
|
|
1184
|
+
<div class="glass-modal__footer">
|
|
1185
|
+
<button class="glass-modal__action" onclick="closeModal()">Cancel</button>
|
|
1186
|
+
<button class="glass-modal__action glass-modal__action--danger" onclick="deleteContract()">Delete</button>
|
|
1187
|
+
</div>
|
|
1188
|
+
</div>
|
|
1189
|
+
</div>
|
|
1190
|
+
```
|
|
1191
|
+
|
|
1192
|
+
### Settings Page
|
|
1193
|
+
|
|
1194
|
+
```html
|
|
1195
|
+
<div class="glass-bg">
|
|
1196
|
+
<nav class="glass-nav">
|
|
1197
|
+
<button class="glass-pill">
|
|
1198
|
+
<svg viewBox="0 0 24 24"><polyline points="15 18 9 12 15 6"/></svg>
|
|
1199
|
+
</button>
|
|
1200
|
+
</nav>
|
|
1201
|
+
|
|
1202
|
+
<h1 class="glass-title">Settings</h1>
|
|
1203
|
+
|
|
1204
|
+
<div class="gl-stack gl-stack--md">
|
|
1205
|
+
<label class="glass-toggle">
|
|
1206
|
+
<input class="glass-toggle__input" type="checkbox" checked>
|
|
1207
|
+
<span class="glass-toggle__track"><span class="glass-toggle__thumb"></span></span>
|
|
1208
|
+
<span class="glass-toggle__label">Push Notifications</span>
|
|
1209
|
+
</label>
|
|
1210
|
+
|
|
1211
|
+
<hr class="glass-divider">
|
|
1212
|
+
|
|
1213
|
+
<label class="glass-toggle">
|
|
1214
|
+
<input class="glass-toggle__input" type="checkbox">
|
|
1215
|
+
<span class="glass-toggle__track"><span class="glass-toggle__thumb"></span></span>
|
|
1216
|
+
<span class="glass-toggle__label">Dark Mode</span>
|
|
1217
|
+
</label>
|
|
1218
|
+
|
|
1219
|
+
<hr class="glass-divider">
|
|
1220
|
+
|
|
1221
|
+
<div class="glass-range-group">
|
|
1222
|
+
<div class="glass-range-header">
|
|
1223
|
+
<label class="glass-label">Font Size</label>
|
|
1224
|
+
<span class="glass-range-value">100%</span>
|
|
1225
|
+
</div>
|
|
1226
|
+
<input class="glass-range" type="range" min="80" max="150" value="100">
|
|
1227
|
+
</div>
|
|
1228
|
+
|
|
1229
|
+
<hr class="glass-divider">
|
|
1230
|
+
|
|
1231
|
+
<div class="glass-accordion">
|
|
1232
|
+
<div class="glass-accordion__item">
|
|
1233
|
+
<button class="glass-accordion__trigger" onclick="this.parentElement.classList.toggle('is-open')">
|
|
1234
|
+
<span>Advanced Settings</span>
|
|
1235
|
+
<span class="glass-accordion__trigger-icon">
|
|
1236
|
+
<svg viewBox="0 0 24 24"><polyline points="6 9 12 15 18 9"/></svg>
|
|
1237
|
+
</span>
|
|
1238
|
+
</button>
|
|
1239
|
+
<div class="glass-accordion__content">
|
|
1240
|
+
<div class="glass-accordion__body">
|
|
1241
|
+
Advanced options go here…
|
|
1242
|
+
</div>
|
|
1243
|
+
</div>
|
|
1244
|
+
</div>
|
|
1245
|
+
</div>
|
|
1246
|
+
</div>
|
|
1247
|
+
</div>
|
|
1248
|
+
```
|
|
1249
|
+
|
|
1250
|
+
### iOS-style Settings Screen (List + Popover)
|
|
1251
|
+
|
|
1252
|
+
A grouped settings screen using `glass-list` for the rows and `glass-popover` for an inline action menu. Reproduces the layout of native iOS Settings screens.
|
|
1253
|
+
|
|
1254
|
+
```html
|
|
1255
|
+
<div class="glass-bg">
|
|
1256
|
+
<nav class="glass-nav">
|
|
1257
|
+
<button class="glass-pill">
|
|
1258
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
1259
|
+
<polyline points="15 18 9 12 15 6"/>
|
|
1260
|
+
</svg>
|
|
1261
|
+
</button>
|
|
1262
|
+
<h1 class="glass-title">Settings</h1>
|
|
1263
|
+
|
|
1264
|
+
<!-- Inline action menu (popover) -->
|
|
1265
|
+
<div class="glass-popover-anchor">
|
|
1266
|
+
<button class="glass-pill" onclick="gkTogglePopover(this, event)" aria-label="More">
|
|
1267
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
1268
|
+
<circle cx="12" cy="5" r="1.5" fill="currentColor"/>
|
|
1269
|
+
<circle cx="12" cy="12" r="1.5" fill="currentColor"/>
|
|
1270
|
+
<circle cx="12" cy="19" r="1.5" fill="currentColor"/>
|
|
1271
|
+
</svg>
|
|
1272
|
+
</button>
|
|
1273
|
+
<div class="glass-popover glass-popover--end">
|
|
1274
|
+
<ul class="glass-list glass-list--bare">
|
|
1275
|
+
<li class="glass-list__item glass-list__item--interactive">
|
|
1276
|
+
<div class="glass-list__content"><div class="glass-list__title">Edit profile</div></div>
|
|
1277
|
+
</li>
|
|
1278
|
+
<li class="glass-list__item glass-list__item--interactive">
|
|
1279
|
+
<div class="glass-list__content"><div class="glass-list__title">Sign out</div></div>
|
|
1280
|
+
</li>
|
|
1281
|
+
</ul>
|
|
1282
|
+
</div>
|
|
1283
|
+
</div>
|
|
1284
|
+
</nav>
|
|
1285
|
+
|
|
1286
|
+
<!-- Account section -->
|
|
1287
|
+
<p class="gl-text-muted gl-text-sm gl-mb-sm">ACCOUNT</p>
|
|
1288
|
+
<ul class="glass-list gl-mb-lg">
|
|
1289
|
+
<li class="glass-list__item glass-list__item--interactive">
|
|
1290
|
+
<span class="glass-list__leading">
|
|
1291
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
1292
|
+
<path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"/>
|
|
1293
|
+
<circle cx="12" cy="7" r="4"/>
|
|
1294
|
+
</svg>
|
|
1295
|
+
</span>
|
|
1296
|
+
<div class="glass-list__content">
|
|
1297
|
+
<div class="glass-list__title">Marcel Jungherz</div>
|
|
1298
|
+
<div class="glass-list__subtitle">marcel@jungherz.com</div>
|
|
1299
|
+
</div>
|
|
1300
|
+
<div class="glass-list__trailing">
|
|
1301
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
1302
|
+
<polyline points="9 18 15 12 9 6"/>
|
|
1303
|
+
</svg>
|
|
1304
|
+
</div>
|
|
1305
|
+
</li>
|
|
1306
|
+
<li class="glass-list__item glass-list__item--interactive">
|
|
1307
|
+
<span class="glass-list__leading">
|
|
1308
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
1309
|
+
<rect x="2" y="5" width="20" height="14" rx="2"/>
|
|
1310
|
+
<line x1="2" y1="10" x2="22" y2="10"/>
|
|
1311
|
+
</svg>
|
|
1312
|
+
</span>
|
|
1313
|
+
<div class="glass-list__content">
|
|
1314
|
+
<div class="glass-list__title">Subscriptions</div>
|
|
1315
|
+
</div>
|
|
1316
|
+
<div class="glass-list__trailing">
|
|
1317
|
+
$34.94
|
|
1318
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
1319
|
+
<polyline points="9 18 15 12 9 6"/>
|
|
1320
|
+
</svg>
|
|
1321
|
+
</div>
|
|
1322
|
+
</li>
|
|
1323
|
+
</ul>
|
|
1324
|
+
|
|
1325
|
+
<!-- Notifications section -->
|
|
1326
|
+
<p class="gl-text-muted gl-text-sm gl-mb-sm">NOTIFICATIONS</p>
|
|
1327
|
+
<ul class="glass-list gl-mb-lg">
|
|
1328
|
+
<li class="glass-list__item glass-list__item--interactive">
|
|
1329
|
+
<span class="glass-list__leading">
|
|
1330
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
1331
|
+
<path d="M18 8a6 6 0 1 0-12 0c0 7-3 9-3 9h18s-3-2-3-9"/>
|
|
1332
|
+
<path d="M13.73 21a2 2 0 0 1-3.46 0"/>
|
|
1333
|
+
</svg>
|
|
1334
|
+
</span>
|
|
1335
|
+
<div class="glass-list__content"><div class="glass-list__title">Push notifications</div></div>
|
|
1336
|
+
<div class="glass-list__trailing">On</div>
|
|
1337
|
+
</li>
|
|
1338
|
+
<li class="glass-list__item glass-list__item--interactive">
|
|
1339
|
+
<span class="glass-list__leading">
|
|
1340
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
1341
|
+
<path d="M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z"/>
|
|
1342
|
+
<polyline points="22 6 12 13 2 6"/>
|
|
1343
|
+
</svg>
|
|
1344
|
+
</span>
|
|
1345
|
+
<div class="glass-list__content"><div class="glass-list__title">Email digest</div></div>
|
|
1346
|
+
<div class="glass-list__trailing">Weekly</div>
|
|
1347
|
+
</li>
|
|
1348
|
+
<li class="glass-list__item glass-list__item--center glass-list__item--interactive">
|
|
1349
|
+
Reset to defaults
|
|
1350
|
+
</li>
|
|
1351
|
+
</ul>
|
|
1352
|
+
</div>
|
|
1353
|
+
```
|
|
1354
|
+
|
|
1355
|
+
Key points in this composition:
|
|
1356
|
+
|
|
1357
|
+
- **Two grouped sections** — labeled by small uppercase muted text above each list, matching iOS settings.
|
|
1358
|
+
- **Auto-dividers** — no `<hr>` between rows; the `::after` pseudo-element handles them.
|
|
1359
|
+
- **Mixed trailing types** — chevron, value text, value + chevron, all in the same list.
|
|
1360
|
+
- **Centered destructive action** — last item uses `--center` for a "Reset to defaults" style row, gets a full-width divider above (no leading icon → standard padding inset).
|
|
1361
|
+
- **Popover in nav** — `glass-popover--end` aligns the menu to the right edge of the trigger so it doesn't overflow the viewport.
|
|
1362
|
+
- **Bare list inside popover** — `glass-list--bare` strips the inner glass surface so the popover stays the only glass layer.
|
|
1363
|
+
|
|
1364
|
+
---
|
|
1365
|
+
|
|
1366
|
+
### Progress + Toast
|
|
1367
|
+
|
|
1368
|
+
```html
|
|
1369
|
+
<!-- Progress -->
|
|
1370
|
+
<div class="glass-progress glass-progress--success">
|
|
1371
|
+
<div class="glass-progress__header">
|
|
1372
|
+
<span class="glass-progress__label">Upload</span>
|
|
1373
|
+
<span class="glass-progress__value">100%</span>
|
|
1374
|
+
</div>
|
|
1375
|
+
<div class="glass-progress__track">
|
|
1376
|
+
<div class="glass-progress__fill" style="width: 100%"></div>
|
|
1377
|
+
</div>
|
|
1378
|
+
</div>
|
|
1379
|
+
|
|
1380
|
+
<!-- Toast (shown via JS) -->
|
|
1381
|
+
<div class="glass-toast glass-toast--success is-visible">
|
|
1382
|
+
<svg class="glass-toast__icon" viewBox="0 0 24 24">
|
|
1383
|
+
<polyline points="20 6 9 17 4 12"/>
|
|
1384
|
+
</svg>
|
|
1385
|
+
<span class="glass-toast__text">Upload successful!</span>
|
|
1386
|
+
</div>
|
|
1387
|
+
```
|
|
1388
|
+
|
|
1389
|
+
---
|
|
1390
|
+
|
|
1391
|
+
## 7. Rules & Common Mistakes
|
|
1392
|
+
|
|
1393
|
+
### ✅ Always follow
|
|
1394
|
+
|
|
1395
|
+
1. **`glass-bg` as outermost container** – Without the background wrapper, the aurora background is missing and glass effects won't render correctly.
|
|
1396
|
+
2. **`glass-bg--has-tab-bar`** – When a tab bar is present, this modifier must be set on `glass-bg`, otherwise the tab bar covers the bottom content.
|
|
1397
|
+
3. **Buttons are full-width** – `glass-btn` has `width: 100%`. Always add `glass-btn--auto` for inline buttons.
|
|
1398
|
+
4. **Wrap inputs in `glass-input-group`** – For correct label/hint spacing.
|
|
1399
|
+
5. **Place state classes correctly:**
|
|
1400
|
+
- `is-active` → on `.glass-modal-overlay` (not on `.glass-modal`)
|
|
1401
|
+
- `is-active` → on `.glass-tab-bar__item`
|
|
1402
|
+
- `is-open` → on `.glass-accordion__item`
|
|
1403
|
+
- `is-open` → on `.glass-popover` (not on the trigger or anchor)
|
|
1404
|
+
- `is-visible` → on `.glass-toast`
|
|
1405
|
+
6. **SVG icons** – GlassKit uses inline SVGs (stroke-based, not fill). Typical attributes: `viewBox="0 0 24 24"`, stroke via `currentColor`.
|
|
1406
|
+
7. **`data-theme`** – Always set on `<html>`, never on `<body>` or deeper elements.
|
|
1407
|
+
8. **List dividers are automatic** – Never add a `<hr>` or divider element between `.glass-list__item`s. The divider is rendered via `::after` and respects `:has(.glass-list__leading)` for the inset.
|
|
1408
|
+
9. **Popover toggle naming** – Never name your popover toggle JS function `togglePopover`. It collides with the native `HTMLElement.togglePopover()` method. Use a prefix like `gkTogglePopover`.
|
|
1409
|
+
|
|
1410
|
+
### ❌ Common Mistakes
|
|
1411
|
+
|
|
1412
|
+
| Mistake | Correction |
|
|
1413
|
+
|---|---|
|
|
1414
|
+
| `is-active` on `.glass-modal` instead of `.glass-modal-overlay` | Set `is-active` on the overlay |
|
|
1415
|
+
| `glass-btn` without variant (`--primary` etc.) | Always specify a variant |
|
|
1416
|
+
| Inputs without `glass-input-group` wrapper | Wrap in `glass-input-group` |
|
|
1417
|
+
| `glass-tab-bar` without `glass-bg--has-tab-bar` | Add modifier to the background container |
|
|
1418
|
+
| `data-theme` on `<body>` | Set on `<html>` |
|
|
1419
|
+
| Progress width via class instead of inline style | Use `style="width: X%"` on `.glass-progress__fill` |
|
|
1420
|
+
| Toggle without `__track > __thumb` nesting | Follow correct BEM hierarchy |
|
|
1421
|
+
| Manually adding `<hr>` or divider element between `.glass-list__item`s | Remove it — dividers are automatic via `::after` |
|
|
1422
|
+
| Putting `glass-list` inside `glass-popover` without `--bare` | Add `.glass-list--bare` to strip the double glass surface |
|
|
1423
|
+
| JS function named `togglePopover()` | Rename to `gkTogglePopover()` or similar to avoid native API clash |
|
|
1424
|
+
| Putting `.is-open` on the trigger button instead of `.glass-popover` | The state class belongs on the popover element |
|
|
1425
|
+
|
|
1426
|
+
---
|
|
1427
|
+
|
|
1428
|
+
## 8. Quick Class Reference
|
|
1429
|
+
|
|
1430
|
+
| Component | Base Class | Modifiers / States |
|
|
1431
|
+
|---|---|---|
|
|
1432
|
+
| Background | `.glass-bg` | `--has-tab-bar` |
|
|
1433
|
+
| Navigation | `.glass-nav` | – |
|
|
1434
|
+
| Pill Button | `.glass-pill` | – |
|
|
1435
|
+
| Theme Toggle | `.glass-theme-toggle` | – |
|
|
1436
|
+
| Title | `.glass-title` | – |
|
|
1437
|
+
| Card | `.glass-card` | `--glow` |
|
|
1438
|
+
| Button | `.glass-btn` | `--primary`, `--secondary`, `--tertiary`, `--sm`, `--lg`, `--auto` |
|
|
1439
|
+
| Badge | `.glass-badge` | `--primary`, `--success`, `--error` |
|
|
1440
|
+
| Avatar | `.glass-avatar` | `--sm`, `--lg` |
|
|
1441
|
+
| Divider | `.glass-divider` | – |
|
|
1442
|
+
| Status | `.glass-status` | – |
|
|
1443
|
+
| Input | `.glass-input` | `--error`, `:disabled` |
|
|
1444
|
+
| Input Group | `.glass-input-group` | – |
|
|
1445
|
+
| Label | `.glass-label` | – |
|
|
1446
|
+
| Hint | `.glass-hint` | `--error` |
|
|
1447
|
+
| Textarea | `.glass-textarea` | – |
|
|
1448
|
+
| Select | `.glass-select` | – |
|
|
1449
|
+
| Search | `.glass-search` | – |
|
|
1450
|
+
| Toggle | `.glass-toggle` | `:checked` |
|
|
1451
|
+
| Checkbox | `.glass-checkbox` | `:checked` |
|
|
1452
|
+
| Radio | `.glass-radio` | `:checked` |
|
|
1453
|
+
| Range | `.glass-range` | – |
|
|
1454
|
+
| Progress | `.glass-progress` | `--sm`, `--lg`, `--success`, `--error` |
|
|
1455
|
+
| Modal | `.glass-modal-overlay` | `.is-active` |
|
|
1456
|
+
| Toast | `.glass-toast` | `--success`, `--error`, `--warning`, `.is-visible` |
|
|
1457
|
+
| Tab Bar | `.glass-tab-bar` | `.is-active` on items |
|
|
1458
|
+
| Accordion | `.glass-accordion` | `.is-open` on items |
|
|
1459
|
+
| List | `.glass-list` | `--flush`, `--bare`, `__item--interactive`, `__item--center` |
|
|
1460
|
+
| Popover | `.glass-popover` | `--top`, `--start`, `--end`, `.is-open` |
|
|
1461
|
+
|
|
1462
|
+
---
|
|
1463
|
+
|
|
1464
|
+
## 9. Web Components / Shadow DOM
|
|
1465
|
+
|
|
1466
|
+
GlassKit ships a Constructable Stylesheet for Shadow DOM usage:
|
|
1467
|
+
|
|
1468
|
+
```js
|
|
1469
|
+
import { glassSheet } from '@jungherz-de/glasskit/glasskit-styles.js';
|
|
1470
|
+
|
|
1471
|
+
class MyCard extends HTMLElement {
|
|
1472
|
+
constructor() {
|
|
1473
|
+
super();
|
|
1474
|
+
const shadow = this.attachShadow({ mode: 'open' });
|
|
1475
|
+
shadow.adoptedStyleSheets = [glassSheet];
|
|
1476
|
+
shadow.innerHTML = `
|
|
1477
|
+
<div class="glass-card glass-card--glow">
|
|
1478
|
+
<p class="glass-card__text"><slot></slot></p>
|
|
1479
|
+
</div>
|
|
1480
|
+
`;
|
|
1481
|
+
}
|
|
1482
|
+
}
|
|
1483
|
+
customElements.define('my-card', MyCard);
|
|
1484
|
+
```
|
|
1485
|
+
|
|
1486
|
+
| Export | Type | Description |
|
|
1487
|
+
|---|---|---|
|
|
1488
|
+
| `glassSheet` | `CSSStyleSheet` | Constructable Stylesheet for `adoptedStyleSheets` |
|
|
1489
|
+
| `css` | `string` | CSS as string (fallback) |
|
|
1490
|
+
|
|
1491
|
+
**Note:** CSS Custom Properties (`--gl-*`) penetrate the shadow boundary automatically. Theme switching works globally.
|
|
1492
|
+
|
|
1493
|
+
---
|
|
1494
|
+
|
|
1495
|
+
## 10. Custom Theming
|
|
1496
|
+
|
|
1497
|
+
Load custom brand colors via `theme-override.css` after the base library:
|
|
1498
|
+
|
|
1499
|
+
```css
|
|
1500
|
+
:root {
|
|
1501
|
+
--gl-color-primary: #007AFF;
|
|
1502
|
+
--gl-color-primary-dark: #0055CC;
|
|
1503
|
+
--gl-color-primary-mid: #0066E0;
|
|
1504
|
+
|
|
1505
|
+
--gl-border-warm: rgba(0, 122, 255, 0.35);
|
|
1506
|
+
--gl-border-focus: rgba(0, 122, 255, 0.60);
|
|
1507
|
+
|
|
1508
|
+
--gl-shadow-btn-primary: 0 6px 24px rgba(0, 100, 220, 0.35),
|
|
1509
|
+
0 2px 8px rgba(0, 0, 0, 0.15);
|
|
1510
|
+
--gl-shadow-focus: 0 0 0 3px rgba(0, 122, 255, 0.3);
|
|
1511
|
+
}
|
|
1512
|
+
```
|
|
1513
|
+
|
|
1514
|
+
Included theme templates in `theme-override.css`:
|
|
1515
|
+
- 🔵 Ocean Blue
|
|
1516
|
+
- 🟢 Emerald Green
|
|
1517
|
+
- 🌹 Rose
|
|
1518
|
+
- 🎨 Custom (empty, ready to fill)
|