- name
- rezi-modal-dialogs
- description
- Add modal dialogs and overlay UI with focus trapping. Use when implementing confirmations, alerts, or layered interfaces.
- user-invocable
- true
- allowed-tools
- Read, Glob, Grep, Edit, Write
- argument-hint
- [modal-type]
- metadata
- {"short-description":"Add modal dialogs"}
## When to use
Use this skill when:
- Adding confirmation dialogs, alerts, or prompts
- Building layered/overlay UI
- Need focus trapping within a dialog
## Source of truth
- `packages/core/src/widgets/useModalStack.ts` — `useModalStack()` hook
- `packages/core/src/widgets/types.ts` — `ModalProps`, `LayersProps`
- `packages/core/src/widgets/ui.ts` — `ui.modal()`, `ui.layers()`
- `packages/core/src/ui/recipes.ts` — `recipe.modal()` and `recipe.surface()` for design-system-consistent modal styling
## Steps
### Option A: useModalStack (recommended for multiple modals)
1. **Use `useModalStack()`** inside a `defineWidget`:
```typescript
const modals = useModalStack(ctx);
// Push a modal
modals.push("confirm", {
title: "Confirm",
content: body,
onClose: () => modals.pop(),
});
// Include in view
return ui.layers([mainContent, ...modals.render()]);
```
### Option B: ui.modal (simple single modal)
1. **Use `ui.modal()` directly** with a state-controlled flag:
```typescript
return ui.layers([
mainContent,
...(state.showModal
? [
ui.modal({
id: "confirm-modal",
title: "Confirm",
initialFocus: "confirm-ok",
returnFocusTo: "open-confirm",
onClose: () => app.update((s) => ({ ...s, showModal: false })),
content: ui.text("Are you sure?"),
actions: [
ui.button({
id: "confirm-cancel",
label: "Cancel",
intent: "secondary",
onPress: () => app.update((s) => ({ ...s, showModal: false })),
}),
ui.button({
id: "confirm-ok",
label: "OK",
intent: "primary",
onPress: () => app.update((s) => ({ ...s, showModal: false })),
}),
],
}),
]
: []),
]);
```
2. **Overlay ordering note**:
- Modal, dropdown, and toast overlays share unified z-ordering through the LayerRegistry.
- Prefer `ui.layers([...])` as the common overlay composition root.
3. **Dialog action intent note**:
- Use `intent` to communicate action semantics in modal/dialog button rows.
- Recommended mapping: confirm/continue -> `primary`, cancel/back -> `secondary`, destructive -> `danger`, positive approval -> `success`, cautionary acknowledgment -> `warning`.
## Verification
- Modal opens and closes correctly
- Focus traps within the modal (Tab doesn't escape)
- Focus returns to previous element on close
View on GitHub