{ "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "modal-glass", "type": "registry:ui", "title": "Modal Glass", "description": "ModalGlass Component (Radix UI Dialog-based)", "dependencies": [ "@radix-ui/react-dialog", "lucide-react", "react", "shadcn-glass-ui" ], "registryDependencies": [ "cn", "primitives", "variants" ], "files": [ { "path": "components/glass/ui/modal-glass.tsx", "type": "registry:component", "content": "/* eslint-disable react-refresh/only-export-components */\n/**\n * ModalGlass Component (Radix UI Dialog-based)\n *\n * Glass-themed modal/dialog with full shadcn/ui Dialog API compatibility.\n * Built on @radix-ui/react-dialog for accessibility and state management.\n *\n * @example Uncontrolled with Trigger (shadcn/ui pattern)\n * ```tsx\n * \n * \n * Open Dialog\n * \n * \n * \n * Dialog Title\n * Dialog description\n * \n * Content here\n * \n * \n * Cancel\n * \n * Confirm\n * \n * \n * \n * ```\n *\n * @example Controlled mode (programmatic)\n * ```tsx\n * \n * \n * \n * Confirm Action\n * \n * Are you sure?\n * \n * setOpen(false)}>Cancel\n * \n * \n * \n * ```\n *\n * @accessibility\n * - Built on Radix UI Dialog with full WCAG 2.1 AA compliance\n * - Keyboard: Escape to close, Tab for focus trap\n * - Screen Readers: role=\"dialog\", aria-modal, aria-labelledby, aria-describedby\n * - Focus Management: Auto-focus on open, return focus on close\n *\n * @since v2.0.0 - Migrated to Radix UI Dialog, added Trigger and Portal\n */\n\nimport * as React from 'react';\nimport * as DialogPrimitive from '@radix-ui/react-dialog';\nimport { X } from 'lucide-react';\nimport { cn } from '@/lib/utils';\nimport { modalSizes, type ModalSize } from '@/lib/variants/modal-glass-variants';\nimport { ICON_SIZES } from '@/components/glass/primitives';\nimport '@/glass-theme.css';\n\n// ========================================\n// CONTEXT FOR SIZE (optional enhancement)\n// ========================================\n\ninterface ModalContextValue {\n size: ModalSize;\n}\n\nconst ModalContext = React.createContext({ size: 'sm' });\n\nconst useModalContext = () => React.useContext(ModalContext);\n\n// ========================================\n// COMPOUND COMPONENT: ROOT\n// ========================================\n\ninterface ModalRootProps extends React.ComponentProps {\n /** Size variant for the modal */\n size?: ModalSize;\n}\n\n/**\n * ModalGlass.Root - Dialog root component\n *\n * Supports both controlled (open/onOpenChange) and uncontrolled (with Trigger) modes.\n */\nfunction ModalRoot({ size = 'sm', children, ...props }: ModalRootProps) {\n return (\n \n \n {children}\n \n \n );\n}\n\n// ========================================\n// COMPOUND COMPONENT: TRIGGER\n// ========================================\n\n/**\n * ModalGlass.Trigger - Opens the modal when clicked\n *\n * Use `asChild` to render as the child element instead of a button.\n */\nfunction ModalTrigger({ ...props }: React.ComponentProps) {\n return ;\n}\n\n// ========================================\n// COMPOUND COMPONENT: PORTAL\n// ========================================\n\n/**\n * ModalGlass.Portal - Renders children into a portal\n */\nfunction ModalPortal({ ...props }: React.ComponentProps) {\n return ;\n}\n\n// ========================================\n// COMPOUND COMPONENT: OVERLAY\n// ========================================\n\n/**\n * ModalGlass.Overlay - Backdrop with glass blur effect\n */\nconst ModalOverlay = React.forwardRef<\n React.ElementRef,\n React.ComponentPropsWithoutRef\n>(({ className, ...props }, ref) => (\n \n));\nModalOverlay.displayName = 'ModalOverlay';\n\n// ========================================\n// COMPOUND COMPONENT: CONTENT\n// ========================================\n\ninterface ModalContentProps extends React.ComponentPropsWithoutRef {\n /** Show close button in top-right corner */\n showCloseButton?: boolean;\n /** Override size from Root */\n size?: ModalSize;\n}\n\n/**\n * ModalGlass.Content - Main modal container with glass styling\n *\n * Automatically renders Portal and Overlay.\n */\nconst ModalContent = React.forwardRef<\n React.ElementRef,\n ModalContentProps\n>(({ className, children, showCloseButton = true, size: sizeProp, ...props }, ref) => {\n const { size: contextSize } = useModalContext();\n const size = sizeProp ?? contextSize;\n\n return (\n \n \n \n {/* Glow effect layer */}\n \n {/* Content */}\n
{children}
\n {/* Close button */}\n {showCloseButton && (\n \n \n Close\n \n )}\n \n
\n );\n});\nModalContent.displayName = 'ModalContent';\n\n// ========================================\n// COMPOUND COMPONENT: HEADER\n// ========================================\n\n/**\n * ModalGlass.Header - Header section with flex layout\n */\nfunction ModalHeader({ className, ...props }: React.ComponentProps<'div'>) {\n return (\n \n );\n}\n\n// ========================================\n// COMPOUND COMPONENT: BODY\n// ========================================\n\n/**\n * ModalGlass.Body - Optional wrapper for main content area\n *\n * Note: This component is OPTIONAL. Unlike some implementations, content can go\n * directly inside ModalGlass.Content (matching shadcn/ui DialogContent pattern).\n * Use Body when you want the text-secondary color styling applied.\n *\n * @example Direct content (shadcn/ui pattern)\n * ```tsx\n * \n * \n * Title\n * \n *

Content goes here directly

\n * ...\n *
\n * ```\n *\n * @example With Body wrapper (original pattern)\n * ```tsx\n * \n * ...\n * \n *

Content with text-secondary styling

\n *
\n * ...\n *
\n * ```\n */\nfunction ModalBody({ className, ...props }: React.ComponentProps<'div'>) {\n return (\n \n );\n}\n\n// ========================================\n// COMPOUND COMPONENT: FOOTER\n// ========================================\n\n/**\n * ModalGlass.Footer - Footer section with flex layout for actions\n */\nfunction ModalFooter({ className, ...props }: React.ComponentProps<'div'>) {\n return (\n \n );\n}\n\n// ========================================\n// COMPOUND COMPONENT: TITLE\n// ========================================\n\n/**\n * ModalGlass.Title - Modal title with proper accessibility\n */\nconst ModalTitle = React.forwardRef<\n React.ElementRef,\n React.ComponentPropsWithoutRef\n>(({ className, ...props }, ref) => (\n \n));\nModalTitle.displayName = 'ModalTitle';\n\n// ========================================\n// COMPOUND COMPONENT: DESCRIPTION\n// ========================================\n\n/**\n * ModalGlass.Description - Modal description text\n */\nconst ModalDescription = React.forwardRef<\n React.ElementRef,\n React.ComponentPropsWithoutRef\n>(({ className, ...props }, ref) => (\n \n));\nModalDescription.displayName = 'ModalDescription';\n\n// ========================================\n// COMPOUND COMPONENT: CLOSE\n// ========================================\n\n/**\n * ModalGlass.Close - Closes the modal when clicked\n *\n * Use `asChild` to render as the child element.\n *\n * @example\n * ```tsx\n * \n * Cancel\n * \n * ```\n */\nfunction ModalClose({ ...props }: React.ComponentProps) {\n return ;\n}\n\n// ========================================\n// EXPORT COMPOUND COMPONENT\n// ========================================\n\n/**\n * ModalGlass - Glass-themed Dialog with shadcn/ui API compatibility\n *\n * Built on @radix-ui/react-dialog for full accessibility support.\n *\n * @example Uncontrolled (with Trigger)\n * ```tsx\n * \n * \n * Open\n * \n * \n * \n * Title\n * \n * Content\n * \n * \n * Close\n * \n * \n * \n * \n * ```\n *\n * @example Controlled\n * ```tsx\n * \n * \n * \n * Confirm\n * \n * \n * setOpen(false)}>OK\n * \n * \n * \n * ```\n */\nexport const ModalGlass = {\n Root: ModalRoot,\n Trigger: ModalTrigger,\n Portal: ModalPortal,\n Overlay: ModalOverlay,\n Content: ModalContent,\n Header: ModalHeader,\n Body: ModalBody,\n Footer: ModalFooter,\n Title: ModalTitle,\n Description: ModalDescription,\n Close: ModalClose,\n};\n\n// Named exports for direct imports\nexport {\n ModalRoot,\n ModalTrigger,\n ModalPortal,\n ModalOverlay,\n ModalContent,\n ModalHeader,\n ModalBody,\n ModalFooter,\n ModalTitle,\n ModalDescription,\n ModalClose,\n};\n\nexport type { ModalRootProps, ModalContentProps };\n\n// ========================================\n// SHADCN/UI COMPATIBLE ALIASES\n// ========================================\n\n/**\n * Dialog - shadcn/ui compatible alias for ModalGlass.Root\n *\n * @example shadcn/ui compatible usage\n * ```tsx\n * import { Dialog, DialogTrigger, DialogContent, DialogHeader, DialogTitle } from 'shadcn-glass-ui'\n *\n * \n * \n * \n * \n * \n * \n * Title\n * \n *

Content goes directly here (no DialogBody needed)

\n *
\n *
\n * ```\n */\nexport const Dialog = ModalRoot;\n\n/** DialogTrigger - shadcn/ui compatible alias for ModalGlass.Trigger */\nexport const DialogTrigger = ModalTrigger;\n\n/** DialogPortal - shadcn/ui compatible alias for ModalGlass.Portal */\nexport const DialogPortal = ModalPortal;\n\n/** DialogOverlay - shadcn/ui compatible alias for ModalGlass.Overlay */\nexport const DialogOverlay = ModalOverlay;\n\n/** DialogContent - shadcn/ui compatible alias for ModalGlass.Content */\nexport const DialogContent = ModalContent;\n\n/** DialogHeader - shadcn/ui compatible alias for ModalGlass.Header */\nexport const DialogHeader = ModalHeader;\n\n/** DialogFooter - shadcn/ui compatible alias for ModalGlass.Footer */\nexport const DialogFooter = ModalFooter;\n\n/** DialogTitle - shadcn/ui compatible alias for ModalGlass.Title */\nexport const DialogTitle = ModalTitle;\n\n/** DialogDescription - shadcn/ui compatible alias for ModalGlass.Description */\nexport const DialogDescription = ModalDescription;\n\n/** DialogClose - shadcn/ui compatible alias for ModalGlass.Close */\nexport const DialogClose = ModalClose;\n" } ], "categories": [ "ui" ], "cssVars": { "light": { "--glass-bg": "rgba(255, 255, 255, 0.1)", "--glass-border": "rgba(255, 255, 255, 0.2)", "--blur-sm": "8px", "--blur-md": "16px", "--blur-lg": "24px" }, "dark": { "--glass-bg": "rgba(255, 255, 255, 0.05)", "--glass-border": "rgba(255, 255, 255, 0.1)", "--blur-sm": "8px", "--blur-md": "16px", "--blur-lg": "24px" } } }