shadcn-glass-ui 2.1.5 → 2.2.1

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 (44) hide show
  1. package/README.md +5 -6
  2. package/context7.json +2 -2
  3. package/dist/cli/index.cjs +1 -1
  4. package/dist/components.cjs +4 -4
  5. package/dist/components.d.ts +87 -144
  6. package/dist/components.js +1 -1
  7. package/dist/hooks.cjs +2 -2
  8. package/dist/index.cjs +5 -5
  9. package/dist/index.js +1 -1
  10. package/dist/r/alert-glass.json +1 -1
  11. package/dist/r/badge-glass.json +1 -1
  12. package/dist/r/button-glass.json +1 -1
  13. package/dist/r/card-glass.json +40 -0
  14. package/dist/r/input-glass.json +1 -1
  15. package/dist/r/modal-glass.json +5 -5
  16. package/dist/r/registry.json +7 -1
  17. package/dist/r/tooltip-glass.json +1 -1
  18. package/dist/shadcn-glass-ui.css +1 -1
  19. package/dist/{theme-context-Y98bGvcm.cjs → theme-context-BEA8K_rq.cjs} +2 -2
  20. package/dist/{theme-context-Y98bGvcm.cjs.map → theme-context-BEA8K_rq.cjs.map} +1 -1
  21. package/dist/themes.cjs +1 -1
  22. package/dist/{trust-score-card-glass-2rjz00d_.cjs → trust-score-card-glass-DTS1RdIt.cjs} +172 -181
  23. package/dist/trust-score-card-glass-DTS1RdIt.cjs.map +1 -0
  24. package/dist/{trust-score-card-glass-zjkx4OC2.js → trust-score-card-glass-Dg4_b_g_.js} +158 -167
  25. package/dist/trust-score-card-glass-Dg4_b_g_.js.map +1 -0
  26. package/dist/{use-focus-DbpBEuee.cjs → use-focus-CdoUzFQ8.cjs} +2 -2
  27. package/dist/{use-focus-DbpBEuee.cjs.map → use-focus-CdoUzFQ8.cjs.map} +1 -1
  28. package/dist/{use-wallpaper-tint-DbawS9zh.cjs → use-wallpaper-tint-Rq5UgY9L.cjs} +2 -2
  29. package/dist/{use-wallpaper-tint-DbawS9zh.cjs.map → use-wallpaper-tint-Rq5UgY9L.cjs.map} +1 -1
  30. package/dist/{utils-XlyXIhuP.cjs → utils-NLnOCttr.cjs} +2 -2
  31. package/dist/{utils-XlyXIhuP.cjs.map → utils-NLnOCttr.cjs.map} +1 -1
  32. package/dist/utils.cjs +1 -1
  33. package/docs/ADVANCED_PATTERNS.md +7 -5
  34. package/docs/AI_USAGE.md +0 -1
  35. package/docs/BEST_PRACTICES.md +0 -2
  36. package/docs/BREAKING_CHANGES.md +0 -1
  37. package/docs/COMPONENTS_CATALOG.md +1 -4
  38. package/docs/COMPONENT_PATTERNS.md +325 -0
  39. package/docs/GETTING_STARTED.md +52 -28
  40. package/docs/api/README.md +0 -2
  41. package/docs/api/variables/ModalGlass.md +5 -4
  42. package/package.json +1 -1
  43. package/dist/trust-score-card-glass-2rjz00d_.cjs.map +0 -1
  44. package/dist/trust-score-card-glass-zjkx4OC2.js.map +0 -1
package/README.md CHANGED
@@ -6,7 +6,7 @@
6
6
  [![Bundle Size](https://img.shields.io/bundlephobia/minzip/shadcn-glass-ui?cacheSeconds=86400)](https://bundlephobia.com/package/shadcn-glass-ui)
7
7
  [![AI-Friendly](https://img.shields.io/badge/AI-Optimized-blueviolet)](docs/AI_USAGE.md)
8
8
 
9
- **Glassmorphism components for React** — drop-in compatible with shadcn/ui. 57 components, 3 themes,
9
+ **Glassmorphism components for React** — drop-in compatible with shadcn/ui. 59 components, 3 themes,
10
10
  zero migration.
11
11
 
12
12
  <div align="center">
@@ -74,7 +74,7 @@ npx shadcn@latest add @shadcn-glass-ui/button-glass
74
74
  | ----------------- | ------------------------------- | ------------ |
75
75
  | **Themes** | 3 built-in (Glass/Light/Aurora) | 1 base |
76
76
  | **Glass effects** | Native blur, glow, transparency | Manual CSS |
77
- | **Components** | 57 specialized | ~40 base |
77
+ | **Components** | 59 specialized | ~40 base |
78
78
  | **Custom theme** | 15 lines CSS | Full rewrite |
79
79
  | **AI docs** | Context7, Claude Code, Copilot | Basic |
80
80
 
@@ -94,14 +94,13 @@ import { ButtonGlass } from '@/components/glass/ui/button-glass'; // Glass vari
94
94
 
95
95
  | Category | Count | Examples |
96
96
  | --------------- | ----- | -------------------------------------------------- |
97
- | **Core UI** | 19 | ButtonGlass, InputGlass, ModalGlass, SidebarGlass |
97
+ | **Core UI** | 22 | ButtonGlass, InputGlass, ModalGlass, SidebarGlass |
98
98
  | **Composite** | 14 | MetricCardGlass, SplitLayoutGlass, AICardGlass |
99
- | **Specialized** | 10 | StepperGlass, SparklineGlass, RainbowProgressGlass |
99
+ | **Specialized** | 9 | StepperGlass, SparklineGlass, RainbowProgressGlass |
100
100
  | **Sections** | 7 | HeaderNavGlass, ProfileHeaderGlass |
101
101
  | **Atomic** | 7 | SearchBoxGlass, ThemeToggleGlass |
102
- | **Primitives** | 3 | TouchTarget, FormFieldWrapper |
103
102
 
104
- [**Browse all 58 components →**](https://yhooi2.github.io/shadcn-glass-ui-library/)
103
+ [**Browse all 59 components →**](https://yhooi2.github.io/shadcn-glass-ui-library/)
105
104
 
106
105
  ---
107
106
 
package/context7.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://context7.com/schema/context7.json",
3
3
  "projectTitle": "shadcn-glass-ui",
4
- "description": "Glassmorphism UI library for React - AI-friendly with 57 components, strict TypeScript, and comprehensive docs",
4
+ "description": "Glassmorphism UI library for React - AI-friendly with 59 components, strict TypeScript, and comprehensive docs",
5
5
  "branch": "main",
6
6
  "folders": ["docs"],
7
7
  "includeFiles": ["README.md", "CLAUDE.md", "CHANGELOG.md"],
@@ -13,7 +13,7 @@
13
13
  "Always wrap components with ThemeProvider from 'shadcn-glass-ui'",
14
14
  "Import CSS: '@import \"shadcn-glass-ui/styles.css\"' in main CSS file",
15
15
  "Use TypeScript strict mode - no 'any' types allowed",
16
- "ModalGlass and TabsGlass use compound component API (e.g., ModalGlass.Root, ModalGlass.Content)",
16
+ "ModalGlass and TabsGlass use compound component API (e.g., ModalGlass.Root, ModalGlass.Content) - ModalGlass.Content automatically includes Overlay, do NOT add <ModalGlass.Overlay /> separately",
17
17
  "Three themes available: 'glass' (dark), 'light', 'aurora' (gradient)",
18
18
  "WCAG 2.1 AA accessibility compliance required",
19
19
  "Use asChild prop on ButtonGlass for polymorphic rendering: <ButtonGlass asChild><Link href='/'>Home</Link></ButtonGlass>",
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- const require_trust_score_card_glass = require("../trust-score-card-glass-2rjz00d_.cjs");
2
+ const require_trust_score_card_glass = require("../trust-score-card-glass-DTS1RdIt.cjs");
3
3
  let node_util = require("node:util");
4
4
  let node_fs = require("node:fs");
5
5
  let node_path = require("node:path");
@@ -1,7 +1,7 @@
1
- const require_trust_score_card_glass = require("./trust-score-card-glass-2rjz00d_.cjs");
2
- require("./utils-XlyXIhuP.cjs");
3
- require("./use-focus-DbpBEuee.cjs");
4
- require("./theme-context-Y98bGvcm.cjs");
1
+ const require_trust_score_card_glass = require("./trust-score-card-glass-DTS1RdIt.cjs");
2
+ require("./utils-NLnOCttr.cjs");
3
+ require("./use-focus-CdoUzFQ8.cjs");
4
+ require("./theme-context-BEA8K_rq.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;
@@ -2,7 +2,7 @@ import * as AvatarPrimitive from '@radix-ui/react-avatar';
2
2
  import { ButtonHTMLAttributes } from 'react';
3
3
  import { ClassProp } from 'class-variance-authority/types';
4
4
  import { ComponentPropsWithoutRef } from 'react';
5
- import { default as default_2 } from 'react';
5
+ import * as DialogPrimitive from '@radix-ui/react-dialog';
6
6
  import { FC } from 'react';
7
7
  import { ForwardRefExoticComponent } from 'react';
8
8
  import { HTMLAttributes } from 'react';
@@ -1128,177 +1128,112 @@ declare interface MetricTrend {
1128
1128
  */
1129
1129
  declare type MetricVariant = 'default' | 'secondary' | 'success' | 'warning' | 'destructive';
1130
1130
 
1131
- declare interface ModalBodyProps {
1132
- children: ReactNode;
1133
- className?: string;
1134
- }
1135
-
1136
- declare interface ModalCloseProps {
1137
- className?: string;
1138
- }
1139
-
1140
- declare interface ModalContentProps {
1141
- children: ReactNode;
1142
- className?: string;
1143
- }
1144
-
1145
- declare interface ModalDescriptionProps {
1146
- children: ReactNode;
1147
- className?: string;
1148
- }
1149
-
1150
- declare interface ModalFooterProps {
1151
- children: ReactNode;
1152
- className?: string;
1153
- }
1131
+ /**
1132
+ * ModalGlass.Body - Main content area
1133
+ *
1134
+ * Note: shadcn/ui Dialog doesn't have DialogBody, but we keep it for convenience.
1135
+ */
1136
+ declare function ModalBody({ className, ...props }: React_2.ComponentProps<'div'>): JSX.Element;
1154
1137
 
1155
1138
  /**
1156
- * ModalGlass - Compound Component API
1139
+ * ModalGlass.Close - Closes the modal when clicked
1140
+ *
1141
+ * Use `asChild` to render as the child element.
1157
1142
  *
1158
1143
  * @example
1159
1144
  * ```tsx
1160
- * <ModalGlass.Root open={open} onOpenChange={setOpen}>
1161
- * <ModalGlass.Overlay />
1162
- * <ModalGlass.Content>
1163
- * <ModalGlass.Header>
1164
- * <ModalGlass.Title>Confirm</ModalGlass.Title>
1165
- * <ModalGlass.Description>Are you sure?</ModalGlass.Description>
1166
- * <ModalGlass.Close />
1167
- * </ModalGlass.Header>
1168
- * <ModalGlass.Body>
1169
- * <p>Body content</p>
1170
- * </ModalGlass.Body>
1171
- * <ModalGlass.Footer>
1172
- * <ButtonGlass>Cancel</ButtonGlass>
1173
- * </ModalGlass.Footer>
1174
- * </ModalGlass.Content>
1175
- * </ModalGlass.Root>
1145
+ * <ModalGlass.Close asChild>
1146
+ * <ButtonGlass variant="ghost">Cancel</ButtonGlass>
1147
+ * </ModalGlass.Close>
1176
1148
  * ```
1177
1149
  */
1178
- export declare const ModalGlass: {
1179
- Root: default_2.FC<ModalRootProps>;
1180
- Overlay: default_2.FC<ModalOverlayProps>;
1181
- Content: default_2.ForwardRefExoticComponent<ModalContentProps & default_2.RefAttributes<HTMLDivElement>>;
1182
- Header: default_2.FC<ModalHeaderProps>;
1183
- Body: default_2.FC<ModalBodyProps>;
1184
- Footer: default_2.FC<ModalFooterProps>;
1185
- Title: default_2.FC<ModalTitleProps>;
1186
- Description: default_2.FC<ModalDescriptionProps>;
1187
- Close: default_2.FC<ModalCloseProps>;
1188
- };
1150
+ declare function ModalClose({ ...props }: React_2.ComponentProps<typeof DialogPrimitive.Close>): JSX.Element;
1189
1151
 
1190
- declare interface ModalHeaderProps {
1191
- children: ReactNode;
1192
- className?: string;
1152
+ declare interface ModalContentProps extends React_2.ComponentPropsWithoutRef<typeof DialogPrimitive.Content> {
1153
+ /** Show close button in top-right corner */
1154
+ showCloseButton?: boolean;
1155
+ /** Override size from Root */
1156
+ size?: ModalSize;
1193
1157
  }
1194
1158
 
1195
- declare interface ModalOverlayProps {
1196
- className?: string;
1197
- }
1159
+ /**
1160
+ * ModalGlass.Footer - Footer section with flex layout for actions
1161
+ */
1162
+ declare function ModalFooter({ className, ...props }: React_2.ComponentProps<'div'>): JSX.Element;
1198
1163
 
1199
1164
  /**
1200
- * Props for ModalGlass.Root component
1165
+ * ModalGlass - Glass-themed Dialog with shadcn/ui API compatibility
1201
1166
  *
1202
- * Root component that provides context and manages open/close state for the modal.
1203
- * Handles keyboard events, body scroll lock, and accessibility attributes.
1204
- *
1205
- * @accessibility
1206
- * - **Keyboard Navigation:** Escape key closes modal, Tab key traps focus within modal content
1207
- * - **Focus Management:** Focus automatically moved to modal on open, returned to trigger on close (WCAG 2.4.3)
1208
- * - **Screen Readers:** Uses `role="dialog"` and `aria-modal="true"` for proper modal semantics (WCAG 4.1.3)
1209
- * - **Title Association:** Modal title automatically linked via `aria-labelledby="modal-title"`
1210
- * - **Description Association:** Optional description linked via `aria-describedby="modal-description"`
1211
- * - **Body Scroll Lock:** Prevents background scrolling when modal is open (improves UX and focus management)
1212
- * - **Touch Targets:** All interactive elements (close button, action buttons) meet 44x44px minimum (WCAG 2.5.5)
1213
- * - **Color Contrast:** Modal content and overlay meet WCAG AA contrast requirements
1214
- * - **Motion:** Open/close animations respect `prefers-reduced-motion` settings
1167
+ * Built on @radix-ui/react-dialog for full accessibility support.
1215
1168
  *
1216
- * @example
1169
+ * @example Uncontrolled (with Trigger)
1217
1170
  * ```tsx
1218
- * // Basic modal with title and description
1219
- * <ModalGlass.Root open={open} onOpenChange={setOpen}>
1220
- * <ModalGlass.Overlay />
1171
+ * <ModalGlass.Root>
1172
+ * <ModalGlass.Trigger asChild>
1173
+ * <ButtonGlass>Open</ButtonGlass>
1174
+ * </ModalGlass.Trigger>
1221
1175
  * <ModalGlass.Content>
1222
1176
  * <ModalGlass.Header>
1223
- * <ModalGlass.Title>Confirm Action</ModalGlass.Title>
1224
- * <ModalGlass.Description>
1225
- * This action cannot be undone.
1226
- * </ModalGlass.Description>
1227
- * <ModalGlass.Close />
1177
+ * <ModalGlass.Title>Title</ModalGlass.Title>
1228
1178
  * </ModalGlass.Header>
1229
- * <ModalGlass.Body>
1230
- * <p>Are you sure you want to proceed?</p>
1231
- * </ModalGlass.Body>
1179
+ * <ModalGlass.Body>Content</ModalGlass.Body>
1232
1180
  * <ModalGlass.Footer>
1233
- * <ButtonGlass variant="ghost" onClick={() => setOpen(false)}>
1234
- * Cancel
1235
- * </ButtonGlass>
1236
- * <ButtonGlass variant="destructive" onClick={handleConfirm}>
1237
- * Confirm
1238
- * </ButtonGlass>
1181
+ * <ModalGlass.Close asChild>
1182
+ * <ButtonGlass>Close</ButtonGlass>
1183
+ * </ModalGlass.Close>
1239
1184
  * </ModalGlass.Footer>
1240
1185
  * </ModalGlass.Content>
1241
1186
  * </ModalGlass.Root>
1187
+ * ```
1242
1188
  *
1243
- * // Different sizes
1244
- * <ModalGlass.Root open={open} onOpenChange={setOpen} size="sm">
1245
- * {// Small modal content}
1246
- * </ModalGlass.Root>
1247
- * <ModalGlass.Root open={open} onOpenChange={setOpen} size="lg">
1248
- * {// Large modal content}
1249
- * </ModalGlass.Root>
1250
- *
1251
- * // Form modal with proper focus management
1189
+ * @example Controlled
1190
+ * ```tsx
1252
1191
  * <ModalGlass.Root open={open} onOpenChange={setOpen}>
1253
- * <ModalGlass.Overlay />
1254
- * <ModalGlass.Content>
1192
+ * <ModalGlass.Content showCloseButton={false}>
1255
1193
  * <ModalGlass.Header>
1256
- * <ModalGlass.Title>Create Account</ModalGlass.Title>
1257
- * <ModalGlass.Close />
1258
- * </ModalGlass.Header>
1259
- * <ModalGlass.Body>
1260
- * <form id="signup-form" onSubmit={handleSubmit}>
1261
- * <InputGlass label="Email" type="email" required />
1262
- * <InputGlass label="Password" type="password" required />
1263
- * </form>
1264
- * </ModalGlass.Body>
1265
- * <ModalGlass.Footer>
1266
- * <ButtonGlass variant="ghost" onClick={() => setOpen(false)}>
1267
- * Cancel
1268
- * </ButtonGlass>
1269
- * <ButtonGlass type="submit" form="signup-form">
1270
- * Sign Up
1271
- * </ButtonGlass>
1272
- * </ModalGlass.Footer>
1273
- * </ModalGlass.Content>
1274
- * </ModalGlass.Root>
1275
- *
1276
- * // Alert modal (no close button)
1277
- * <ModalGlass.Root open={showAlert} onOpenChange={setShowAlert}>
1278
- * <ModalGlass.Overlay />
1279
- * <ModalGlass.Content>
1280
- * <ModalGlass.Header>
1281
- * <ModalGlass.Title>Session Expired</ModalGlass.Title>
1194
+ * <ModalGlass.Title>Confirm</ModalGlass.Title>
1282
1195
  * </ModalGlass.Header>
1283
- * <ModalGlass.Body>
1284
- * Your session has expired. Please log in again.
1285
- * </ModalGlass.Body>
1286
1196
  * <ModalGlass.Footer>
1287
- * <ButtonGlass onClick={handleLogin}>Log In</ButtonGlass>
1197
+ * <ButtonGlass onClick={() => setOpen(false)}>OK</ButtonGlass>
1288
1198
  * </ModalGlass.Footer>
1289
1199
  * </ModalGlass.Content>
1290
1200
  * </ModalGlass.Root>
1291
1201
  * ```
1292
1202
  */
1293
- declare interface ModalRootProps extends default_2.HTMLAttributes<HTMLDivElement> {
1294
- /** Open state */
1295
- open: boolean;
1296
- /** Callback when open state changes */
1297
- onOpenChange?: (open: boolean) => void;
1298
- /** Size variant */
1203
+ export declare const ModalGlass: {
1204
+ Root: typeof ModalRoot;
1205
+ Trigger: typeof ModalTrigger;
1206
+ Portal: typeof ModalPortal;
1207
+ Overlay: React_2.ForwardRefExoticComponent<Omit<DialogPrimitive.DialogOverlayProps & React_2.RefAttributes<HTMLDivElement>, "ref"> & React_2.RefAttributes<HTMLDivElement>>;
1208
+ Content: React_2.ForwardRefExoticComponent<ModalContentProps & React_2.RefAttributes<HTMLDivElement>>;
1209
+ Header: typeof ModalHeader;
1210
+ Body: typeof ModalBody;
1211
+ Footer: typeof ModalFooter;
1212
+ Title: React_2.ForwardRefExoticComponent<Omit<DialogPrimitive.DialogTitleProps & React_2.RefAttributes<HTMLHeadingElement>, "ref"> & React_2.RefAttributes<HTMLHeadingElement>>;
1213
+ Description: React_2.ForwardRefExoticComponent<Omit<DialogPrimitive.DialogDescriptionProps & React_2.RefAttributes<HTMLParagraphElement>, "ref"> & React_2.RefAttributes<HTMLParagraphElement>>;
1214
+ Close: typeof ModalClose;
1215
+ };
1216
+
1217
+ /**
1218
+ * ModalGlass.Header - Header section with flex layout
1219
+ */
1220
+ declare function ModalHeader({ className, ...props }: React_2.ComponentProps<'div'>): JSX.Element;
1221
+
1222
+ /**
1223
+ * ModalGlass.Portal - Renders children into a portal
1224
+ */
1225
+ declare function ModalPortal({ ...props }: React_2.ComponentProps<typeof DialogPrimitive.Portal>): JSX.Element;
1226
+
1227
+ /**
1228
+ * ModalGlass.Root - Dialog root component
1229
+ *
1230
+ * Supports both controlled (open/onOpenChange) and uncontrolled (with Trigger) modes.
1231
+ */
1232
+ declare function ModalRoot({ size, children, ...props }: ModalRootProps): JSX.Element;
1233
+
1234
+ declare interface ModalRootProps extends React_2.ComponentProps<typeof DialogPrimitive.Root> {
1235
+ /** Size variant for the modal */
1299
1236
  size?: ModalSize;
1300
- /** Child components */
1301
- children: ReactNode;
1302
1237
  }
1303
1238
 
1304
1239
  /**
@@ -1307,10 +1242,12 @@ declare interface ModalRootProps extends default_2.HTMLAttributes<HTMLDivElement
1307
1242
  */
1308
1243
  declare type ModalSize = 'sm' | 'md' | 'lg' | 'xl' | 'full';
1309
1244
 
1310
- declare interface ModalTitleProps {
1311
- children: ReactNode;
1312
- className?: string;
1313
- }
1245
+ /**
1246
+ * ModalGlass.Trigger - Opens the modal when clicked
1247
+ *
1248
+ * Use `asChild` to render as the child element instead of a button.
1249
+ */
1250
+ declare function ModalTrigger({ ...props }: React_2.ComponentProps<typeof DialogPrimitive.Trigger>): JSX.Element;
1314
1251
 
1315
1252
  export declare const NotificationGlass: ForwardRefExoticComponent<NotificationGlassProps & RefAttributes<HTMLDivElement>>;
1316
1253
 
@@ -1820,7 +1757,13 @@ declare const toggleSizes: (props?: ({
1820
1757
  variant?: "default" | "outline" | null | undefined;
1821
1758
  } & ClassProp) | undefined) => string;
1822
1759
 
1823
- export declare const TooltipGlass: React_2.FC<TooltipPrimitive.TooltipProps>;
1760
+ export declare const TooltipGlass: typeof TooltipGlassRoot;
1761
+
1762
+ /**
1763
+ * TooltipGlassRoot - Individual tooltip instance
1764
+ * Wraps Radix TooltipPrimitive.Root with auto-included Provider (shadcn/ui pattern)
1765
+ */
1766
+ declare function TooltipGlassRoot({ ...props }: React_2.ComponentPropsWithoutRef<typeof TooltipPrimitive.Root>): JSX.Element;
1824
1767
 
1825
1768
  /**
1826
1769
  * TouchTarget wrapper component
@@ -1,4 +1,4 @@
1
- import { $ as BaseProgressGlass, Dt as NotificationGlass, G as SegmentedControlGlass, K as RainbowProgressGlass, Mt as GlassCard, Pt as DropdownGlass, Q as StatusIndicatorGlass, St as PopoverGlass, X as LanguageBarGlass, Xt as ComboBoxGlass, Y as ProfileAvatarGlass, Z as FlagAlertGlass, _ as ContributionMetricsGlass, _t as SliderGlass, a as HeaderBrandingGlass, an as ButtonGlass, b as AICardGlass, bn as TouchTarget, bt as SkeletonGlass, c as YearCardGlass, ct as ExpandableHeaderGlass, d as TrustScoreDisplayGlass, et as ThemeToggleGlass, f as RepositoryMetadataGlass, g as MetricCardGlass, gt as TabsGlass, h as MetricsGridGlass, hn as AlertGlass, i as HeaderNavGlass, in as CheckboxGlass, jt as InputGlass, kt as ModalGlass, l as UserStatsLineGlass, ln as AvatarGlass, lt as TooltipGlass, m as RepositoryCardGlass, mt as ToggleGlass, n as ProjectsListGlass, nt as SortDropdownGlass, o as FlagsSectionGlass, p as RepositoryHeaderGlass, q as ProgressGlass, r as ProfileHeaderGlass, rn as CircularProgressGlass, rt as SearchBoxGlass, s as CareerStatsGlass, sn as BadgeGlass, st as IconButtonGlass, t as TrustScoreCardGlass, tt as StatItemGlass, u as UserInfoGlass, v as CircularMetricGlass, vn as InteractiveCard, y as CareerStatsHeaderGlass, yn as FormFieldWrapper } from "./trust-score-card-glass-zjkx4OC2.js";
1
+ import { $ as BaseProgressGlass, Dt as NotificationGlass, G as SegmentedControlGlass, K as RainbowProgressGlass, Mt as GlassCard, Pt as DropdownGlass, Q as StatusIndicatorGlass, St as PopoverGlass, X as LanguageBarGlass, Xt as ComboBoxGlass, Y as ProfileAvatarGlass, Z as FlagAlertGlass, _ as ContributionMetricsGlass, _t as SliderGlass, a as HeaderBrandingGlass, an as ButtonGlass, b as AICardGlass, bn as TouchTarget, bt as SkeletonGlass, c as YearCardGlass, ct as ExpandableHeaderGlass, d as TrustScoreDisplayGlass, et as ThemeToggleGlass, f as RepositoryMetadataGlass, g as MetricCardGlass, gt as TabsGlass, h as MetricsGridGlass, hn as AlertGlass, i as HeaderNavGlass, in as CheckboxGlass, jt as InputGlass, kt as ModalGlass, l as UserStatsLineGlass, ln as AvatarGlass, lt as TooltipGlass, m as RepositoryCardGlass, mt as ToggleGlass, n as ProjectsListGlass, nt as SortDropdownGlass, o as FlagsSectionGlass, p as RepositoryHeaderGlass, q as ProgressGlass, r as ProfileHeaderGlass, rn as CircularProgressGlass, rt as SearchBoxGlass, s as CareerStatsGlass, sn as BadgeGlass, st as IconButtonGlass, t as TrustScoreCardGlass, tt as StatItemGlass, u as UserInfoGlass, v as CircularMetricGlass, vn as InteractiveCard, y as CareerStatsHeaderGlass, yn as FormFieldWrapper } from "./trust-score-card-glass-Dg4_b_g_.js";
2
2
  import "./utils-CcyeqpKQ.js";
3
3
  import "./use-focus-CX0TJJIj.js";
4
4
  import "./theme-context-_T5r1KG4.js";
package/dist/hooks.cjs CHANGED
@@ -1,5 +1,5 @@
1
- const require_use_focus = require("./use-focus-DbpBEuee.cjs");
2
- const require_use_wallpaper_tint = require("./use-wallpaper-tint-DbawS9zh.cjs");
1
+ const require_use_focus = require("./use-focus-CdoUzFQ8.cjs");
2
+ const require_use_wallpaper_tint = require("./use-wallpaper-tint-Rq5UgY9L.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-2rjz00d_.cjs");
2
- const require_utils = require("./utils-XlyXIhuP.cjs");
3
- const require_use_focus = require("./use-focus-DbpBEuee.cjs");
4
- const require_theme_context = require("./theme-context-Y98bGvcm.cjs");
5
- const require_use_wallpaper_tint = require("./use-wallpaper-tint-DbawS9zh.cjs");
1
+ const require_trust_score_card_glass = require("./trust-score-card-glass-DTS1RdIt.cjs");
2
+ const require_utils = require("./utils-NLnOCttr.cjs");
3
+ const require_use_focus = require("./use-focus-CdoUzFQ8.cjs");
4
+ const require_theme_context = require("./theme-context-BEA8K_rq.cjs");
5
+ const require_use_wallpaper_tint = require("./use-wallpaper-tint-Rq5UgY9L.cjs");
6
6
  let react = require("react");
7
7
  react = require_trust_score_card_glass.__toESM(react);
8
8
  let lucide_react = require("lucide-react");
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { $ as BaseProgressGlass, $t as useLayoutEffect2, A as useChartHeight, At as modalSizes, B as adaptEventsOfChild, Bt as DropdownMenuGlassLabel, C as sparklineContainerVariants, Ct as PopoverGlassAnchor, D as Tooltip, Dt as NotificationGlass, E as Cell, Et as PopoverGlassTrigger, F as selectLegendPayload, Ft as DropdownMenuGlass, G as SegmentedControlGlass, Gt as DropdownMenuGlassShortcut, H as isNumber, Ht as DropdownMenuGlassRadioGroup, I as useAppDispatch, It as DropdownMenuGlassCheckboxItem, J as progressSizes, Jt as DropdownMenuGlassSubTrigger, K as RainbowProgressGlass, Kt as DropdownMenuGlassSub, L as useAppSelector, Lt as DropdownMenuGlassContent, M as useMargin, Mt as GlassCard, N as ResponsiveContainer, Nt as cardIntensity, O as setLegendSettings, Ot as notificationVariants, P as useElementOffset, Pt as DropdownGlass, Q as StatusIndicatorGlass, Qt as Presence, R as getUniqPayload, Rt as DropdownMenuGlassGroup, S as sparklineBarVariants, St as PopoverGlass, T as Bar, Tt as PopoverGlassLegacy, U as useLegendPortal, Ut as DropdownMenuGlassRadioItem, V as Symbols, Vt as DropdownMenuGlassPortal, W as Surface, Wt as DropdownMenuGlassSeparator, X as LanguageBarGlass, Xt as ComboBoxGlass, Y as ProfileAvatarGlass, Yt as DropdownMenuGlassTrigger, Z as FlagAlertGlass, Zt as inputVariants, _ as ContributionMetricsGlass, _n as AlertGlassTitle, _t as SliderGlass, a as HeaderBrandingGlass, an as ButtonGlass, at as insightCardVariants, b as AICardGlass, bn as TouchTarget, bt as SkeletonGlass, c as YearCardGlass, cn as badgeVariants, ct as ExpandableHeaderGlass, d as TrustScoreDisplayGlass, dn as AvatarGlassImage, dt as TooltipGlassProvider, en as useCallbackRef, et as ThemeToggleGlass, f as RepositoryMetadataGlass, fn as AvatarGlassSimple, ft as TooltipGlassSimple, g as MetricCardGlass, gn as AlertGlassDescription, gt as TabsGlass, h as MetricsGridGlass, hn as AlertGlass, ht as toggleSizes, i as HeaderNavGlass, in as CheckboxGlass, it as InsightCardGlass, j as useChartWidth, jt as InputGlass, k as setLegendSize, kt as ModalGlass, l as UserStatsLineGlass, ln as AvatarGlass, lt as TooltipGlass, m as RepositoryCardGlass, mn as statusSizes, mt as ToggleGlass, n as ProjectsListGlass, nn as composeEventHandlers, nt as SortDropdownGlass, o as FlagsSectionGlass, on as buttonGlassVariants, ot as insightVariantConfig, p as RepositoryHeaderGlass, pn as avatarSizes, pt as TooltipGlassTrigger, q as ProgressGlass, qt as DropdownMenuGlassSubContent, r as ProfileHeaderGlass, rn as CircularProgressGlass, rt as SearchBoxGlass, s as CareerStatsGlass, sn as BadgeGlass, st as IconButtonGlass, t as TrustScoreCardGlass, tn as useComposedRefs, tt as StatItemGlass, u as UserInfoGlass, un as AvatarGlassFallback, ut as TooltipGlassContent, v as CircularMetricGlass, vn as InteractiveCard, vt as useDirection, w as BarChart, wt as PopoverGlassContent, x as SparklineGlass, xn as alertVariants, xt as skeletonVariants, y as CareerStatsHeaderGlass, yn as FormFieldWrapper, yt as clamp, z as resolveDefaultProps, zt as DropdownMenuGlassItem } from "./trust-score-card-glass-zjkx4OC2.js";
1
+ import { $ as BaseProgressGlass, $t as useLayoutEffect2, A as useChartHeight, At as modalSizes, B as adaptEventsOfChild, Bt as DropdownMenuGlassLabel, C as sparklineContainerVariants, Ct as PopoverGlassAnchor, D as Tooltip, Dt as NotificationGlass, E as Cell, Et as PopoverGlassTrigger, F as selectLegendPayload, Ft as DropdownMenuGlass, G as SegmentedControlGlass, Gt as DropdownMenuGlassShortcut, H as isNumber, Ht as DropdownMenuGlassRadioGroup, I as useAppDispatch, It as DropdownMenuGlassCheckboxItem, J as progressSizes, Jt as DropdownMenuGlassSubTrigger, K as RainbowProgressGlass, Kt as DropdownMenuGlassSub, L as useAppSelector, Lt as DropdownMenuGlassContent, M as useMargin, Mt as GlassCard, N as ResponsiveContainer, Nt as cardIntensity, O as setLegendSettings, Ot as notificationVariants, P as useElementOffset, Pt as DropdownGlass, Q as StatusIndicatorGlass, Qt as Presence, R as getUniqPayload, Rt as DropdownMenuGlassGroup, S as sparklineBarVariants, St as PopoverGlass, T as Bar, Tt as PopoverGlassLegacy, U as useLegendPortal, Ut as DropdownMenuGlassRadioItem, V as Symbols, Vt as DropdownMenuGlassPortal, W as Surface, Wt as DropdownMenuGlassSeparator, X as LanguageBarGlass, Xt as ComboBoxGlass, Y as ProfileAvatarGlass, Yt as DropdownMenuGlassTrigger, Z as FlagAlertGlass, Zt as inputVariants, _ as ContributionMetricsGlass, _n as AlertGlassTitle, _t as SliderGlass, a as HeaderBrandingGlass, an as ButtonGlass, at as insightCardVariants, b as AICardGlass, bn as TouchTarget, bt as SkeletonGlass, c as YearCardGlass, cn as badgeVariants, ct as ExpandableHeaderGlass, d as TrustScoreDisplayGlass, dn as AvatarGlassImage, dt as TooltipGlassProvider, en as useCallbackRef, et as ThemeToggleGlass, f as RepositoryMetadataGlass, fn as AvatarGlassSimple, ft as TooltipGlassSimple, g as MetricCardGlass, gn as AlertGlassDescription, gt as TabsGlass, h as MetricsGridGlass, hn as AlertGlass, ht as toggleSizes, i as HeaderNavGlass, in as CheckboxGlass, it as InsightCardGlass, j as useChartWidth, jt as InputGlass, k as setLegendSize, kt as ModalGlass, l as UserStatsLineGlass, ln as AvatarGlass, lt as TooltipGlass, m as RepositoryCardGlass, mn as statusSizes, mt as ToggleGlass, n as ProjectsListGlass, nn as composeEventHandlers, nt as SortDropdownGlass, o as FlagsSectionGlass, on as buttonGlassVariants, ot as insightVariantConfig, p as RepositoryHeaderGlass, pn as avatarSizes, pt as TooltipGlassTrigger, q as ProgressGlass, qt as DropdownMenuGlassSubContent, r as ProfileHeaderGlass, rn as CircularProgressGlass, rt as SearchBoxGlass, s as CareerStatsGlass, sn as BadgeGlass, st as IconButtonGlass, t as TrustScoreCardGlass, tn as useComposedRefs, tt as StatItemGlass, u as UserInfoGlass, un as AvatarGlassFallback, ut as TooltipGlassContent, v as CircularMetricGlass, vn as InteractiveCard, vt as useDirection, w as BarChart, wt as PopoverGlassContent, x as SparklineGlass, xn as alertVariants, xt as skeletonVariants, y as CareerStatsHeaderGlass, yn as FormFieldWrapper, yt as clamp, z as resolveDefaultProps, zt as DropdownMenuGlassItem } from "./trust-score-card-glass-Dg4_b_g_.js";
2
2
  import { t as cn } from "./utils-CcyeqpKQ.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-_T5r1KG4.js";
@@ -18,7 +18,7 @@
18
18
  {
19
19
  "path": "components/glass/ui/alert-glass.tsx",
20
20
  "type": "registry:component",
21
- "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 * - Compound component API for flexible composition\n * - Dismissible option\n * - Backdrop blur effect\n *\n * @example Compound API (recommended)\n * ```tsx\n * <AlertGlass variant=\"default\">\n * <AlertGlassTitle>Heads up!</AlertGlassTitle>\n * <AlertGlassDescription>\n * You can add components to your app using the cli.\n * </AlertGlassDescription>\n * </AlertGlass>\n * ```\n *\n * @example With dismiss button\n * ```tsx\n * <AlertGlass variant=\"destructive\" dismissible onDismiss={() => setShow(false)}>\n * <AlertGlassTitle>Error</AlertGlassTitle>\n * <AlertGlassDescription>\n * Your session has expired.\n * </AlertGlassDescription>\n * </AlertGlass>\n * ```\n */\n\n'use client';\n\nimport { forwardRef, type CSSProperties } from 'react';\nimport { type VariantProps } from 'class-variance-authority';\nimport { Info, CheckCircle, AlertTriangle, AlertCircle, X } 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 color: config.text,\n };\n};\n\n// ========================================\n// COMPOUND COMPONENT: ROOT\n// ========================================\n\nexport interface AlertGlassProps\n extends Omit<React.HTMLAttributes<HTMLDivElement>, 'style'>, VariantProps<typeof alertVariants> {\n dismissible?: boolean;\n onDismiss?: () => void;\n}\n\nconst AlertGlassRoot = forwardRef<HTMLDivElement, AlertGlassProps>(\n ({ className, variant = 'default', dismissible, onDismiss, children, ...props }, ref) => {\n const effectiveVariant: AlertVariant = variant ?? 'default';\n const Icon = iconMap[effectiveVariant];\n const config = variantStyles[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 shrink-0 mt-0.5\"\n style={{ color: config.text }}\n aria-hidden=\"true\"\n />\n <div className=\"flex-1\">{children}</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 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\nAlertGlassRoot.displayName = 'AlertGlass';\n\n// ========================================\n// COMPOUND COMPONENT: TITLE\n// ========================================\n\nexport type AlertGlassTitleProps = React.HTMLAttributes<HTMLParagraphElement>;\n\nconst AlertGlassTitle = forwardRef<HTMLParagraphElement, AlertGlassTitleProps>(\n ({ className, style, ...props }, ref) => {\n return (\n <p\n ref={ref}\n className={cn('font-medium text-xs md:text-sm mb-0.5 md:mb-1', className)}\n style={{ color: 'inherit', ...style }}\n {...props}\n />\n );\n }\n);\n\nAlertGlassTitle.displayName = 'AlertGlassTitle';\n\n// ========================================\n// COMPOUND COMPONENT: DESCRIPTION\n// ========================================\n\nexport type AlertGlassDescriptionProps = React.HTMLAttributes<HTMLParagraphElement>;\n\nconst AlertGlassDescription = forwardRef<HTMLParagraphElement, AlertGlassDescriptionProps>(\n ({ className, style, ...props }, ref) => {\n return (\n <p\n ref={ref}\n className={cn('text-xs md:text-sm opacity-80', className)}\n style={{ color: 'inherit', ...style }}\n {...props}\n />\n );\n }\n);\n\nAlertGlassDescription.displayName = 'AlertGlassDescription';\n\n// ========================================\n// EXPORTS\n// ========================================\n\n// Compound API (shadcn/ui pattern)\nexport const AlertGlass = AlertGlassRoot;\nexport { AlertGlassTitle, AlertGlassDescription };\n"
21
+ "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 * - Compound component API for flexible composition\n * - Dismissible option\n * - Backdrop blur effect\n *\n * @example Compound API (recommended)\n * ```tsx\n * <AlertGlass variant=\"default\">\n * <AlertGlassTitle>Heads up!</AlertGlassTitle>\n * <AlertGlassDescription>\n * You can add components to your app using the cli.\n * </AlertGlassDescription>\n * </AlertGlass>\n * ```\n *\n * @example With dismiss button\n * ```tsx\n * <AlertGlass variant=\"destructive\" dismissible onDismiss={() => setShow(false)}>\n * <AlertGlassTitle>Error</AlertGlassTitle>\n * <AlertGlassDescription>\n * Your session has expired.\n * </AlertGlassDescription>\n * </AlertGlass>\n * ```\n */\n\n'use client';\n\nimport { forwardRef, type CSSProperties } from 'react';\nimport { type VariantProps } from 'class-variance-authority';\nimport { Info, CheckCircle, AlertTriangle, AlertCircle, X } 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 color: config.text,\n };\n};\n\n// ========================================\n// COMPOUND COMPONENT: ROOT\n// ========================================\n\nexport interface AlertGlassProps\n extends Omit<React.HTMLAttributes<HTMLDivElement>, 'style'>, VariantProps<typeof alertVariants> {\n dismissible?: boolean;\n onDismiss?: () => void;\n}\n\nconst AlertGlassRoot = forwardRef<HTMLDivElement, AlertGlassProps>(\n ({ className, variant = 'default', dismissible, onDismiss, children, ...props }, ref) => {\n const effectiveVariant: AlertVariant = variant ?? 'default';\n const Icon = iconMap[effectiveVariant];\n const config = variantStyles[effectiveVariant];\n\n return (\n <div\n ref={ref}\n data-slot=\"alert\"\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 shrink-0 mt-0.5\"\n style={{ color: config.text }}\n aria-hidden=\"true\"\n />\n <div className=\"flex-1\">{children}</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 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\nAlertGlassRoot.displayName = 'AlertGlass';\n\n// ========================================\n// COMPOUND COMPONENT: TITLE\n// ========================================\n\nexport type AlertGlassTitleProps = React.HTMLAttributes<HTMLDivElement>;\n\nconst AlertGlassTitle = forwardRef<HTMLDivElement, AlertGlassTitleProps>(\n ({ className, style, ...props }, ref) => {\n return (\n <div\n ref={ref}\n data-slot=\"alert-title\"\n className={cn('font-medium text-xs md:text-sm mb-0.5 md:mb-1', className)}\n style={{ color: 'inherit', ...style }}\n {...props}\n />\n );\n }\n);\n\nAlertGlassTitle.displayName = 'AlertGlassTitle';\n\n// ========================================\n// COMPOUND COMPONENT: DESCRIPTION\n// ========================================\n\nexport type AlertGlassDescriptionProps = React.HTMLAttributes<HTMLDivElement>;\n\nconst AlertGlassDescription = forwardRef<HTMLDivElement, AlertGlassDescriptionProps>(\n ({ className, style, ...props }, ref) => {\n return (\n <div\n ref={ref}\n data-slot=\"alert-description\"\n className={cn('text-xs md:text-sm opacity-80', className)}\n style={{ color: 'inherit', ...style }}\n {...props}\n />\n );\n }\n);\n\nAlertGlassDescription.displayName = 'AlertGlassDescription';\n\n// ========================================\n// EXPORTS\n// ========================================\n\n// Compound API (shadcn/ui pattern)\nexport const AlertGlass = AlertGlassRoot;\nexport { AlertGlassTitle, AlertGlassDescription };\n"
22
22
  }
23
23
  ],
24
24
  "categories": [
@@ -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\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=\"default\">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'>, 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 ({ children, className, variant = 'default', size = 'md', dot, ...props }, ref) => {\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=\"default\">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'>, 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 ({ children, className, variant = 'default', size = 'md', dot, ...props }, ref) => {\n const v = variantStyles[variant];\n\n return (\n <span\n ref={ref}\n data-slot=\"badge\"\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": [
@@ -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 default: {\n background: isHovered ? 'var(--btn-primary-hover-bg)' : '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 : 'var(--btn-primary-shadow)',\n },\n secondary: {\n background: isHovered ? 'var(--btn-secondary-hover-bg)' : '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 ? 'var(--btn-ghost-hover-bg)' : '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 : 'var(--btn-destructive-shadow)',\n },\n outline: {\n background: isHovered ? 'var(--btn-outline-hover-bg)' : 'transparent',\n color: 'var(--btn-outline-text)',\n border: '1px solid var(--btn-outline-border)',\n boxShadow: isFocusVisible\n ? 'var(--focus-glow)'\n : isHovered\n ? 'var(--btn-outline-glow)'\n : 'none',\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 : 'var(--btn-success-shadow)',\n },\n link: {\n background: 'transparent',\n color: 'var(--btn-link-text)',\n border: 'none',\n boxShadow: isFocusVisible ? 'var(--focus-glow)' : 'none',\n textDecoration: isHovered ? 'underline' : '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 * **shadcn/ui compatible variants:**\n * - `default` - Primary action button with glow effects\n * - `secondary` - Secondary action with border\n * - `ghost` - Minimal visual presence\n * - `destructive` - Dangerous/delete actions (red)\n * - `outline` - Border with transparent background\n * - `link` - Text-only button with underline on hover\n * - `success` - Positive feedback (glass-ui extension)\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 (default variant)\n * <ButtonGlass>Click me</ButtonGlass>\n * <ButtonGlass variant=\"default\">Primary action</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 (shadcn/ui compatible)\n * <ButtonGlass variant=\"secondary\">Secondary</ButtonGlass>\n * <ButtonGlass variant=\"ghost\">Cancel</ButtonGlass>\n * <ButtonGlass variant=\"outline\">Outline</ButtonGlass>\n * <ButtonGlass variant=\"destructive\">Delete</ButtonGlass>\n * <ButtonGlass variant=\"link\">Learn more</ButtonGlass>\n * <ButtonGlass variant=\"success\">Confirm</ButtonGlass>\n *\n * // As a link (asChild pattern) - maintains semantic HTML\n * <ButtonGlass asChild>\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\">\n * Submit Form\n * </ButtonGlass>\n * ```\n */\nexport interface ButtonGlassProps\n extends\n 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 (shadcn/ui compatible)\n * @default \"default\"\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 (shadcn/ui compatible)\n * @default \"default\"\n */\n readonly size?: 'default' | 'sm' | 'lg' | 'xl' | 'icon';\n}\n\n// ========================================\n// COMPONENT\n// ========================================\n\nexport const ButtonGlass = forwardRef<HTMLButtonElement, ButtonGlassProps>(\n (\n {\n asChild = false,\n className,\n variant = 'default',\n size = 'default',\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 default variant */}\n {isHovered && variant === 'default' && !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 === 'default' && !isDisabled && (\n <div\n className=\"absolute inset-0 rounded-xl animate-glow-pulse pointer-events-none\"\n style={{\n background: 'var(--btn-glow-radial)',\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' && <Icon className={ICON_SIZES.md} />}\n\n {/* Content */}\n {!loading && children}\n\n {/* Icon right */}\n {!loading && Icon && iconPosition === 'right' && <Icon className={ICON_SIZES.md} />}\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 default: {\n background: isHovered ? 'var(--btn-primary-hover-bg)' : '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 : 'var(--btn-primary-shadow)',\n },\n secondary: {\n background: isHovered ? 'var(--btn-secondary-hover-bg)' : '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 ? 'var(--btn-ghost-hover-bg)' : '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 : 'var(--btn-destructive-shadow)',\n },\n outline: {\n background: isHovered ? 'var(--btn-outline-hover-bg)' : 'transparent',\n color: 'var(--btn-outline-text)',\n border: '1px solid var(--btn-outline-border)',\n boxShadow: isFocusVisible\n ? 'var(--focus-glow)'\n : isHovered\n ? 'var(--btn-outline-glow)'\n : 'none',\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 : 'var(--btn-success-shadow)',\n },\n link: {\n background: 'transparent',\n color: 'var(--btn-link-text)',\n border: 'none',\n boxShadow: isFocusVisible ? 'var(--focus-glow)' : 'none',\n textDecoration: isHovered ? 'underline' : '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 * **shadcn/ui compatible variants:**\n * - `default` - Primary action button with glow effects\n * - `secondary` - Secondary action with border\n * - `ghost` - Minimal visual presence\n * - `destructive` - Dangerous/delete actions (red)\n * - `outline` - Border with transparent background\n * - `link` - Text-only button with underline on hover\n * - `success` - Positive feedback (glass-ui extension)\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 (default variant)\n * <ButtonGlass>Click me</ButtonGlass>\n * <ButtonGlass variant=\"default\">Primary action</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 (shadcn/ui compatible)\n * <ButtonGlass variant=\"secondary\">Secondary</ButtonGlass>\n * <ButtonGlass variant=\"ghost\">Cancel</ButtonGlass>\n * <ButtonGlass variant=\"outline\">Outline</ButtonGlass>\n * <ButtonGlass variant=\"destructive\">Delete</ButtonGlass>\n * <ButtonGlass variant=\"link\">Learn more</ButtonGlass>\n * <ButtonGlass variant=\"success\">Confirm</ButtonGlass>\n *\n * // As a link (asChild pattern) - maintains semantic HTML\n * <ButtonGlass asChild>\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\">\n * Submit Form\n * </ButtonGlass>\n * ```\n */\nexport interface ButtonGlassProps\n extends\n 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 (shadcn/ui compatible)\n * @default \"default\"\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 (shadcn/ui compatible)\n * @default \"default\"\n */\n readonly size?: 'default' | 'sm' | 'lg' | 'xl' | 'icon';\n}\n\n// ========================================\n// COMPONENT\n// ========================================\n\nexport const ButtonGlass = forwardRef<HTMLButtonElement, ButtonGlassProps>(\n (\n {\n asChild = false,\n className,\n variant = 'default',\n size = 'default',\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 data-slot=\"button\"\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 default variant */}\n {isHovered && variant === 'default' && !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 === 'default' && !isDisabled && (\n <div\n className=\"absolute inset-0 rounded-xl animate-glow-pulse pointer-events-none\"\n style={{\n background: 'var(--btn-glow-radial)',\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' && <Icon className={ICON_SIZES.md} />}\n\n {/* Content */}\n {!loading && children}\n\n {/* Icon right */}\n {!loading && Icon && iconPosition === 'right' && <Icon className={ICON_SIZES.md} />}\n </>\n )}\n </Comp>\n );\n }\n);\n\nButtonGlass.displayName = 'ButtonGlass';\n"
24
24
  }
25
25
  ],
26
26
  "categories": [