### Install Shadcn UI Dialog and Drawer Components Source: https://credenza.rdev.pro/index Command to add the `dialog` and `drawer` components from shadcn/ui to your project. These components are prerequisites for the Credenza component, providing the underlying UI for desktop and mobile modals. ```bash npx shadcn@latest add dialog drawer ``` -------------------------------- ### Importing Credenza UI Components Source: https://credenza.rdev.pro/index This snippet shows how to import all necessary Credenza components, such as Credenza, CredenzaBody, CredenzaTrigger, and others, from the local UI library path. ```typescript import { Credenza, CredenzaBody, CredenzaClose, CredenzaContent, CredenzaDescription, CredenzaFooter, CredenzaHeader, CredenzaTitle, CredenzaTrigger, } from "@/components/ui/credenza" ``` -------------------------------- ### Basic Credenza Modal with Trigger Source: https://credenza.rdev.pro/index Demonstrates the fundamental usage of the Credenza component. It uses a CredenzaTrigger wrapped around a Button to open the modal, which contains a header, description, body, and a close button in the footer. ```tsx Credenza A responsive modal component for shadcn/ui. This component is built using shadcn/ui's dialog and drawer component, which is built on top of Vaul. ``` -------------------------------- ### Implement Responsive Credenza React Component Source: https://credenza.rdev.pro/index The core Credenza component and its sub-components (Trigger, Close, Content, Description, Header, Title, Body, Footer). This component dynamically renders either a `Dialog` (for desktop) or a `Drawer` (for mobile) based on the `useMediaQuery` hook, providing a unified API for responsive modal interactions. ```typescript "use client" import * as React from "react" import { cn } from "@/lib/utils" import { useMediaQuery } from "@/hooks/use-media-query" import { Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger } from "@/components/ui/dialog" import { Drawer, DrawerClose, DrawerContent, DrawerDescription, DrawerFooter, DrawerHeader, DrawerTitle, DrawerTrigger } from "@/components/ui/drawer" interface BaseProps { children: React.ReactNode } interface RootCredenzaProps extends BaseProps { open?: boolean onOpenChange?: (open: boolean) => void } interface CredenzaProps extends BaseProps { className?: string asChild?: true } const CredenzaContext = React.createContext<{ isDesktop: boolean }>( { isDesktop: false } ); const useCredenzaContext = () => { const context = React.useContext(CredenzaContext); if (!context) { throw new Error( "Credenza components cannot be rendered outside the Credenza Context" ); } return context; }; const Credenza = ({ children, ...props }: RootCredenzaProps) => { const isDesktop = useMediaQuery("(min-width: 768px)"); const Credenza = isDesktop ? Dialog : Drawer; return ( {children} ); }; const CredenzaTrigger = ({ className, children, ...props }: CredenzaProps) => { const { isDesktop } = useCredenzaContext(); const CredenzaTrigger = isDesktop ? DialogTrigger : DrawerTrigger; return ( {children} ); }; const CredenzaClose = ({ className, children, ...props }: CredenzaProps) => { const { isDesktop } = useCredenzaContext(); const CredenzaClose = isDesktop ? DialogClose : DrawerClose; return ( {children} ); }; const CredenzaContent = ({ className, children, ...props }: CredenzaProps) => { const { isDesktop } = useCredenzaContext(); const CredenzaContent = isDesktop ? DialogContent : DrawerContent; return ( {children} ); }; const CredenzaDescription = ({ className, children, ...props }: CredenzaProps) => { const { isDesktop } = useCredenzaContext(); const CredenzaDescription = isDesktop ? DialogDescription : DrawerDescription; return ( {children} ); }; const CredenzaHeader = ({ className, children, ...props }: CredenzaProps) => { const { isDesktop } = useCredenzaContext(); const CredenzaHeader = isDesktop ? DialogHeader : DrawerHeader; return ( {children} ); }; const CredenzaTitle = ({ className, children, ...props }: CredenzaProps) => { const { isDesktop } = useCredenzaContext(); const CredenzaTitle = isDesktop ? DialogTitle : DrawerTitle; return ( {children} ); }; const CredenzaBody = ({ className, children, ...props }: CredenzaProps) => { return (
{children}
); }; const CredenzaFooter = ({ className, children, ...props }: CredenzaProps) => { const { isDesktop } = useCredenzaContext(); const CredenzaFooter = isDesktop ? DialogFooter : DrawerFooter; return ( {children} ); }; export { Credenza, CredenzaTrigger, CredenzaClose, CredenzaContent, CredenzaDescription, CredenzaHeader, CredenzaTitle, CredenzaBody, CredenzaFooter } ``` -------------------------------- ### Wrap App with Vaul Drawer Wrapper for Background Scaling Source: https://credenza.rdev.pro/index HTML/JSX snippet to wrap your application's main content with a `div` element that includes the `vaul-drawer-wrapper` attribute and a background class. This enables visual effects like background scaling when the drawer component is active. ```jsx
{children}
``` -------------------------------- ### Controlling Credenza Modal with React State Source: https://credenza.rdev.pro/index Illustrates how to manage the Credenza modal's open/close state programmatically using React's useState hook. The modal's visibility is controlled by the 'open' state variable, which is toggled by a button click. ```tsx function StateModal() { const [open, setOpen] = React.useState(false) const handleOpen = () => { setOpen(true) } return ( <> Credenza A responsive modal component for shadcn/ui. This modal got triggered using state ) } ``` -------------------------------- ### Implement useMediaQuery React Hook Source: https://credenza.rdev.pro/index A custom React hook that tracks the state of a CSS media query. It returns a boolean indicating whether the query currently matches, enabling responsive behavior based on viewport size. This hook is crucial for the Credenza component to determine if it should render a Dialog or a Drawer. ```typescript import * as React from "react" export function useMediaQuery(query: string) { const [value, setValue] = React.useState(false) React.useEffect(() => { function onChange(event: MediaQueryListEvent) { setValue(event.matches) } const result = matchMedia(query) result.addEventListener("change", onChange) setValue(result.matches) return () => result.removeEventListener("change", onChange) }, [query]) return value } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.