Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -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<TReturn>((ctrl) => <FooDialog ctrl={ctrl} {...props} />) }`. `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
Expand Down
15 changes: 10 additions & 5 deletions docs/ui/dialog.md
Original file line number Diff line number Diff line change
Expand Up @@ -148,8 +148,11 @@ export const AddNoteDialog: FC<DialogApiDialogProps> = ({ 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"
Expand Down Expand Up @@ -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.
Expand Down
Loading