@wordpress/components 25.10.0 → 25.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +16 -0
- package/build/autocomplete/index.js +104 -52
- package/build/autocomplete/index.js.map +1 -1
- package/build/dropdown-menu-v2-ariakit/index.js +217 -0
- package/build/dropdown-menu-v2-ariakit/index.js.map +1 -0
- package/build/dropdown-menu-v2-ariakit/styles.js +157 -0
- package/build/dropdown-menu-v2-ariakit/styles.js.map +1 -0
- package/build/dropdown-menu-v2-ariakit/types.js +6 -0
- package/build/dropdown-menu-v2-ariakit/types.js.map +1 -0
- package/build/input-control/styles/input-control-styles.js +23 -23
- package/build/input-control/styles/input-control-styles.js.map +1 -1
- package/build/mobile/global-styles-context/utils.native.js +1 -1
- package/build/mobile/global-styles-context/utils.native.js.map +1 -1
- package/build/private-apis.js +9 -1
- package/build/private-apis.js.map +1 -1
- package/build/select-control/styles/select-control-styles.js +8 -8
- package/build/select-control/styles/select-control-styles.js.map +1 -1
- package/build/slot-fill/bubbles-virtually/slot-fill-provider.js +1 -1
- package/build/slot-fill/bubbles-virtually/slot-fill-provider.js.map +1 -1
- package/build/tabs/index.js +2 -2
- package/build/tabs/index.js.map +1 -1
- package/build/tooltip/index.js +2 -2
- package/build/tooltip/index.js.map +1 -1
- package/build-module/autocomplete/index.js +104 -52
- package/build-module/autocomplete/index.js.map +1 -1
- package/build-module/dropdown-menu-v2-ariakit/index.js +199 -0
- package/build-module/dropdown-menu-v2-ariakit/index.js.map +1 -0
- package/build-module/dropdown-menu-v2-ariakit/styles.js +136 -0
- package/build-module/dropdown-menu-v2-ariakit/styles.js.map +1 -0
- package/build-module/dropdown-menu-v2-ariakit/types.js +2 -0
- package/build-module/dropdown-menu-v2-ariakit/types.js.map +1 -0
- package/build-module/input-control/styles/input-control-styles.js +23 -23
- package/build-module/input-control/styles/input-control-styles.js.map +1 -1
- package/build-module/mobile/global-styles-context/utils.native.js +2 -2
- package/build-module/mobile/global-styles-context/utils.native.js.map +1 -1
- package/build-module/private-apis.js +9 -1
- package/build-module/private-apis.js.map +1 -1
- package/build-module/select-control/styles/select-control-styles.js +8 -8
- package/build-module/select-control/styles/select-control-styles.js.map +1 -1
- package/build-module/slot-fill/bubbles-virtually/slot-fill-provider.js +1 -1
- package/build-module/slot-fill/bubbles-virtually/slot-fill-provider.js.map +1 -1
- package/build-module/tabs/index.js +3 -3
- package/build-module/tabs/index.js.map +1 -1
- package/build-module/tooltip/index.js +2 -2
- package/build-module/tooltip/index.js.map +1 -1
- package/build-style/style-rtl.css +1 -1
- package/build-style/style.css +1 -1
- package/build-types/autocomplete/index.d.ts.map +1 -1
- package/build-types/dropdown-menu-v2-ariakit/index.d.ts +11 -0
- package/build-types/dropdown-menu-v2-ariakit/index.d.ts.map +1 -0
- package/build-types/dropdown-menu-v2-ariakit/stories/index.story.d.ts +16 -0
- package/build-types/dropdown-menu-v2-ariakit/stories/index.story.d.ts.map +1 -0
- package/build-types/dropdown-menu-v2-ariakit/styles.d.ts +88 -0
- package/build-types/dropdown-menu-v2-ariakit/styles.d.ts.map +1 -0
- package/build-types/dropdown-menu-v2-ariakit/test/index.d.ts +2 -0
- package/build-types/dropdown-menu-v2-ariakit/test/index.d.ts.map +1 -0
- package/build-types/dropdown-menu-v2-ariakit/types.d.ts +174 -0
- package/build-types/dropdown-menu-v2-ariakit/types.d.ts.map +1 -0
- package/build-types/private-apis.d.ts.map +1 -1
- package/build-types/tooltip/index.d.ts.map +1 -1
- package/package.json +21 -20
- package/src/autocomplete/index.tsx +136 -77
- package/src/dimension-control/test/__snapshots__/index.test.js.snap +8 -8
- package/src/dropdown-menu-v2-ariakit/README.md +324 -0
- package/src/dropdown-menu-v2-ariakit/index.tsx +318 -0
- package/src/dropdown-menu-v2-ariakit/stories/index.story.tsx +506 -0
- package/src/dropdown-menu-v2-ariakit/styles.ts +297 -0
- package/src/dropdown-menu-v2-ariakit/test/index.tsx +1139 -0
- package/src/dropdown-menu-v2-ariakit/types.ts +186 -0
- package/src/input-control/styles/input-control-styles.tsx +2 -2
- package/src/mobile/global-styles-context/utils.native.js +2 -2
- package/src/private-apis.ts +16 -0
- package/src/select-control/styles/select-control-styles.ts +2 -2
- package/src/slot-fill/bubbles-virtually/slot-fill-provider.tsx +1 -1
- package/src/tabs/index.tsx +3 -3
- package/src/tabs/test/index.tsx +12 -3
- package/src/toggle-group-control/test/__snapshots__/index.tsx.snap +8 -0
- package/src/tooltip/index.tsx +2 -3
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -22,6 +22,8 @@ import {
|
|
|
22
22
|
isCollapsed,
|
|
23
23
|
getTextContent,
|
|
24
24
|
} from '@wordpress/rich-text';
|
|
25
|
+
import { speak } from '@wordpress/a11y';
|
|
26
|
+
import { isAppleOS } from '@wordpress/keycodes';
|
|
25
27
|
|
|
26
28
|
/**
|
|
27
29
|
* Internal dependencies
|
|
@@ -39,6 +41,35 @@ import type {
|
|
|
39
41
|
WPCompleter,
|
|
40
42
|
} from './types';
|
|
41
43
|
|
|
44
|
+
const getNodeText = ( node: React.ReactNode ): string => {
|
|
45
|
+
if ( node === null ) {
|
|
46
|
+
return '';
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
switch ( typeof node ) {
|
|
50
|
+
case 'string':
|
|
51
|
+
case 'number':
|
|
52
|
+
return node.toString();
|
|
53
|
+
break;
|
|
54
|
+
case 'boolean':
|
|
55
|
+
return '';
|
|
56
|
+
break;
|
|
57
|
+
case 'object': {
|
|
58
|
+
if ( node instanceof Array ) {
|
|
59
|
+
return node.map( getNodeText ).join( '' );
|
|
60
|
+
}
|
|
61
|
+
if ( 'props' in node ) {
|
|
62
|
+
return getNodeText( node.props.children );
|
|
63
|
+
}
|
|
64
|
+
break;
|
|
65
|
+
}
|
|
66
|
+
default:
|
|
67
|
+
return '';
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return '';
|
|
71
|
+
};
|
|
72
|
+
|
|
42
73
|
const EMPTY_FILTERED_OPTIONS: KeyedOption[] = [];
|
|
43
74
|
|
|
44
75
|
export function useAutocomplete( {
|
|
@@ -163,20 +194,35 @@ export function useAutocomplete( {
|
|
|
163
194
|
) {
|
|
164
195
|
return;
|
|
165
196
|
}
|
|
197
|
+
|
|
166
198
|
switch ( event.key ) {
|
|
167
|
-
case 'ArrowUp':
|
|
168
|
-
|
|
199
|
+
case 'ArrowUp': {
|
|
200
|
+
const newIndex =
|
|
169
201
|
( selectedIndex === 0
|
|
170
202
|
? filteredOptions.length
|
|
171
|
-
: selectedIndex ) - 1
|
|
172
|
-
);
|
|
203
|
+
: selectedIndex ) - 1;
|
|
204
|
+
setSelectedIndex( newIndex );
|
|
205
|
+
// See the related PR as to why this is necessary: https://github.com/WordPress/gutenberg/pull/54902.
|
|
206
|
+
if ( isAppleOS() ) {
|
|
207
|
+
speak(
|
|
208
|
+
getNodeText( filteredOptions[ newIndex ].label ),
|
|
209
|
+
'assertive'
|
|
210
|
+
);
|
|
211
|
+
}
|
|
173
212
|
break;
|
|
213
|
+
}
|
|
174
214
|
|
|
175
|
-
case 'ArrowDown':
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
)
|
|
215
|
+
case 'ArrowDown': {
|
|
216
|
+
const newIndex = ( selectedIndex + 1 ) % filteredOptions.length;
|
|
217
|
+
setSelectedIndex( newIndex );
|
|
218
|
+
if ( isAppleOS() ) {
|
|
219
|
+
speak(
|
|
220
|
+
getNodeText( filteredOptions[ newIndex ].label ),
|
|
221
|
+
'assertive'
|
|
222
|
+
);
|
|
223
|
+
}
|
|
179
224
|
break;
|
|
225
|
+
}
|
|
180
226
|
|
|
181
227
|
case 'Escape':
|
|
182
228
|
setAutocompleter( null );
|
|
@@ -218,82 +264,95 @@ export function useAutocomplete( {
|
|
|
218
264
|
return;
|
|
219
265
|
}
|
|
220
266
|
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
const textWithoutTrigger = textContent.slice(
|
|
230
|
-
index + triggerPrefix.length
|
|
267
|
+
// Find the completer with the highest triggerPrefix index in the
|
|
268
|
+
// textContent.
|
|
269
|
+
const completer = completers.reduce< WPCompleter | null >(
|
|
270
|
+
( lastTrigger, currentCompleter ) => {
|
|
271
|
+
const triggerIndex = textContent.lastIndexOf(
|
|
272
|
+
currentCompleter.triggerPrefix
|
|
231
273
|
);
|
|
274
|
+
const lastTriggerIndex =
|
|
275
|
+
lastTrigger !== null
|
|
276
|
+
? textContent.lastIndexOf( lastTrigger.triggerPrefix )
|
|
277
|
+
: -1;
|
|
278
|
+
|
|
279
|
+
return triggerIndex > lastTriggerIndex
|
|
280
|
+
? currentCompleter
|
|
281
|
+
: lastTrigger;
|
|
282
|
+
},
|
|
283
|
+
null
|
|
284
|
+
);
|
|
232
285
|
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
// is true and one of the "words" end up being too long. If that's the case,
|
|
238
|
-
// it will be caught by this guard.
|
|
239
|
-
if ( tooDistantFromTrigger ) return false;
|
|
240
|
-
|
|
241
|
-
const mismatch = filteredOptions.length === 0;
|
|
242
|
-
const wordsFromTrigger = textWithoutTrigger.split( /\s/ );
|
|
243
|
-
// We need to allow the effect to run when not backspacing and if there
|
|
244
|
-
// was a mismatch. i.e when typing a trigger + the match string or when
|
|
245
|
-
// clicking in an existing trigger word on the page. We do that if we
|
|
246
|
-
// detect that we have one word from trigger in the current textual context.
|
|
247
|
-
//
|
|
248
|
-
// Ex.: "Some text @a" <-- "@a" will be detected as the trigger word and
|
|
249
|
-
// allow the effect to run. It will run until there's a mismatch.
|
|
250
|
-
const hasOneTriggerWord = wordsFromTrigger.length === 1;
|
|
251
|
-
// This is used to allow the effect to run when backspacing and if
|
|
252
|
-
// "touching" a word that "belongs" to a trigger. We consider a "trigger
|
|
253
|
-
// word" any word up to the limit of 3 from the trigger character.
|
|
254
|
-
// Anything beyond that is ignored if there's a mismatch. This allows
|
|
255
|
-
// us to "escape" a mismatch when backspacing, but still imposing some
|
|
256
|
-
// sane limits.
|
|
257
|
-
//
|
|
258
|
-
// Ex: "Some text @marcelo sekkkk" <--- "kkkk" caused a mismatch, but
|
|
259
|
-
// if the user presses backspace here, it will show the completion popup again.
|
|
260
|
-
const matchingWhileBackspacing =
|
|
261
|
-
backspacing.current &&
|
|
262
|
-
textWithoutTrigger.split( /\s/ ).length <= 3;
|
|
263
|
-
|
|
264
|
-
if (
|
|
265
|
-
mismatch &&
|
|
266
|
-
! ( matchingWhileBackspacing || hasOneTriggerWord )
|
|
267
|
-
) {
|
|
268
|
-
return false;
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
const textAfterSelection = getTextContent(
|
|
272
|
-
slice( record, undefined, getTextContent( record ).length )
|
|
273
|
-
);
|
|
286
|
+
if ( ! completer ) {
|
|
287
|
+
if ( autocompleter ) reset();
|
|
288
|
+
return;
|
|
289
|
+
}
|
|
274
290
|
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
)
|
|
281
|
-
) {
|
|
282
|
-
return false;
|
|
283
|
-
}
|
|
291
|
+
const { allowContext, triggerPrefix } = completer;
|
|
292
|
+
const triggerIndex = textContent.lastIndexOf( triggerPrefix );
|
|
293
|
+
const textWithoutTrigger = textContent.slice(
|
|
294
|
+
triggerIndex + triggerPrefix.length
|
|
295
|
+
);
|
|
284
296
|
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
297
|
+
const tooDistantFromTrigger = textWithoutTrigger.length > 50; // 50 chars seems to be a good limit.
|
|
298
|
+
// This is a final barrier to prevent the effect from completing with
|
|
299
|
+
// an extremely long string, which causes the editor to slow-down
|
|
300
|
+
// significantly. This could happen, for example, if `matchingWhileBackspacing`
|
|
301
|
+
// is true and one of the "words" end up being too long. If that's the case,
|
|
302
|
+
// it will be caught by this guard.
|
|
303
|
+
if ( tooDistantFromTrigger ) return;
|
|
304
|
+
|
|
305
|
+
const mismatch = filteredOptions.length === 0;
|
|
306
|
+
const wordsFromTrigger = textWithoutTrigger.split( /\s/ );
|
|
307
|
+
// We need to allow the effect to run when not backspacing and if there
|
|
308
|
+
// was a mismatch. i.e when typing a trigger + the match string or when
|
|
309
|
+
// clicking in an existing trigger word on the page. We do that if we
|
|
310
|
+
// detect that we have one word from trigger in the current textual context.
|
|
311
|
+
//
|
|
312
|
+
// Ex.: "Some text @a" <-- "@a" will be detected as the trigger word and
|
|
313
|
+
// allow the effect to run. It will run until there's a mismatch.
|
|
314
|
+
const hasOneTriggerWord = wordsFromTrigger.length === 1;
|
|
315
|
+
// This is used to allow the effect to run when backspacing and if
|
|
316
|
+
// "touching" a word that "belongs" to a trigger. We consider a "trigger
|
|
317
|
+
// word" any word up to the limit of 3 from the trigger character.
|
|
318
|
+
// Anything beyond that is ignored if there's a mismatch. This allows
|
|
319
|
+
// us to "escape" a mismatch when backspacing, but still imposing some
|
|
320
|
+
// sane limits.
|
|
321
|
+
//
|
|
322
|
+
// Ex: "Some text @marcelo sekkkk" <--- "kkkk" caused a mismatch, but
|
|
323
|
+
// if the user presses backspace here, it will show the completion popup again.
|
|
324
|
+
const matchingWhileBackspacing =
|
|
325
|
+
backspacing.current && wordsFromTrigger.length <= 3;
|
|
326
|
+
|
|
327
|
+
if ( mismatch && ! ( matchingWhileBackspacing || hasOneTriggerWord ) ) {
|
|
328
|
+
if ( autocompleter ) reset();
|
|
329
|
+
return;
|
|
330
|
+
}
|
|
291
331
|
|
|
292
|
-
|
|
293
|
-
|
|
332
|
+
const textAfterSelection = getTextContent(
|
|
333
|
+
slice( record, undefined, getTextContent( record ).length )
|
|
294
334
|
);
|
|
295
335
|
|
|
296
|
-
if (
|
|
336
|
+
if (
|
|
337
|
+
allowContext &&
|
|
338
|
+
! allowContext(
|
|
339
|
+
textContent.slice( 0, triggerIndex ),
|
|
340
|
+
textAfterSelection
|
|
341
|
+
)
|
|
342
|
+
) {
|
|
343
|
+
if ( autocompleter ) reset();
|
|
344
|
+
return;
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
if (
|
|
348
|
+
/^\s/.test( textWithoutTrigger ) ||
|
|
349
|
+
/\s\s+$/.test( textWithoutTrigger )
|
|
350
|
+
) {
|
|
351
|
+
if ( autocompleter ) reset();
|
|
352
|
+
return;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
if ( ! /[\u0000-\uFFFF]*$/.test( textWithoutTrigger ) ) {
|
|
297
356
|
if ( autocompleter ) reset();
|
|
298
357
|
return;
|
|
299
358
|
}
|
|
@@ -119,8 +119,8 @@ exports[`DimensionControl rendering renders with custom sizes 1`] = `
|
|
|
119
119
|
white-space: nowrap;
|
|
120
120
|
text-overflow: ellipsis;
|
|
121
121
|
font-size: 16px;
|
|
122
|
-
height:
|
|
123
|
-
min-height:
|
|
122
|
+
height: 32px;
|
|
123
|
+
min-height: 32px;
|
|
124
124
|
padding-top: 0;
|
|
125
125
|
padding-bottom: 0;
|
|
126
126
|
padding-left: 8px;
|
|
@@ -390,8 +390,8 @@ exports[`DimensionControl rendering renders with defaults 1`] = `
|
|
|
390
390
|
white-space: nowrap;
|
|
391
391
|
text-overflow: ellipsis;
|
|
392
392
|
font-size: 16px;
|
|
393
|
-
height:
|
|
394
|
-
min-height:
|
|
393
|
+
height: 32px;
|
|
394
|
+
min-height: 32px;
|
|
395
395
|
padding-top: 0;
|
|
396
396
|
padding-bottom: 0;
|
|
397
397
|
padding-left: 8px;
|
|
@@ -671,8 +671,8 @@ exports[`DimensionControl rendering renders with icon and custom icon label 1`]
|
|
|
671
671
|
white-space: nowrap;
|
|
672
672
|
text-overflow: ellipsis;
|
|
673
673
|
font-size: 16px;
|
|
674
|
-
height:
|
|
675
|
-
min-height:
|
|
674
|
+
height: 32px;
|
|
675
|
+
min-height: 32px;
|
|
676
676
|
padding-top: 0;
|
|
677
677
|
padding-bottom: 0;
|
|
678
678
|
padding-left: 8px;
|
|
@@ -964,8 +964,8 @@ exports[`DimensionControl rendering renders with icon and default icon label 1`]
|
|
|
964
964
|
white-space: nowrap;
|
|
965
965
|
text-overflow: ellipsis;
|
|
966
966
|
font-size: 16px;
|
|
967
|
-
height:
|
|
968
|
-
min-height:
|
|
967
|
+
height: 32px;
|
|
968
|
+
min-height: 32px;
|
|
969
969
|
padding-top: 0;
|
|
970
970
|
padding-bottom: 0;
|
|
971
971
|
padding-left: 8px;
|
|
@@ -0,0 +1,324 @@
|
|
|
1
|
+
# `DropdownMenu` (v2)
|
|
2
|
+
|
|
3
|
+
<div class="callout callout-alert">
|
|
4
|
+
This feature is still experimental. “Experimental” means this is an early implementation subject to drastic and breaking changes.
|
|
5
|
+
</div>
|
|
6
|
+
|
|
7
|
+
`DropdownMenu` displays a menu to the user (such as a set of actions or functions) triggered by a button.
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
## Design guidelines
|
|
11
|
+
|
|
12
|
+
### Usage
|
|
13
|
+
|
|
14
|
+
#### When to use a DropdownMenu
|
|
15
|
+
|
|
16
|
+
Use a DropdownMenu when you want users to:
|
|
17
|
+
|
|
18
|
+
- Choose an action or change a setting from a list, AND
|
|
19
|
+
- Only see the available choices contextually.
|
|
20
|
+
|
|
21
|
+
`DropdownMenu` is a React component to render an expandable menu of buttons. It is similar in purpose to a `<select>` element, with the distinction that it does not maintain a value. Instead, each option behaves as an action button.
|
|
22
|
+
|
|
23
|
+
If you need to display all the available options at all times, consider using a Toolbar instead. Use a `DropdownMenu` to display a list of actions after the user interacts with a button.
|
|
24
|
+
|
|
25
|
+
**Do**
|
|
26
|
+
Use a `DropdownMenu` to display a list of actions after the user interacts with an icon.
|
|
27
|
+
|
|
28
|
+
**Don’t** use a `DropdownMenu` for important actions that should always be visible. Use a `Toolbar` instead.
|
|
29
|
+
|
|
30
|
+
**Don’t**
|
|
31
|
+
Don’t use a `DropdownMenu` for frequently used actions. Use a `Toolbar` instead.
|
|
32
|
+
|
|
33
|
+
#### Behavior
|
|
34
|
+
|
|
35
|
+
Generally, the parent button should indicate that interacting with it will show a `DropdownMenu`.
|
|
36
|
+
|
|
37
|
+
The parent button should retain the same visual styling regardless of whether the `DropdownMenu` is displayed or not.
|
|
38
|
+
|
|
39
|
+
#### Placement
|
|
40
|
+
|
|
41
|
+
The `DropdownMenu` should typically appear directly below, or below and to the left of, the parent button. If there isn’t enough space below to display the full `DropdownMenu`, it can be displayed instead above the parent button.
|
|
42
|
+
|
|
43
|
+
## Development guidelines
|
|
44
|
+
|
|
45
|
+
This component is still highly experimental, and it's not normally accessible to consumers of the `@wordpress/components` package.
|
|
46
|
+
|
|
47
|
+
The component exposes a set of components that are meant to be used in combination with each other in order to implement a `DropdownMenu` correctly.
|
|
48
|
+
|
|
49
|
+
### `DropdownMenu`
|
|
50
|
+
|
|
51
|
+
The root component, used to specify the menu's trigger and its contents.
|
|
52
|
+
|
|
53
|
+
#### Props
|
|
54
|
+
|
|
55
|
+
The component accepts the following props:
|
|
56
|
+
|
|
57
|
+
##### `trigger`: `React.ReactNode`
|
|
58
|
+
|
|
59
|
+
The trigger button
|
|
60
|
+
|
|
61
|
+
- Required: yes
|
|
62
|
+
|
|
63
|
+
##### `children`: `React.ReactNode`
|
|
64
|
+
|
|
65
|
+
The contents of the dropdown
|
|
66
|
+
|
|
67
|
+
- Required: yes
|
|
68
|
+
|
|
69
|
+
##### `defaultOpen`: `boolean`
|
|
70
|
+
|
|
71
|
+
The open state of the dropdown menu when it is initially rendered. Use when not wanting to control its open state.
|
|
72
|
+
|
|
73
|
+
- Required: no
|
|
74
|
+
- Default: `false`
|
|
75
|
+
|
|
76
|
+
##### `open`: `boolean`
|
|
77
|
+
|
|
78
|
+
The controlled open state of the dropdown menu. Must be used in conjunction with `onOpenChange`.
|
|
79
|
+
|
|
80
|
+
- Required: no
|
|
81
|
+
|
|
82
|
+
##### `onOpenChange`: `(open: boolean) => void`
|
|
83
|
+
|
|
84
|
+
Event handler called when the open state of the dropdown menu changes.
|
|
85
|
+
|
|
86
|
+
- Required: no
|
|
87
|
+
|
|
88
|
+
##### `modal`: `boolean`
|
|
89
|
+
|
|
90
|
+
The modality of the dropdown menu. When set to true, interaction with outside elements will be disabled and only menu content will be visible to screen readers.
|
|
91
|
+
|
|
92
|
+
- Required: no
|
|
93
|
+
- Default: `true`
|
|
94
|
+
|
|
95
|
+
##### `placement`: ``'top' | 'top-start' | 'top-end' | 'right' | 'right-start' | 'right-end' | 'bottom' | 'bottom-start' | 'bottom-end' | 'left' | 'left-start' | 'left-end'`
|
|
96
|
+
|
|
97
|
+
The placement of the dropdown menu popover.
|
|
98
|
+
|
|
99
|
+
- Required: no
|
|
100
|
+
- Default: `'bottom-start'` for root-level menus, `'right-start'` for nested menus
|
|
101
|
+
|
|
102
|
+
##### `gutter`: `number`
|
|
103
|
+
|
|
104
|
+
The distance in pixels from the trigger.
|
|
105
|
+
|
|
106
|
+
- Required: no
|
|
107
|
+
- Default: `8` for root-level menus, `16` for nested menus
|
|
108
|
+
|
|
109
|
+
##### `shift`: `number`
|
|
110
|
+
|
|
111
|
+
The skidding of the popover along the anchor element. Can be set to negative values to make the popover shift to the opposite side.
|
|
112
|
+
|
|
113
|
+
- Required: no
|
|
114
|
+
- Default: `0` for root-level menus, `-8` for nested menus
|
|
115
|
+
|
|
116
|
+
##### `hideOnEscape`: `boolean | ( ( event: KeyboardEvent | React.KeyboardEvent< Element > ) => boolean )`
|
|
117
|
+
|
|
118
|
+
Determines whether the menu popover will be hidden when the user presses the Escape key.
|
|
119
|
+
|
|
120
|
+
- Required: no
|
|
121
|
+
- Default: `true`
|
|
122
|
+
|
|
123
|
+
### `DropdownMenuItem`
|
|
124
|
+
|
|
125
|
+
Used to render a menu item.
|
|
126
|
+
|
|
127
|
+
#### Props
|
|
128
|
+
|
|
129
|
+
The component accepts the following props:
|
|
130
|
+
|
|
131
|
+
##### `children`: `React.ReactNode`
|
|
132
|
+
|
|
133
|
+
The contents of the item
|
|
134
|
+
|
|
135
|
+
- Required: yes
|
|
136
|
+
|
|
137
|
+
##### `prefix`: `React.ReactNode`
|
|
138
|
+
|
|
139
|
+
The contents of the item's prefix.
|
|
140
|
+
|
|
141
|
+
- Required: no
|
|
142
|
+
|
|
143
|
+
##### `suffix`: `React.ReactNode`
|
|
144
|
+
|
|
145
|
+
The contents of the item's suffix.
|
|
146
|
+
|
|
147
|
+
- Required: no
|
|
148
|
+
|
|
149
|
+
##### `hideOnClick`: `boolean`
|
|
150
|
+
|
|
151
|
+
Whether to hide the dropdown menu when the menu item is clicked.
|
|
152
|
+
|
|
153
|
+
- Required: no
|
|
154
|
+
- Default: `true`
|
|
155
|
+
|
|
156
|
+
##### `disabled`: `boolean`
|
|
157
|
+
|
|
158
|
+
Determines if the element is disabled.
|
|
159
|
+
|
|
160
|
+
- Required: no
|
|
161
|
+
- Default: `false`
|
|
162
|
+
|
|
163
|
+
### `DropdownMenuCheckboxItem`
|
|
164
|
+
|
|
165
|
+
Used to render a checkbox item.
|
|
166
|
+
|
|
167
|
+
#### Props
|
|
168
|
+
|
|
169
|
+
The component accepts the following props:
|
|
170
|
+
|
|
171
|
+
##### `children`: `React.ReactNode`
|
|
172
|
+
|
|
173
|
+
The contents of the item
|
|
174
|
+
|
|
175
|
+
- Required: yes
|
|
176
|
+
|
|
177
|
+
##### `suffix`: `React.ReactNode`
|
|
178
|
+
|
|
179
|
+
The contents of the item's suffix.
|
|
180
|
+
|
|
181
|
+
- Required: no
|
|
182
|
+
|
|
183
|
+
##### `hideOnClick`: `boolean`
|
|
184
|
+
|
|
185
|
+
Whether to hide the dropdown menu when the menu item is clicked.
|
|
186
|
+
|
|
187
|
+
- Required: no
|
|
188
|
+
- Default: `false`
|
|
189
|
+
|
|
190
|
+
##### `disabled`: `boolean`
|
|
191
|
+
|
|
192
|
+
Determines if the element is disabled.
|
|
193
|
+
|
|
194
|
+
- Required: no
|
|
195
|
+
- Default: `false`
|
|
196
|
+
|
|
197
|
+
##### `name`: `string`
|
|
198
|
+
|
|
199
|
+
The checkbox item's name.
|
|
200
|
+
|
|
201
|
+
- Required: yes
|
|
202
|
+
|
|
203
|
+
##### `value`: `string`
|
|
204
|
+
|
|
205
|
+
The checkbox item's value, useful when using multiple checkbox items
|
|
206
|
+
associated to the same `name`.
|
|
207
|
+
|
|
208
|
+
- Required: no
|
|
209
|
+
|
|
210
|
+
##### `checked`: `boolean`
|
|
211
|
+
|
|
212
|
+
The checkbox item's value, useful when using multiple checkbox items
|
|
213
|
+
associated to the same `name`.
|
|
214
|
+
|
|
215
|
+
- Required: no
|
|
216
|
+
|
|
217
|
+
##### `defaultChecked`: `boolean`
|
|
218
|
+
|
|
219
|
+
The checked state of the checkbox menu item when it is initially rendered. Use when not wanting to control its checked state.
|
|
220
|
+
|
|
221
|
+
- Required: no
|
|
222
|
+
|
|
223
|
+
##### `onChange`: `( event: React.ChangeEvent< HTMLInputElement > ) => void;`
|
|
224
|
+
|
|
225
|
+
Event handler called when the checked state of the checkbox menu item changes.
|
|
226
|
+
|
|
227
|
+
- Required: no
|
|
228
|
+
|
|
229
|
+
### `DropdownMenuRadioItem`
|
|
230
|
+
|
|
231
|
+
Used to render a radio item.
|
|
232
|
+
|
|
233
|
+
#### Props
|
|
234
|
+
|
|
235
|
+
The component accepts the following props:
|
|
236
|
+
|
|
237
|
+
##### `children`: `React.ReactNode`
|
|
238
|
+
|
|
239
|
+
The contents of the item
|
|
240
|
+
|
|
241
|
+
- Required: yes
|
|
242
|
+
|
|
243
|
+
##### `suffix`: `React.ReactNode`
|
|
244
|
+
|
|
245
|
+
The contents of the item's suffix.
|
|
246
|
+
|
|
247
|
+
- Required: no
|
|
248
|
+
|
|
249
|
+
##### `hideOnClick`: `boolean`
|
|
250
|
+
|
|
251
|
+
Whether to hide the dropdown menu when the menu item is clicked.
|
|
252
|
+
|
|
253
|
+
- Required: no
|
|
254
|
+
- Default: `false`
|
|
255
|
+
|
|
256
|
+
##### `disabled`: `boolean`
|
|
257
|
+
|
|
258
|
+
Determines if the element is disabled.
|
|
259
|
+
|
|
260
|
+
- Required: no
|
|
261
|
+
- Default: `false`
|
|
262
|
+
|
|
263
|
+
##### `name`: `string`
|
|
264
|
+
|
|
265
|
+
The radio item's name.
|
|
266
|
+
|
|
267
|
+
- Required: yes
|
|
268
|
+
|
|
269
|
+
##### `value`: `string | number`
|
|
270
|
+
|
|
271
|
+
The radio item's value.
|
|
272
|
+
|
|
273
|
+
- Required: yes
|
|
274
|
+
|
|
275
|
+
##### `checked`: `boolean`
|
|
276
|
+
|
|
277
|
+
The checkbox item's value, useful when using multiple checkbox items
|
|
278
|
+
associated to the same `name`.
|
|
279
|
+
|
|
280
|
+
- Required: no
|
|
281
|
+
|
|
282
|
+
##### `defaultChecked`: `boolean`
|
|
283
|
+
|
|
284
|
+
The checked state of the radio menu item when it is initially rendered. Use when not wanting to control its checked state.
|
|
285
|
+
|
|
286
|
+
- Required: no
|
|
287
|
+
|
|
288
|
+
##### `onChange`: `( event: React.ChangeEvent< HTMLInputElement > ) => void;`
|
|
289
|
+
|
|
290
|
+
Event handler called when the checked radio menu item changes.
|
|
291
|
+
|
|
292
|
+
- Required: no
|
|
293
|
+
|
|
294
|
+
### `DropdownMenuGroup`
|
|
295
|
+
|
|
296
|
+
Used to group menu items.
|
|
297
|
+
|
|
298
|
+
#### Props
|
|
299
|
+
|
|
300
|
+
The component accepts the following props:
|
|
301
|
+
|
|
302
|
+
##### `children`: `React.ReactNode`
|
|
303
|
+
|
|
304
|
+
The contents of the group.
|
|
305
|
+
|
|
306
|
+
- Required: yes
|
|
307
|
+
|
|
308
|
+
### `DropdownMenuGroupLabel`
|
|
309
|
+
|
|
310
|
+
Used to render a group label.
|
|
311
|
+
|
|
312
|
+
#### Props
|
|
313
|
+
|
|
314
|
+
The component accepts the following props:
|
|
315
|
+
|
|
316
|
+
##### `children`: `React.ReactNode`
|
|
317
|
+
|
|
318
|
+
The contents of the group.
|
|
319
|
+
|
|
320
|
+
- Required: yes
|
|
321
|
+
|
|
322
|
+
### `DropdownMenuSeparatorProps`
|
|
323
|
+
|
|
324
|
+
Used to render a visual separator.
|