shadcn-glass-ui 1.0.9 → 1.0.11
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 +46 -16
- package/README.md +78 -15
- package/dist/components.cjs +4 -4
- package/dist/components.js +1 -1
- package/dist/hooks.cjs +2 -2
- package/dist/index.cjs +5 -5
- package/dist/index.js +1 -1
- package/dist/r/alert-glass.json +1 -1
- package/dist/r/badge-glass.json +1 -1
- package/dist/r/button-glass.json +1 -1
- package/dist/r/checkbox-glass.json +1 -1
- package/dist/r/dropdown-glass.json +1 -1
- package/dist/r/glass-card.json +1 -1
- package/dist/r/input-glass.json +1 -1
- package/dist/r/language-bar-glass.json +1 -1
- package/dist/r/modal-glass.json +1 -1
- package/dist/r/popover-glass.json +1 -1
- package/dist/r/progress-glass.json +1 -1
- package/dist/r/registry.json +0 -2
- package/dist/r/segmented-control-glass.json +1 -1
- package/dist/r/tabs-glass.json +1 -1
- package/dist/r/tooltip-glass.json +1 -1
- package/dist/shadcn-glass-ui.css +1 -1
- package/dist/{theme-context-BcTQdqsj.cjs → theme-context-XtasSxRT.cjs} +2 -2
- package/dist/{theme-context-BcTQdqsj.cjs.map → theme-context-XtasSxRT.cjs.map} +1 -1
- package/dist/themes.cjs +1 -1
- package/dist/{trust-score-card-glass-Dq28n8en.cjs → trust-score-card-glass-CNcQveNY.cjs} +19 -15
- package/dist/{trust-score-card-glass-Dq28n8en.cjs.map → trust-score-card-glass-CNcQveNY.cjs.map} +1 -1
- package/dist/{trust-score-card-glass-CHzWGuko.js → trust-score-card-glass-CowcDyxH.js} +16 -12
- package/dist/{trust-score-card-glass-CHzWGuko.js.map → trust-score-card-glass-CowcDyxH.js.map} +1 -1
- package/dist/{use-focus-CH8KNgcY.cjs → use-focus-BbpE2qGq.cjs} +2 -2
- package/dist/{use-focus-CH8KNgcY.cjs.map → use-focus-BbpE2qGq.cjs.map} +1 -1
- package/dist/{use-wallpaper-tint-DNecAf46.cjs → use-wallpaper-tint-CIqtoETa.cjs} +2 -2
- package/dist/{use-wallpaper-tint-DNecAf46.cjs.map → use-wallpaper-tint-CIqtoETa.cjs.map} +1 -1
- package/dist/{utils-3cDWhVvH.cjs → utils-CriE74ig.cjs} +2 -2
- package/dist/{utils-3cDWhVvH.cjs.map → utils-CriE74ig.cjs.map} +1 -1
- package/dist/utils.cjs +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,14 +2,25 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
|
|
5
|
-
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
|
-
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project
|
|
6
|
+
adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [1.0.9] - 2025-12-06
|
|
9
|
+
|
|
10
|
+
### 📚 AIDocumentation
|
|
11
|
+
|
|
12
|
+
- Added improved AI-focused documentation to help LLMs understand and work with the codebase more
|
|
13
|
+
effectively
|
|
14
|
+
- Added guidance for AI assistants, workflows, and common automation patterns
|
|
15
|
+
- Enhanced internal docs to optimize reasoning and code navigation for AI tools
|
|
16
|
+
- Added improved storybook stories
|
|
7
17
|
|
|
8
18
|
## [1.0.9] - 2025-12-06
|
|
9
19
|
|
|
10
20
|
### 🐛 Bug Fixes
|
|
11
21
|
|
|
12
22
|
**CSS Import Order:**
|
|
23
|
+
|
|
13
24
|
- Fixed PostCSS warnings by moving all `@import` directives before CSS rules
|
|
14
25
|
- All imports now precede style declarations (per CSS spec requirement)
|
|
15
26
|
- Build process now runs completely clean without warnings
|
|
@@ -21,6 +32,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
21
32
|
### 📚 Documentation
|
|
22
33
|
|
|
23
34
|
**Major CLAUDE.md Restructure - AI-Friendly Documentation:**
|
|
35
|
+
|
|
24
36
|
- Added **Quick Commands Cheatsheet** at the top for instant reference
|
|
25
37
|
- Added **Common Tasks for AI** section with step-by-step workflows:
|
|
26
38
|
- Adding new Glass components
|
|
@@ -66,11 +78,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
66
78
|
### 🔄 Changed
|
|
67
79
|
|
|
68
80
|
**Package Name:**
|
|
81
|
+
|
|
69
82
|
- Renamed package from `@yhooi2/shadcn-glass-ui` to `shadcn-glass-ui`
|
|
70
83
|
- Simpler installation: `npm install shadcn-glass-ui`
|
|
71
|
-
- **Migration:** Update your `package.json` dependencies from `@yhooi2/shadcn-glass-ui` to
|
|
84
|
+
- **Migration:** Update your `package.json` dependencies from `@yhooi2/shadcn-glass-ui` to
|
|
85
|
+
`shadcn-glass-ui`
|
|
72
86
|
|
|
73
87
|
**Publishing:**
|
|
88
|
+
|
|
74
89
|
- Now publishing only to npm Registry (removed GitHub Packages)
|
|
75
90
|
- Simplified installation - no authentication required
|
|
76
91
|
- Single source of truth for package distribution
|
|
@@ -101,6 +116,7 @@ npm install shadcn-glass-ui
|
|
|
101
116
|
```
|
|
102
117
|
|
|
103
118
|
Update your imports (no changes needed - imports remain the same):
|
|
119
|
+
|
|
104
120
|
```tsx
|
|
105
121
|
// Still works the same way
|
|
106
122
|
import { ButtonGlass, InputGlass } from 'shadcn-glass-ui';
|
|
@@ -111,11 +127,14 @@ import { ButtonGlass, InputGlass } from 'shadcn-glass-ui';
|
|
|
111
127
|
### 🔄 Changed
|
|
112
128
|
|
|
113
129
|
**Package Name:**
|
|
130
|
+
|
|
114
131
|
- Renamed package from `@yhooi2/shadcn-glass-ui` to `shadcn-glass-ui`
|
|
115
132
|
- Simpler installation: `npm install shadcn-glass-ui`
|
|
116
|
-
- **Migration:** Update your `package.json` dependencies from `@yhooi2/shadcn-glass-ui` to
|
|
133
|
+
- **Migration:** Update your `package.json` dependencies from `@yhooi2/shadcn-glass-ui` to
|
|
134
|
+
`shadcn-glass-ui`
|
|
117
135
|
|
|
118
136
|
**Publishing:**
|
|
137
|
+
|
|
119
138
|
- Now publishing only to npm Registry (removed GitHub Packages)
|
|
120
139
|
- Simplified installation - no authentication required
|
|
121
140
|
- Single source of truth for package distribution
|
|
@@ -146,6 +165,7 @@ npm install shadcn-glass-ui
|
|
|
146
165
|
```
|
|
147
166
|
|
|
148
167
|
Update your imports (no changes needed - imports remain the same):
|
|
168
|
+
|
|
149
169
|
```tsx
|
|
150
170
|
// Still works the same way
|
|
151
171
|
import { ButtonGlass, InputGlass } from 'shadcn-glass-ui';
|
|
@@ -156,6 +176,7 @@ import { ButtonGlass, InputGlass } from 'shadcn-glass-ui';
|
|
|
156
176
|
### ✨ Added
|
|
157
177
|
|
|
158
178
|
**Glass Variants System:**
|
|
179
|
+
|
|
159
180
|
- New comprehensive glass effect variants: `crystal`, `frosted`, `fluted`, `glass`
|
|
160
181
|
- Color tint modifiers: `purple`, `cyan`, `amber`, `emerald`, `rose`
|
|
161
182
|
- Intensity modifiers: `subtle`, `medium`, `strong`
|
|
@@ -163,10 +184,12 @@ import { ButtonGlass, InputGlass } from 'shadcn-glass-ui';
|
|
|
163
184
|
- New CSS utility classes in `primitives.css` for all variants
|
|
164
185
|
|
|
165
186
|
**Components:**
|
|
187
|
+
|
|
166
188
|
- `GlassVariantsDemo` - Interactive showcase of all 72 glass variant combinations
|
|
167
189
|
- Updated `GlassCard.stories.tsx` with variant demonstrations
|
|
168
190
|
|
|
169
191
|
**Publishing:**
|
|
192
|
+
|
|
170
193
|
- Dual registry support: npm Registry + GitHub Packages
|
|
171
194
|
- Automated publishing to both registries on release
|
|
172
195
|
- Enhanced GitHub Actions workflow with registry validation
|
|
@@ -239,7 +262,8 @@ import { ButtonGlass, InputGlass } from 'shadcn-glass-ui';
|
|
|
239
262
|
|
|
240
263
|
- **ModalGlass:** Legacy props API completely removed
|
|
241
264
|
- **Old API:** `isOpen`, `onClose`, `title` props
|
|
242
|
-
- **New API:** Compound API only (`ModalGlass.Root`, `.Overlay`, `.Content`, `.Header`, `.Body`,
|
|
265
|
+
- **New API:** Compound API only (`ModalGlass.Root`, `.Overlay`, `.Content`, `.Header`, `.Body`,
|
|
266
|
+
`.Footer`, `.Title`, `.Description`, `.Close`)
|
|
243
267
|
- **Migration:** See [ModalGlass Compound API guide](docs/migration/modal-glass-compound-api.md)
|
|
244
268
|
- **Key Changes:**
|
|
245
269
|
- `isOpen` → `open` (on ModalGlass.Root)
|
|
@@ -291,7 +315,8 @@ import { ButtonGlass, InputGlass } from 'shadcn-glass-ui';
|
|
|
291
315
|
|
|
292
316
|
### ⚠️ BREAKING CHANGES
|
|
293
317
|
|
|
294
|
-
- **ButtonGlass:** Removed `danger` variant in favor of `destructive` for shadcn/ui API
|
|
318
|
+
- **ButtonGlass:** Removed `danger` variant in favor of `destructive` for shadcn/ui API
|
|
319
|
+
compatibility
|
|
295
320
|
- **Migration:** Replace `variant="danger"` with `variant="destructive"`
|
|
296
321
|
- **Affected:** 3 files in library, user code may require updates
|
|
297
322
|
- **Rationale:** Aligns with shadcn/ui design system standards
|
|
@@ -312,7 +337,8 @@ import { ButtonGlass, InputGlass } from 'shadcn-glass-ui';
|
|
|
312
337
|
|
|
313
338
|
### 🔧 Refactored
|
|
314
339
|
|
|
315
|
-
- **AlertGlass:** Migrated from deprecated `type` prop to `variant` prop (57 instances across
|
|
340
|
+
- **AlertGlass:** Migrated from deprecated `type` prop to `variant` prop (57 instances across
|
|
341
|
+
codebase)
|
|
316
342
|
- **NotificationGlass:** Migrated from deprecated `type` prop to `variant` prop (8 source files)
|
|
317
343
|
- Updated all visual regression tests to use new `variant` API (582 tests passing)
|
|
318
344
|
- Updated all unit tests to use new `variant` API (32 NotificationGlass tests, 32 AlertGlass tests)
|
|
@@ -398,8 +424,10 @@ If you're using this library and have code that breaks after updating, here's ho
|
|
|
398
424
|
|
|
399
425
|
All changes align the library with shadcn/ui design system standards:
|
|
400
426
|
|
|
401
|
-
1. **Consistent Naming**: `variant` is the standard prop name across shadcn/ui components (Button,
|
|
402
|
-
|
|
427
|
+
1. **Consistent Naming**: `variant` is the standard prop name across shadcn/ui components (Button,
|
|
428
|
+
Badge, Alert, etc.)
|
|
429
|
+
2. **Semantic Correctness**: `variant` describes visual style variations, while `type` describes
|
|
430
|
+
data types
|
|
403
431
|
3. **Better DX**: Consistent APIs across all Glass components improve developer experience
|
|
404
432
|
4. **Design System Compliance**: Makes the library easier to integrate with shadcn/ui projects
|
|
405
433
|
|
|
@@ -415,13 +443,13 @@ All changes align the library with shadcn/ui design system standards:
|
|
|
415
443
|
|
|
416
444
|
### Changes Summary
|
|
417
445
|
|
|
418
|
-
| Category | Count
|
|
419
|
-
|
|
446
|
+
| Category | Count |
|
|
447
|
+
| ------------------ | ---------------------------------------------- |
|
|
420
448
|
| Breaking changes | 3 (ButtonGlass, AlertGlass, NotificationGlass) |
|
|
421
|
-
| Files modified | 20+
|
|
422
|
-
| Empty dirs removed | 9
|
|
423
|
-
| Tests updated | 582 visual + 64 unit
|
|
424
|
-
| Documentation | 5 new files (1,967 lines)
|
|
449
|
+
| Files modified | 20+ |
|
|
450
|
+
| Empty dirs removed | 9 |
|
|
451
|
+
| Tests updated | 582 visual + 64 unit |
|
|
452
|
+
| Documentation | 5 new files (1,967 lines) |
|
|
425
453
|
|
|
426
454
|
### Quality Metrics
|
|
427
455
|
|
|
@@ -448,4 +476,6 @@ All changes align the library with shadcn/ui design system standards:
|
|
|
448
476
|
|
|
449
477
|
---
|
|
450
478
|
|
|
451
|
-
**Note**: This changelog documents the breaking changes and migrations performed during the legacy
|
|
479
|
+
**Note**: This changelog documents the breaking changes and migrations performed during the legacy
|
|
480
|
+
code cleanup initiative. For future releases, this file will continue to track all notable changes
|
|
481
|
+
to the project.
|
package/README.md
CHANGED
|
@@ -12,11 +12,13 @@
|
|
|
12
12
|
[](docs/AI_USAGE.md)
|
|
13
13
|
[](docs/AI_USAGE.md)
|
|
14
14
|
|
|
15
|
-
Glassmorphism UI library for React - AI-friendly with 55+ components, strict TypeScript, and
|
|
15
|
+
Glassmorphism UI library for React - AI-friendly with 55+ components, strict TypeScript, and
|
|
16
|
+
comprehensive docs.
|
|
16
17
|
|
|
17
18
|
## ✨ Highlights
|
|
18
19
|
|
|
19
|
-
- 🎨 **55 Components** - Core UI (18) + Atomic (6) + Composite (13) + Sections (7) + Specialized
|
|
20
|
+
- 🎨 **55 Components** - Core UI (18) + Atomic (6) + Composite (13) + Sections (7) + Specialized
|
|
21
|
+
(8) + Primitives (3)
|
|
20
22
|
- 🌈 **3 Themes** - Glass (dark glassmorphism), Light (clean minimal), Aurora (gradient glow)
|
|
21
23
|
- 🤖 **AI-Friendly** - Optimized for Claude Code, Copilot, GPT with comprehensive docs
|
|
22
24
|
- 🔮 **Advanced Patterns** - asChild polymorphic rendering, Compound components (Modal, Tabs)
|
|
@@ -25,7 +27,8 @@ Glassmorphism UI library for React - AI-friendly with 55+ components, strict Typ
|
|
|
25
27
|
- ⚡ **Modern Stack** - React 19, Tailwind v4, Vitest 4, Storybook 10, Vite 7
|
|
26
28
|
- 🧪 **1355+ Tests** - 650+ compliance + 580 visual regression + 125 unit tests
|
|
27
29
|
- 📦 **shadcn Compatible** - Works seamlessly with existing shadcn/ui projects
|
|
28
|
-
- 🎯 **Design System** - Comprehensive [UI_DESIGN.md](docs/design-system/UI_DESIGN.md)
|
|
30
|
+
- 🎯 **Design System** - Comprehensive [UI_DESIGN.md](docs/design-system/UI_DESIGN.md)
|
|
31
|
+
specifications
|
|
29
32
|
- 📦 **Bundle Size** - ~110KB gzipped (production build)
|
|
30
33
|
|
|
31
34
|
## Tech Stack
|
|
@@ -41,30 +44,78 @@ See [DEPENDENCIES.md](DEPENDENCIES.md) for detailed dependency documentation.
|
|
|
41
44
|
|
|
42
45
|
## 🤖 AI Assistant Support
|
|
43
46
|
|
|
44
|
-
This library is **optimized for AI coding assistants** including Claude Code, GitHub Copilot, and
|
|
47
|
+
This library is **optimized for AI coding assistants** including Claude Code, GitHub Copilot, and
|
|
48
|
+
ChatGPT:
|
|
45
49
|
|
|
46
50
|
- 📖 **Dedicated AI Guide** - [AI_USAGE.md](docs/AI_USAGE.md) with decision trees and workflows
|
|
47
51
|
- 🎯 **TypeScript Strict Mode** - Full type inference for autocomplete
|
|
48
52
|
- 📝 **Rich JSDoc** - Every component documented with @example, @accessibility
|
|
49
|
-
- 🗂️ **Component Catalog** - [COMPONENTS_CATALOG.md](docs/COMPONENTS_CATALOG.md) with searchable
|
|
53
|
+
- 🗂️ **Component Catalog** - [COMPONENTS_CATALOG.md](docs/COMPONENTS_CATALOG.md) with searchable
|
|
54
|
+
index
|
|
50
55
|
- 🔍 **Exports Map** - Machine-readable [EXPORTS_MAP.json](docs/EXPORTS_MAP.json)
|
|
51
56
|
- 🧪 **Real-World Examples** - Use-case based Storybook stories
|
|
52
|
-
- 📦 **shadcn CLI Compatible** - Install components via
|
|
57
|
+
- 📦 **shadcn CLI Compatible** - Install components via
|
|
58
|
+
`npx shadcn add @shadcn-glass-ui/button-glass`
|
|
53
59
|
|
|
54
|
-
[**→ Read AI Usage Guide**](docs/AI_USAGE.md) |
|
|
60
|
+
[**→ Read AI Usage Guide**](docs/AI_USAGE.md) |
|
|
61
|
+
[**→ Component Catalog**](docs/COMPONENTS_CATALOG.md)
|
|
55
62
|
|
|
56
63
|
## 📚 Documentation
|
|
57
64
|
|
|
58
|
-
- **[Live Storybook](https://yhooi2.github.io/shadcn-glass-ui-library/)** - Interactive component
|
|
65
|
+
- **[Live Storybook](https://yhooi2.github.io/shadcn-glass-ui-library/)** - Interactive component
|
|
66
|
+
demos
|
|
59
67
|
- **[npm Package](https://www.npmjs.com/package/shadcn-glass-ui)** - Public npm registry
|
|
68
|
+
- **[Registry Guide](docs/REGISTRY_USAGE.md)** - shadcn CLI installation via registry
|
|
60
69
|
- **[Getting Started Guide](docs/GETTING_STARTED.md)** - Setup tutorial
|
|
61
70
|
- **[GitHub](https://github.com/Yhooi2/shadcn-glass-ui-library)** - Source code
|
|
62
|
-
- [Component Documentation](https://yhooi2.github.io/shadcn-glass-ui-library/?path=/docs) - Detailed
|
|
63
|
-
|
|
71
|
+
- [Component Documentation](https://yhooi2.github.io/shadcn-glass-ui-library/?path=/docs) - Detailed
|
|
72
|
+
API references
|
|
64
73
|
- [Design System](docs/design-system/UI_DESIGN.md) - Comprehensive UI specifications
|
|
65
74
|
- [Migration Guides](docs/migration/) - Upgrade and API changes
|
|
66
75
|
|
|
67
|
-
## 📦 Installation
|
|
76
|
+
## 📦 Installation Methods
|
|
77
|
+
|
|
78
|
+
shadcn-glass-ui can be installed in two ways:
|
|
79
|
+
|
|
80
|
+
### Option 1: Registry (shadcn CLI) ⭐ Recommended
|
|
81
|
+
|
|
82
|
+
**Listed on [registry.directory](https://registry.directory)!**
|
|
83
|
+
|
|
84
|
+
Configure your `components.json`:
|
|
85
|
+
|
|
86
|
+
```json
|
|
87
|
+
{
|
|
88
|
+
"registries": {
|
|
89
|
+
"@shadcn-glass-ui": {
|
|
90
|
+
"url": "https://raw.githubusercontent.com/Yhooi2/shadcn-glass-ui-library/main/public/r"
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
Install components via shadcn CLI:
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
# Single component
|
|
100
|
+
npx shadcn@latest add @shadcn-glass-ui/button-glass
|
|
101
|
+
|
|
102
|
+
# Multiple components
|
|
103
|
+
npx shadcn@latest add @shadcn-glass-ui/button-glass @shadcn-glass-ui/input-glass @shadcn-glass-ui/modal-glass
|
|
104
|
+
|
|
105
|
+
# With automatic dependencies
|
|
106
|
+
npx shadcn@latest add @shadcn-glass-ui/button-glass --deps
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
**Benefits:**
|
|
110
|
+
|
|
111
|
+
- ✅ Automatic dependency installation
|
|
112
|
+
- ✅ Type-safe CLI workflow
|
|
113
|
+
- ✅ Compatible with existing shadcn/ui projects
|
|
114
|
+
- ✅ 55+ components available
|
|
115
|
+
|
|
116
|
+
**[→ Full Registry Documentation](docs/REGISTRY_USAGE.md)**
|
|
117
|
+
|
|
118
|
+
### Option 2: npm Package
|
|
68
119
|
|
|
69
120
|
Install from npm registry:
|
|
70
121
|
|
|
@@ -72,9 +123,14 @@ Install from npm registry:
|
|
|
72
123
|
npm install shadcn-glass-ui
|
|
73
124
|
```
|
|
74
125
|
|
|
126
|
+
**[→ npm Installation Guide](docs/GETTING_STARTED.md)**
|
|
127
|
+
|
|
128
|
+
---
|
|
129
|
+
|
|
75
130
|
## 🚀 Quick Start
|
|
76
131
|
|
|
77
132
|
**Requirements:**
|
|
133
|
+
|
|
78
134
|
- React 18.0+ or 19.0+
|
|
79
135
|
- React-DOM 18.0+ or 19.0+
|
|
80
136
|
- Tailwind CSS 4.0+
|
|
@@ -171,7 +227,8 @@ import { ModalGlass, TabsGlass } from 'shadcn-glass-ui';
|
|
|
171
227
|
|
|
172
228
|
## ⚠️ Breaking Changes (v1.0.0)
|
|
173
229
|
|
|
174
|
-
**v1.0.0 removes all legacy/deprecated APIs.** This is a clean slate release with only Compound API
|
|
230
|
+
**v1.0.0 removes all legacy/deprecated APIs.** This is a clean slate release with only Compound API
|
|
231
|
+
support.
|
|
175
232
|
|
|
176
233
|
### Removed Components
|
|
177
234
|
|
|
@@ -223,8 +280,10 @@ import { ModalGlass, TabsGlass } from 'shadcn-glass-ui';
|
|
|
223
280
|
```
|
|
224
281
|
|
|
225
282
|
**Key Changes:**
|
|
283
|
+
|
|
226
284
|
- `isOpen` → `open` (on ModalGlass.Root)
|
|
227
|
-
- `onClose` → `onOpenChange` (callback signature changed from `() => void` to
|
|
285
|
+
- `onClose` → `onOpenChange` (callback signature changed from `() => void` to
|
|
286
|
+
`(open: boolean) => void`)
|
|
228
287
|
- `title` prop removed → use `<ModalGlass.Title>` component
|
|
229
288
|
- Manual structure required (Overlay, Content, Header, Body, Footer)
|
|
230
289
|
|
|
@@ -255,6 +314,7 @@ import { ModalGlass, TabsGlass } from 'shadcn-glass-ui';
|
|
|
255
314
|
```
|
|
256
315
|
|
|
257
316
|
**Key Changes:**
|
|
317
|
+
|
|
258
318
|
- `tabs` array prop removed → use individual `<TabsGlass.Trigger>` components
|
|
259
319
|
- `activeTab` → `value` (on TabsGlass.Root)
|
|
260
320
|
- `onChange` → `onValueChange`
|
|
@@ -364,7 +424,8 @@ Full-page sections ready to use in your application:
|
|
|
364
424
|
|
|
365
425
|
### Blocks (6 ready-to-use demo sections)
|
|
366
426
|
|
|
367
|
-
Complete component showcases following shadcn/ui pattern - these are demo/documentation components,
|
|
427
|
+
Complete component showcases following shadcn/ui pattern - these are demo/documentation components,
|
|
428
|
+
not production-ready blocks:
|
|
368
429
|
|
|
369
430
|
- **ButtonsBlock** - All button variants, sizes, states demo
|
|
370
431
|
- **FormElementsBlock** - Input, Slider, Toggle, Checkbox demos
|
|
@@ -373,7 +434,8 @@ Complete component showcases following shadcn/ui pattern - these are demo/docume
|
|
|
373
434
|
- **BadgesBlock** - Badge variants with tooltips demo
|
|
374
435
|
- **NotificationsBlock** - Notifications and alerts demo
|
|
375
436
|
|
|
376
|
-
**Note:** Blocks are showcase/demo components visible in Storybook. For production use, utilize
|
|
437
|
+
**Note:** Blocks are showcase/demo components visible in Storybook. For production use, utilize
|
|
438
|
+
individual components from the categories above.
|
|
377
439
|
|
|
378
440
|
[View Blocks in Storybook →](https://yhooi2.github.io/shadcn-glass-ui-library/?path=/story/glass-blocks--default)
|
|
379
441
|
|
|
@@ -491,6 +553,7 @@ GlassCard supports 3 intensity levels for customizable blur effects:
|
|
|
491
553
|
```
|
|
492
554
|
|
|
493
555
|
**Intensity Levels:**
|
|
556
|
+
|
|
494
557
|
- `subtle` - 8px blur (--blur-sm) - Light glass effect
|
|
495
558
|
- `medium` - 16px blur (--blur-md) - Standard cards (default)
|
|
496
559
|
- `strong` - 24px blur (--blur-lg) - Featured cards
|
package/dist/components.cjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
const require_trust_score_card_glass = require("./trust-score-card-glass-
|
|
2
|
-
require("./utils-
|
|
3
|
-
require("./use-focus-
|
|
4
|
-
require("./theme-context-
|
|
1
|
+
const require_trust_score_card_glass = require("./trust-score-card-glass-CNcQveNY.cjs");
|
|
2
|
+
require("./utils-CriE74ig.cjs");
|
|
3
|
+
require("./use-focus-BbpE2qGq.cjs");
|
|
4
|
+
require("./theme-context-XtasSxRT.cjs");
|
|
5
5
|
exports.AICardGlass = require_trust_score_card_glass.AICardGlass;
|
|
6
6
|
exports.AlertGlass = require_trust_score_card_glass.AlertGlass;
|
|
7
7
|
exports.AvatarGlass = require_trust_score_card_glass.AvatarGlass;
|
package/dist/components.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import "./utils-CGCOTvxT.js";
|
|
2
|
-
import { $ as ComboBoxGlass, A as ThemeToggleGlass, B as TabsGlass, C as ProgressGlass, D as FlagAlertGlass, E as LanguageBarGlass, F as ExpandableHeaderGlass, G as NotificationGlass, H as SkeletonGlass, I as TooltipGlass, M as SortDropdownGlass, N as SearchBoxGlass, O as StatusIndicatorGlass, P as IconButtonGlass, Q as DropdownGlass, R as ToggleGlass, S as RainbowProgressGlass, T as ProfileAvatarGlass, V as SliderGlass, W as PopoverGlass, X as GlassCard, Y as InputGlass, _ as ContributionMetricsGlass, a as HeaderBrandingGlass, at as BadgeGlass, b as AICardGlass, c as YearCardGlass, d as TrustScoreDisplayGlass, dt as InteractiveCard, f as RepositoryMetadataGlass, ft as FormFieldWrapper, g as MetricCardGlass, h as MetricsGridGlass, i as HeaderNavGlass, j as StatItemGlass, k as BaseProgressGlass, l as UserStatsLineGlass, m as RepositoryCardGlass, n as ProjectsListGlass, nt as CheckboxGlass, o as FlagsSectionGlass, p as RepositoryHeaderGlass, pt as TouchTarget, q as ModalGlass, r as ProfileHeaderGlass, rt as ButtonGlass, s as CareerStatsGlass, st as AvatarGlass, t as TrustScoreCardGlass, tt as CircularProgressGlass, u as UserInfoGlass, ut as AlertGlass, v as CircularMetricGlass, x as SegmentedControlGlass, y as CareerStatsHeaderGlass } from "./trust-score-card-glass-
|
|
2
|
+
import { $ as ComboBoxGlass, A as ThemeToggleGlass, B as TabsGlass, C as ProgressGlass, D as FlagAlertGlass, E as LanguageBarGlass, F as ExpandableHeaderGlass, G as NotificationGlass, H as SkeletonGlass, I as TooltipGlass, M as SortDropdownGlass, N as SearchBoxGlass, O as StatusIndicatorGlass, P as IconButtonGlass, Q as DropdownGlass, R as ToggleGlass, S as RainbowProgressGlass, T as ProfileAvatarGlass, V as SliderGlass, W as PopoverGlass, X as GlassCard, Y as InputGlass, _ as ContributionMetricsGlass, a as HeaderBrandingGlass, at as BadgeGlass, b as AICardGlass, c as YearCardGlass, d as TrustScoreDisplayGlass, dt as InteractiveCard, f as RepositoryMetadataGlass, ft as FormFieldWrapper, g as MetricCardGlass, h as MetricsGridGlass, i as HeaderNavGlass, j as StatItemGlass, k as BaseProgressGlass, l as UserStatsLineGlass, m as RepositoryCardGlass, n as ProjectsListGlass, nt as CheckboxGlass, o as FlagsSectionGlass, p as RepositoryHeaderGlass, pt as TouchTarget, q as ModalGlass, r as ProfileHeaderGlass, rt as ButtonGlass, s as CareerStatsGlass, st as AvatarGlass, t as TrustScoreCardGlass, tt as CircularProgressGlass, u as UserInfoGlass, ut as AlertGlass, v as CircularMetricGlass, x as SegmentedControlGlass, y as CareerStatsHeaderGlass } from "./trust-score-card-glass-CowcDyxH.js";
|
|
3
3
|
import "./use-focus-CX0TJJIj.js";
|
|
4
4
|
import "./theme-context-BZoCplcU.js";
|
|
5
5
|
export { AICardGlass, AlertGlass, AvatarGlass, BadgeGlass, BaseProgressGlass, ButtonGlass, CareerStatsGlass, CareerStatsHeaderGlass, CheckboxGlass, CircularMetricGlass, CircularProgressGlass, ComboBoxGlass, ContributionMetricsGlass, DropdownGlass, ExpandableHeaderGlass, FlagAlertGlass, FlagsSectionGlass, FormFieldWrapper, GlassCard, HeaderBrandingGlass, HeaderNavGlass, IconButtonGlass, InputGlass, InteractiveCard, LanguageBarGlass, MetricCardGlass, MetricsGridGlass, ModalGlass, NotificationGlass, PopoverGlass, ProfileAvatarGlass, ProfileHeaderGlass, ProgressGlass, ProjectsListGlass, RainbowProgressGlass, RepositoryCardGlass, RepositoryHeaderGlass, RepositoryMetadataGlass, SearchBoxGlass, SegmentedControlGlass, SkeletonGlass, SliderGlass, SortDropdownGlass, StatItemGlass, StatusIndicatorGlass, TabsGlass, ThemeToggleGlass, ToggleGlass, TooltipGlass, TouchTarget, TrustScoreCardGlass, TrustScoreDisplayGlass, UserInfoGlass, UserStatsLineGlass, YearCardGlass };
|
package/dist/hooks.cjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
const require_use_focus = require("./use-focus-
|
|
2
|
-
const require_use_wallpaper_tint = require("./use-wallpaper-tint-
|
|
1
|
+
const require_use_focus = require("./use-focus-BbpE2qGq.cjs");
|
|
2
|
+
const require_use_wallpaper_tint = require("./use-wallpaper-tint-CIqtoETa.cjs");
|
|
3
3
|
exports.useFocus = require_use_focus.useFocus;
|
|
4
4
|
exports.useHover = require_use_focus.useHover;
|
|
5
5
|
exports.useResponsive = require_use_wallpaper_tint.useResponsive;
|
package/dist/index.cjs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
const require_trust_score_card_glass = require("./trust-score-card-glass-
|
|
2
|
-
const require_utils = require("./utils-
|
|
3
|
-
const require_use_focus = require("./use-focus-
|
|
4
|
-
const require_theme_context = require("./theme-context-
|
|
5
|
-
const require_use_wallpaper_tint = require("./use-wallpaper-tint-
|
|
1
|
+
const require_trust_score_card_glass = require("./trust-score-card-glass-CNcQveNY.cjs");
|
|
2
|
+
const require_utils = require("./utils-CriE74ig.cjs");
|
|
3
|
+
const require_use_focus = require("./use-focus-BbpE2qGq.cjs");
|
|
4
|
+
const require_theme_context = require("./theme-context-XtasSxRT.cjs");
|
|
5
|
+
const require_use_wallpaper_tint = require("./use-wallpaper-tint-CIqtoETa.cjs");
|
|
6
6
|
let class_variance_authority = require("class-variance-authority");
|
|
7
7
|
const dropdownAlign = (0, class_variance_authority.cva)("absolute mt-2 min-w-[160px] md:min-w-[200px] rounded-2xl py-1.5 md:py-2", {
|
|
8
8
|
variants: { align: {
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { t as cn } from "./utils-CGCOTvxT.js";
|
|
2
|
-
import { $ as ComboBoxGlass, A as ThemeToggleGlass, B as TabsGlass, C as ProgressGlass, D as FlagAlertGlass, E as LanguageBarGlass, F as ExpandableHeaderGlass, G as NotificationGlass, H as SkeletonGlass, I as TooltipGlass, J as modalSizes, K as notificationVariants, L as tooltipPositions, M as SortDropdownGlass, N as SearchBoxGlass, O as StatusIndicatorGlass, P as IconButtonGlass, Q as DropdownGlass, R as ToggleGlass, S as RainbowProgressGlass, T as ProfileAvatarGlass, U as skeletonVariants, V as SliderGlass, W as PopoverGlass, X as GlassCard, Y as InputGlass, Z as cardIntensity, _ as ContributionMetricsGlass, a as HeaderBrandingGlass, at as BadgeGlass, b as AICardGlass, c as YearCardGlass, ct as avatarSizes, d as TrustScoreDisplayGlass, dt as InteractiveCard, et as inputVariants, f as RepositoryMetadataGlass, ft as FormFieldWrapper, g as MetricCardGlass, h as MetricsGridGlass, i as HeaderNavGlass, it as buttonGlassVariants, j as StatItemGlass, k as BaseProgressGlass, l as UserStatsLineGlass, lt as statusSizes, m as RepositoryCardGlass, mt as alertVariants, n as ProjectsListGlass, nt as CheckboxGlass, o as FlagsSectionGlass, ot as badgeVariants, p as RepositoryHeaderGlass, pt as TouchTarget, q as ModalGlass, r as ProfileHeaderGlass, rt as ButtonGlass, s as CareerStatsGlass, st as AvatarGlass, t as TrustScoreCardGlass, tt as CircularProgressGlass, u as UserInfoGlass, ut as AlertGlass, v as CircularMetricGlass, w as progressSizes, x as SegmentedControlGlass, y as CareerStatsHeaderGlass, z as toggleSizes } from "./trust-score-card-glass-
|
|
2
|
+
import { $ as ComboBoxGlass, A as ThemeToggleGlass, B as TabsGlass, C as ProgressGlass, D as FlagAlertGlass, E as LanguageBarGlass, F as ExpandableHeaderGlass, G as NotificationGlass, H as SkeletonGlass, I as TooltipGlass, J as modalSizes, K as notificationVariants, L as tooltipPositions, M as SortDropdownGlass, N as SearchBoxGlass, O as StatusIndicatorGlass, P as IconButtonGlass, Q as DropdownGlass, R as ToggleGlass, S as RainbowProgressGlass, T as ProfileAvatarGlass, U as skeletonVariants, V as SliderGlass, W as PopoverGlass, X as GlassCard, Y as InputGlass, Z as cardIntensity, _ as ContributionMetricsGlass, a as HeaderBrandingGlass, at as BadgeGlass, b as AICardGlass, c as YearCardGlass, ct as avatarSizes, d as TrustScoreDisplayGlass, dt as InteractiveCard, et as inputVariants, f as RepositoryMetadataGlass, ft as FormFieldWrapper, g as MetricCardGlass, h as MetricsGridGlass, i as HeaderNavGlass, it as buttonGlassVariants, j as StatItemGlass, k as BaseProgressGlass, l as UserStatsLineGlass, lt as statusSizes, m as RepositoryCardGlass, mt as alertVariants, n as ProjectsListGlass, nt as CheckboxGlass, o as FlagsSectionGlass, ot as badgeVariants, p as RepositoryHeaderGlass, pt as TouchTarget, q as ModalGlass, r as ProfileHeaderGlass, rt as ButtonGlass, s as CareerStatsGlass, st as AvatarGlass, t as TrustScoreCardGlass, tt as CircularProgressGlass, u as UserInfoGlass, ut as AlertGlass, v as CircularMetricGlass, w as progressSizes, x as SegmentedControlGlass, y as CareerStatsHeaderGlass, z as toggleSizes } from "./trust-score-card-glass-CowcDyxH.js";
|
|
3
3
|
import { n as useHover, t as useFocus } from "./use-focus-CX0TJJIj.js";
|
|
4
4
|
import { a as getThemeConfig, i as getNextTheme, n as THEME_CONFIG, o as useTheme, r as ThemeProvider, t as THEMES } from "./theme-context-BZoCplcU.js";
|
|
5
5
|
import { n as useResponsive, t as useWallpaperTint } from "./use-wallpaper-tint-DUgmytlY.js";
|
package/dist/r/alert-glass.json
CHANGED
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
{
|
|
18
18
|
"path": "components/glass/ui/alert-glass.tsx",
|
|
19
19
|
"type": "registry:component",
|
|
20
|
-
"content": "/**\n * AlertGlass Component\n *\n * Glass-themed alert with:\n * - Theme-aware styling via CSS variables (glass/light/aurora)\n * - shadcn/ui compatible variants (default, destructive)\n * - Extended Glass UI variants (success, warning)\n * - Optional title\n * - Dismissible option\n * - Backdrop blur effect\n */\n\nimport { forwardRef, type ReactNode, type CSSProperties } from 'react';\nimport { type VariantProps } from 'class-variance-authority';\nimport {\n Info,\n CheckCircle,\n AlertTriangle,\n AlertCircle,\n X,\n} from 'lucide-react';\nimport { cn } from '@/lib/utils';\nimport { alertVariants } from '@/lib/variants/alert-glass-variants';\nimport { ICON_SIZES } from '@/components/glass/primitives';\nimport '@/glass-theme.css';\n\nimport type { AlertVariant } from '@/lib/variants/alert-glass-variants';\n\n// ========================================\n// ICON MAP\n// ========================================\n\nconst iconMap: Record<AlertVariant, typeof Info> = {\n default: Info,\n destructive: AlertCircle,\n success: CheckCircle,\n warning: AlertTriangle,\n // Aliases\n info: Info,\n error: AlertCircle,\n};\n\n// ========================================\n// CSS VARIABLE HELPERS\n// ========================================\n\ntype AlertStyleVars = { bg: string; border: string; text: string };\n\nconst variantStyles: Record<AlertVariant, AlertStyleVars> = {\n // shadcn/ui compatible variants\n default: {\n bg: 'var(--alert-default-bg)',\n border: 'var(--alert-default-border)',\n text: 'var(--alert-default-text)',\n },\n destructive: {\n bg: 'var(--alert-destructive-bg)',\n border: 'var(--alert-destructive-border)',\n text: 'var(--alert-destructive-text)',\n },\n // Glass UI extended variants\n success: {\n bg: 'var(--alert-success-bg)',\n border: 'var(--alert-success-border)',\n text: 'var(--alert-success-text)',\n },\n warning: {\n bg: 'var(--alert-warning-bg)',\n border: 'var(--alert-warning-border)',\n text: 'var(--alert-warning-text)',\n },\n // Backward compatibility aliases\n info: {\n bg: 'var(--alert-default-bg)',\n border: 'var(--alert-default-border)',\n text: 'var(--alert-default-text)',\n },\n error: {\n bg: 'var(--alert-destructive-bg)',\n border: 'var(--alert-destructive-border)',\n text: 'var(--alert-destructive-text)',\n },\n};\n\nconst getAlertStyles = (variant: AlertVariant): CSSProperties => {\n const config = variantStyles[variant];\n return {\n background: config.bg,\n border: `1px solid ${config.border}`,\n };\n};\n\n// ========================================\n// PROPS INTERFACE\n// ========================================\n\nexport interface AlertGlassProps\n extends Omit<React.HTMLAttributes<HTMLDivElement>, 'style' | 'title'>,\n VariantProps<typeof alertVariants> {\n readonly title?: string;\n readonly children: ReactNode;\n readonly dismissible?: boolean;\n readonly onDismiss?: () => void;\n}\n\n// ========================================\n// COMPONENT\n// ========================================\n\nexport const AlertGlass = forwardRef<HTMLDivElement, AlertGlassProps>(\n (\n {\n className,\n variant = 'default',\n title,\n children,\n dismissible,\n onDismiss,\n ...props\n },\n ref\n ) => {\n // Ensure variant is never null/undefined for type safety\n const effectiveVariant: AlertVariant = variant ?? 'default';\n\n const config = variantStyles[effectiveVariant];\n const Icon = iconMap[effectiveVariant];\n\n return (\n <div\n ref={ref}\n className={cn(alertVariants({ variant: effectiveVariant }), className)}\n style={getAlertStyles(effectiveVariant)}\n role=\"alert\"\n {...props}\n >\n <Icon\n className=\"w-4 h-4 md:w-5 md:h-5 flex-shrink-0 mt-0.5\"\n style={{ color: config.text }}\n />\n <div className=\"flex-1\">\n {title && (\n <p\n className=\"font-medium text-xs md:text-sm mb-0.5 md:mb-1\"\n style={{ color: config.text }}\n >\n {title}\n </p>\n )}\n <p className=\"text-xs md:text-sm opacity-80\" style={{ color: config.text }}>\n {children}\n </p>\n </div>\n {dismissible && (\n <button\n onClick={onDismiss}\n className=\"p-0.5 md:p-1 rounded transition-colors duration-200 hover:bg-black/5 flex-shrink-0\"\n aria-label=\"Dismiss alert\"\n >\n <X className={ICON_SIZES.md} style={{ color: config.text }} />\n </button>\n )}\n </div>\n );\n }\n);\n\nAlertGlass.displayName = 'AlertGlass';\n"
|
|
20
|
+
"content": "/**\n * AlertGlass Component\n *\n * Glass-themed alert with:\n * - Theme-aware styling via CSS variables (glass/light/aurora)\n * - shadcn/ui compatible variants (default, destructive)\n * - Extended Glass UI variants (success, warning)\n * - Optional title\n * - Dismissible option\n * - Backdrop blur effect\n */\n\nimport { forwardRef, type ReactNode, type CSSProperties } from 'react';\nimport { type VariantProps } from 'class-variance-authority';\nimport {\n Info,\n CheckCircle,\n AlertTriangle,\n AlertCircle,\n X,\n} from 'lucide-react';\nimport { cn } from '@/lib/utils';\nimport { alertVariants } from '@/lib/variants/alert-glass-variants';\nimport { ICON_SIZES } from '@/components/glass/primitives';\nimport '@/glass-theme.css';\n\nimport type { AlertVariant } from '@/lib/variants/alert-glass-variants';\n\n// ========================================\n// ICON MAP\n// ========================================\n\nconst iconMap: Record<AlertVariant, typeof Info> = {\n default: Info,\n destructive: AlertCircle,\n success: CheckCircle,\n warning: AlertTriangle,\n // Aliases\n info: Info,\n error: AlertCircle,\n};\n\n// ========================================\n// CSS VARIABLE HELPERS\n// ========================================\n\ntype AlertStyleVars = { bg: string; border: string; text: string };\n\nconst variantStyles: Record<AlertVariant, AlertStyleVars> = {\n // shadcn/ui compatible variants\n default: {\n bg: 'var(--alert-default-bg)',\n border: 'var(--alert-default-border)',\n text: 'var(--alert-default-text)',\n },\n destructive: {\n bg: 'var(--alert-destructive-bg)',\n border: 'var(--alert-destructive-border)',\n text: 'var(--alert-destructive-text)',\n },\n // Glass UI extended variants\n success: {\n bg: 'var(--alert-success-bg)',\n border: 'var(--alert-success-border)',\n text: 'var(--alert-success-text)',\n },\n warning: {\n bg: 'var(--alert-warning-bg)',\n border: 'var(--alert-warning-border)',\n text: 'var(--alert-warning-text)',\n },\n // Backward compatibility aliases\n info: {\n bg: 'var(--alert-default-bg)',\n border: 'var(--alert-default-border)',\n text: 'var(--alert-default-text)',\n },\n error: {\n bg: 'var(--alert-destructive-bg)',\n border: 'var(--alert-destructive-border)',\n text: 'var(--alert-destructive-text)',\n },\n};\n\nconst getAlertStyles = (variant: AlertVariant): CSSProperties => {\n const config = variantStyles[variant];\n return {\n background: config.bg,\n border: `1px solid ${config.border}`,\n };\n};\n\n// ========================================\n// PROPS INTERFACE\n// ========================================\n\n/**\n * Props for the AlertGlass component\n *\n * A glass-themed alert with semantic variants, dismissible option, and automatic icon selection.\n * Features theme-aware styling and WCAG-compliant role attributes.\n *\n * @accessibility\n * - **Keyboard Navigation:** Dismissible alerts include a keyboard-accessible close button (Tab + Enter/Space)\n * - **Focus Management:** Close button receives visible focus ring (WCAG 2.4.7)\n * - **Screen Readers:** Uses `role=\"alert\"` for immediate announcement to screen readers (WCAG 4.1.3)\n * - **Icon Semantics:** Icons are decorative and hidden from screen readers with `aria-hidden=\"true\"`\n * - **Variant Semantics:** Each variant uses distinct colors and icons for multi-modal communication (color + icon)\n * - **Touch Targets:** Dismiss button meets minimum 44x44px touch target (WCAG 2.5.5)\n * - **Color Contrast:** All variant text and backgrounds meet WCAG AA contrast ratio 4.5:1\n * - **Motion:** Transitions respect `prefers-reduced-motion` settings\n *\n * @example\n * ```tsx\n * // Basic alert (info/default variant)\n * <AlertGlass title=\"Information\" variant=\"default\">\n * This is an informational message\n * </AlertGlass>\n *\n * // Error alert with aria-live for dynamic updates\n * <AlertGlass variant=\"destructive\" title=\"Error\" aria-live=\"assertive\">\n * Your session has expired. Please log in again.\n * </AlertGlass>\n *\n * // Success alert\n * <AlertGlass variant=\"success\" title=\"Success\">\n * Your changes have been saved successfully.\n * </AlertGlass>\n *\n * // Warning alert\n * <AlertGlass variant=\"warning\" title=\"Warning\">\n * Your subscription expires in 3 days.\n * </AlertGlass>\n *\n * // Dismissible alert with accessible close button\n * <AlertGlass\n * variant=\"default\"\n * title=\"Welcome\"\n * dismissible\n * onDismiss={() => setShowAlert(false)}\n * >\n * Check out our new features!\n * </AlertGlass>\n *\n * // Alert without title\n * <AlertGlass variant=\"destructive\">\n * Quick error message without title\n * </AlertGlass>\n *\n * // Form validation alert\n * <form onSubmit={handleSubmit}>\n * {formError && (\n * <AlertGlass variant=\"destructive\" title=\"Validation Error\" role=\"alert\">\n * {formError}\n * </AlertGlass>\n * )}\n * <InputGlass label=\"Email\" />\n * <ButtonGlass type=\"submit\">Submit</ButtonGlass>\n * </form>\n * ```\n */\nexport interface AlertGlassProps\n extends Omit<React.HTMLAttributes<HTMLDivElement>, 'style' | 'title'>,\n VariantProps<typeof alertVariants> {\n readonly title?: string;\n readonly children: ReactNode;\n readonly dismissible?: boolean;\n readonly onDismiss?: () => void;\n}\n\n// ========================================\n// COMPONENT\n// ========================================\n\nexport const AlertGlass = forwardRef<HTMLDivElement, AlertGlassProps>(\n (\n {\n className,\n variant = 'default',\n title,\n children,\n dismissible,\n onDismiss,\n ...props\n },\n ref\n ) => {\n // Ensure variant is never null/undefined for type safety\n const effectiveVariant: AlertVariant = variant ?? 'default';\n\n const config = variantStyles[effectiveVariant];\n const Icon = iconMap[effectiveVariant];\n\n return (\n <div\n ref={ref}\n className={cn(alertVariants({ variant: effectiveVariant }), className)}\n style={getAlertStyles(effectiveVariant)}\n role=\"alert\"\n {...props}\n >\n <Icon\n className=\"w-4 h-4 md:w-5 md:h-5 flex-shrink-0 mt-0.5\"\n style={{ color: config.text }}\n />\n <div className=\"flex-1\">\n {title && (\n <p\n className=\"font-medium text-xs md:text-sm mb-0.5 md:mb-1\"\n style={{ color: config.text }}\n >\n {title}\n </p>\n )}\n <p className=\"text-xs md:text-sm opacity-80\" style={{ color: config.text }}>\n {children}\n </p>\n </div>\n {dismissible && (\n <button\n onClick={onDismiss}\n className=\"p-0.5 md:p-1 rounded transition-colors duration-200 hover:bg-black/5 flex-shrink-0\"\n aria-label=\"Dismiss alert\"\n >\n <X className={ICON_SIZES.md} style={{ color: config.text }} />\n </button>\n )}\n </div>\n );\n }\n);\n\nAlertGlass.displayName = 'AlertGlass';\n"
|
|
21
21
|
}
|
|
22
22
|
],
|
|
23
23
|
"categories": [
|
package/dist/r/badge-glass.json
CHANGED
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
{
|
|
17
17
|
"path": "components/glass/ui/badge-glass.tsx",
|
|
18
18
|
"type": "registry:component",
|
|
19
|
-
"content": "/**\n * BadgeGlass Component\n *\n * Glass-themed badge with:\n * - Theme-aware styling via CSS variables (glass/light/aurora)\n * - shadcn/ui compatible variants (default, secondary, destructive, outline)\n * - Extended Glass UI variants (success, warning, info)\n * - Size options\n * - Optional animated dot\n */\n\nimport { forwardRef, type ReactNode, type CSSProperties } from 'react';\nimport { type VariantProps } from 'class-variance-authority';\nimport { cn } from '@/lib/utils';\nimport { badgeVariants, type BadgeVariant } from '@/lib/variants/badge-glass-variants';\nimport '@/glass-theme.css';\n\n// ========================================\n// CSS VARIABLE HELPERS\n// ========================================\n\ntype BadgeStyleVars = { bg: string; text: string; border: string };\n\nconst variantStyles: Record<BadgeVariant, BadgeStyleVars> = {\n // shadcn/ui compatible variants\n default: {\n bg: 'var(--badge-default-bg)',\n text: 'var(--badge-default-text)',\n border: 'var(--badge-default-border)',\n },\n secondary: {\n bg: 'var(--badge-secondary-bg)',\n text: 'var(--badge-secondary-text)',\n border: 'var(--badge-secondary-border)',\n },\n destructive: {\n bg: 'var(--badge-destructive-bg)',\n text: 'var(--badge-destructive-text)',\n border: 'var(--badge-destructive-border)',\n },\n outline: {\n bg: 'var(--badge-outline-bg)',\n text: 'var(--badge-outline-text)',\n border: 'var(--badge-outline-border)',\n },\n // Glass UI extended variants\n success: {\n bg: 'var(--badge-success-bg)',\n text: 'var(--badge-success-text)',\n border: 'var(--badge-success-border)',\n },\n warning: {\n bg: 'var(--badge-warning-bg)',\n text: 'var(--badge-warning-text)',\n border: 'var(--badge-warning-border)',\n },\n info: {\n bg: 'var(--badge-info-bg)',\n text: 'var(--badge-info-text)',\n border: 'var(--badge-info-border)',\n },\n};\n\nconst getBadgeStyles = (variant: BadgeVariant): CSSProperties => {\n const v = variantStyles[variant] || variantStyles.default;\n return {\n background: v.bg,\n color: v.text,\n border: `1px solid ${v.border}`,\n };\n};\n\n// ========================================\n// PROPS INTERFACE\n// ========================================\n\nexport interface BadgeGlassProps\n extends Omit<React.HTMLAttributes<HTMLSpanElement>, 'style'>,\n VariantProps<typeof badgeVariants> {\n readonly children: ReactNode;\n readonly variant?: BadgeVariant;\n readonly dot?: boolean;\n}\n\n// ========================================\n// COMPONENT\n// ========================================\n\nexport const BadgeGlass = forwardRef<HTMLSpanElement, BadgeGlassProps>(\n (\n { children, className, variant = 'default', size = 'md', dot, ...props },\n ref\n ) => {\n const v = variantStyles[variant];\n\n return (\n <span\n ref={ref}\n className={cn(badgeVariants({ size }), className)}\n style={getBadgeStyles(variant)}\n {...props}\n >\n {dot && (\n <span\n className=\"w-1 h-1 md:w-1.5 md:h-1.5 rounded-full animate-pulse\"\n style={{ background: v.text }}\n />\n )}\n {children}\n </span>\n );\n }\n);\n\nBadgeGlass.displayName = 'BadgeGlass';\n"
|
|
19
|
+
"content": "/**\n * BadgeGlass Component\n *\n * Glass-themed badge with:\n * - Theme-aware styling via CSS variables (glass/light/aurora)\n * - shadcn/ui compatible variants (default, secondary, destructive, outline)\n * - Extended Glass UI variants (success, warning, info)\n * - Size options\n * - Optional animated dot\n */\n\nimport { forwardRef, type ReactNode, type CSSProperties } from 'react';\nimport { type VariantProps } from 'class-variance-authority';\nimport { cn } from '@/lib/utils';\nimport { badgeVariants, type BadgeVariant } from '@/lib/variants/badge-glass-variants';\nimport '@/glass-theme.css';\n\n// ========================================\n// CSS VARIABLE HELPERS\n// ========================================\n\ntype BadgeStyleVars = { bg: string; text: string; border: string };\n\nconst variantStyles: Record<BadgeVariant, BadgeStyleVars> = {\n // shadcn/ui compatible variants\n default: {\n bg: 'var(--badge-default-bg)',\n text: 'var(--badge-default-text)',\n border: 'var(--badge-default-border)',\n },\n secondary: {\n bg: 'var(--badge-secondary-bg)',\n text: 'var(--badge-secondary-text)',\n border: 'var(--badge-secondary-border)',\n },\n destructive: {\n bg: 'var(--badge-destructive-bg)',\n text: 'var(--badge-destructive-text)',\n border: 'var(--badge-destructive-border)',\n },\n outline: {\n bg: 'var(--badge-outline-bg)',\n text: 'var(--badge-outline-text)',\n border: 'var(--badge-outline-border)',\n },\n // Glass UI extended variants\n success: {\n bg: 'var(--badge-success-bg)',\n text: 'var(--badge-success-text)',\n border: 'var(--badge-success-border)',\n },\n warning: {\n bg: 'var(--badge-warning-bg)',\n text: 'var(--badge-warning-text)',\n border: 'var(--badge-warning-border)',\n },\n info: {\n bg: 'var(--badge-info-bg)',\n text: 'var(--badge-info-text)',\n border: 'var(--badge-info-border)',\n },\n};\n\nconst getBadgeStyles = (variant: BadgeVariant): CSSProperties => {\n const v = variantStyles[variant] || variantStyles.default;\n return {\n background: v.bg,\n color: v.text,\n border: `1px solid ${v.border}`,\n };\n};\n\n// ========================================\n// PROPS INTERFACE\n// ========================================\n\n/**\n * Props for the BadgeGlass component\n *\n * A glass-themed badge with semantic variants and optional animated status dot.\n * Features shadcn/ui compatible variants plus extended Glass UI variants.\n *\n * @accessibility\n * - **Keyboard Navigation:** Badges are non-interactive by default (display-only)\n * - **Focus Management:** N/A - badges do not receive focus unless wrapped in interactive elements\n * - **Screen Readers:** Semantic `<span>` element, content announced naturally\n * - **Status Indicators:** Use `aria-label` to provide context for status badges (e.g., \"Status: Active\")\n * - **Animated Dot:** Pulse animation respects `prefers-reduced-motion` settings\n * - **Touch Targets:** N/A for display badges, ensure 44x44px if wrapping in button/link (WCAG 2.5.5)\n * - **Color Contrast:** All variant text meets WCAG AA contrast ratio 4.5:1 against badge background\n * - **Motion:** Dot pulse animation can be disabled for users with motion sensitivity\n *\n * @example\n * ```tsx\n * // Basic badge with variant\n * <BadgeGlass variant=\"default\">New</BadgeGlass>\n *\n * // Status badge with aria-label for screen readers\n * <BadgeGlass variant=\"success\" aria-label=\"Status: Active\">\n * Active\n * </BadgeGlass>\n *\n * // Different variants (shadcn/ui compatible)\n * <BadgeGlass variant=\"default\">Default</BadgeGlass>\n * <BadgeGlass variant=\"secondary\">Secondary</BadgeGlass>\n * <BadgeGlass variant=\"destructive\">Error</BadgeGlass>\n * <BadgeGlass variant=\"outline\">Outline</BadgeGlass>\n *\n * // Extended Glass UI variants\n * <BadgeGlass variant=\"success\">Success</BadgeGlass>\n * <BadgeGlass variant=\"warning\">Warning</BadgeGlass>\n * <BadgeGlass variant=\"info\">Info</BadgeGlass>\n *\n * // With animated status dot\n * <BadgeGlass variant=\"success\" dot aria-label=\"Status: Online\">\n * Online\n * </BadgeGlass>\n * <BadgeGlass variant=\"destructive\" dot aria-label=\"Status: Offline\">\n * Offline\n * </BadgeGlass>\n *\n * // Size variants\n * <BadgeGlass size=\"sm\">Small</BadgeGlass>\n * <BadgeGlass size=\"md\">Medium</BadgeGlass>\n * <BadgeGlass size=\"lg\">Large</BadgeGlass>\n *\n * // Inside interactive elements (ensure accessible labels)\n * <button aria-label=\"Filter by active status\">\n * Filter: <BadgeGlass variant=\"success\">Active</BadgeGlass>\n * </button>\n *\n * // Count badge with semantic meaning\n * <div>\n * <span>Notifications</span>\n * <BadgeGlass variant=\"destructive\" aria-label=\"3 unread notifications\">\n * 3\n * </BadgeGlass>\n * </div>\n * ```\n */\nexport interface BadgeGlassProps\n extends Omit<React.HTMLAttributes<HTMLSpanElement>, 'style'>,\n VariantProps<typeof badgeVariants> {\n readonly children: ReactNode;\n readonly variant?: BadgeVariant;\n readonly dot?: boolean;\n}\n\n// ========================================\n// COMPONENT\n// ========================================\n\nexport const BadgeGlass = forwardRef<HTMLSpanElement, BadgeGlassProps>(\n (\n { children, className, variant = 'default', size = 'md', dot, ...props },\n ref\n ) => {\n const v = variantStyles[variant];\n\n return (\n <span\n ref={ref}\n className={cn(badgeVariants({ size }), className)}\n style={getBadgeStyles(variant)}\n {...props}\n >\n {dot && (\n <span\n className=\"w-1 h-1 md:w-1.5 md:h-1.5 rounded-full animate-pulse\"\n style={{ background: v.text }}\n />\n )}\n {children}\n </span>\n );\n }\n);\n\nBadgeGlass.displayName = 'BadgeGlass';\n"
|
|
20
20
|
}
|
|
21
21
|
],
|
|
22
22
|
"categories": [
|
package/dist/r/button-glass.json
CHANGED
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
{
|
|
21
21
|
"path": "components/glass/ui/button-glass.tsx",
|
|
22
22
|
"type": "registry:component",
|
|
23
|
-
"content": "/**\n * ButtonGlass Component\n *\n * Glass-themed button with:\n * - Theme-aware styling via CSS variables (glass/light/aurora)\n * - Glow effects on hover\n * - Ripple effect on click (JS)\n * - Shine animation for primary variant (JS)\n * - Loading state with spinner\n * - Icon support (left/right position)\n */\n\nimport {\n forwardRef,\n useState,\n useCallback,\n useEffect,\n useRef,\n type MouseEvent,\n type CSSProperties,\n} from 'react';\nimport { Slot } from '@radix-ui/react-slot';\nimport { type VariantProps } from 'class-variance-authority';\nimport { RefreshCw, type LucideIcon } from 'lucide-react';\nimport { cn } from '@/lib/utils';\nimport { useHover } from '@/lib/hooks/use-hover';\nimport { useFocus } from '@/lib/hooks/use-focus';\nimport { buttonGlassVariants, type ButtonGlassVariant } from '@/lib/variants/button-glass-variants';\nimport { ICON_SIZES } from '@/components/glass/primitives';\nimport '@/glass-theme.css';\n\n// ========================================\n// CSS VARIABLE STYLE MAPS\n// ========================================\n\nconst getVariantStyles = (\n variant: ButtonGlassVariant,\n isHovered: boolean,\n isFocusVisible: boolean\n): CSSProperties => {\n const baseStyles: Record<ButtonGlassVariant, CSSProperties> = {\n primary: {\n background: isHovered\n ? 'var(--btn-primary-hover-bg)'\n : 'var(--btn-primary-bg)',\n color: 'var(--btn-primary-text)',\n border: 'none',\n boxShadow: isFocusVisible\n ? 'var(--focus-glow)'\n : isHovered\n ? 'var(--btn-primary-glow)'\n : '0 4px 15px oklch(48.5% 0.26 283 / 0.25)',\n },\n secondary: {\n background: isHovered\n ? 'var(--btn-secondary-hover-bg)'\n : 'var(--btn-secondary-bg)',\n color: 'var(--btn-secondary-text)',\n border: '1px solid var(--btn-secondary-border)',\n boxShadow: isFocusVisible\n ? 'var(--focus-glow)'\n : isHovered\n ? 'var(--btn-secondary-glow)'\n : 'none',\n },\n ghost: {\n background: isHovered\n ? 'var(--btn-ghost-hover-bg)'\n : 'var(--btn-ghost-bg)',\n color: 'var(--btn-ghost-text)',\n border: 'none',\n boxShadow: isFocusVisible ? 'var(--focus-glow)' : 'none',\n },\n destructive: {\n background: 'var(--btn-destructive-bg)',\n color: 'var(--btn-destructive-text)',\n border: 'none',\n boxShadow: isFocusVisible\n ? 'var(--focus-glow)'\n : isHovered\n ? 'var(--btn-destructive-glow)'\n : '0 4px 15px oklch(62.8% 0.225 29 / 0.25)',\n },\n success: {\n background: 'var(--btn-success-bg)',\n color: 'var(--btn-success-text)',\n border: 'none',\n boxShadow: isFocusVisible\n ? 'var(--focus-glow)'\n : isHovered\n ? 'var(--btn-success-glow)'\n : '0 4px 15px oklch(70.7% 0.143 167 / 0.25)',\n },\n text: {\n background: 'transparent',\n color: 'var(--text-secondary)',\n border: 'none',\n boxShadow: isFocusVisible ? 'var(--focus-glow)' : 'none',\n },\n };\n\n return baseStyles[variant];\n};\n\n// ========================================\n// PROPS INTERFACE\n// ========================================\n\n/**\n * Props for the ButtonGlass component\n *\n * A glass-themed button with ripple effects, loading states, and icon support.\n * Features theme-aware styling and hover animations.\n *\n * @example\n * ```tsx\n * // Basic button\n * <ButtonGlass variant=\"primary\">Click me</ButtonGlass>\n *\n * // With icon\n * <ButtonGlass icon={Check} iconPosition=\"left\">Save</ButtonGlass>\n *\n * // Loading state\n * <ButtonGlass loading>Processing...</ButtonGlass>\n *\n * // Different variants\n * <ButtonGlass variant=\"ghost\">Cancel</ButtonGlass>\n * <ButtonGlass variant=\"success\">Confirm</ButtonGlass>\n *\n * // As a link (asChild pattern)\n * <ButtonGlass asChild variant=\"primary\">\n * <a href=\"/dashboard\">Go to Dashboard</a>\n * </ButtonGlass>\n *\n * // With Next.js Link\n * <ButtonGlass asChild variant=\"ghost\">\n * <Link href=\"/settings\">Settings</Link>\n * </ButtonGlass>\n * ```\n */\nexport interface ButtonGlassProps\n extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, 'style'>,\n VariantProps<typeof buttonGlassVariants> {\n /**\n * Render as child element instead of button (polymorphic rendering).\n * Useful for rendering buttons as links or other interactive elements.\n *\n * **Note:** When using `asChild`, decorative effects (ripple, shine, glow)\n * are disabled to maintain compatibility with Radix UI Slot.\n * Only styles and event handlers are passed to the child element.\n *\n * @default false\n * @example\n * ```tsx\n * <ButtonGlass asChild>\n * <a href=\"/about\">About Us</a>\n * </ButtonGlass>\n * ```\n */\n readonly asChild?: boolean;\n\n /**\n * Visual style variant of the button\n * @default \"primary\"\n */\n readonly variant?: ButtonGlassVariant;\n\n /**\n * Show loading spinner and disable interactions\n * @default false\n */\n readonly loading?: boolean;\n\n /**\n * Icon component from lucide-react to display\n * @example icon={Check}\n */\n readonly icon?: LucideIcon;\n\n /**\n * Position of the icon relative to button text\n * @default \"left\"\n */\n readonly iconPosition?: 'left' | 'right';\n\n /**\n * Size variant of the button\n * @default \"md\"\n */\n readonly size?: 'sm' | 'md' | 'lg' | 'icon';\n}\n\n// ========================================\n// COMPONENT\n// ========================================\n\nexport const ButtonGlass = forwardRef<HTMLButtonElement, ButtonGlassProps>(\n (\n {\n asChild = false,\n className,\n variant = 'primary',\n size = 'md',\n children,\n loading = false,\n disabled,\n icon: Icon,\n iconPosition = 'left',\n onClick,\n ...props\n },\n ref\n ) => {\n const { isHovered, hoverProps } = useHover();\n const { isFocusVisible, focusProps } = useFocus({ focusVisible: true });\n const [ripple, setRipple] = useState<{ x: number; y: number } | null>(null);\n\n const isDisabled = disabled || loading;\n const rippleTimeoutRef = useRef<NodeJS.Timeout | null>(null);\n\n // Cleanup ripple timeout on unmount\n useEffect(() => {\n return () => {\n if (rippleTimeoutRef.current) {\n clearTimeout(rippleTimeoutRef.current);\n }\n };\n }, []);\n\n // Ripple effect handler\n const handleClick = useCallback(\n (e: MouseEvent<HTMLButtonElement>) => {\n if (isDisabled) return;\n\n // Create ripple effect\n const rect = e.currentTarget.getBoundingClientRect();\n const x = e.clientX - rect.left;\n const y = e.clientY - rect.top;\n setRipple({ x, y });\n\n // Clear previous timeout if exists\n if (rippleTimeoutRef.current) {\n clearTimeout(rippleTimeoutRef.current);\n }\n\n rippleTimeoutRef.current = setTimeout(() => {\n setRipple(null);\n rippleTimeoutRef.current = null;\n }, 600);\n\n onClick?.(e);\n },\n [isDisabled, onClick]\n );\n\n // Polymorphic component - render as Slot when asChild is true\n const Comp = asChild ? Slot : 'button';\n\n return (\n <Comp\n ref={ref}\n className={cn(\n buttonGlassVariants({ variant, size }),\n isHovered && !isDisabled && 'scale-[1.02]',\n className\n )}\n style={{\n ...getVariantStyles(variant, isHovered && !isDisabled, isFocusVisible && !isDisabled),\n outline: 'none',\n }}\n type={asChild ? undefined : 'button'}\n disabled={isDisabled}\n onClick={handleClick}\n onMouseEnter={hoverProps.onMouseEnter}\n onMouseLeave={hoverProps.onMouseLeave}\n onFocus={focusProps.onFocus}\n onBlur={focusProps.onBlur}\n {...props}\n >\n {/* When asChild is true, only render children (Slot expects a single child) */}\n {asChild ? (\n children\n ) : (\n <>\n {/* Shine effect on hover for primary */}\n {isHovered && variant === 'primary' && !isDisabled && (\n <div\n className=\"absolute inset-0 overflow-hidden pointer-events-none\"\n style={{ borderRadius: 'inherit' }}\n >\n <div\n className=\"absolute top-0 h-full w-1/3 bg-linear-to-r from-transparent via-white/20 to-transparent\"\n style={{ animation: 'btn-shine 1.5s ease-in-out infinite' }}\n />\n </div>\n )}\n\n {/* Ripple effect */}\n {ripple && (\n <span\n className=\"absolute rounded-full bg-white/30 pointer-events-none\"\n style={{\n left: ripple.x,\n top: ripple.y,\n width: 10,\n height: 10,\n transform: 'translate(-50%, -50%)',\n animation: 'ripple 0.6s ease-out',\n }}\n />\n )}\n\n {/* Pulsing glow on hover */}\n {isHovered && variant === 'primary' && !isDisabled && (\n <div\n className=\"absolute inset-0 rounded-xl animate-glow-pulse pointer-events-none\"\n style={{\n background:\n 'radial-gradient(circle, oklch(100% 0 0 / 0.1) 0%, transparent 70%)',\n }}\n />\n )}\n\n {/* Loading spinner */}\n {loading && <RefreshCw className={cn(ICON_SIZES.md, 'animate-spin')} />}\n\n {/* Icon left */}\n {!loading && Icon && iconPosition === 'left' && (\n <Icon className={ICON_SIZES.md} />\n )}\n\n {/* Content */}\n {!loading && children}\n\n {/* Icon right */}\n {!loading && Icon && iconPosition === 'right' && (\n <Icon className={ICON_SIZES.md} />\n )}\n </>\n )}\n </Comp>\n );\n }\n);\n\nButtonGlass.displayName = 'ButtonGlass';\n"
|
|
23
|
+
"content": "/**\n * ButtonGlass Component\n *\n * Glass-themed button with:\n * - Theme-aware styling via CSS variables (glass/light/aurora)\n * - Glow effects on hover\n * - Ripple effect on click (JS)\n * - Shine animation for primary variant (JS)\n * - Loading state with spinner\n * - Icon support (left/right position)\n */\n\nimport {\n forwardRef,\n useState,\n useCallback,\n useEffect,\n useRef,\n type MouseEvent,\n type CSSProperties,\n} from 'react';\nimport { Slot } from '@radix-ui/react-slot';\nimport { type VariantProps } from 'class-variance-authority';\nimport { RefreshCw, type LucideIcon } from 'lucide-react';\nimport { cn } from '@/lib/utils';\nimport { useHover } from '@/lib/hooks/use-hover';\nimport { useFocus } from '@/lib/hooks/use-focus';\nimport { buttonGlassVariants, type ButtonGlassVariant } from '@/lib/variants/button-glass-variants';\nimport { ICON_SIZES } from '@/components/glass/primitives';\nimport '@/glass-theme.css';\n\n// ========================================\n// CSS VARIABLE STYLE MAPS\n// ========================================\n\nconst getVariantStyles = (\n variant: ButtonGlassVariant,\n isHovered: boolean,\n isFocusVisible: boolean\n): CSSProperties => {\n const baseStyles: Record<ButtonGlassVariant, CSSProperties> = {\n primary: {\n background: isHovered\n ? 'var(--btn-primary-hover-bg)'\n : 'var(--btn-primary-bg)',\n color: 'var(--btn-primary-text)',\n border: 'none',\n boxShadow: isFocusVisible\n ? 'var(--focus-glow)'\n : isHovered\n ? 'var(--btn-primary-glow)'\n : '0 4px 15px oklch(48.5% 0.26 283 / 0.25)',\n },\n secondary: {\n background: isHovered\n ? 'var(--btn-secondary-hover-bg)'\n : 'var(--btn-secondary-bg)',\n color: 'var(--btn-secondary-text)',\n border: '1px solid var(--btn-secondary-border)',\n boxShadow: isFocusVisible\n ? 'var(--focus-glow)'\n : isHovered\n ? 'var(--btn-secondary-glow)'\n : 'none',\n },\n ghost: {\n background: isHovered\n ? 'var(--btn-ghost-hover-bg)'\n : 'var(--btn-ghost-bg)',\n color: 'var(--btn-ghost-text)',\n border: 'none',\n boxShadow: isFocusVisible ? 'var(--focus-glow)' : 'none',\n },\n destructive: {\n background: 'var(--btn-destructive-bg)',\n color: 'var(--btn-destructive-text)',\n border: 'none',\n boxShadow: isFocusVisible\n ? 'var(--focus-glow)'\n : isHovered\n ? 'var(--btn-destructive-glow)'\n : '0 4px 15px oklch(62.8% 0.225 29 / 0.25)',\n },\n success: {\n background: 'var(--btn-success-bg)',\n color: 'var(--btn-success-text)',\n border: 'none',\n boxShadow: isFocusVisible\n ? 'var(--focus-glow)'\n : isHovered\n ? 'var(--btn-success-glow)'\n : '0 4px 15px oklch(70.7% 0.143 167 / 0.25)',\n },\n text: {\n background: 'transparent',\n color: 'var(--text-secondary)',\n border: 'none',\n boxShadow: isFocusVisible ? 'var(--focus-glow)' : 'none',\n },\n };\n\n return baseStyles[variant];\n};\n\n// ========================================\n// PROPS INTERFACE\n// ========================================\n\n/**\n * Props for the ButtonGlass component\n *\n * A glass-themed button with ripple effects, loading states, and icon support.\n * Features theme-aware styling and hover animations.\n *\n * @accessibility\n * - **Keyboard Navigation:** Fully keyboard accessible with native `<button>` element\n * - **Focus Management:** Visible focus ring using `--focus-glow` CSS variable (WCAG 2.4.7)\n * - **Screen Readers:** Semantic `<button>` element, disabled state announced automatically\n * - **Loading State:** When loading=true, button is disabled and loading spinner is visible\n * - **Touch Targets:** Minimum 44x44px touch target (WCAG 2.5.5) via size variants\n * - **Color Contrast:** All variants meet WCAG AA contrast ratio 4.5:1 minimum\n * - **Motion:** Respects `prefers-reduced-motion` for ripple/shine animations\n *\n * @example\n * ```tsx\n * // Basic button\n * <ButtonGlass variant=\"primary\">Click me</ButtonGlass>\n *\n * // With icon and aria-label for icon-only buttons\n * <ButtonGlass icon={Check} iconPosition=\"left\">Save</ButtonGlass>\n * <ButtonGlass icon={X} size=\"icon\" aria-label=\"Close dialog\" />\n *\n * // Loading state (automatically disables and shows spinner)\n * <ButtonGlass loading aria-live=\"polite\">Processing...</ButtonGlass>\n *\n * // Different variants\n * <ButtonGlass variant=\"ghost\">Cancel</ButtonGlass>\n * <ButtonGlass variant=\"success\">Confirm</ButtonGlass>\n * <ButtonGlass variant=\"destructive\">Delete</ButtonGlass>\n *\n * // As a link (asChild pattern) - maintains semantic HTML\n * <ButtonGlass asChild variant=\"primary\">\n * <a href=\"/dashboard\">Go to Dashboard</a>\n * </ButtonGlass>\n *\n * // With Next.js Link\n * <ButtonGlass asChild variant=\"ghost\">\n * <Link href=\"/settings\">Settings</Link>\n * </ButtonGlass>\n *\n * // Form submit button\n * <ButtonGlass type=\"submit\" variant=\"primary\">\n * Submit Form\n * </ButtonGlass>\n * ```\n */\nexport interface ButtonGlassProps\n extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, 'style'>,\n VariantProps<typeof buttonGlassVariants> {\n /**\n * Render as child element instead of button (polymorphic rendering).\n * Useful for rendering buttons as links or other interactive elements.\n *\n * **Note:** When using `asChild`, decorative effects (ripple, shine, glow)\n * are disabled to maintain compatibility with Radix UI Slot.\n * Only styles and event handlers are passed to the child element.\n *\n * @default false\n * @example\n * ```tsx\n * <ButtonGlass asChild>\n * <a href=\"/about\">About Us</a>\n * </ButtonGlass>\n * ```\n */\n readonly asChild?: boolean;\n\n /**\n * Visual style variant of the button\n * @default \"primary\"\n */\n readonly variant?: ButtonGlassVariant;\n\n /**\n * Show loading spinner and disable interactions\n * @default false\n */\n readonly loading?: boolean;\n\n /**\n * Icon component from lucide-react to display\n * @example icon={Check}\n */\n readonly icon?: LucideIcon;\n\n /**\n * Position of the icon relative to button text\n * @default \"left\"\n */\n readonly iconPosition?: 'left' | 'right';\n\n /**\n * Size variant of the button\n * @default \"md\"\n */\n readonly size?: 'sm' | 'md' | 'lg' | 'icon';\n}\n\n// ========================================\n// COMPONENT\n// ========================================\n\nexport const ButtonGlass = forwardRef<HTMLButtonElement, ButtonGlassProps>(\n (\n {\n asChild = false,\n className,\n variant = 'primary',\n size = 'md',\n children,\n loading = false,\n disabled,\n icon: Icon,\n iconPosition = 'left',\n onClick,\n ...props\n },\n ref\n ) => {\n const { isHovered, hoverProps } = useHover();\n const { isFocusVisible, focusProps } = useFocus({ focusVisible: true });\n const [ripple, setRipple] = useState<{ x: number; y: number } | null>(null);\n\n const isDisabled = disabled || loading;\n const rippleTimeoutRef = useRef<NodeJS.Timeout | null>(null);\n\n // Cleanup ripple timeout on unmount\n useEffect(() => {\n return () => {\n if (rippleTimeoutRef.current) {\n clearTimeout(rippleTimeoutRef.current);\n }\n };\n }, []);\n\n // Ripple effect handler\n const handleClick = useCallback(\n (e: MouseEvent<HTMLButtonElement>) => {\n if (isDisabled) return;\n\n // Create ripple effect\n const rect = e.currentTarget.getBoundingClientRect();\n const x = e.clientX - rect.left;\n const y = e.clientY - rect.top;\n setRipple({ x, y });\n\n // Clear previous timeout if exists\n if (rippleTimeoutRef.current) {\n clearTimeout(rippleTimeoutRef.current);\n }\n\n rippleTimeoutRef.current = setTimeout(() => {\n setRipple(null);\n rippleTimeoutRef.current = null;\n }, 600);\n\n onClick?.(e);\n },\n [isDisabled, onClick]\n );\n\n // Polymorphic component - render as Slot when asChild is true\n const Comp = asChild ? Slot : 'button';\n\n return (\n <Comp\n ref={ref}\n className={cn(\n buttonGlassVariants({ variant, size }),\n isHovered && !isDisabled && 'scale-[1.02]',\n className\n )}\n style={{\n ...getVariantStyles(variant, isHovered && !isDisabled, isFocusVisible && !isDisabled),\n outline: 'none',\n }}\n type={asChild ? undefined : 'button'}\n disabled={isDisabled}\n onClick={handleClick}\n onMouseEnter={hoverProps.onMouseEnter}\n onMouseLeave={hoverProps.onMouseLeave}\n onFocus={focusProps.onFocus}\n onBlur={focusProps.onBlur}\n {...props}\n >\n {/* When asChild is true, only render children (Slot expects a single child) */}\n {asChild ? (\n children\n ) : (\n <>\n {/* Shine effect on hover for primary */}\n {isHovered && variant === 'primary' && !isDisabled && (\n <div\n className=\"absolute inset-0 overflow-hidden pointer-events-none\"\n style={{ borderRadius: 'inherit' }}\n >\n <div\n className=\"absolute top-0 h-full w-1/3 bg-linear-to-r from-transparent via-white/20 to-transparent\"\n style={{ animation: 'btn-shine 1.5s ease-in-out infinite' }}\n />\n </div>\n )}\n\n {/* Ripple effect */}\n {ripple && (\n <span\n className=\"absolute rounded-full bg-white/30 pointer-events-none\"\n style={{\n left: ripple.x,\n top: ripple.y,\n width: 10,\n height: 10,\n transform: 'translate(-50%, -50%)',\n animation: 'ripple 0.6s ease-out',\n }}\n />\n )}\n\n {/* Pulsing glow on hover */}\n {isHovered && variant === 'primary' && !isDisabled && (\n <div\n className=\"absolute inset-0 rounded-xl animate-glow-pulse pointer-events-none\"\n style={{\n background:\n 'radial-gradient(circle, oklch(100% 0 0 / 0.1) 0%, transparent 70%)',\n }}\n />\n )}\n\n {/* Loading spinner */}\n {loading && <RefreshCw className={cn(ICON_SIZES.md, 'animate-spin')} />}\n\n {/* Icon left */}\n {!loading && Icon && iconPosition === 'left' && (\n <Icon className={ICON_SIZES.md} />\n )}\n\n {/* Content */}\n {!loading && children}\n\n {/* Icon right */}\n {!loading && Icon && iconPosition === 'right' && (\n <Icon className={ICON_SIZES.md} />\n )}\n </>\n )}\n </Comp>\n );\n }\n);\n\nButtonGlass.displayName = 'ButtonGlass';\n"
|
|
24
24
|
}
|
|
25
25
|
],
|
|
26
26
|
"categories": [
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
{
|
|
18
18
|
"path": "components/glass/ui/checkbox-glass.tsx",
|
|
19
19
|
"type": "registry:component",
|
|
20
|
-
"content": "/**\n * CheckboxGlass Component\n *\n * Glass-themed checkbox with:\n * - Theme-aware styling (glass/light/aurora)\n * - Glow effect on hover\n * - Optional label\n */\n\nimport { forwardRef, type CSSProperties } from 'react';\nimport { Check } from 'lucide-react';\nimport { cn } from '@/lib/utils';\nimport { useHover } from '@/lib/hooks/use-hover';\nimport { useFocus } from '@/lib/hooks/use-focus';\nimport '@/glass-theme.css';\n\n// ========================================\n// PROPS INTERFACE\n// ========================================\n\nexport interface CheckboxGlassProps\n extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'onChange'> {\n readonly checked: boolean;\n readonly onChange?: (checked: boolean) => void;\n readonly label?: string;\n}\n\n// ========================================\n// COMPONENT\n// ========================================\n\nexport const CheckboxGlass = forwardRef<HTMLInputElement, CheckboxGlassProps>(\n (\n {\n className,\n checked,\n onChange,\n label,\n disabled,\n ...props\n },\n ref\n ) => {\n const { isHovered, hoverProps } = useHover();\n const { isFocusVisible, focusProps } = useFocus({ focusVisible: true });\n\n const checkboxStyles: CSSProperties = {\n background: checked ? 'var(--checkbox-checked-bg)' : 'var(--checkbox-bg)',\n border: `2px solid ${checked ? 'var(--checkbox-checked-bg)' : 'var(--checkbox-border)'}`,\n boxShadow: isFocusVisible && !disabled\n ? 'var(--focus-glow)'\n : isHovered && !disabled\n ? 'var(--checkbox-glow)'\n : 'none',\n };\n\n return (\n <label\n className={cn(\n 'inline-flex items-center gap-2 md:gap-2.5',\n disabled ? 'opacity-50 cursor-not-allowed' : 'cursor-pointer',\n className\n )}\n onMouseEnter={hoverProps.onMouseEnter}\n onMouseLeave={hoverProps.onMouseLeave}\n >\n <input\n ref={ref}\n type=\"checkbox\"\n checked={checked}\n onChange={(e) => !disabled && onChange?.(e.target.checked)}\n disabled={disabled}\n className=\"sr-only\"\n {...props}\n />\n {/* Touch area wrapper - 44px minimum for Apple HIG compliance */}\n <span className=\"inline-flex items-center justify-center min-w-11 min-h-11\">\n {/* Visual checkbox - smaller but within 44px touch area */}\n <div\n onClick={() => !disabled && onChange?.(!checked)}\n onFocus={focusProps.onFocus}\n onBlur={focusProps.onBlur}\n className=\"relative w-6 h-6 md:w-5 md:h-5 rounded-md flex items-center justify-center transition-all duration-300\"\n style={checkboxStyles}\n role=\"checkbox\"\n aria-checked={checked}\n aria-label={label || 'Checkbox'}\n tabIndex={disabled ? -1 : 0}\n onKeyDown={(e) => {\n if (!disabled && (e.key === 'Enter' || e.key === ' ')) {\n e.preventDefault();\n onChange?.(!checked);\n }\n }}\n >\n {checked && (\n <Check className=\"w-3.5 h-3.5 md:w-3 md:h-3\" style={{ color: 'var(--text-inverse)' }} />\n )}\n </div>\n </span>\n {label && (\n <span className=\"text-xs md:text-sm\" style={{ color: 'var(--text-secondary)' }}>\n {label}\n </span>\n )}\n </label>\n );\n }\n);\n\nCheckboxGlass.displayName = 'CheckboxGlass';\n"
|
|
20
|
+
"content": "/**\n * CheckboxGlass Component\n *\n * Glass-themed checkbox with:\n * - Theme-aware styling (glass/light/aurora)\n * - Glow effect on hover\n * - Optional label\n */\n\nimport { forwardRef, type CSSProperties } from 'react';\nimport { Check } from 'lucide-react';\nimport { cn } from '@/lib/utils';\nimport { useHover } from '@/lib/hooks/use-hover';\nimport { useFocus } from '@/lib/hooks/use-focus';\nimport '@/glass-theme.css';\n\n// ========================================\n// PROPS INTERFACE\n// ========================================\n\n/**\n * Props for the CheckboxGlass component\n *\n * A glass-themed checkbox with accessible keyboard navigation, focus management,\n * and touch-friendly targets. Features glow effects and theme-aware styling.\n *\n * @accessibility\n * - **Keyboard Navigation:** Full keyboard support with Enter/Space to toggle, Tab to focus (WCAG 2.1.1)\n * - **Focus Management:** Visible focus ring using `--focus-glow` CSS variable (WCAG 2.4.7)\n * - **Screen Readers:** Dual implementation with native `<input type=\"checkbox\">` (hidden) + visual `<div role=\"checkbox\">`\n * - **ARIA Attributes:** Uses `role=\"checkbox\"` and `aria-checked` for proper state announcement\n * - **Label Association:** Visual label automatically associated with checkbox via `<label>` wrapper\n * - **Touch Targets:** 44x44px minimum touch area per Apple HIG (WCAG 2.5.5 compliance)\n * - **Color Contrast:** Check mark and backgrounds meet WCAG AA contrast ratio 4.5:1\n * - **Motion:** Transitions respect `prefers-reduced-motion` settings\n *\n * @example\n * ```tsx\n * // Basic checkbox with label\n * <CheckboxGlass checked={agreed} onChange={setAgreed} label=\"I agree to terms\" />\n *\n * // Checkbox with accessible name (no visual label)\n * <CheckboxGlass\n * checked={checked}\n * onChange={setChecked}\n * aria-label=\"Select all items\"\n * />\n *\n * // Form integration with validation\n * <form onSubmit={handleSubmit}>\n * <CheckboxGlass\n * checked={newsletter}\n * onChange={setNewsletter}\n * label=\"Subscribe to newsletter\"\n * aria-describedby=\"newsletter-help\"\n * />\n * <p id=\"newsletter-help\">Receive weekly updates</p>\n * <CheckboxGlass\n * checked={terms}\n * onChange={setTerms}\n * label=\"Accept terms and conditions\"\n * required\n * aria-invalid={submitted && !terms}\n * />\n * {submitted && !terms && (\n * <span role=\"alert\">You must accept the terms</span>\n * )}\n * </form>\n *\n * // Disabled checkbox (state announced to screen readers)\n * <CheckboxGlass\n * checked={true}\n * onChange={() => {}}\n * label=\"This option is locked\"\n * disabled\n * />\n *\n * // Checkbox group with fieldset\n * <fieldset>\n * <legend>Select your interests</legend>\n * <CheckboxGlass\n * checked={interests.tech}\n * onChange={(checked) => setInterests({ ...interests, tech: checked })}\n * label=\"Technology\"\n * />\n * <CheckboxGlass\n * checked={interests.design}\n * onChange={(checked) => setInterests({ ...interests, design: checked })}\n * label=\"Design\"\n * />\n * </fieldset>\n * ```\n */\nexport interface CheckboxGlassProps\n extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'onChange'> {\n readonly checked: boolean;\n readonly onChange?: (checked: boolean) => void;\n readonly label?: string;\n}\n\n// ========================================\n// COMPONENT\n// ========================================\n\nexport const CheckboxGlass = forwardRef<HTMLInputElement, CheckboxGlassProps>(\n (\n {\n className,\n checked,\n onChange,\n label,\n disabled,\n ...props\n },\n ref\n ) => {\n const { isHovered, hoverProps } = useHover();\n const { isFocusVisible, focusProps } = useFocus({ focusVisible: true });\n\n const checkboxStyles: CSSProperties = {\n background: checked ? 'var(--checkbox-checked-bg)' : 'var(--checkbox-bg)',\n border: `2px solid ${checked ? 'var(--checkbox-checked-bg)' : 'var(--checkbox-border)'}`,\n boxShadow: isFocusVisible && !disabled\n ? 'var(--focus-glow)'\n : isHovered && !disabled\n ? 'var(--checkbox-glow)'\n : 'none',\n };\n\n return (\n <label\n className={cn(\n 'inline-flex items-center gap-2 md:gap-2.5',\n disabled ? 'opacity-50 cursor-not-allowed' : 'cursor-pointer',\n className\n )}\n onMouseEnter={hoverProps.onMouseEnter}\n onMouseLeave={hoverProps.onMouseLeave}\n >\n <input\n ref={ref}\n type=\"checkbox\"\n checked={checked}\n onChange={(e) => !disabled && onChange?.(e.target.checked)}\n disabled={disabled}\n className=\"sr-only\"\n {...props}\n />\n {/* Touch area wrapper - 44px minimum for Apple HIG compliance */}\n <span className=\"inline-flex items-center justify-center min-w-11 min-h-11\">\n {/* Visual checkbox - smaller but within 44px touch area */}\n <div\n onClick={() => !disabled && onChange?.(!checked)}\n onFocus={focusProps.onFocus}\n onBlur={focusProps.onBlur}\n className=\"relative w-6 h-6 md:w-5 md:h-5 rounded-md flex items-center justify-center transition-all duration-300\"\n style={checkboxStyles}\n role=\"checkbox\"\n aria-checked={checked}\n aria-label={label || 'Checkbox'}\n tabIndex={disabled ? -1 : 0}\n onKeyDown={(e) => {\n if (!disabled && (e.key === 'Enter' || e.key === ' ')) {\n e.preventDefault();\n onChange?.(!checked);\n }\n }}\n >\n {checked && (\n <Check className=\"w-3.5 h-3.5 md:w-3 md:h-3\" style={{ color: 'var(--text-inverse)' }} />\n )}\n </div>\n </span>\n {label && (\n <span className=\"text-xs md:text-sm\" style={{ color: 'var(--text-secondary)' }}>\n {label}\n </span>\n )}\n </label>\n );\n }\n);\n\nCheckboxGlass.displayName = 'CheckboxGlass';\n"
|
|
21
21
|
}
|
|
22
22
|
],
|
|
23
23
|
"categories": [
|