@patternfly/react-core 4.211.0 → 4.211.3
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 +30 -0
- package/dist/esm/components/Menu/Menu.js +1 -1
- package/dist/esm/components/Menu/Menu.js.map +1 -1
- package/dist/esm/components/Page/PageBreadcrumb.d.ts.map +1 -1
- package/dist/esm/components/Page/PageBreadcrumb.js +1 -1
- package/dist/esm/components/Page/PageBreadcrumb.js.map +1 -1
- package/dist/esm/components/Page/PageGroup.d.ts.map +1 -1
- package/dist/esm/components/Page/PageGroup.js +1 -1
- package/dist/esm/components/Page/PageGroup.js.map +1 -1
- package/dist/esm/components/Page/PageNavigation.d.ts.map +1 -1
- package/dist/esm/components/Page/PageNavigation.js +1 -1
- package/dist/esm/components/Page/PageNavigation.js.map +1 -1
- package/dist/esm/components/Page/PageSection.d.ts.map +1 -1
- package/dist/esm/components/Page/PageSection.js +1 -1
- package/dist/esm/components/Page/PageSection.js.map +1 -1
- package/dist/esm/components/Panel/Panel.d.ts +3 -1
- package/dist/esm/components/Panel/Panel.d.ts.map +1 -1
- package/dist/esm/components/Panel/Panel.js +4 -3
- package/dist/esm/components/Panel/Panel.js.map +1 -1
- package/dist/esm/components/Tooltip/Tooltip.d.ts +6 -0
- package/dist/esm/components/Tooltip/Tooltip.d.ts.map +1 -1
- package/dist/esm/components/Tooltip/Tooltip.js +2 -2
- package/dist/esm/components/Tooltip/Tooltip.js.map +1 -1
- package/dist/esm/helpers/KeyboardHandler.d.ts +2 -0
- package/dist/esm/helpers/KeyboardHandler.d.ts.map +1 -1
- package/dist/esm/helpers/KeyboardHandler.js +3 -2
- package/dist/esm/helpers/KeyboardHandler.js.map +1 -1
- package/dist/js/components/Menu/Menu.js +1 -1
- package/dist/js/components/Menu/Menu.js.map +1 -1
- package/dist/js/components/Page/PageBreadcrumb.d.ts.map +1 -1
- package/dist/js/components/Page/PageBreadcrumb.js +1 -1
- package/dist/js/components/Page/PageBreadcrumb.js.map +1 -1
- package/dist/js/components/Page/PageGroup.d.ts.map +1 -1
- package/dist/js/components/Page/PageGroup.js +1 -1
- package/dist/js/components/Page/PageGroup.js.map +1 -1
- package/dist/js/components/Page/PageNavigation.d.ts.map +1 -1
- package/dist/js/components/Page/PageNavigation.js +1 -1
- package/dist/js/components/Page/PageNavigation.js.map +1 -1
- package/dist/js/components/Page/PageSection.d.ts.map +1 -1
- package/dist/js/components/Page/PageSection.js +1 -1
- package/dist/js/components/Page/PageSection.js.map +1 -1
- package/dist/js/components/Panel/Panel.d.ts +3 -1
- package/dist/js/components/Panel/Panel.d.ts.map +1 -1
- package/dist/js/components/Panel/Panel.js +4 -4
- package/dist/js/components/Panel/Panel.js.map +1 -1
- package/dist/js/components/Tooltip/Tooltip.d.ts +6 -0
- package/dist/js/components/Tooltip/Tooltip.d.ts.map +1 -1
- package/dist/js/components/Tooltip/Tooltip.js +2 -2
- package/dist/js/components/Tooltip/Tooltip.js.map +1 -1
- package/dist/js/helpers/KeyboardHandler.d.ts +2 -0
- package/dist/js/helpers/KeyboardHandler.d.ts.map +1 -1
- package/dist/js/helpers/KeyboardHandler.js +3 -2
- package/dist/js/helpers/KeyboardHandler.js.map +1 -1
- package/dist/umd/react-core.js +14 -12
- package/dist/umd/react-core.min.js +4 -4
- package/package.json +6 -6
- package/src/components/Menu/Menu.tsx +1 -1
- package/src/components/Page/PageBreadcrumb.tsx +1 -0
- package/src/components/Page/PageGroup.tsx +1 -0
- package/src/components/Page/PageNavigation.tsx +1 -0
- package/src/components/Page/PageSection.tsx +1 -0
- package/src/components/Page/__tests__/__snapshots__/PageBreadcrumb.test.tsx.snap +1 -0
- package/src/components/Page/__tests__/__snapshots__/PageGroup.test.tsx.snap +1 -0
- package/src/components/Page/__tests__/__snapshots__/PageNavigation.test.tsx.snap +1 -0
- package/src/components/Page/__tests__/__snapshots__/PageSection.test.tsx.snap +1 -0
- package/src/components/Panel/Panel.tsx +8 -1
- package/src/components/Tabs/examples/Tabs.md +144 -25
- package/src/components/Tooltip/Tooltip.tsx +8 -0
- package/src/components/Tooltip/examples/Tooltip.md +86 -41
- package/src/demos/ComposableMenu/ComposableMenu.md +2 -0
- package/src/demos/ComposableMenu/examples/ComposableTreeViewMenu.tsx +62 -28
- package/src/helpers/KeyboardHandler.tsx +7 -2
|
@@ -12,6 +12,7 @@ import './TooltipExamples.css';
|
|
|
12
12
|
## Examples
|
|
13
13
|
|
|
14
14
|
### Basic
|
|
15
|
+
|
|
15
16
|
```js
|
|
16
17
|
import React from 'react';
|
|
17
18
|
import { Tooltip } from '@patternfly/react-core';
|
|
@@ -22,12 +23,15 @@ import { Tooltip } from '@patternfly/react-core';
|
|
|
22
23
|
<div>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam id feugiat augue, nec fringilla turpis.</div>
|
|
23
24
|
}
|
|
24
25
|
>
|
|
25
|
-
<span tabIndex="0" style={{ border: '1px dashed' }}>
|
|
26
|
+
<span tabIndex="0" style={{ border: '1px dashed' }}>
|
|
27
|
+
I have a tooltip!
|
|
28
|
+
</span>
|
|
26
29
|
</Tooltip>
|
|
27
|
-
</div
|
|
30
|
+
</div>;
|
|
28
31
|
```
|
|
29
32
|
|
|
30
33
|
### Tooltip react ref
|
|
34
|
+
|
|
31
35
|
```js
|
|
32
36
|
import React from 'react';
|
|
33
37
|
import { Tooltip } from '@patternfly/react-core';
|
|
@@ -36,35 +40,49 @@ TooltipReactRef = () => {
|
|
|
36
40
|
const tooltipRef = React.useRef();
|
|
37
41
|
return (
|
|
38
42
|
<div style={{ margin: '100px' }}>
|
|
39
|
-
<button ref={tooltipRef}>
|
|
43
|
+
<button aria-describedby="tooltip-ref1" ref={tooltipRef}>
|
|
44
|
+
Tooltip attached via react ref
|
|
45
|
+
</button>
|
|
40
46
|
<Tooltip
|
|
47
|
+
id="tooltip-ref1"
|
|
41
48
|
content={
|
|
42
|
-
<div>
|
|
49
|
+
<div>
|
|
50
|
+
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam id feugiat augue, nec fringilla turpis.
|
|
51
|
+
</div>
|
|
43
52
|
}
|
|
44
53
|
reference={tooltipRef}
|
|
45
54
|
/>
|
|
46
55
|
</div>
|
|
47
56
|
);
|
|
48
|
-
}
|
|
57
|
+
};
|
|
49
58
|
```
|
|
50
59
|
|
|
51
60
|
### Tooltip selector ref
|
|
61
|
+
|
|
52
62
|
```js
|
|
53
63
|
import React from 'react';
|
|
54
64
|
import { Tooltip } from '@patternfly/react-core';
|
|
55
65
|
|
|
56
66
|
<div style={{ margin: '100px' }}>
|
|
57
|
-
<button id="tooltip-selector">
|
|
67
|
+
<button aria-describedby="tooltip-ref2" id="tooltip-selector">
|
|
68
|
+
Tooltip attached via selector ref
|
|
69
|
+
</button>
|
|
58
70
|
<Tooltip
|
|
71
|
+
id="tooltip-ref2"
|
|
59
72
|
content={
|
|
60
73
|
<div>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam id feugiat augue, nec fringilla turpis.</div>
|
|
61
74
|
}
|
|
62
75
|
reference={() => document.getElementById('tooltip-selector')}
|
|
63
76
|
/>
|
|
64
|
-
</div
|
|
77
|
+
</div>;
|
|
65
78
|
```
|
|
66
79
|
|
|
67
|
-
### On icon
|
|
80
|
+
### On icon with dynamic content
|
|
81
|
+
|
|
82
|
+
When the tooltip is used as a wrapper and its content will dynamically update, the `aria` prop should have a value of "none" passed in. This prevents assistive technologies from announcing the tooltip contents more than once. Additionally, the `aria-live` prop should have a value of "polite" passed in, in order for assistive technologies to announce when the tooltip contents gets updated.
|
|
83
|
+
|
|
84
|
+
When using a React or selector ref with a tooltip that has dynamic content, the `aria` and `aria-live` props do not need to be manually passed in.
|
|
85
|
+
|
|
68
86
|
```js
|
|
69
87
|
import React from 'react';
|
|
70
88
|
import { Tooltip, Button } from '@patternfly/react-core';
|
|
@@ -77,8 +95,13 @@ IconExample = () => {
|
|
|
77
95
|
const [content, setContent] = React.useState(copyText);
|
|
78
96
|
return (
|
|
79
97
|
<div style={{ margin: '100px' }}>
|
|
80
|
-
<Tooltip content={showSuccessContent ? doneCopyText : copyText}>
|
|
81
|
-
<Button
|
|
98
|
+
<Tooltip aria="none" aria-live="polite" content={showSuccessContent ? doneCopyText : copyText}>
|
|
99
|
+
<Button
|
|
100
|
+
aria-label="Clipboard"
|
|
101
|
+
variant="plain"
|
|
102
|
+
id="tt-ref"
|
|
103
|
+
onClick={() => setShowSuccessContent(!showSuccessContent)}
|
|
104
|
+
>
|
|
82
105
|
<CopyIcon />
|
|
83
106
|
</Button>
|
|
84
107
|
</Tooltip>
|
|
@@ -88,6 +111,7 @@ IconExample = () => {
|
|
|
88
111
|
```
|
|
89
112
|
|
|
90
113
|
### Options
|
|
114
|
+
|
|
91
115
|
```js
|
|
92
116
|
import React from 'react';
|
|
93
117
|
import { Button, Tooltip, Checkbox, Select, SelectOption, TextInput } from '@patternfly/react-core';
|
|
@@ -105,26 +129,26 @@ OptionsTooltip = () => {
|
|
|
105
129
|
const [exitDelayInput, setExitDelayInput] = React.useState(0);
|
|
106
130
|
const [animationDuration, setAnimationDuration] = React.useState(300);
|
|
107
131
|
const tipBoxRef = React.useRef(null);
|
|
108
|
-
|
|
132
|
+
|
|
109
133
|
const scrollToRef = ref => {
|
|
110
134
|
if (ref && ref.current) {
|
|
111
135
|
ref.current.scrollTop = 400;
|
|
112
136
|
ref.current.scrollLeft = 300;
|
|
113
137
|
}
|
|
114
|
-
}
|
|
115
|
-
|
|
138
|
+
};
|
|
139
|
+
|
|
116
140
|
React.useEffect(() => {
|
|
117
141
|
scrollToRef(tipBoxRef);
|
|
118
142
|
}, []);
|
|
119
|
-
|
|
143
|
+
|
|
120
144
|
return (
|
|
121
145
|
<>
|
|
122
146
|
<div>
|
|
123
|
-
<div style={{ border: '1px solid'}}>
|
|
147
|
+
<div style={{ border: '1px solid' }}>
|
|
124
148
|
<Checkbox
|
|
125
149
|
label="trigger: mouseenter"
|
|
126
150
|
isChecked={trigger.includes('mouseenter')}
|
|
127
|
-
onChange={
|
|
151
|
+
onChange={checked => {
|
|
128
152
|
let updatedTrigger;
|
|
129
153
|
checked && (updatedTrigger = trigger.concat('mouseenter'));
|
|
130
154
|
!checked && (updatedTrigger = trigger.filter(t => t !== 'mouseenter'));
|
|
@@ -137,7 +161,7 @@ OptionsTooltip = () => {
|
|
|
137
161
|
<Checkbox
|
|
138
162
|
label="trigger: focus"
|
|
139
163
|
isChecked={trigger.includes('focus')}
|
|
140
|
-
onChange={
|
|
164
|
+
onChange={checked => {
|
|
141
165
|
let updatedTrigger;
|
|
142
166
|
checked && (updatedTrigger = trigger.concat('focus'));
|
|
143
167
|
!checked && (updatedTrigger = trigger.filter(t => t !== 'focus'));
|
|
@@ -150,7 +174,7 @@ OptionsTooltip = () => {
|
|
|
150
174
|
<Checkbox
|
|
151
175
|
label="trigger: click"
|
|
152
176
|
isChecked={trigger.includes('click')}
|
|
153
|
-
onChange={
|
|
177
|
+
onChange={checked => {
|
|
154
178
|
let updatedTrigger;
|
|
155
179
|
checked && (updatedTrigger = trigger.concat('click'));
|
|
156
180
|
!checked && (updatedTrigger = trigger.filter(t => t !== 'click'));
|
|
@@ -163,36 +187,36 @@ OptionsTooltip = () => {
|
|
|
163
187
|
<Checkbox
|
|
164
188
|
label="trigger: manual"
|
|
165
189
|
isChecked={trigger.includes('manual')}
|
|
166
|
-
onChange={
|
|
190
|
+
onChange={checked => {
|
|
167
191
|
let updatedTrigger;
|
|
168
192
|
checked && (updatedTrigger = trigger.concat('manual'));
|
|
169
193
|
!checked && (updatedTrigger = trigger.filter(t => t !== 'manual'));
|
|
170
194
|
setIsVisible(false);
|
|
171
195
|
setTrigger(updatedTrigger);
|
|
172
196
|
}}
|
|
173
|
-
aria-label="trigger: manual"
|
|
174
|
-
id="trigger_manual"
|
|
197
|
+
aria-label="trigger: manual"
|
|
198
|
+
id="trigger_manual"
|
|
175
199
|
/>
|
|
176
200
|
</div>
|
|
177
|
-
<div style={{ border: '1px solid'}}>
|
|
201
|
+
<div style={{ border: '1px solid' }}>
|
|
178
202
|
<Checkbox
|
|
179
203
|
label="content left-aligned"
|
|
180
204
|
isChecked={contentLeftAligned}
|
|
181
|
-
onChange={
|
|
205
|
+
onChange={checked => setContentLeftAligned(checked)}
|
|
182
206
|
aria-label="content left-aligned"
|
|
183
|
-
id="content_left_aligned"
|
|
207
|
+
id="content_left_aligned"
|
|
184
208
|
/>
|
|
185
209
|
</div>
|
|
186
|
-
<div style={{ border: '1px solid'}}>
|
|
210
|
+
<div style={{ border: '1px solid' }}>
|
|
187
211
|
<Checkbox
|
|
188
212
|
label="enableFlip"
|
|
189
213
|
isChecked={enableFlip}
|
|
190
|
-
onChange={
|
|
191
|
-
aria-label="enableFlip"
|
|
192
|
-
id="enable_flip"
|
|
214
|
+
onChange={checked => setEnableFlip(checked)}
|
|
215
|
+
aria-label="enableFlip"
|
|
216
|
+
id="enable_flip"
|
|
193
217
|
/>
|
|
194
218
|
</div>
|
|
195
|
-
<div style={{ border: '1px solid'}}>
|
|
219
|
+
<div style={{ border: '1px solid' }}>
|
|
196
220
|
position (will flip if enableFlip is true). The 'auto' position requires enableFlip to be set to true.
|
|
197
221
|
<Select
|
|
198
222
|
onToggle={() => setPositionSelectOpen(!positionSelectOpen)}
|
|
@@ -219,22 +243,41 @@ OptionsTooltip = () => {
|
|
|
219
243
|
<SelectOption value="right-end" />
|
|
220
244
|
</Select>
|
|
221
245
|
</div>
|
|
222
|
-
<div style={{ border: '1px solid'}}>
|
|
246
|
+
<div style={{ border: '1px solid' }}>
|
|
223
247
|
<Checkbox
|
|
224
248
|
label="isVisible (also set trigger to only manual to programmatically control it)"
|
|
225
249
|
isChecked={isVisible}
|
|
226
|
-
onChange={
|
|
227
|
-
aria-label="isVisible"
|
|
228
|
-
id="is_visible"
|
|
250
|
+
onChange={checked => setIsVisible(checked)}
|
|
251
|
+
aria-label="isVisible"
|
|
252
|
+
id="is_visible"
|
|
229
253
|
/>
|
|
230
254
|
</div>
|
|
231
|
-
<div style={{ border: '1px solid'}}>
|
|
232
|
-
Entry delay (ms)
|
|
233
|
-
|
|
234
|
-
|
|
255
|
+
<div style={{ border: '1px solid' }}>
|
|
256
|
+
Entry delay (ms){' '}
|
|
257
|
+
<TextInput
|
|
258
|
+
value={entryDelayInput}
|
|
259
|
+
type="number"
|
|
260
|
+
onChange={val => setEntryDelayInput(val)}
|
|
261
|
+
aria-label="entry delay"
|
|
262
|
+
/>
|
|
263
|
+
Exit delay (ms) <TextInput
|
|
264
|
+
value={exitDelayInput}
|
|
265
|
+
type="number"
|
|
266
|
+
onChange={val => setExitDelayInput(val)}
|
|
267
|
+
aria-label="exit delay"
|
|
268
|
+
/>
|
|
269
|
+
Animation duration (ms){' '}
|
|
270
|
+
<TextInput
|
|
271
|
+
value={animationDuration}
|
|
272
|
+
type="number"
|
|
273
|
+
onChange={val => setAnimationDuration(val)}
|
|
274
|
+
aria-label="animation duration"
|
|
275
|
+
/>
|
|
235
276
|
</div>
|
|
236
|
-
<div style={{ border: '1px solid'}}>
|
|
237
|
-
flip behavior examples (enableFlip has to be true). "flip" will try to flip the tooltip to the opposite of the
|
|
277
|
+
<div style={{ border: '1px solid' }}>
|
|
278
|
+
flip behavior examples (enableFlip has to be true). "flip" will try to flip the tooltip to the opposite of the
|
|
279
|
+
starting position. The second option ensures that there are 3 escape positions for every possible starting
|
|
280
|
+
position (default). This setting is ignored if position prop is set to 'auto'.
|
|
238
281
|
<Select
|
|
239
282
|
onToggle={() => setFlipSelectOpen(!flipSelectOpen)}
|
|
240
283
|
onSelect={(event, selection) => {
|
|
@@ -254,7 +297,9 @@ OptionsTooltip = () => {
|
|
|
254
297
|
<div id="tooltip-boundary" className="tooltip-box" ref={tipBoxRef}>
|
|
255
298
|
<Tooltip
|
|
256
299
|
content={
|
|
257
|
-
<div>
|
|
300
|
+
<div>
|
|
301
|
+
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam id feugiat augue, nec fringilla turpis.
|
|
302
|
+
</div>
|
|
258
303
|
}
|
|
259
304
|
trigger={trigger.join(' ')}
|
|
260
305
|
enableFlip={enableFlip}
|
|
@@ -272,5 +317,5 @@ OptionsTooltip = () => {
|
|
|
272
317
|
</div>
|
|
273
318
|
</>
|
|
274
319
|
);
|
|
275
|
-
}
|
|
320
|
+
};
|
|
276
321
|
```
|
|
@@ -47,6 +47,8 @@ Composable menus currently require consumer keyboard handling and use of our und
|
|
|
47
47
|
|
|
48
48
|
### Composable tree view menu
|
|
49
49
|
|
|
50
|
+
When rendering a menu-like element that does not contain MenuItem components, [Panel](/components/panel) allows more flexible control and customization.
|
|
51
|
+
|
|
50
52
|
```ts file="./examples/ComposableTreeViewMenu.tsx"
|
|
51
53
|
```
|
|
52
54
|
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import {
|
|
3
3
|
MenuToggle,
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
4
|
+
Panel,
|
|
5
|
+
PanelMain,
|
|
6
|
+
PanelMainBody,
|
|
7
|
+
Title,
|
|
8
8
|
Popper,
|
|
9
9
|
TreeView,
|
|
10
10
|
TreeViewDataItem
|
|
@@ -14,6 +14,7 @@ export const ComposableTreeViewMenu: React.FunctionComponent = () => {
|
|
|
14
14
|
const [isOpen, setIsOpen] = React.useState<boolean>(false);
|
|
15
15
|
const [checkedItems, setCheckedItems] = React.useState<TreeViewDataItem[]>([]);
|
|
16
16
|
const toggleRef = React.useRef<HTMLButtonElement>();
|
|
17
|
+
const containerRef = React.useRef<HTMLDivElement>();
|
|
17
18
|
const menuRef = React.useRef<HTMLDivElement>();
|
|
18
19
|
|
|
19
20
|
const statusOptions: TreeViewDataItem[] = [
|
|
@@ -85,7 +86,7 @@ export const ComposableTreeViewMenu: React.FunctionComponent = () => {
|
|
|
85
86
|
customBadgeContent: 0
|
|
86
87
|
}
|
|
87
88
|
];
|
|
88
|
-
// Helper functions
|
|
89
|
+
// Helper functions for tree
|
|
89
90
|
const isChecked = (dataItem: TreeViewDataItem) => checkedItems.some(item => item.id === dataItem.id);
|
|
90
91
|
const areAllDescendantsChecked = (dataItem: TreeViewDataItem) =>
|
|
91
92
|
dataItem.children ? dataItem.children.every(child => areAllDescendantsChecked(child)) : isChecked(dataItem);
|
|
@@ -163,18 +164,32 @@ export const ComposableTreeViewMenu: React.FunctionComponent = () => {
|
|
|
163
164
|
);
|
|
164
165
|
};
|
|
165
166
|
|
|
167
|
+
// Controls keys that should open/close the menu
|
|
166
168
|
const handleMenuKeys = (event: KeyboardEvent) => {
|
|
167
169
|
if (!isOpen) {
|
|
168
170
|
return;
|
|
169
171
|
}
|
|
170
172
|
if (menuRef.current.contains(event.target as Node) || toggleRef.current.contains(event.target as Node)) {
|
|
171
|
-
|
|
173
|
+
// The escape key when pressed while inside the menu should close the menu and refocus the toggle
|
|
174
|
+
if (event.key === 'Escape') {
|
|
172
175
|
setIsOpen(!isOpen);
|
|
173
176
|
toggleRef.current.focus();
|
|
174
177
|
}
|
|
178
|
+
|
|
179
|
+
// The tab key when pressed while inside the menu and on the contained last tree view should close the menu and refocus the toggle
|
|
180
|
+
// Shift tab should keep the default behavior to return to a previous tree view
|
|
181
|
+
if (event.key === 'Tab' && !event.shiftKey) {
|
|
182
|
+
const treeList = menuRef.current.querySelectorAll('.pf-c-tree-view');
|
|
183
|
+
if (treeList[treeList.length - 1].contains(event.target as Node)) {
|
|
184
|
+
event.preventDefault();
|
|
185
|
+
setIsOpen(!isOpen);
|
|
186
|
+
toggleRef.current.focus();
|
|
187
|
+
}
|
|
188
|
+
}
|
|
175
189
|
}
|
|
176
190
|
};
|
|
177
191
|
|
|
192
|
+
// Controls that a click outside the menu while the menu is open should close the menu
|
|
178
193
|
const handleClickOutside = (event: MouseEvent) => {
|
|
179
194
|
if (isOpen && !menuRef.current.contains(event.target as Node)) {
|
|
180
195
|
setIsOpen(false);
|
|
@@ -194,7 +209,7 @@ export const ComposableTreeViewMenu: React.FunctionComponent = () => {
|
|
|
194
209
|
ev.stopPropagation(); // Stop handleClickOutside from handling
|
|
195
210
|
setTimeout(() => {
|
|
196
211
|
if (menuRef.current) {
|
|
197
|
-
const firstElement = menuRef.current.querySelector('li
|
|
212
|
+
const firstElement = menuRef.current.querySelector('li button:not(:disabled)');
|
|
198
213
|
firstElement && (firstElement as HTMLElement).focus();
|
|
199
214
|
}
|
|
200
215
|
}, 0);
|
|
@@ -202,39 +217,58 @@ export const ComposableTreeViewMenu: React.FunctionComponent = () => {
|
|
|
202
217
|
};
|
|
203
218
|
|
|
204
219
|
const toggle = (
|
|
205
|
-
<
|
|
206
|
-
{
|
|
207
|
-
|
|
220
|
+
<div ref={containerRef}>
|
|
221
|
+
<MenuToggle ref={toggleRef} onClick={onToggleClick} isExpanded={isOpen}>
|
|
222
|
+
{isOpen ? 'Expanded' : 'Collapsed'}
|
|
223
|
+
</MenuToggle>
|
|
224
|
+
</div>
|
|
208
225
|
);
|
|
209
226
|
const statusMapped = statusOptions.map(mapTree);
|
|
210
227
|
const roleMapped = roleOptions.map(mapTree);
|
|
211
228
|
const menu = (
|
|
212
|
-
<
|
|
229
|
+
<Panel
|
|
213
230
|
ref={menuRef}
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
'--pf-c-menu--Width': '300px'
|
|
219
|
-
} as React.CSSProperties
|
|
220
|
-
}
|
|
231
|
+
variant="raised"
|
|
232
|
+
style={{
|
|
233
|
+
width: '300px'
|
|
234
|
+
}}
|
|
221
235
|
>
|
|
222
|
-
<
|
|
223
|
-
<
|
|
224
|
-
<
|
|
236
|
+
<PanelMain>
|
|
237
|
+
<section>
|
|
238
|
+
<PanelMainBody style={{ paddingBottom: 0 }}>
|
|
239
|
+
<Title headingLevel="h1" size={'md'}>
|
|
240
|
+
Status
|
|
241
|
+
</Title>
|
|
242
|
+
</PanelMainBody>
|
|
243
|
+
<PanelMainBody style={{ padding: 0 }}>
|
|
225
244
|
<TreeView
|
|
226
245
|
data={statusMapped}
|
|
227
246
|
hasBadges
|
|
228
247
|
hasChecks
|
|
229
248
|
onCheck={(event, item) => onCheck(event, item, 'status')}
|
|
230
249
|
/>
|
|
231
|
-
</
|
|
232
|
-
|
|
250
|
+
</PanelMainBody>
|
|
251
|
+
</section>
|
|
252
|
+
<section>
|
|
253
|
+
<PanelMainBody style={{ paddingBottom: 0, paddingTop: 0 }}>
|
|
254
|
+
<Title headingLevel="h1" size={'md'}>
|
|
255
|
+
Roles
|
|
256
|
+
</Title>
|
|
257
|
+
</PanelMainBody>
|
|
258
|
+
<PanelMainBody style={{ padding: 0 }}>
|
|
233
259
|
<TreeView data={roleMapped} hasBadges hasChecks onCheck={(event, item) => onCheck(event, item, 'role')} />
|
|
234
|
-
</
|
|
235
|
-
</
|
|
236
|
-
</
|
|
237
|
-
</
|
|
260
|
+
</PanelMainBody>
|
|
261
|
+
</section>
|
|
262
|
+
</PanelMain>
|
|
263
|
+
</Panel>
|
|
264
|
+
);
|
|
265
|
+
return (
|
|
266
|
+
<Popper
|
|
267
|
+
trigger={toggle}
|
|
268
|
+
popper={menu}
|
|
269
|
+
isVisible={isOpen}
|
|
270
|
+
appendTo={containerRef.current}
|
|
271
|
+
popperMatchesTriggerWidth={false}
|
|
272
|
+
/>
|
|
238
273
|
);
|
|
239
|
-
return <Popper trigger={toggle} popper={menu} isVisible={isOpen} popperMatchesTriggerWidth={false} />;
|
|
240
274
|
};
|
|
@@ -18,6 +18,8 @@ export interface KeyboardHandlerProps {
|
|
|
18
18
|
validSiblingTags?: string[];
|
|
19
19
|
/** Flag indicating that the tabIndex of the currently focused element and next focused element should be updated, in the case of using a roving tabIndex */
|
|
20
20
|
updateTabIndex?: boolean;
|
|
21
|
+
/** Flag indicating that next focusable element of a horizontal movement will be this element's sibling */
|
|
22
|
+
onlyTraverseSiblings?: boolean;
|
|
21
23
|
/** Flag indicating that the included vertical arrow key handling should be ignored */
|
|
22
24
|
noVerticalArrowHandling?: boolean;
|
|
23
25
|
/** Flag indicating that the included horizontal arrow key handling should be ignored */
|
|
@@ -176,6 +178,7 @@ export class KeyboardHandler extends React.Component<KeyboardHandlerProps> {
|
|
|
176
178
|
isActiveElement: (navigableElement: Element) => document.activeElement === navigableElement,
|
|
177
179
|
getFocusableElement: (navigableElement: Element) => navigableElement,
|
|
178
180
|
validSiblingTags: ['BUTTON', 'A'],
|
|
181
|
+
onlyTraverseSiblings: true,
|
|
179
182
|
updateTabIndex: true,
|
|
180
183
|
noHorizontalArrowHandling: false,
|
|
181
184
|
noVerticalArrowHandling: false,
|
|
@@ -212,7 +215,8 @@ export class KeyboardHandler extends React.Component<KeyboardHandlerProps> {
|
|
|
212
215
|
updateTabIndex,
|
|
213
216
|
validSiblingTags,
|
|
214
217
|
additionalKeyHandler,
|
|
215
|
-
createNavigableElements
|
|
218
|
+
createNavigableElements,
|
|
219
|
+
onlyTraverseSiblings
|
|
216
220
|
} = this.props;
|
|
217
221
|
|
|
218
222
|
// Pass the event off to be handled by any custom handler
|
|
@@ -256,7 +260,8 @@ export class KeyboardHandler extends React.Component<KeyboardHandlerProps> {
|
|
|
256
260
|
validSiblingTags,
|
|
257
261
|
noVerticalArrowHandling,
|
|
258
262
|
noHorizontalArrowHandling,
|
|
259
|
-
updateTabIndex
|
|
263
|
+
updateTabIndex,
|
|
264
|
+
onlyTraverseSiblings
|
|
260
265
|
);
|
|
261
266
|
};
|
|
262
267
|
|