0
# Triggers and Controls
1
2
Components for opening and closing dialogs with proper accessibility, keyboard navigation, and focus management.
3
4
## Capabilities
5
6
### DialogTrigger
7
8
Button component that opens the dialog when activated, with automatic accessibility attributes.
9
10
```typescript { .api }
11
/**
12
* Button component that opens the dialog when activated
13
* Extends all standard button props and automatically adds accessibility attributes
14
*/
15
type DialogTriggerElement = React.ComponentRef<typeof Primitive.button>;
16
interface DialogTriggerProps extends React.ComponentPropsWithoutRef<typeof Primitive.button> {}
17
18
const DialogTrigger: React.ForwardRefExoticComponent<
19
DialogTriggerProps & React.RefAttributes<DialogTriggerElement>
20
>;
21
```
22
23
**Usage Examples:**
24
25
```typescript
26
import { Dialog, DialogTrigger, DialogContent } from "@radix-ui/react-dialog";
27
28
// Basic trigger
29
function BasicTrigger() {
30
return (
31
<Dialog>
32
<DialogTrigger>Open Dialog</DialogTrigger>
33
<DialogContent>Content here</DialogContent>
34
</Dialog>
35
);
36
}
37
38
// Custom styled trigger
39
function StyledTrigger() {
40
return (
41
<Dialog>
42
<DialogTrigger className="custom-button" disabled={false}>
43
<span className="icon">๐</span>
44
Open Settings
45
</DialogTrigger>
46
<DialogContent>Settings content</DialogContent>
47
</Dialog>
48
);
49
}
50
51
// Trigger with custom click handler
52
function TriggerWithHandler() {
53
const handleClick = (event: React.MouseEvent) => {
54
console.log('Trigger clicked');
55
// Dialog will still open automatically
56
};
57
58
return (
59
<Dialog>
60
<DialogTrigger onClick={handleClick}>
61
Open with Custom Handler
62
</DialogTrigger>
63
<DialogContent>Content here</DialogContent>
64
</Dialog>
65
);
66
}
67
68
// Using asChild pattern with existing element
69
function AsChildTrigger() {
70
return (
71
<Dialog>
72
<DialogTrigger asChild>
73
<button className="existing-button-class">
74
Open Dialog
75
</button>
76
</DialogTrigger>
77
<DialogContent>Content here</DialogContent>
78
</Dialog>
79
);
80
}
81
```
82
83
### DialogClose
84
85
Button component that closes the dialog when activated, can be placed anywhere within the dialog content.
86
87
```typescript { .api }
88
/**
89
* Button component that closes the dialog when activated
90
* Can be placed anywhere within dialog content
91
* Extends all standard button props
92
*/
93
type DialogCloseElement = React.ComponentRef<typeof Primitive.button>;
94
interface DialogCloseProps extends React.ComponentPropsWithoutRef<typeof Primitive.button> {}
95
96
const DialogClose: React.ForwardRefExoticComponent<
97
DialogCloseProps & React.RefAttributes<DialogCloseElement>
98
>;
99
```
100
101
**Usage Examples:**
102
103
```typescript
104
import { Dialog, DialogTrigger, DialogContent, DialogClose } from "@radix-ui/react-dialog";
105
106
// Basic close button
107
function BasicClose() {
108
return (
109
<Dialog>
110
<DialogTrigger>Open</DialogTrigger>
111
<DialogContent>
112
<p>Dialog content</p>
113
<DialogClose>Close</DialogClose>
114
</DialogContent>
115
</Dialog>
116
);
117
}
118
119
// Multiple close buttons
120
function MultipleCloseButtons() {
121
return (
122
<Dialog>
123
<DialogTrigger>Open</DialogTrigger>
124
<DialogContent>
125
<div className="dialog-header">
126
<h2>Confirm Action</h2>
127
<DialogClose className="close-icon">ร</DialogClose>
128
</div>
129
<p>Are you sure you want to continue?</p>
130
<div className="dialog-actions">
131
<DialogClose className="cancel-btn">Cancel</DialogClose>
132
<DialogClose className="confirm-btn">Confirm</DialogClose>
133
</div>
134
</DialogContent>
135
</Dialog>
136
);
137
}
138
139
// Close button with custom handler
140
function CloseWithHandler() {
141
const handleClose = (event: React.MouseEvent) => {
142
console.log('Dialog closing');
143
// Dialog will still close automatically
144
};
145
146
return (
147
<Dialog>
148
<DialogTrigger>Open</DialogTrigger>
149
<DialogContent>
150
<p>Content here</p>
151
<DialogClose onClick={handleClose}>
152
Close with Handler
153
</DialogClose>
154
</DialogContent>
155
</Dialog>
156
);
157
}
158
159
// Using asChild pattern
160
function AsChildClose() {
161
return (
162
<Dialog>
163
<DialogTrigger>Open</DialogTrigger>
164
<DialogContent>
165
<p>Content here</p>
166
<DialogClose asChild>
167
<button className="existing-close-class">
168
Close Dialog
169
</button>
170
</DialogClose>
171
</DialogContent>
172
</Dialog>
173
);
174
}
175
```
176
177
## Accessibility Features
178
179
### DialogTrigger Accessibility
180
181
The DialogTrigger component automatically provides:
182
183
- `type="button"` for proper button semantics
184
- `aria-haspopup="dialog"` to indicate it opens a dialog
185
- `aria-expanded` that reflects the current dialog state
186
- `aria-controls` that references the dialog content ID
187
- `data-state` attribute with "open" or "closed" values
188
189
### DialogClose Accessibility
190
191
The DialogClose component automatically provides:
192
193
- `type="button"` for proper button semantics
194
- Proper event handling for keyboard activation (Enter, Space)
195
- Focus restoration to the trigger when dialog closes
196
197
## Event Handling
198
199
Both components compose event handlers, meaning you can add your own click handlers and they will be called alongside the built-in dialog control logic:
200
201
```typescript
202
// Your handler is called first, then the built-in logic
203
<DialogTrigger onClick={(e) => {
204
console.log('Custom logic before opening');
205
// Dialog opens automatically after this
206
}}>
207
Open
208
</DialogTrigger>
209
210
<DialogClose onClick={(e) => {
211
console.log('Custom logic before closing');
212
// Dialog closes automatically after this
213
}}>
214
Close
215
</DialogClose>
216
```
217
218
## Styling and Customization
219
220
Both components render as buttons by default but can be customized:
221
222
### CSS Classes and Styling
223
224
```typescript
225
<DialogTrigger className="btn btn-primary" style={{ fontSize: '16px' }}>
226
Styled Trigger
227
</DialogTrigger>
228
229
<DialogClose className="btn btn-secondary" data-testid="close-btn">
230
Styled Close
231
</DialogClose>
232
```
233
234
### AsChild Pattern
235
236
Use the `asChild` prop to render the functionality on your own element:
237
238
```typescript
239
<DialogTrigger asChild>
240
<YourCustomButton>Open</YourCustomButton>
241
</DialogTrigger>
242
243
<DialogClose asChild>
244
<YourCustomCloseIcon />
245
</DialogClose>
246
```