shadcn-glass-ui 2.0.6 → 2.0.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. package/README.md +159 -105
  2. package/dist/cli/index.cjs +1 -1
  3. package/dist/components.cjs +4 -4
  4. package/dist/components.d.ts +63 -322
  5. package/dist/components.js +2 -2
  6. package/dist/hooks.cjs +2 -2
  7. package/dist/index.cjs +43 -6
  8. package/dist/index.cjs.map +1 -1
  9. package/dist/index.js +12 -3
  10. package/dist/index.js.map +1 -1
  11. package/dist/r/alert-glass.json +2 -1
  12. package/dist/r/avatar-glass.json +2 -3
  13. package/dist/r/button-glass.json +1 -1
  14. package/dist/r/circular-progress-glass.json +1 -1
  15. package/dist/r/combobox-glass.json +1 -1
  16. package/dist/r/dropdown-glass.json +3 -5
  17. package/dist/r/dropdown-menu-glass.json +42 -0
  18. package/dist/r/language-bar-glass.json +2 -2
  19. package/dist/r/popover-glass.json +1 -1
  20. package/dist/r/profile-avatar-glass.json +5 -3
  21. package/dist/r/rainbow-progress-glass.json +1 -1
  22. package/dist/r/registry.json +10 -4
  23. package/dist/r/sort-dropdown-glass.json +3 -4
  24. package/dist/r/tooltip-glass.json +3 -5
  25. package/dist/r/trust-score-card-glass.json +1 -1
  26. package/dist/r/trust-score-display-glass.json +1 -1
  27. package/dist/shadcn-glass-ui.css +1 -1
  28. package/dist/{theme-context-CVW50BKW.cjs → theme-context-DNe_2vWJ.cjs} +2 -2
  29. package/dist/theme-context-DNe_2vWJ.cjs.map +1 -0
  30. package/dist/{theme-context-BZoCplcU.js → theme-context-_T5r1KG4.js} +1 -1
  31. package/dist/theme-context-_T5r1KG4.js.map +1 -0
  32. package/dist/themes.cjs +1 -1
  33. package/dist/themes.d.ts +89 -1
  34. package/dist/themes.js +1 -1
  35. package/dist/{trust-score-card-glass-BcZbul0P.js → trust-score-card-glass-A7kas5OS.js} +353 -279
  36. package/dist/trust-score-card-glass-A7kas5OS.js.map +1 -0
  37. package/dist/{trust-score-card-glass-r3qM09Jp.cjs → trust-score-card-glass-Dgu46oWI.cjs} +551 -313
  38. package/dist/trust-score-card-glass-Dgu46oWI.cjs.map +1 -0
  39. package/dist/{use-focus-ZE8ozmZE.cjs → use-focus-BRkQtQCj.cjs} +2 -2
  40. package/dist/{use-focus-ZE8ozmZE.cjs.map → use-focus-BRkQtQCj.cjs.map} +1 -1
  41. package/dist/{use-wallpaper-tint-BuS80tbN.cjs → use-wallpaper-tint-CfShPBo2.cjs} +2 -2
  42. package/dist/{use-wallpaper-tint-BuS80tbN.cjs.map → use-wallpaper-tint-CfShPBo2.cjs.map} +1 -1
  43. package/dist/{utils-DLXayspX.cjs → utils-BXN7AcRu.cjs} +2 -2
  44. package/dist/{utils-DLXayspX.cjs.map → utils-BXN7AcRu.cjs.map} +1 -1
  45. package/dist/utils.cjs +1 -1
  46. package/docs/AI_USAGE.md +1 -32
  47. package/docs/API_PATTERNS_COMPARISON.md +10 -9
  48. package/docs/COMPONENTS_CATALOG.md +140 -45
  49. package/docs/DROPDOWN_ARCHITECTURE.md +290 -0
  50. package/docs/GETTING_STARTED.md +6 -5
  51. package/docs/TOKEN_ARCHITECTURE.md +100 -0
  52. package/docs/api/README.md +3 -3
  53. package/docs/migration/compound-components-v2.md +384 -0
  54. package/docs/visual-testing-guide.md +50 -12
  55. package/package.json +2 -2
  56. package/dist/theme-context-BZoCplcU.js.map +0 -1
  57. package/dist/theme-context-CVW50BKW.cjs.map +0 -1
  58. package/dist/trust-score-card-glass-BcZbul0P.js.map +0 -1
  59. package/dist/trust-score-card-glass-r3qM09Jp.cjs.map +0 -1
  60. package/docs/ADVANCED_PATTERNS.md +0 -408
  61. package/docs/BREAKING_CHANGES.md +0 -213
  62. package/docs/announcements/v1.0.5-devto.md +0 -363
  63. package/docs/announcements/v1.0.5-reddit.md +0 -115
  64. package/docs/announcements/v1.0.5-twitter.md +0 -70
@@ -0,0 +1,384 @@
1
+ # Compound Components Migration Guide (v2.0+)
2
+
3
+ ## Overview
4
+
5
+ As of v2.0.0, five component families have been migrated to the **compound component API** pattern
6
+ following shadcn/ui best practices:
7
+
8
+ - **AlertGlass** - Alert notifications with Title/Description
9
+ - **AvatarGlass** - User avatars with Image/Fallback
10
+ - **TooltipGlass** - Tooltips with Provider/Trigger/Content
11
+ - **PopoverGlass** - Popovers with Trigger/Content/Anchor
12
+ - **DropdownMenuGlass** - Dropdown menus with full shadcn/ui pattern (alongside simple
13
+ DropdownGlass)
14
+
15
+ All components maintain **100% backward compatibility** through wrapper components or simple APIs.
16
+
17
+ ---
18
+
19
+ ## AlertGlass Migration
20
+
21
+ ### Old API (v1.x)
22
+
23
+ ```tsx
24
+ <AlertGlass variant="destructive" title="Error">
25
+ Something went wrong
26
+ </AlertGlass>
27
+ ```
28
+
29
+ ### New API (v2.0+)
30
+
31
+ ```tsx
32
+ <AlertGlass variant="destructive">
33
+ <AlertGlassTitle>Error</AlertGlassTitle>
34
+ <AlertGlassDescription>Something went wrong</AlertGlassDescription>
35
+ </AlertGlass>
36
+ ```
37
+
38
+ ### Benefits
39
+
40
+ - ✅ **Flexible composition** - Mix and match Title/Description
41
+ - ✅ **Type safety** - Better TypeScript inference
42
+ - ✅ **shadcn/ui compatible** - Same pattern as shadcn Alert
43
+ - ✅ **Custom styling** - Style Title/Description independently
44
+
45
+ ### Available Components
46
+
47
+ ```tsx
48
+ // Main container
49
+ <AlertGlass variant="default" | "destructive" | "success" | "warning" dismissible onDismiss={() => {}}>
50
+
51
+ // Sub-components (inherit color from variant)
52
+ <AlertGlassTitle>...</AlertGlassTitle>
53
+ <AlertGlassDescription>...</AlertGlassDescription>
54
+ ```
55
+
56
+ ---
57
+
58
+ ## AvatarGlass Migration
59
+
60
+ ### Old API (v1.x)
61
+
62
+ ```tsx
63
+ <AvatarGlass name="John Doe" size="lg" status="online" />
64
+ ```
65
+
66
+ ### New API (v2.0+) - Compound
67
+
68
+ ```tsx
69
+ <AvatarGlass size="lg" status="online">
70
+ <AvatarGlassImage src="/avatar.jpg" alt="John Doe" />
71
+ <AvatarGlassFallback>JD</AvatarGlassFallback>
72
+ </AvatarGlass>
73
+ ```
74
+
75
+ ### Backward Compatible - Simple Wrapper
76
+
77
+ ```tsx
78
+ <AvatarGlassSimple name="John Doe" size="lg" status="online" />
79
+ ```
80
+
81
+ ### Benefits
82
+
83
+ - ✅ **Image control** - Full control over image loading/fallback
84
+ - ✅ **Radix UI based** - Built on `@radix-ui/react-avatar`
85
+ - ✅ **Custom fallback** - Any React element, not just initials
86
+ - ✅ **asChild pattern** - Use any element as container
87
+
88
+ ### Available Components
89
+
90
+ ```tsx
91
+ // Main container
92
+ <AvatarGlass size="sm" | "md" | "lg" | "xl" status="online" | "offline" | "busy" | "away" glowing>
93
+
94
+ // Sub-components
95
+ <AvatarGlassImage src="..." alt="..." />
96
+ <AvatarGlassFallback>...</AvatarGlassFallback>
97
+
98
+ // Simple wrapper (backward compatible)
99
+ <AvatarGlassSimple name="..." size="..." status="..." />
100
+ ```
101
+
102
+ ---
103
+
104
+ ## TooltipGlass Migration
105
+
106
+ ### Old API (v1.x)
107
+
108
+ ```tsx
109
+ <TooltipGlass content="Tooltip text" side="top">
110
+ <button>Hover me</button>
111
+ </TooltipGlass>
112
+ ```
113
+
114
+ ### New API (v2.0+) - Compound
115
+
116
+ ```tsx
117
+ <TooltipGlassProvider>
118
+ <TooltipGlass>
119
+ <TooltipGlassTrigger asChild>
120
+ <button>Hover me</button>
121
+ </TooltipGlassTrigger>
122
+ <TooltipGlassContent side="top">
123
+ <p>Tooltip text</p>
124
+ </TooltipGlassContent>
125
+ </TooltipGlass>
126
+ </TooltipGlassProvider>
127
+ ```
128
+
129
+ ### Backward Compatible - Simple Wrapper
130
+
131
+ ```tsx
132
+ <TooltipGlassProvider>
133
+ <TooltipGlassSimple content="Tooltip text" side="top">
134
+ <button>Hover me</button>
135
+ </TooltipGlassSimple>
136
+ </TooltipGlassProvider>
137
+ ```
138
+
139
+ ### Benefits
140
+
141
+ - ✅ **Rich content** - Any React element in tooltip
142
+ - ✅ **Radix UI based** - Built on `@radix-ui/react-tooltip`
143
+ - ✅ **Provider pattern** - Share delay settings across tooltips
144
+ - ✅ **Accessibility** - WCAG 2.1 AA compliant
145
+
146
+ ### Available Components
147
+
148
+ ```tsx
149
+ // Provider (wrap all tooltips to share settings)
150
+ <TooltipGlassProvider delayDuration={0}>
151
+
152
+ // Root container
153
+ <TooltipGlass>
154
+
155
+ // Trigger (usually with asChild)
156
+ <TooltipGlassTrigger asChild>
157
+
158
+ // Content
159
+ <TooltipGlassContent side="top" | "bottom" | "left" | "right" sideOffset={4}>
160
+
161
+ // Simple wrapper (backward compatible)
162
+ <TooltipGlassSimple content="..." side="..." />
163
+ ```
164
+
165
+ ---
166
+
167
+ ## PopoverGlass Migration
168
+
169
+ ### Old API (v1.x)
170
+
171
+ ```tsx
172
+ <PopoverGlass trigger={<button>Open</button>} side="bottom" align="center">
173
+ <p>Popover content</p>
174
+ </PopoverGlass>
175
+ ```
176
+
177
+ ### New API (v2.0+) - Compound
178
+
179
+ ```tsx
180
+ <PopoverGlass>
181
+ <PopoverGlassTrigger asChild>
182
+ <button>Open</button>
183
+ </PopoverGlassTrigger>
184
+ <PopoverGlassContent side="bottom" align="center">
185
+ <p>Popover content</p>
186
+ </PopoverGlassContent>
187
+ </PopoverGlass>
188
+ ```
189
+
190
+ ### Backward Compatible - Legacy Wrapper
191
+
192
+ ```tsx
193
+ <PopoverGlassLegacy trigger={<button>Open</button>} side="bottom" align="center">
194
+ <p>Popover content</p>
195
+ </PopoverGlassLegacy>
196
+ ```
197
+
198
+ ### Benefits
199
+
200
+ - ✅ **Flexible positioning** - Full control over trigger/content
201
+ - ✅ **Radix UI based** - Built on `@radix-ui/react-popover`
202
+ - ✅ **Anchor support** - Position relative to custom anchor
203
+ - ✅ **Portal rendering** - Escape z-index issues
204
+
205
+ ### Available Components
206
+
207
+ ```tsx
208
+ // Root container
209
+ <PopoverGlass>
210
+
211
+ // Trigger (usually with asChild)
212
+ <PopoverGlassTrigger asChild>
213
+
214
+ // Content
215
+ <PopoverGlassContent side="top" | "bottom" | "left" | "right" align="start" | "center" | "end">
216
+
217
+ // Optional anchor
218
+ <PopoverGlassAnchor>
219
+
220
+ // Legacy wrapper (backward compatible)
221
+ <PopoverGlassLegacy trigger={...} side="..." align="...">
222
+ ```
223
+
224
+ ---
225
+
226
+ ## Migration Checklist
227
+
228
+ When migrating your codebase to compound components:
229
+
230
+ ### 1. AlertGlass
231
+
232
+ - [ ] Replace `title` prop with `<AlertGlassTitle>`
233
+ - [ ] Wrap children in `<AlertGlassDescription>`
234
+ - [ ] Update imports to include `AlertGlassTitle`, `AlertGlassDescription`
235
+
236
+ ### 2. AvatarGlass
237
+
238
+ **Option A: Full migration (recommended)**
239
+
240
+ - [ ] Use `<AvatarGlassImage>` for images
241
+ - [ ] Use `<AvatarGlassFallback>` for fallback content
242
+ - [ ] Update imports to include `AvatarGlassImage`, `AvatarGlassFallback`
243
+
244
+ **Option B: Quick fix (backward compatible)**
245
+
246
+ - [ ] Replace `<AvatarGlass>` with `<AvatarGlassSimple>`
247
+ - [ ] Update import to include `AvatarGlassSimple`
248
+
249
+ ### 3. TooltipGlass
250
+
251
+ **Option A: Full migration (recommended)**
252
+
253
+ - [ ] Wrap tooltips in `<TooltipGlassProvider>`
254
+ - [ ] Use `<TooltipGlassTrigger asChild>` for trigger
255
+ - [ ] Use `<TooltipGlassContent>` for content
256
+ - [ ] Update imports
257
+
258
+ **Option B: Quick fix (backward compatible)**
259
+
260
+ - [ ] Wrap tooltips in `<TooltipGlassProvider>`
261
+ - [ ] Replace `<TooltipGlass>` with `<TooltipGlassSimple>`
262
+ - [ ] Update import to include `TooltipGlassProvider`, `TooltipGlassSimple`
263
+
264
+ ### 4. PopoverGlass
265
+
266
+ **Option A: Full migration (recommended)**
267
+
268
+ - [ ] Use `<PopoverGlassTrigger asChild>` for trigger
269
+ - [ ] Use `<PopoverGlassContent>` for content
270
+ - [ ] Update imports
271
+
272
+ **Option B: Quick fix (backward compatible)**
273
+
274
+ - [ ] Replace `<PopoverGlass>` with `<PopoverGlassLegacy>`
275
+ - [ ] Update import to include `PopoverGlassLegacy`
276
+
277
+ ### 5. DropdownMenuGlass (New in v2.0)
278
+
279
+ **No migration needed!** DropdownMenuGlass is a **new addition** alongside the existing
280
+ DropdownGlass.
281
+
282
+ **DropdownGlass (simple API)** - Already available, no changes:
283
+
284
+ - [ ] Continue using `items` prop for simple dropdowns
285
+ - [ ] No migration required
286
+
287
+ **DropdownMenuGlass (compound API)** - New compound component for complex menus:
288
+
289
+ - [ ] Use for advanced features (checkboxes, radio groups, submenus, labels)
290
+ - [ ] Follow shadcn/ui DropdownMenu pattern
291
+ - [ ] Import from `@/components/glass/ui/dropdown-menu-glass`
292
+
293
+ **When to use which:**
294
+
295
+ - Use `DropdownGlass` for simple menus with basic items (quick setup)
296
+ - Use `DropdownMenuGlass` for complex menus with advanced features (full control)
297
+
298
+ ---
299
+
300
+ ## Automated Migration Scripts
301
+
302
+ ### Find all AlertGlass with old API
303
+
304
+ ```bash
305
+ # macOS/Linux
306
+ grep -r "title=" src/ | grep "AlertGlass"
307
+
308
+ # Find and update (use with caution!)
309
+ find src/ -type f \( -name "*.tsx" -o -name "*.ts" \) -exec sed -i '' \
310
+ 's/<AlertGlass variant="\([^"]*\)" title="\([^"]*\)">\s*\([^<]*\)\s*<\/AlertGlass>/<AlertGlass variant="\1">\n <AlertGlassTitle>\2<\/AlertGlassTitle>\n <AlertGlassDescription>\3<\/AlertGlassDescription>\n<\/AlertGlass>/g' \
311
+ {} +
312
+ ```
313
+
314
+ ### Find all AvatarGlass with old API
315
+
316
+ ```bash
317
+ # macOS/Linux
318
+ grep -r "name=" src/ | grep "AvatarGlass"
319
+ ```
320
+
321
+ ### Find all TooltipGlass with old API
322
+
323
+ ```bash
324
+ # macOS/Linux
325
+ grep -r "content=" src/ | grep "TooltipGlass"
326
+ ```
327
+
328
+ ### Find all PopoverGlass with old API
329
+
330
+ ```bash
331
+ # macOS/Linux
332
+ grep -r "trigger=" src/ | grep "PopoverGlass"
333
+ ```
334
+
335
+ ---
336
+
337
+ ## Breaking Changes Summary
338
+
339
+ **None!** All components maintain 100% backward compatibility through wrapper components:
340
+
341
+ - `AlertGlass` - No wrapper needed, but `title` prop removed
342
+ - `AvatarGlass` → `AvatarGlassSimple` (wrapper available)
343
+ - `TooltipGlass` → `TooltipGlassSimple` (wrapper available)
344
+ - `PopoverGlass` → `PopoverGlassLegacy` (wrapper available)
345
+
346
+ ---
347
+
348
+ ## TypeScript Support
349
+
350
+ All compound components have full TypeScript support with:
351
+
352
+ - ✅ Strict type checking
353
+ - ✅ Autocomplete for props
354
+ - ✅ Generic constraints for `asChild` pattern
355
+ - ✅ Proper `React.forwardRef` types
356
+
357
+ Example:
358
+
359
+ ```tsx
360
+ import type { ComponentPropsWithoutRef, ElementRef } from 'react';
361
+
362
+ // Type inference works automatically
363
+ const ref = useRef<ElementRef<typeof AlertGlass>>(null);
364
+
365
+ // Props are fully typed
366
+ const props: ComponentPropsWithoutRef<typeof AlertGlass> = {
367
+ variant: 'success',
368
+ dismissible: true,
369
+ onDismiss: () => {},
370
+ };
371
+ ```
372
+
373
+ ---
374
+
375
+ ## Further Reading
376
+
377
+ - [shadcn/ui Alert](https://ui.shadcn.com/docs/components/alert) - Reference implementation
378
+ - [Radix UI Primitives](https://www.radix-ui.com/primitives) - Base components
379
+ - [Compound Component Pattern](https://kentcdodds.com/blog/compound-components-with-react-hooks) -
380
+ Pattern explanation
381
+
382
+ ---
383
+
384
+ **Questions?** Open an issue at [github.com/your-repo/issues](https://github.com/your-repo/issues)
@@ -4,9 +4,12 @@ This guide explains how to work with visual regression tests in this project.
4
4
 
5
5
  ## Overview
6
6
 
7
- The project uses **Vitest 4.0 browser mode** with **Playwright** for visual regression testing. All reference screenshots are generated on **Linux (ubuntu-latest)** in CI to ensure consistency across environments.
7
+ The project uses **Vitest 4.0 browser mode** with **Playwright** for visual regression testing. All
8
+ reference screenshots are generated on **Linux (ubuntu-latest)** in CI to ensure consistency across
9
+ environments.
8
10
 
9
11
  **Key Points:**
12
+
10
13
  - ✅ Reference screenshots are generated on Linux
11
14
  - ✅ All platforms use the same screenshot files (no `-darwin`/`-linux` suffixes)
12
15
  - ✅ Automatic workflow for updating screenshots
@@ -15,27 +18,34 @@ The project uses **Vitest 4.0 browser mode** with **Playwright** for visual regr
15
18
  ## Running Tests Locally
16
19
 
17
20
  ### Run all visual tests
21
+
18
22
  ```bash
19
23
  npm run test:visual:ci
20
24
  ```
21
25
 
22
26
  ### Update screenshots locally (for reference only)
27
+
23
28
  ```bash
24
29
  npm run test:visual:update
25
30
  ```
26
31
 
27
- **⚠️ IMPORTANT:** Do NOT commit screenshots generated on macOS. Always use the GitHub Actions workflow to generate production screenshots.
32
+ **⚠️ IMPORTANT:** Do NOT commit screenshots generated on macOS. Always use the GitHub Actions
33
+ workflow to generate production screenshots.
34
+
35
+ **Cleaning local screenshots:** If you accidentally generated screenshots locally, use this script
36
+ to remove them:
28
37
 
29
- **Cleaning local screenshots:**
30
- If you accidentally generated screenshots locally, use this script to remove them:
31
38
  ```bash
32
39
  ./scripts/clean-local-screenshots.sh
33
40
  ```
34
41
 
35
- **Protection:** A pre-commit hook automatically blocks commits of new screenshots from non-Linux platforms. If you see this error:
42
+ **Protection:** A pre-commit hook automatically blocks commits of new screenshots from non-Linux
43
+ platforms. If you see this error:
44
+
36
45
  ```
37
46
  ❌ ERROR: Cannot commit visual test screenshots from Darwin
38
47
  ```
48
+
39
49
  This is working as intended. Use the GitHub Actions workflow instead.
40
50
 
41
51
  ## Updating Reference Screenshots
@@ -43,23 +53,27 @@ This is working as intended. Use the GitHub Actions workflow instead.
43
53
  When you modify UI components and need to update screenshots:
44
54
 
45
55
  ### Option 1: Using GitHub CLI (Recommended)
56
+
46
57
  ```bash
47
58
  gh workflow run update-screenshots.yml
48
59
  ```
49
60
 
50
61
  ### Option 2: Via GitHub Web UI
62
+
51
63
  1. Go to **Actions** → **Update Visual Test Screenshots**
52
64
  2. Click **Run workflow**
53
65
  3. Optionally provide a custom commit message
54
66
  4. Click **Run workflow**
55
67
 
56
68
  The workflow will:
69
+
57
70
  1. Delete existing screenshots
58
71
  2. Generate new screenshots on Linux (ubuntu-latest)
59
72
  3. Commit and push changes automatically
60
73
  4. Upload screenshots as artifacts
61
74
 
62
75
  ### Monitoring Workflow Progress
76
+
63
77
  ```bash
64
78
  # Check workflow status
65
79
  gh run list --workflow=update-screenshots.yml --limit 1
@@ -82,6 +96,7 @@ comparatorOptions: {
82
96
  ```
83
97
 
84
98
  These tolerances account for:
99
+
85
100
  - Font rendering differences between macOS and Linux
86
101
  - Subpixel anti-aliasing variations
87
102
  - Minor layout shifts (1-2px height differences)
@@ -89,6 +104,7 @@ These tolerances account for:
89
104
  ### Screenshot Naming
90
105
 
91
106
  Screenshots use a unified naming pattern:
107
+
92
108
  ```
93
109
  {test-name}-{theme}-chromium.png
94
110
  ```
@@ -100,6 +116,7 @@ Example: `button-primary-glass-chromium.png`
100
116
  ## Test Structure
101
117
 
102
118
  ### Visual Test Locations
119
+
103
120
  ```
104
121
  src/components/__visual__/
105
122
  ├── components.visual.test.tsx # Individual component tests
@@ -112,6 +129,7 @@ src/components/__visual__/
112
129
  ```
113
130
 
114
131
  ### Screenshot Organization
132
+
115
133
  ```
116
134
  src/components/__visual__/__screenshots__/
117
135
  ├── components.visual.test.tsx/
@@ -125,11 +143,13 @@ src/components/__visual__/__screenshots__/
125
143
 
126
144
  ## Git Pre-commit Hook
127
145
 
128
- The repository includes a pre-commit hook that prevents accidentally committing screenshots generated on non-Linux platforms.
146
+ The repository includes a pre-commit hook that prevents accidentally committing screenshots
147
+ generated on non-Linux platforms.
129
148
 
130
149
  **Setup (Automatic):**
131
150
 
132
- The hook is located at `.git/hooks/pre-commit` and should work automatically. If you encounter issues:
151
+ The hook is located at `.git/hooks/pre-commit` and should work automatically. If you encounter
152
+ issues:
133
153
 
134
154
  ```bash
135
155
  # Ensure Git is using the correct hooks directory
@@ -140,11 +160,13 @@ chmod +x .git/hooks/pre-commit
140
160
  ```
141
161
 
142
162
  **How it works:**
163
+
143
164
  - Blocks commits of new `.png` files in `__screenshots__/` directories
144
165
  - Only allows commits from Linux (CI environment)
145
166
  - Shows helpful error message with instructions
146
167
 
147
168
  **Bypassing the hook (not recommended):**
169
+
148
170
  ```bash
149
171
  git commit --no-verify # Skip all git hooks
150
172
  ```
@@ -169,6 +191,7 @@ Visual tests run automatically on every push/PR:
169
191
  **File:** `.github/workflows/update-screenshots.yml`
170
192
 
171
193
  Workflow features:
194
+
172
195
  - ✅ Manual trigger only (`workflow_dispatch`)
173
196
  - ✅ Runs on Linux (ubuntu-latest)
174
197
  - ✅ Deletes old screenshots before regeneration
@@ -181,11 +204,13 @@ Workflow features:
181
204
  ### Tests Fail After Component Changes
182
205
 
183
206
  **Symptoms:**
207
+
184
208
  - CI shows screenshot mismatches
185
209
  - Error: "Screenshot does not match the stored reference"
186
210
  - Pixel ratio > 0.08 or dimension differences
187
211
 
188
212
  **Solution:**
213
+
189
214
  1. Review the changes to ensure they're intentional
190
215
  2. Run the screenshot update workflow:
191
216
  ```bash
@@ -201,15 +226,18 @@ Workflow features:
201
226
  ### Local Screenshots Don't Match CI
202
227
 
203
228
  **Symptoms:**
229
+
204
230
  - Tests pass locally but fail in CI
205
231
  - Opposite: tests fail locally but pass in CI
206
232
 
207
233
  **Cause:**
234
+
208
235
  - Platform differences (macOS vs Linux)
209
236
  - Font rendering variations
210
237
  - Different screenshot generation environment
211
238
 
212
239
  **Solution:**
240
+
213
241
  - **DO NOT** commit local screenshots from macOS
214
242
  - Always use the GitHub Actions workflow
215
243
  - Linux screenshots are the source of truth
@@ -217,13 +245,16 @@ Workflow features:
217
245
  ### Workflow Fails to Commit
218
246
 
219
247
  **Symptoms:**
248
+
220
249
  - Workflow succeeds but no new commit appears
221
250
  - Error: "Updates were rejected"
222
251
 
223
252
  **Cause:**
253
+
224
254
  - Race condition: new commits pushed while workflow was running
225
255
 
226
256
  **Solution:**
257
+
227
258
  - Workflow includes `git pull --rebase` before push
228
259
  - If still failing, manually re-run the workflow
229
260
 
@@ -232,12 +263,14 @@ Workflow features:
232
263
  ### When to Update Screenshots
233
264
 
234
265
  Update screenshots when:
266
+
235
267
  - ✅ Intentional UI changes (new features, design updates)
236
268
  - ✅ Component refactoring that affects rendering
237
269
  - ✅ Theme or styling changes
238
270
  - ✅ Breaking changes in dependencies (React, Tailwind, etc.)
239
271
 
240
272
  Do NOT update screenshots for:
273
+
241
274
  - ❌ Random pixel differences without code changes
242
275
  - ❌ Flaky tests (investigate root cause first)
243
276
  - ❌ Local development screenshots
@@ -268,6 +301,7 @@ test('MyComponent - default state - glass theme', async () => {
268
301
  ```
269
302
 
270
303
  **Naming convention:**
304
+
271
305
  - Use descriptive names: `{component}-{variant}-{theme}`
272
306
  - Include theme: `glass`, `light`, `aurora`
273
307
  - Use kebab-case
@@ -275,6 +309,7 @@ test('MyComponent - default state - glass theme', async () => {
275
309
  ## Statistics
276
310
 
277
311
  **Current Coverage:**
312
+
278
313
  - **582 visual tests** (as of v1.0.0)
279
314
  - **603 reference screenshots**
280
315
  - **99.5% pass rate** in CI
@@ -283,7 +318,7 @@ test('MyComponent - default state - glass theme', async () => {
283
318
  ## Related Documentation
284
319
 
285
320
  - [CLAUDE.md](../CLAUDE.md) - Project overview and architecture
286
- - [DEPENDENCIES.md](../DEPENDENCIES.md) - Tech stack details
321
+ - [DEPENDENCIES.md](technical/DEPENDENCIES.md) - Tech stack details
287
322
  - [visual-tests-audit.md](./visual-tests-audit.md) - Detailed test audit
288
323
  - [Migration Guides](./migration/) - Component API changes
289
324
 
@@ -292,33 +327,36 @@ test('MyComponent - default state - glass theme', async () => {
292
327
  ### Update Screenshots Workflow
293
328
 
294
329
  **Trigger:**
330
+
295
331
  ```bash
296
332
  gh workflow run update-screenshots.yml
297
333
  ```
298
334
 
299
335
  **With custom message:**
336
+
300
337
  ```bash
301
338
  gh workflow run update-screenshots.yml -f commit_message="chore: update screenshots after AlertGlass refactor"
302
339
  ```
303
340
 
304
341
  **Check status:**
342
+
305
343
  ```bash
306
344
  gh run list --workflow=update-screenshots.yml --limit 1
307
345
  ```
308
346
 
309
347
  **View logs:**
348
+
310
349
  ```bash
311
350
  gh run view <run-id> --log
312
351
  ```
313
352
 
314
353
  **Download artifacts:**
354
+
315
355
  ```bash
316
356
  gh run download <run-id> -n visual-test-screenshots
317
357
  ```
318
358
 
319
359
  ---
320
360
 
321
- **Last Updated:** 2025-12-05
322
- **Vitest Version:** 4.0
323
- **Playwright Version:** Latest
324
- **Node Version:** 20.16+, 22.19+, or 24+
361
+ **Last Updated:** 2025-12-05 **Vitest Version:** 4.0 **Playwright Version:** Latest **Node
362
+ Version:** 20.16+, 22.19+, or 24+
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "shadcn-glass-ui",
3
3
  "private": false,
4
- "version": "2.0.6",
5
- "description": "Glassmorphism UI components for React — drop-in shadcn/ui compatible, AI-optimized. 58 components, 3 themes, WCAG 2.1 AA.",
4
+ "version": "2.0.9",
5
+ "description": "Glassmorphism UI library for React - AI-friendly with 58 components, strict TypeScript, and comprehensive docs",
6
6
  "author": "Yhooi2",
7
7
  "license": "MIT",
8
8
  "keywords": [
@@ -1 +0,0 @@
1
- {"version":3,"file":"theme-context-BZoCplcU.js","names":["THEMES: readonly Theme[]","THEME_CONFIG: Record<Theme, ThemeConfig>","DEFAULT_THEME: Theme","value: ThemeContextValue"],"sources":["../src/lib/theme-context.tsx"],"sourcesContent":["// ========================================\n// THEME SYSTEM\n// Multi-theme support with CSS variables\n// ========================================\n\nimport {\n createContext,\n useContext,\n useState,\n useEffect,\n useCallback,\n type ReactNode,\n} from \"react\";\nimport { Sun, Moon, Palette, type LucideIcon } from \"lucide-react\";\n\n// ========================================\n// TYPES\n// ========================================\n\nexport type Theme = \"light\" | \"aurora\" | \"glass\";\n\n/** @deprecated Use Theme instead */\nexport type ThemeName = Theme;\n\nexport interface ThemeConfig {\n readonly label: string;\n readonly icon: LucideIcon;\n}\n\nexport interface ThemeContextValue {\n readonly theme: Theme;\n readonly setTheme: (theme: Theme) => void;\n readonly cycleTheme: () => void;\n}\n\n// ========================================\n// CONSTANTS\n// ========================================\n\nexport const THEMES: readonly Theme[] = [\"light\", \"aurora\", \"glass\"] as const;\n\n// eslint-disable-next-line react-refresh/only-export-components\nexport const THEME_CONFIG: Record<Theme, ThemeConfig> = {\n light: { label: \"Light\", icon: Sun },\n aurora: { label: \"Aurora\", icon: Moon },\n glass: { label: \"Glass\", icon: Palette },\n} as const;\n\nconst STORAGE_KEY = \"glass-ui-theme\";\nconst DEFAULT_THEME: Theme = \"glass\";\n\n// ========================================\n// CONTEXT\n// ========================================\n\nconst ThemeContext = createContext<ThemeContextValue | null>(null);\n\n// ========================================\n// PROVIDER\n// ========================================\n\ninterface ThemeProviderProps {\n readonly children: ReactNode;\n readonly defaultTheme?: Theme;\n readonly storageKey?: string;\n}\n\nexport function ThemeProvider({\n children,\n defaultTheme = DEFAULT_THEME,\n storageKey = STORAGE_KEY,\n}: ThemeProviderProps) {\n const [theme, setThemeState] = useState<Theme>(() => {\n if (typeof window === \"undefined\") {\n return defaultTheme;\n }\n\n const stored = localStorage.getItem(storageKey);\n if (stored && THEMES.includes(stored as Theme)) {\n return stored as Theme;\n }\n\n return defaultTheme;\n });\n\n // Apply theme to document\n useEffect(() => {\n const root = document.documentElement;\n root.setAttribute(\"data-theme\", theme);\n localStorage.setItem(storageKey, theme);\n }, [theme, storageKey]);\n\n const setTheme = useCallback((newTheme: Theme) => {\n if (THEMES.includes(newTheme)) {\n setThemeState(newTheme);\n }\n }, []);\n\n const cycleTheme = useCallback(() => {\n setThemeState((current) => {\n const currentIndex = THEMES.indexOf(current);\n const nextIndex = (currentIndex + 1) % THEMES.length;\n return THEMES[nextIndex];\n });\n }, []);\n\n const value: ThemeContextValue = {\n theme,\n setTheme,\n cycleTheme,\n };\n\n return (\n <ThemeContext.Provider value={value}>\n {children}\n </ThemeContext.Provider>\n );\n}\n\n// ========================================\n// HOOK\n// ========================================\n\n// eslint-disable-next-line react-refresh/only-export-components\nexport function useTheme(): ThemeContextValue {\n const context = useContext(ThemeContext);\n\n if (!context) {\n throw new Error(\"useTheme must be used within a ThemeProvider\");\n }\n\n return context;\n}\n\n// ========================================\n// UTILITIES\n// ========================================\n\n// eslint-disable-next-line react-refresh/only-export-components\nexport function getNextTheme(current: Theme): Theme {\n const currentIndex = THEMES.indexOf(current);\n const nextIndex = (currentIndex + 1) % THEMES.length;\n return THEMES[nextIndex];\n}\n\n// eslint-disable-next-line react-refresh/only-export-components\nexport function getThemeConfig(theme: Theme): ThemeConfig {\n return THEME_CONFIG[theme];\n}\n"],"mappings":";;;AAuCA,MAAaA,SAA2B;CAAC;CAAS;CAAU;CAAQ;AAGpE,MAAaC,eAA2C;CACtD,OAAO;EAAE,OAAO;EAAS,MAAM;EAAK;CACpC,QAAQ;EAAE,OAAO;EAAU,MAAM;EAAM;CACvC,OAAO;EAAE,OAAO;EAAS,MAAM;EAAS;CACzC;AAED,IAAM,cAAc;AACpB,IAAMC,gBAAuB;AAM7B,IAAM,eAAe,cAAwC,KAAK;AAYlE,SAAgB,cAAc,EAC5B,UACA,eAAe,eACf,aAAa,eACQ;CACrB,MAAM,CAAC,OAAO,iBAAiB,eAAsB;AACnD,MAAI,OAAO,WAAW,YACpB,QAAO;EAGT,MAAM,SAAS,aAAa,QAAQ,WAAW;AAC/C,MAAI,UAAU,OAAO,SAAS,OAAgB,CAC5C,QAAO;AAGT,SAAO;GACP;AAGF,iBAAgB;AACD,WAAS,gBACjB,aAAa,cAAc,MAAM;AACtC,eAAa,QAAQ,YAAY,MAAM;IACtC,CAAC,OAAO,WAAW,CAAC;CAgBvB,MAAMC,QAA2B;EAC/B;EACA,UAhBe,aAAa,aAAoB;AAChD,OAAI,OAAO,SAAS,SAAS,CAC3B,eAAc,SAAS;KAExB,EAAE,CAAC;EAaJ,YAXiB,kBAAkB;AACnC,kBAAe,YAAY;AAGzB,WAAO,QAFc,OAAO,QAAQ,QAAQ,GACV,KAAK,OAAO;KAE9C;KACD,EAAE,CAAC;EAML;AAED,QACE,oBAAC,aAAa,UAAA;EAAgB;EAC3B;GACqB;;AAS5B,SAAgB,WAA8B;CAC5C,MAAM,UAAU,WAAW,aAAa;AAExC,KAAI,CAAC,QACH,OAAM,IAAI,MAAM,+CAA+C;AAGjE,QAAO;;AAQT,SAAgB,aAAa,SAAuB;AAGlD,QAAO,QAFc,OAAO,QAAQ,QAAQ,GACV,KAAK,OAAO;;AAKhD,SAAgB,eAAe,OAA2B;AACxD,QAAO,aAAa"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"theme-context-CVW50BKW.cjs","names":["THEMES: readonly Theme[]","THEME_CONFIG: Record<Theme, ThemeConfig>","DEFAULT_THEME: Theme","value: ThemeContextValue"],"sources":["../src/lib/theme-context.tsx"],"sourcesContent":["// ========================================\n// THEME SYSTEM\n// Multi-theme support with CSS variables\n// ========================================\n\nimport {\n createContext,\n useContext,\n useState,\n useEffect,\n useCallback,\n type ReactNode,\n} from \"react\";\nimport { Sun, Moon, Palette, type LucideIcon } from \"lucide-react\";\n\n// ========================================\n// TYPES\n// ========================================\n\nexport type Theme = \"light\" | \"aurora\" | \"glass\";\n\n/** @deprecated Use Theme instead */\nexport type ThemeName = Theme;\n\nexport interface ThemeConfig {\n readonly label: string;\n readonly icon: LucideIcon;\n}\n\nexport interface ThemeContextValue {\n readonly theme: Theme;\n readonly setTheme: (theme: Theme) => void;\n readonly cycleTheme: () => void;\n}\n\n// ========================================\n// CONSTANTS\n// ========================================\n\nexport const THEMES: readonly Theme[] = [\"light\", \"aurora\", \"glass\"] as const;\n\n// eslint-disable-next-line react-refresh/only-export-components\nexport const THEME_CONFIG: Record<Theme, ThemeConfig> = {\n light: { label: \"Light\", icon: Sun },\n aurora: { label: \"Aurora\", icon: Moon },\n glass: { label: \"Glass\", icon: Palette },\n} as const;\n\nconst STORAGE_KEY = \"glass-ui-theme\";\nconst DEFAULT_THEME: Theme = \"glass\";\n\n// ========================================\n// CONTEXT\n// ========================================\n\nconst ThemeContext = createContext<ThemeContextValue | null>(null);\n\n// ========================================\n// PROVIDER\n// ========================================\n\ninterface ThemeProviderProps {\n readonly children: ReactNode;\n readonly defaultTheme?: Theme;\n readonly storageKey?: string;\n}\n\nexport function ThemeProvider({\n children,\n defaultTheme = DEFAULT_THEME,\n storageKey = STORAGE_KEY,\n}: ThemeProviderProps) {\n const [theme, setThemeState] = useState<Theme>(() => {\n if (typeof window === \"undefined\") {\n return defaultTheme;\n }\n\n const stored = localStorage.getItem(storageKey);\n if (stored && THEMES.includes(stored as Theme)) {\n return stored as Theme;\n }\n\n return defaultTheme;\n });\n\n // Apply theme to document\n useEffect(() => {\n const root = document.documentElement;\n root.setAttribute(\"data-theme\", theme);\n localStorage.setItem(storageKey, theme);\n }, [theme, storageKey]);\n\n const setTheme = useCallback((newTheme: Theme) => {\n if (THEMES.includes(newTheme)) {\n setThemeState(newTheme);\n }\n }, []);\n\n const cycleTheme = useCallback(() => {\n setThemeState((current) => {\n const currentIndex = THEMES.indexOf(current);\n const nextIndex = (currentIndex + 1) % THEMES.length;\n return THEMES[nextIndex];\n });\n }, []);\n\n const value: ThemeContextValue = {\n theme,\n setTheme,\n cycleTheme,\n };\n\n return (\n <ThemeContext.Provider value={value}>\n {children}\n </ThemeContext.Provider>\n );\n}\n\n// ========================================\n// HOOK\n// ========================================\n\n// eslint-disable-next-line react-refresh/only-export-components\nexport function useTheme(): ThemeContextValue {\n const context = useContext(ThemeContext);\n\n if (!context) {\n throw new Error(\"useTheme must be used within a ThemeProvider\");\n }\n\n return context;\n}\n\n// ========================================\n// UTILITIES\n// ========================================\n\n// eslint-disable-next-line react-refresh/only-export-components\nexport function getNextTheme(current: Theme): Theme {\n const currentIndex = THEMES.indexOf(current);\n const nextIndex = (currentIndex + 1) % THEMES.length;\n return THEMES[nextIndex];\n}\n\n// eslint-disable-next-line react-refresh/only-export-components\nexport function getThemeConfig(theme: Theme): ThemeConfig {\n return THEME_CONFIG[theme];\n}\n"],"mappings":";;;;AAuCA,MAAaA,SAA2B;CAAC;CAAS;CAAU;CAAQ;AAGpE,MAAaC,eAA2C;CACtD,OAAO;EAAE,OAAO;EAAS,MAAM,aAAA;EAAK;CACpC,QAAQ;EAAE,OAAO;EAAU,MAAM,aAAA;EAAM;CACvC,OAAO;EAAE,OAAO;EAAS,MAAM,aAAA;EAAS;CACzC;AAED,IAAM,cAAc;AACpB,IAAMC,gBAAuB;AAM7B,IAAM,gBAAA,GAAA,MAAA,eAAuD,KAAK;AAYlE,SAAgB,cAAc,EAC5B,UACA,eAAe,eACf,aAAa,eACQ;CACrB,MAAM,CAAC,OAAO,kBAAA,GAAA,MAAA,gBAAuC;AACnD,MAAI,OAAO,WAAW,YACpB,QAAO;EAGT,MAAM,SAAS,aAAa,QAAQ,WAAW;AAC/C,MAAI,UAAU,OAAO,SAAS,OAAgB,CAC5C,QAAO;AAGT,SAAO;GACP;AAGF,EAAA,GAAA,MAAA,iBAAgB;AACD,WAAS,gBACjB,aAAa,cAAc,MAAM;AACtC,eAAa,QAAQ,YAAY,MAAM;IACtC,CAAC,OAAO,WAAW,CAAC;CAgBvB,MAAMC,QAA2B;EAC/B;EACA,WAAA,GAAA,MAAA,cAhB4B,aAAoB;AAChD,OAAI,OAAO,SAAS,SAAS,CAC3B,eAAc,SAAS;KAExB,EAAE,CAAC;EAaJ,aAAA,GAAA,MAAA,mBAXmC;AACnC,kBAAe,YAAY;AAGzB,WAAO,QAFc,OAAO,QAAQ,QAAQ,GACV,KAAK,OAAO;KAE9C;KACD,EAAE,CAAC;EAML;AAED,QACE,iBAAA,GAAA,kBAAA,KAAC,aAAa,UAAA;EAAgB;EAC3B;GACqB;;AAS5B,SAAgB,WAA8B;CAC5C,MAAM,WAAA,GAAA,MAAA,YAAqB,aAAa;AAExC,KAAI,CAAC,QACH,OAAM,IAAI,MAAM,+CAA+C;AAGjE,QAAO;;AAQT,SAAgB,aAAa,SAAuB;AAGlD,QAAO,QAFc,OAAO,QAAQ,QAAQ,GACV,KAAK,OAAO;;AAKhD,SAAgB,eAAe,OAA2B;AACxD,QAAO,aAAa"}