diff --git a/AGENTS.md b/AGENTS.md index b8de35cf..3a9a7c43 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -242,8 +242,11 @@ commit ## Dialog patterns -- Prefer inline `useState`-managed dialogs (open/closed state in the parent component) over `dialogApi` for dialogs that - need access to `CharacterSheetProvider` or other React context, since `dialogApi` renders outside the provider tree. +- Prefer the `dialogApi` + `use*Dialog` hook pattern for new dialogs: the hook calls `useDialogApi()` and returns + `{ open: (props) => dialogApi.open((ctrl) => ) }`. `DialogApiProvider` is + mounted inside `CharacterSheetProvider` (in the character routes and the builder root), so React context including + `CharacterSheetProvider` propagates normally — no inline state is needed for context access. See + `useAddKarmaDialog` and `useActiveSkillDialog` for minimal examples. - Use `useConfirmDialog()` from `#/components/ui/dialog/confirmDialog.tsx` for confirmation prompts before destructive actions. - Use the compound `Dialog` component from `#/components/ui/dialog/dialog.tsx` for all new dialogs — it enforces diff --git a/docs/ui/dialog.md b/docs/ui/dialog.md index c63e6fed..0c0d3f64 100644 --- a/docs/ui/dialog.md +++ b/docs/ui/dialog.md @@ -148,8 +148,11 @@ export const AddNoteDialog: FC = ({ open, onClose, onClose ### Inline `useState` dialog (no `DialogApi`) -Prefer this pattern when the dialog needs access to `CharacterSheetProvider` -or other React context (since `DialogApi` renders outside the provider tree). +Use this pattern only when the consumer truly has no `DialogApi` available — +uncommon in production code. `DialogApiProvider` is mounted inside +`CharacterSheetProvider` in the app routes and the builder root, so the +`useDialogApi`-based hook pattern shown above already has access to React +context and is the project default. ```tsx import Button from "@mui/material/Button" @@ -183,9 +186,11 @@ export const ExamplePage = () => { ## Guidelines -- **Prefer inline `useState` dialogs** over `DialogApi` when the dialog needs access to `CharacterSheetProvider` or - other React context — `DialogApi` - renders outside the provider tree. See `AGENTS.md` → *Dialog patterns*. +- **Prefer the `useDialogApi` + `use*Dialog` hook pattern** for new dialogs — + it's the project default and React context (including + `CharacterSheetProvider`) propagates normally because `DialogApiProvider` + is mounted inside the relevant providers. See the `DialogApi`-based + examples above and `AGENTS.md` → *Dialog patterns*. - **`onClosed` vs `onClose`**: `onClose` triggers the close animation; `onClosed` fires after it finishes. Reset form state in `onClosed` to avoid a flash of empty fields while the animation runs.