UNPKG

laif-ds

Version:

Design System di Laif con componenti React basati su principi di Atomic Design

272 lines (226 loc) 8.7 kB
# AppDialog ## Overview Enhanced modal dialog component built on top of the base Dialog component. Provides a simplified API with built-in header, body, and footer sections, multiple size variants, and support for both controlled and uncontrolled usage patterns. --- ## Props ### AppDialogProps | Prop | Type | Default | Description | | ------------------ | --------------------------------------------- | ------------ | --------------------------------------------- | | `trigger` | `React.ReactNode` | `undefined` | Element that triggers the dialog on click. | | `title` | `string \| React.ReactNode` | **required** | Dialog title displayed in the header. | | `description` | `string \| React.ReactNode` | `undefined` | Dialog description displayed below the title. | | `footer` | `React.ReactNode` | `undefined` | Footer content (typically action buttons). | | `size` | `"sm" \| "default" \| "lg" \| "xl" \| "full"` | `"default"` | Size variant of the dialog. | | `open` | `boolean` | `undefined` | Controlled open state. | | `defaultOpen` | `boolean` | `undefined` | Default open state for uncontrolled usage. | | `onOpenChange` | `(open: boolean) => void` | `undefined` | Callback when open state changes. | | `disabled` | `boolean` | `false` | Whether to disable the trigger. | | `asChild` | `boolean` | `false` | Whether to use asChild pattern for trigger. | | `preventClose` | `"overlay" \| "all"` | `undefined` | Prevent closing via overlay or all methods. | | `triggerClassName` | `string` | `undefined` | Additional className for the trigger wrapper. | | `contentClassName` | `string` | `undefined` | Additional className for the dialog content. | | `headerClassName` | `string` | `undefined` | Additional className for the dialog header. | | `bodyClassName` | `string` | `undefined` | Additional className for the dialog body. | | `footerClassName` | `string` | `undefined` | Additional className for the dialog footer. | ### Size Variants | Size | Dimensions | | --------- | ---------------------------------- | | `sm` | 5/12 width and height | | `default` | 7/12 width and height | | `lg` | 9/12 width and height | | `xl` | 11/12 width and height | | `full` | Full viewport (no rounded corners) | --- ## Exports - **AppDialog**: Main dialog component. - **AppDialogClose**: Re-export of DialogClose for closing the dialog programmatically. --- ## Behavior - **Responsive**: On small screens (`max-sm`), the dialog takes full viewport. - **Scrollable body**: Content in the body section scrolls if it exceeds available space. - **Close button**: Built-in close button in the header (top-right). - **Border separators**: Automatic borders between header/body and body/footer when content exists. - **Focus management**: Inherits Radix Dialog focus trapping behavior. --- ## Examples ### Basic Usage ```tsx import { AppDialog, Button } from "laif-ds"; export function BasicAppDialog() { return ( <AppDialog title="Dialog Title" description="Optional description text." trigger={<Button>Open Dialog</Button>} asChild > <p>Dialog content goes here.</p> </AppDialog> ); } ``` ### With Footer Actions ```tsx import { AppDialog, AppDialogClose, Button } from "laif-ds"; export function DialogWithFooter() { return ( <AppDialog title="Confirm Action" description="Are you sure you want to proceed?" trigger={<Button>Open Dialog</Button>} footer={ <> <AppDialogClose asChild> <Button variant="outline">Cancel</Button> </AppDialogClose> <AppDialogClose asChild> <Button>Confirm</Button> </AppDialogClose> </> } asChild > <p>This action cannot be undone.</p> </AppDialog> ); } ``` ### Controlled Dialog ```tsx import { useState } from "react"; import { AppDialog, Button } from "laif-ds"; export function ControlledDialog() { const [open, setOpen] = useState(false); return ( <> <Button onClick={() => setOpen(true)}>Open Dialog</Button> <AppDialog open={open} onOpenChange={setOpen} title="Controlled Dialog" description="This dialog is controlled externally." footer={<Button onClick={() => setOpen(false)}>Close</Button>} > <p>The dialog state is managed by the parent component.</p> </AppDialog> </> ); } ``` ### Size Variants ```tsx import { AppDialog, Button } from "laif-ds"; export function SizeVariants() { return ( <div className="flex flex-wrap gap-4"> <AppDialog title="Small Dialog" size="sm" trigger={<Button variant="outline">Small</Button>} asChild > <p>Small dialog content.</p> </AppDialog> <AppDialog title="Default Dialog" size="default" trigger={<Button variant="outline">Default</Button>} asChild > <p>Default dialog content.</p> </AppDialog> <AppDialog title="Large Dialog" size="lg" trigger={<Button variant="outline">Large</Button>} asChild > <p>Large dialog content.</p> </AppDialog> <AppDialog title="Extra Large Dialog" size="xl" trigger={<Button variant="outline">Extra Large</Button>} asChild > <p>Extra large dialog content.</p> </AppDialog> <AppDialog title="Full Dialog" size="full" trigger={<Button variant="outline">Full</Button>} asChild > <p>Full screen dialog content.</p> </AppDialog> </div> ); } ``` ### With Form ```tsx import { useState } from "react"; import { AppDialog, AppDialogClose, Button, Input, Label } from "laif-ds"; export function DialogWithForm() { const [open, setOpen] = useState(false); const handleSubmit = (e: React.FormEvent) => { e.preventDefault(); // Handle form submission setOpen(false); }; return ( <AppDialog open={open} onOpenChange={setOpen} title="Edit Profile" description="Update your profile information." trigger={<Button>Edit Profile</Button>} footer={ <> <AppDialogClose asChild> <Button variant="outline">Cancel</Button> </AppDialogClose> <Button type="submit" onClick={handleSubmit}> Save </Button> </> } asChild > <form onSubmit={handleSubmit} className="space-y-4"> <div className="space-y-2"> <Label htmlFor="name">Name</Label> <Input id="name" placeholder="Your name" /> </div> <div className="space-y-2"> <Label htmlFor="email">Email</Label> <Input id="email" type="email" placeholder="Your email" /> </div> </form> </AppDialog> ); } ``` ### Disabled Trigger ```tsx import { AppDialog, Button } from "laif-ds"; export function DisabledDialog() { return ( <AppDialog title="Disabled Dialog" trigger={<Button disabled>Cannot Open</Button>} disabled asChild > <p>This content won't be accessible.</p> </AppDialog> ); } ``` --- ## Notes - **Use `asChild`**: When passing a Button or other interactive element as trigger, set `asChild={true}` to avoid nesting buttons. - **AppDialogClose**: Use this component to create buttons that close the dialog. Wrap with `asChild` when using custom elements. - **Scrolling content**: The body section automatically handles overflow with scrolling. - **Accessibility**: Title is rendered as an `h5` heading; description uses caption typography. - **vs Dialog**: Use `AppDialog` for simpler use cases with consistent header/body/footer layout. Use base `Dialog` for more complex custom layouts.