UNPKG

alouette

Version:

A modern, customizable design system built on top of NativeWind v5 with configurable defaults

164 lines (126 loc) 5.46 kB
--- name: alouette-dialogs description: > Overlays: Modal (controlled by visible/onClose, with title or required aria-label, optional icon/footer, size sm/md/lg, dismiss via backdrop/close/ Escape/Android-back) and AlertDialog for confirmations. AlertDialog variant is confirm (cancel+confirm) | alert (single acknowledge) | required (single action, non-dismissible); accent defaults to danger. Prefer the icon-fixed presets QuestionAlertDialog / WarningAlertDialog / InfoAlertDialog / SuccessAlertDialog. Load when adding a modal, confirmation, or alert dialog. type: core library: alouette library_version: "22.0.0" requires: - alouette-theming - alouette-actions sources: - "christophehurpeau/alouette:packages/alouette/src/ui/containers/Modal.tsx" - "christophehurpeau/alouette:packages/alouette/src/ui/containers/AlertDialog.tsx" - "christophehurpeau/alouette:packages/alouette/src/ui/containers/Modal.stories.tsx" - "christophehurpeau/alouette:packages/alouette/src/ui/containers/AlertDialog.stories.tsx" --- This skill builds on alouette-theming (accents) and alouette-actions (the footer buttons). Read them first. # alouette — Dialogs `Modal` is a themed, accessible overlay you control with `visible` / `onClose`. `AlertDialog` builds on it for the confirm/alert/required decision pattern with a prebuilt footer. Both render through react-native's `Modal`, animate a fade, and dismiss on backdrop press, the close button, the Android back button, and Escape (web). ## Setup ```tsx import { Modal, Button } from "alouette"; function Example() { const [open, setOpen] = useState(false); return ( <> <Button text="Open" onPress={() => setOpen(true)} /> <Modal visible={open} onClose={() => setOpen(false)} title="Details" footer={<Button text="Done" onPress={() => setOpen(false)} />} > <Text>Body content.</Text> </Modal> </> ); } ``` ## Core Patterns ### Modal labelling A `Modal` must be labelled: pass `title` (rendered as the heading and used as the accessible name) or, when there is no visible heading, an `aria-label`. `size` is `"sm" | "md" | "lg"` (panel max-width + padding; default `md`). Optional `icon` tints with the accent before the title; `footer` is the actions row; long bodies scroll at ~70% viewport height. Use `hideCloseButton` to drop the corner close button (the modal stays dismissible via backdrop/Escape/back). ### AlertDialog — confirmations Prefer the icon-fixed presets; each takes every `AlertDialog` prop except `icon`. The `variant` selects the footer: - `"confirm"` (default) — `onConfirm` + `onCancel`, a Cancel and a Confirm button. - `"alert"` — `onClose`, a single acknowledge button. - `"required"` — `onConfirm`, a single action; **cannot** be dismissed by backdrop/Escape/back (the user must respond). `accent` defaults to `"danger"` (themes the icon and primary button). ```tsx import { QuestionAlertDialog, WarningAlertDialog } from "alouette"; <QuestionAlertDialog visible={confirming} title="Delete project?" confirmText="Delete" onConfirm={handleDelete} onCancel={() => setConfirming(false)} > This permanently removes the project and its data. </QuestionAlertDialog> <WarningAlertDialog variant="alert" visible={notice} title="Session expired" onClose={() => setNotice(false)} > Please sign in again. </WarningAlertDialog> ``` `confirmDisabled` disables the primary button (e.g. while an async action runs). Button labels default to Confirm/Cancel (confirm), OK (alert/required). ## Common Mistakes ### HIGH Modal without title or aria-label Wrong: ```tsx <Modal visible={open} onClose={close}><Text>…</Text></Modal> ``` Correct: ```tsx <Modal visible={open} onClose={close} title="Details"><Text>…</Text></Modal> // or, with no visible heading: <Modal visible={open} onClose={close} aria-label="Image preview"><Image /></Modal> ``` `ModalProps` is a union that requires either `title` or `aria-label`; a dialog with no accessible name is an accessibility failure (and a type error). Source: packages/alouette/src/ui/containers/Modal.tsx ### HIGH Building a confirmation out of a raw Modal Wrong: a `Modal` with hand-placed Cancel/Confirm buttons and manual `role`. Correct: ```tsx <QuestionAlertDialog visible={open} title="Discard changes?" onConfirm={discard} onCancel={close} /> ``` `AlertDialog` sets `role="alertdialog"`, wires the description to `aria-describedby`, hides the close button, and builds the footer for the chosen `variant`. Reach for `Modal` directly only for non-decision content. Source: packages/alouette/src/ui/containers/AlertDialog.tsx ### MEDIUM Expecting a required dialog to close on backdrop/Escape `variant="required"` intentionally ignores backdrop, Escape, and the Android back button — only its explicit action closes it. Use it for must-respond interruptions (accept terms, forced sign-out), not for ordinary dialogs, which should stay dismissible (`confirm` / `alert`). Source: packages/alouette/src/ui/containers/AlertDialog.tsx ### LOW Passing icon to a preset dialog The presets (`QuestionAlertDialog`, `WarningAlertDialog`, `InfoAlertDialog`, `SuccessAlertDialog`) fix the icon; their props are `AlertDialogUsageProps` = every `AlertDialog` prop except `icon`. Use the base `AlertDialog` when you need a custom icon. Source: packages/alouette/src/ui/containers/AlertDialog.tsx