0
# Dialog State Machine
1
2
The dialog state machine manages all dialog behaviors including state transitions, effects, and accessibility features. It provides a framework-agnostic foundation that can be connected to any UI framework.
3
4
## Capabilities
5
6
### Machine Creation
7
8
Creates a configured dialog state machine with all necessary behaviors and effects.
9
10
```typescript { .api }
11
/**
12
* Creates a dialog state machine with configuration and behaviors
13
* @param props - Configuration props for the dialog machine
14
* @returns Configured state machine instance
15
*/
16
function machine(props: Props): Machine;
17
18
interface Machine extends StateMachine<DialogSchema> {
19
/** Current state of the machine */
20
state: State;
21
/** Send events to the machine */
22
send: (event: MachineEvent) => void;
23
/** Access machine context */
24
context: Context;
25
/** Get prop values */
26
prop: (key: keyof Props) => any;
27
/** DOM scope for element access */
28
scope: Scope;
29
}
30
```
31
32
**Usage Example:**
33
34
```typescript
35
import { machine } from "@zag-js/dialog";
36
37
const dialogMachine = machine({
38
id: "my-dialog",
39
modal: true,
40
trapFocus: true,
41
onOpenChange: (details) => {
42
console.log("Dialog state changed:", details.open);
43
},
44
closeOnEscape: true,
45
closeOnInteractOutside: true
46
});
47
```
48
49
### Machine Events
50
51
Events that can be sent to the dialog machine to trigger state changes.
52
53
```typescript { .api }
54
interface MachineEvent {
55
type:
56
| "OPEN" // Open the dialog
57
| "CLOSE" // Close the dialog
58
| "TOGGLE" // Toggle dialog state
59
| "CONTROLLED.OPEN" // Open via controlled prop
60
| "CONTROLLED.CLOSE"; // Close via controlled prop
61
62
/** Optional source information */
63
src?: string;
64
/** Previous event reference */
65
previousEvent?: MachineEvent;
66
}
67
```
68
69
**Usage Examples:**
70
71
```typescript
72
// Open dialog programmatically
73
machine.send({ type: "OPEN" });
74
75
// Close dialog programmatically
76
machine.send({ type: "CLOSE" });
77
78
// Toggle dialog state
79
machine.send({ type: "TOGGLE" });
80
81
// Close via interaction outside (internal use)
82
machine.send({ type: "CLOSE", src: "interact-outside" });
83
```
84
85
### Machine States
86
87
The dialog machine has two primary states with different behaviors and effects.
88
89
```typescript { .api }
90
type DialogState = "open" | "closed";
91
92
interface StateConfig {
93
/** State name */
94
value: DialogState;
95
/** Whether state matches given state(s) */
96
matches: (state: DialogState | DialogState[]) => boolean;
97
/** Active effects in this state */
98
effects?: string[];
99
/** Entry actions when entering state */
100
entry?: string[];
101
/** Available transitions from this state */
102
on?: Record<string, TransitionConfig>;
103
}
104
```
105
106
**State Behaviors:**
107
108
- **"closed"**: Dialog is hidden, no effects active, can transition to "open"
109
- **"open"**: Dialog is visible, all effects active (focus trap, scroll prevention, etc.)
110
111
### Machine Effects
112
113
Effects that run when the dialog is in the "open" state, providing accessibility and interaction features.
114
115
```typescript { .api }
116
interface MachineEffects {
117
/** Track dismissible element for outside interactions */
118
trackDismissableElement: Effect;
119
/** Prevent background scrolling */
120
preventScroll: Effect;
121
/** Trap focus within dialog */
122
trapFocus: Effect;
123
/** Hide content below modal */
124
hideContentBelow: Effect;
125
}
126
127
interface Effect {
128
/** Effect cleanup function */
129
(): (() => void) | void;
130
}
131
```
132
133
**Effect Details:**
134
135
- **trackDismissableElement**: Handles clicks/focus outside dialog, escape key, and dismissal logic
136
- **preventScroll**: Prevents body scrolling when dialog is open (if `preventScroll: true`)
137
- **trapFocus**: Constrains tab navigation within dialog (if `trapFocus: true`)
138
- **hideContentBelow**: Hides content behind modal using `aria-hidden` (if `modal: true`)
139
140
### Machine Actions
141
142
Actions that execute during state transitions to handle side effects and updates.
143
144
```typescript { .api }
145
interface MachineActions {
146
/** Check if title and description elements are rendered */
147
checkRenderedElements: Action;
148
/** Synchronize z-index between positioner and backdrop */
149
syncZIndex: Action;
150
/** Invoke onOpenChange callback with open: false */
151
invokeOnClose: Action;
152
/** Invoke onOpenChange callback with open: true */
153
invokeOnOpen: Action;
154
/** Toggle visibility based on controlled open prop */
155
toggleVisibility: Action;
156
}
157
158
interface Action {
159
/** Action execution context */
160
(context: ActionContext): void;
161
}
162
163
interface ActionContext {
164
/** Machine context */
165
context: Context;
166
/** DOM scope */
167
scope: Scope;
168
/** Get prop value */
169
prop: (key: string) => any;
170
/** Send event to machine */
171
send: (event: MachineEvent) => void;
172
/** Current event being processed */
173
event: MachineEvent;
174
}
175
```
176
177
### Machine Guards
178
179
Guards that determine whether state transitions should occur based on current conditions.
180
181
```typescript { .api }
182
interface MachineGuards {
183
/** Check if open state is controlled via props */
184
isOpenControlled: Guard;
185
}
186
187
interface Guard {
188
/** Guard evaluation */
189
(context: GuardContext): boolean;
190
}
191
192
interface GuardContext {
193
/** Machine context */
194
context: Context;
195
/** Get prop value */
196
prop: (key: string) => any;
197
/** Current event */
198
event: MachineEvent;
199
}
200
```
201
202
**Guard Logic:**
203
204
- **isOpenControlled**: Returns `true` if `open` prop is defined, indicating controlled mode
205
206
### Machine Context
207
208
Internal context maintained by the machine for tracking rendered elements and other state.
209
210
```typescript { .api }
211
interface MachineContext {
212
/** Tracks which elements are currently rendered in DOM */
213
rendered: {
214
title: boolean;
215
description: boolean;
216
};
217
}
218
```
219
220
The context is automatically updated by machine actions and used for proper ARIA labeling and descriptions.
221
222
### Machine Schema
223
224
Complete schema definition for the dialog state machine, used for type safety and validation.
225
226
```typescript { .api }
227
interface DialogSchema {
228
/** Props type for the machine */
229
props: Props;
230
/** Available states */
231
state: "open" | "closed";
232
/** Machine context */
233
context: MachineContext;
234
/** Available guards */
235
guard: "isOpenControlled";
236
/** Available effects */
237
effect: "trackDismissableElement" | "preventScroll" | "trapFocus" | "hideContentBelow";
238
/** Available actions */
239
action: "checkRenderedElements" | "syncZIndex" | "invokeOnClose" | "invokeOnOpen" | "toggleVisibility";
240
/** Event types */
241
event: MachineEvent;
242
}
243
```