@patternfly/react-core 4.224.9 → 4.224.10

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.
Files changed (88) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/dist/esm/components/ContextSelector/ContextSelector.d.ts +2 -0
  3. package/dist/esm/components/ContextSelector/ContextSelector.d.ts.map +1 -1
  4. package/dist/esm/components/ContextSelector/ContextSelector.js +8 -11
  5. package/dist/esm/components/ContextSelector/ContextSelector.js.map +1 -1
  6. package/dist/esm/components/ContextSelector/ContextSelectorMenuList.d.ts.map +1 -1
  7. package/dist/esm/components/ContextSelector/ContextSelectorMenuList.js +2 -1
  8. package/dist/esm/components/ContextSelector/ContextSelectorMenuList.js.map +1 -1
  9. package/dist/esm/components/DualListSelector/DualListSelector.d.ts.map +1 -1
  10. package/dist/esm/components/DualListSelector/DualListSelector.js +6 -6
  11. package/dist/esm/components/DualListSelector/DualListSelector.js.map +1 -1
  12. package/dist/esm/components/DualListSelector/DualListSelectorControlsWrapper.js +1 -1
  13. package/dist/esm/components/DualListSelector/DualListSelectorControlsWrapper.js.map +1 -1
  14. package/dist/esm/components/DualListSelector/DualListSelectorList.d.ts +1 -0
  15. package/dist/esm/components/DualListSelector/DualListSelectorList.d.ts.map +1 -1
  16. package/dist/esm/components/DualListSelector/DualListSelectorList.js +7 -1
  17. package/dist/esm/components/DualListSelector/DualListSelectorList.js.map +1 -1
  18. package/dist/esm/components/DualListSelector/DualListSelectorTree.d.ts +3 -2
  19. package/dist/esm/components/DualListSelector/DualListSelectorTree.d.ts.map +1 -1
  20. package/dist/esm/components/DualListSelector/DualListSelectorTree.js.map +1 -1
  21. package/dist/js/components/ContextSelector/ContextSelector.d.ts +2 -0
  22. package/dist/js/components/ContextSelector/ContextSelector.d.ts.map +1 -1
  23. package/dist/js/components/ContextSelector/ContextSelector.js +7 -10
  24. package/dist/js/components/ContextSelector/ContextSelector.js.map +1 -1
  25. package/dist/js/components/ContextSelector/ContextSelectorMenuList.d.ts.map +1 -1
  26. package/dist/js/components/ContextSelector/ContextSelectorMenuList.js +2 -1
  27. package/dist/js/components/ContextSelector/ContextSelectorMenuList.js.map +1 -1
  28. package/dist/js/components/DualListSelector/DualListSelector.d.ts.map +1 -1
  29. package/dist/js/components/DualListSelector/DualListSelector.js +5 -5
  30. package/dist/js/components/DualListSelector/DualListSelector.js.map +1 -1
  31. package/dist/js/components/DualListSelector/DualListSelectorControlsWrapper.js +1 -1
  32. package/dist/js/components/DualListSelector/DualListSelectorControlsWrapper.js.map +1 -1
  33. package/dist/js/components/DualListSelector/DualListSelectorList.d.ts +1 -0
  34. package/dist/js/components/DualListSelector/DualListSelectorList.d.ts.map +1 -1
  35. package/dist/js/components/DualListSelector/DualListSelectorList.js +7 -1
  36. package/dist/js/components/DualListSelector/DualListSelectorList.js.map +1 -1
  37. package/dist/js/components/DualListSelector/DualListSelectorTree.d.ts +3 -2
  38. package/dist/js/components/DualListSelector/DualListSelectorTree.d.ts.map +1 -1
  39. package/dist/js/components/DualListSelector/DualListSelectorTree.js.map +1 -1
  40. package/dist/styles/base-no-reset.css +10 -10
  41. package/dist/styles/base.css +10 -10
  42. package/dist/umd/react-core.css +424 -392
  43. package/dist/umd/react-core.js +29 -24
  44. package/dist/umd/react-core.min.css +244 -212
  45. package/dist/umd/react-core.min.js +4 -4
  46. package/package.json +6 -6
  47. package/src/components/Accordion/examples/AccordionBordered.tsx +21 -21
  48. package/src/components/Accordion/examples/AccordionDefinitionList.tsx +21 -21
  49. package/src/components/ActionList/examples/ActionListMultipleGroups.tsx +4 -4
  50. package/src/components/ActionList/examples/ActionListSingleGroup.tsx +4 -4
  51. package/src/components/ActionList/examples/ActionListWithCancelButton.tsx +5 -5
  52. package/src/components/ActionList/examples/ActionListWithIcons.tsx +2 -2
  53. package/src/components/Card/examples/CardSelectableA11yHighlight.tsx +4 -4
  54. package/src/components/CodeBlock/examples/CodeBlockBasic.tsx +1 -1
  55. package/src/components/CodeBlock/examples/CodeBlockExpandable.tsx +1 -1
  56. package/src/components/ContextSelector/ContextSelector.tsx +11 -10
  57. package/src/components/ContextSelector/ContextSelectorMenuList.tsx +2 -1
  58. package/src/components/ContextSelector/__tests__/ContextSelector.test.tsx +2 -2
  59. package/src/components/ContextSelector/__tests__/__snapshots__/ContextSelector.test.tsx.snap +11 -7
  60. package/src/components/ContextSelector/__tests__/__snapshots__/ContextSelectorMenuList.test.tsx.snap +10 -0
  61. package/src/components/DataList/examples/DataListCompact.tsx +4 -4
  62. package/src/components/DataList/examples/DataListControllingText.tsx +3 -3
  63. package/src/components/DataList/examples/DataListDraggable.tsx +14 -7
  64. package/src/components/DataList/examples/DataListExpandable.tsx +3 -3
  65. package/src/components/DataList/examples/DataListSmGridBreakpoint.tsx +3 -3
  66. package/src/components/DualListSelector/DualListSelector.tsx +93 -89
  67. package/src/components/DualListSelector/DualListSelectorControlsWrapper.tsx +1 -1
  68. package/src/components/DualListSelector/DualListSelectorList.tsx +10 -4
  69. package/src/components/DualListSelector/DualListSelectorTree.tsx +3 -2
  70. package/src/components/DualListSelector/__tests__/__snapshots__/DualListSelector.test.tsx.snap +6 -20
  71. package/src/components/DualListSelector/examples/DualListSelector.md +3 -1
  72. package/src/components/DualListSelector/examples/DualListSelectorComposable.tsx +1 -1
  73. package/src/components/DualListSelector/examples/DualListSelectorComposableDragDrop.tsx +1 -1
  74. package/src/components/DualListSelector/examples/DualListSelectorComposableTree.tsx +1 -1
  75. package/src/components/DualListSelector/examples/{DualListSelectorTree.tsx → DualListSelectorTreeExample.tsx} +1 -1
  76. package/src/components/FileUpload/examples/FileUploadCustomUpload.tsx +1 -1
  77. package/src/components/FileUpload/examples/FileUploadSimpleText.tsx +1 -1
  78. package/src/components/FileUpload/examples/FileUploadTextWithEdits.tsx +1 -1
  79. package/src/components/FileUpload/examples/FileUploadTextWithRestrictions.tsx +2 -2
  80. package/src/components/InputGroup/examples/InputGroupBasic.tsx +3 -3
  81. package/src/components/InputGroup/examples/InputGroupWithDropdown.tsx +1 -1
  82. package/src/components/InputGroup/examples/InputGroupWithPopover.tsx +12 -2
  83. package/src/components/InputGroup/examples/InputGroupWithSiblings.tsx +7 -2
  84. package/src/components/InputGroup/examples/InputGroupWithTextarea.tsx +1 -1
  85. package/src/components/LoginPage/examples/LoginPage.md +2 -325
  86. package/src/components/LoginPage/examples/LoginPageBasic.tsx +144 -0
  87. package/src/components/LoginPage/examples/LoginPageShowHidePassword.tsx +145 -0
  88. package/src/components/NotificationDrawer/examples/NotificationDrawer.md +69 -68
@@ -12,6 +12,7 @@ exports[`Renders ContextSelectorMenuList closed 1`] = `
12
12
  >
13
13
  <button
14
14
  class="pf-c-context-selector__menu-list-item"
15
+ role="menuitem"
15
16
  >
16
17
  My Project
17
18
  </button>
@@ -21,6 +22,7 @@ exports[`Renders ContextSelectorMenuList closed 1`] = `
21
22
  >
22
23
  <button
23
24
  class="pf-c-context-selector__menu-list-item"
25
+ role="menuitem"
24
26
  >
25
27
  OpenShift Cluster
26
28
  </button>
@@ -30,6 +32,7 @@ exports[`Renders ContextSelectorMenuList closed 1`] = `
30
32
  >
31
33
  <button
32
34
  class="pf-c-context-selector__menu-list-item"
35
+ role="menuitem"
33
36
  >
34
37
  Production Ansible
35
38
  </button>
@@ -39,6 +42,7 @@ exports[`Renders ContextSelectorMenuList closed 1`] = `
39
42
  >
40
43
  <button
41
44
  class="pf-c-context-selector__menu-list-item"
45
+ role="menuitem"
42
46
  >
43
47
  AWS
44
48
  </button>
@@ -48,6 +52,7 @@ exports[`Renders ContextSelectorMenuList closed 1`] = `
48
52
  >
49
53
  <button
50
54
  class="pf-c-context-selector__menu-list-item"
55
+ role="menuitem"
51
56
  >
52
57
  Azure
53
58
  </button>
@@ -68,6 +73,7 @@ exports[`Renders ContextSelectorMenuList open 1`] = `
68
73
  >
69
74
  <button
70
75
  class="pf-c-context-selector__menu-list-item"
76
+ role="menuitem"
71
77
  >
72
78
  My Project
73
79
  </button>
@@ -77,6 +83,7 @@ exports[`Renders ContextSelectorMenuList open 1`] = `
77
83
  >
78
84
  <button
79
85
  class="pf-c-context-selector__menu-list-item"
86
+ role="menuitem"
80
87
  >
81
88
  OpenShift Cluster
82
89
  </button>
@@ -86,6 +93,7 @@ exports[`Renders ContextSelectorMenuList open 1`] = `
86
93
  >
87
94
  <button
88
95
  class="pf-c-context-selector__menu-list-item"
96
+ role="menuitem"
89
97
  >
90
98
  Production Ansible
91
99
  </button>
@@ -95,6 +103,7 @@ exports[`Renders ContextSelectorMenuList open 1`] = `
95
103
  >
96
104
  <button
97
105
  class="pf-c-context-selector__menu-list-item"
106
+ role="menuitem"
98
107
  >
99
108
  AWS
100
109
  </button>
@@ -104,6 +113,7 @@ exports[`Renders ContextSelectorMenuList open 1`] = `
104
113
  >
105
114
  <button
106
115
  class="pf-c-context-selector__menu-list-item"
116
+ role="menuitem"
107
117
  >
108
118
  Azure
109
119
  </button>
@@ -3,24 +3,24 @@ import { DataList, DataListItem, DataListItemRow, DataListItemCells, DataListCel
3
3
 
4
4
  export const DataListCompact: React.FunctionComponent = () => (
5
5
  <DataList aria-label="Compact data list example" isCompact>
6
- <DataListItem aria-labelledby="simple-item1">
6
+ <DataListItem aria-labelledby="compact-item1">
7
7
  <DataListItemRow>
8
8
  <DataListItemCells
9
9
  dataListCells={[
10
10
  <DataListCell key="primary content">
11
- <span id="simple-item1">Primary content</span>
11
+ <span id="compact-item1">Primary content</span>
12
12
  </DataListCell>,
13
13
  <DataListCell key="secondary content">Secondary content</DataListCell>
14
14
  ]}
15
15
  />
16
16
  </DataListItemRow>
17
17
  </DataListItem>
18
- <DataListItem aria-labelledby="simple-item2">
18
+ <DataListItem aria-labelledby="compact-item2">
19
19
  <DataListItemRow>
20
20
  <DataListItemCells
21
21
  dataListCells={[
22
22
  <DataListCell isFilled={false} key="secondary content fill">
23
- <span id="simple-item2">Secondary content (pf-m-no-fill)</span>
23
+ <span id="compact-item2">Secondary content (pf-m-no-fill)</span>
24
24
  </DataListCell>,
25
25
  <DataListCell isFilled={false} alignRight key="secondary content align">
26
26
  Secondary content (pf-m-align-right pf-m-no-fill)
@@ -9,13 +9,13 @@ import {
9
9
  } from '@patternfly/react-core';
10
10
 
11
11
  export const DataListControllingText: React.FunctionComponent = () => (
12
- <DataList aria-label="Simple data list example">
13
- <DataListItem aria-labelledby="simple-item1">
12
+ <DataList aria-label="Controlling text data list example">
13
+ <DataListItem aria-labelledby="controlling-text-item1">
14
14
  <DataListItemRow>
15
15
  <DataListItemCells
16
16
  dataListCells={[
17
17
  <DataListCell key="primary content" wrapModifier={DataListWrapModifier.breakWord}>
18
- <span id="simple-item1">Primary content</span>
18
+ <span id="controlling-text-item1">Primary content</span>
19
19
  </DataListCell>,
20
20
  <DataListCell key="secondary content" wrapModifier={DataListWrapModifier.truncate}>
21
21
  Really really really really really really really really really really really really really really long
@@ -10,7 +10,8 @@ import {
10
10
  DataListItemCells,
11
11
  DragDrop,
12
12
  Draggable,
13
- Droppable
13
+ Droppable,
14
+ getUniqueId
14
15
  } from '@patternfly/react-core';
15
16
 
16
17
  interface ItemType {
@@ -20,7 +21,7 @@ interface ItemType {
20
21
 
21
22
  const getItems = (count: number) =>
22
23
  Array.from({ length: count }, (_, idx) => idx).map(idx => ({
23
- id: `item-${idx}`,
24
+ id: `draggable-item-${idx}`,
24
25
  content: `item ${idx} `.repeat(idx === 4 ? 20 : 1)
25
26
  }));
26
27
 
@@ -60,27 +61,29 @@ export const DataListDraggable: React.FunctionComponent = () => {
60
61
  }
61
62
  }
62
63
 
64
+ const uniqueId = getUniqueId();
65
+
63
66
  return (
64
67
  <DragDrop onDrag={onDrag} onDragMove={onDragMove} onDrop={onDrop}>
65
68
  <Droppable hasNoWrapper>
66
69
  <DataList aria-label="draggable data list example" isCompact>
67
70
  {items.map(({ id, content }) => (
68
71
  <Draggable key={id} hasNoWrapper>
69
- <DataListItem aria-labelledby={id} ref={React.createRef()}>
72
+ <DataListItem aria-labelledby={`draggable-${id}`} ref={React.createRef()}>
70
73
  <DataListItemRow>
71
74
  <DataListControl>
72
75
  <DataListDragButton
73
76
  aria-label="Reorder"
74
- aria-labelledby={id}
75
- aria-describedby="Press space or enter to begin dragging, and use the arrow keys to navigate up or down. Press enter to confirm the drag, or any other key to cancel the drag operation."
77
+ aria-labelledby={`draggable-${id}`}
78
+ aria-describedby={`description-${uniqueId}`}
76
79
  aria-pressed="false"
77
80
  />
78
- <DataListCheck aria-labelledby={id} name={id} otherControls />
81
+ <DataListCheck aria-labelledby={`draggable-${id}`} name={id} otherControls />
79
82
  </DataListControl>
80
83
  <DataListItemCells
81
84
  dataListCells={[
82
85
  <DataListCell key={id}>
83
- <span id={id}>{content}</span>
86
+ <span id={`draggable-${id}`}>{content}</span>
84
87
  </DataListCell>
85
88
  ]}
86
89
  />
@@ -93,6 +96,10 @@ export const DataListDraggable: React.FunctionComponent = () => {
93
96
  <div className="pf-screen-reader" aria-live="assertive">
94
97
  {liveText}
95
98
  </div>
99
+ <div className="pf-screen-reader" id={`description-${uniqueId}`}>
100
+ Press space or enter to begin dragging, and use the arrow keys to navigate up or down. Press enter to confirm
101
+ the drag, or any other key to cancel the drag operation.
102
+ </div>
96
103
  </DragDrop>
97
104
  );
98
105
  };
@@ -104,7 +104,7 @@ export const DataListExpandable: React.FunctionComponent = () => {
104
104
  </DataListAction>
105
105
  </DataListItemRow>
106
106
  <DataListContent
107
- aria-label="Primary Content Details"
107
+ aria-label="First expandable content details"
108
108
  id="ex-expand1"
109
109
  isHidden={!expanded.includes('ex-toggle1')}
110
110
  >
@@ -164,7 +164,7 @@ export const DataListExpandable: React.FunctionComponent = () => {
164
164
  </DataListAction>
165
165
  </DataListItemRow>
166
166
  <DataListContent
167
- aria-label="Primary Content Details"
167
+ aria-label="Second expandable content details"
168
168
  id="ex-expand2"
169
169
  isHidden={!expanded.includes('ex-toggle2')}
170
170
  >
@@ -224,7 +224,7 @@ export const DataListExpandable: React.FunctionComponent = () => {
224
224
  </DataListAction>
225
225
  </DataListItemRow>
226
226
  <DataListContent
227
- aria-label="Primary Content Details"
227
+ aria-label="Third expandable content details"
228
228
  id="ex-expand3"
229
229
  isHidden={!expanded.includes('ex-toggle3')}
230
230
  hasNoPadding
@@ -2,13 +2,13 @@ import React from 'react';
2
2
  import { DataList, DataListItem, DataListItemRow, DataListItemCells, DataListCell } from '@patternfly/react-core';
3
3
 
4
4
  export const DataListSmGridBreakpoint: React.FunctionComponent = () => (
5
- <DataList aria-label="Simple data list example" gridBreakpoint="sm">
6
- <DataListItem aria-labelledby="simple-item1">
5
+ <DataList aria-label="Small grid breakpoint list example" gridBreakpoint="sm">
6
+ <DataListItem aria-labelledby="sm-grid-item1">
7
7
  <DataListItemRow>
8
8
  <DataListItemCells
9
9
  dataListCells={[
10
10
  <DataListCell key="primary content">
11
- <span id="simple-item1">Primary content</span>
11
+ <span id="sm-grid-item1">Primary content</span>
12
12
  </DataListCell>,
13
13
  <DataListCell key="secondary content">
14
14
  Really really really really really really really really really really really really really really long
@@ -6,7 +6,7 @@ import AngleLeftIcon from '@patternfly/react-icons/dist/esm/icons/angle-left-ico
6
6
  import AngleDoubleRightIcon from '@patternfly/react-icons/dist/esm/icons/angle-double-right-icon';
7
7
  import AngleRightIcon from '@patternfly/react-icons/dist/esm/icons/angle-right-icon';
8
8
  import { DualListSelectorPane } from './DualListSelectorPane';
9
- import { getUniqueId, PickOptional } from '../../helpers';
9
+ import { GenerateId, PickOptional } from '../../helpers';
10
10
  import { DualListSelectorTreeItemData } from './DualListSelectorTree';
11
11
  import {
12
12
  flattenTree,
@@ -140,7 +140,6 @@ export class DualListSelector extends React.Component<DualListSelectorProps, Dua
140
140
  chosenOptions: [],
141
141
  chosenOptionsTitle: 'Chosen options',
142
142
  chosenOptionsSearchAriaLabel: 'Chosen search input',
143
- id: getUniqueId('dual-list-selector'),
144
143
  controlsAriaLabel: 'Selector controls',
145
144
  addAllAriaLabel: 'Add all',
146
145
  addSelectedAriaLabel: 'Add selected',
@@ -678,94 +677,99 @@ export class DualListSelector extends React.Component<DualListSelectorProps, Dua
678
677
 
679
678
  return (
680
679
  <DualListSelectorContext.Provider value={{ isTree }}>
681
- <div className={css(styles.dualListSelector, className)} id={id} {...props}>
682
- {children === '' ? (
683
- <>
684
- <DualListSelectorPane
685
- isSearchable={isSearchable}
686
- onFilterUpdate={this.onFilterUpdate}
687
- searchInputAriaLabel={availableOptionsSearchAriaLabel}
688
- filterOption={filterOption}
689
- onSearchInputChanged={onAvailableOptionsSearchInputChanged}
690
- status={availableOptionsStatusToDisplay}
691
- title={availableOptionsTitle}
692
- options={available}
693
- selectedOptions={isTree ? availableTreeOptionsChecked : availableOptionsSelected}
694
- onOptionSelect={this.onOptionSelect}
695
- onOptionCheck={(e, isChecked, itemData) => this.onTreeOptionCheck(e, isChecked, itemData, false)}
696
- actions={availableOptionsActions}
697
- id={`${id}-available-pane`}
698
- isDisabled={isDisabled}
699
- />
700
- <DualListSelectorControlsWrapper aria-label={controlsAriaLabel}>
701
- <DualListSelectorControl
702
- isDisabled={
703
- (isTree ? availableTreeOptionsChecked.length === 0 : availableOptionsSelected.length === 0) ||
704
- isDisabled
705
- }
706
- onClick={isTree ? this.addTreeSelected : this.addSelected}
707
- ref={this.addSelectedButtonRef}
708
- aria-label={addSelectedAriaLabel}
709
- tooltipContent={addSelectedTooltip}
710
- tooltipProps={addSelectedTooltipProps}
711
- >
712
- <AngleRightIcon />
713
- </DualListSelectorControl>
714
- <DualListSelectorControl
715
- isDisabled={availableOptions.length === 0 || isDisabled}
716
- onClick={isTree ? this.addAllTreeVisible : this.addAllVisible}
717
- ref={this.addAllButtonRef}
718
- aria-label={addAllAriaLabel}
719
- tooltipContent={addAllTooltip}
720
- tooltipProps={addAllTooltipProps}
721
- >
722
- <AngleDoubleRightIcon />
723
- </DualListSelectorControl>
724
- <DualListSelectorControl
725
- isDisabled={chosenOptions.length === 0 || isDisabled}
726
- onClick={isTree ? this.removeAllTreeVisible : this.removeAllVisible}
727
- aria-label={removeAllAriaLabel}
728
- ref={this.removeAllButtonRef}
729
- tooltipContent={removeAllTooltip}
730
- tooltipProps={removeAllTooltipProps}
731
- >
732
- <AngleDoubleLeftIcon />
733
- </DualListSelectorControl>
734
- <DualListSelectorControl
735
- onClick={isTree ? this.removeTreeSelected : this.removeSelected}
736
- isDisabled={
737
- (isTree ? chosenTreeOptionsChecked.length === 0 : chosenOptionsSelected.length === 0) || isDisabled
738
- }
739
- ref={this.removeSelectedButtonRef}
740
- aria-label={removeSelectedAriaLabel}
741
- tooltipContent={removeSelectedTooltip}
742
- tooltipProps={removeSelectedTooltipProps}
743
- >
744
- <AngleLeftIcon />
745
- </DualListSelectorControl>
746
- </DualListSelectorControlsWrapper>
747
- <DualListSelectorPane
748
- isChosen
749
- isSearchable={isSearchable}
750
- onFilterUpdate={this.onFilterUpdate}
751
- searchInputAriaLabel={chosenOptionsSearchAriaLabel}
752
- filterOption={filterOption}
753
- onSearchInputChanged={onChosenOptionsSearchInputChanged}
754
- title={chosenOptionsTitle}
755
- status={chosenOptionsStatusToDisplay}
756
- options={chosen}
757
- selectedOptions={isTree ? chosenTreeOptionsChecked : chosenOptionsSelected}
758
- onOptionSelect={this.onOptionSelect}
759
- onOptionCheck={(e, isChecked, itemData) => this.onTreeOptionCheck(e, isChecked, itemData, true)}
760
- actions={chosenOptionsActions}
761
- id={`${id}-chosen-pane`}
762
- isDisabled={isDisabled}
763
- />
764
- </>
765
- ) : (
766
- children
680
+ <GenerateId>
681
+ {randomId => (
682
+ <div className={css(styles.dualListSelector, className)} id={id || randomId} {...props}>
683
+ {children === '' ? (
684
+ <>
685
+ <DualListSelectorPane
686
+ isSearchable={isSearchable}
687
+ onFilterUpdate={this.onFilterUpdate}
688
+ searchInputAriaLabel={availableOptionsSearchAriaLabel}
689
+ filterOption={filterOption}
690
+ onSearchInputChanged={onAvailableOptionsSearchInputChanged}
691
+ status={availableOptionsStatusToDisplay}
692
+ title={availableOptionsTitle}
693
+ options={available}
694
+ selectedOptions={isTree ? availableTreeOptionsChecked : availableOptionsSelected}
695
+ onOptionSelect={this.onOptionSelect}
696
+ onOptionCheck={(e, isChecked, itemData) => this.onTreeOptionCheck(e, isChecked, itemData, false)}
697
+ actions={availableOptionsActions}
698
+ id={`${id || randomId}-available-pane`}
699
+ isDisabled={isDisabled}
700
+ />
701
+ <DualListSelectorControlsWrapper aria-label={controlsAriaLabel}>
702
+ <DualListSelectorControl
703
+ isDisabled={
704
+ (isTree ? availableTreeOptionsChecked.length === 0 : availableOptionsSelected.length === 0) ||
705
+ isDisabled
706
+ }
707
+ onClick={isTree ? this.addTreeSelected : this.addSelected}
708
+ ref={this.addSelectedButtonRef}
709
+ aria-label={addSelectedAriaLabel}
710
+ tooltipContent={addSelectedTooltip}
711
+ tooltipProps={addSelectedTooltipProps}
712
+ >
713
+ <AngleRightIcon />
714
+ </DualListSelectorControl>
715
+ <DualListSelectorControl
716
+ isDisabled={availableOptions.length === 0 || isDisabled}
717
+ onClick={isTree ? this.addAllTreeVisible : this.addAllVisible}
718
+ ref={this.addAllButtonRef}
719
+ aria-label={addAllAriaLabel}
720
+ tooltipContent={addAllTooltip}
721
+ tooltipProps={addAllTooltipProps}
722
+ >
723
+ <AngleDoubleRightIcon />
724
+ </DualListSelectorControl>
725
+ <DualListSelectorControl
726
+ isDisabled={chosenOptions.length === 0 || isDisabled}
727
+ onClick={isTree ? this.removeAllTreeVisible : this.removeAllVisible}
728
+ aria-label={removeAllAriaLabel}
729
+ ref={this.removeAllButtonRef}
730
+ tooltipContent={removeAllTooltip}
731
+ tooltipProps={removeAllTooltipProps}
732
+ >
733
+ <AngleDoubleLeftIcon />
734
+ </DualListSelectorControl>
735
+ <DualListSelectorControl
736
+ onClick={isTree ? this.removeTreeSelected : this.removeSelected}
737
+ isDisabled={
738
+ (isTree ? chosenTreeOptionsChecked.length === 0 : chosenOptionsSelected.length === 0) ||
739
+ isDisabled
740
+ }
741
+ ref={this.removeSelectedButtonRef}
742
+ aria-label={removeSelectedAriaLabel}
743
+ tooltipContent={removeSelectedTooltip}
744
+ tooltipProps={removeSelectedTooltipProps}
745
+ >
746
+ <AngleLeftIcon />
747
+ </DualListSelectorControl>
748
+ </DualListSelectorControlsWrapper>
749
+ <DualListSelectorPane
750
+ isChosen
751
+ isSearchable={isSearchable}
752
+ onFilterUpdate={this.onFilterUpdate}
753
+ searchInputAriaLabel={chosenOptionsSearchAriaLabel}
754
+ filterOption={filterOption}
755
+ onSearchInputChanged={onChosenOptionsSearchInputChanged}
756
+ title={chosenOptionsTitle}
757
+ status={chosenOptionsStatusToDisplay}
758
+ options={chosen}
759
+ selectedOptions={isTree ? chosenTreeOptionsChecked : chosenOptionsSelected}
760
+ onOptionSelect={this.onOptionSelect}
761
+ onOptionCheck={(e, isChecked, itemData) => this.onTreeOptionCheck(e, isChecked, itemData, true)}
762
+ actions={chosenOptionsActions}
763
+ id={`${id || randomId}-chosen-pane`}
764
+ isDisabled={isDisabled}
765
+ />
766
+ </>
767
+ ) : (
768
+ children
769
+ )}
770
+ </div>
767
771
  )}
768
- </div>
772
+ </GenerateId>
769
773
  </DualListSelectorContext.Provider>
770
774
  );
771
775
  }
@@ -76,7 +76,7 @@ DualListSelectorControlsWrapperBase.displayName = 'DualListSelectorControlsWrapp
76
76
 
77
77
  export const DualListSelectorControlsWrapper = React.forwardRef(
78
78
  (props: DualListSelectorControlsWrapperProps, ref: React.Ref<HTMLDivElement>) => (
79
- <DualListSelectorControlsWrapperBase innerRef={ref as React.MutableRefObject<any>} {...props} />
79
+ <DualListSelectorControlsWrapperBase innerRef={ref as React.MutableRefObject<any>} role="group" {...props} />
80
80
  )
81
81
  );
82
82
 
@@ -5,6 +5,7 @@ import * as React from 'react';
5
5
  import { DualListSelectorListContext } from './DualListSelectorContext';
6
6
 
7
7
  export interface DualListSelectorListProps extends React.HTMLProps<HTMLUListElement> {
8
+ /** Content rendered inside the dual list selector list */
8
9
  children?: React.ReactNode;
9
10
  }
10
11
 
@@ -31,13 +32,18 @@ export const DualListSelectorList: React.FunctionComponent<DualListSelectorListP
31
32
  onOptionSelect(e, index, id);
32
33
  };
33
34
 
35
+ const hasOptions = () =>
36
+ options.length !== 0 || (children !== undefined && (children as React.ReactNode[]).length !== 0);
37
+
34
38
  return (
35
39
  <ul
36
40
  className={css(styles.dualListSelectorList)}
37
- role={isTree ? 'tree' : 'listbox'}
38
- aria-multiselectable="true"
39
- aria-labelledby={ariaLabelledBy}
40
- aria-activedescendant={focusedOption}
41
+ {...(hasOptions() && {
42
+ role: isTree ? 'tree' : 'listbox',
43
+ 'aria-multiselectable': true,
44
+ 'aria-labelledby': ariaLabelledBy,
45
+ 'aria-activedescendant': focusedOption
46
+ })}
41
47
  aria-disabled={isDisabled ? 'true' : undefined}
42
48
  {...props}
43
49
  >
@@ -35,7 +35,7 @@ export interface DualListSelectorTreeItemData {
35
35
  isDisabled?: boolean;
36
36
  }
37
37
 
38
- export interface DualListSelectorTreeProps {
38
+ export interface DualListSelectorTreeProps extends Omit<React.HTMLProps<HTMLUListElement>, 'data'> {
39
39
  /** Data of the tree view */
40
40
  data: DualListSelectorTreeItemData[] | (() => DualListSelectorTreeItemData[]);
41
41
  /** ID of the tree view */
@@ -46,8 +46,9 @@ export interface DualListSelectorTreeProps {
46
46
  hasBadges?: boolean;
47
47
  /** Sets the default expanded behavior */
48
48
  defaultAllExpanded?: boolean;
49
- /** Callback fired when an option is checked */
49
+ /** Flag indicating if the dual list selector tree is in the disabled state */
50
50
  isDisabled?: boolean;
51
+ /** Callback fired when an option is checked */
51
52
  onOptionCheck?: (
52
53
  event: React.MouseEvent | React.ChangeEvent<HTMLInputElement> | React.KeyboardEvent,
53
54
  isChecked: boolean,
@@ -99,6 +99,7 @@ exports[`DualListSelector basic 1`] = `
99
99
  <div
100
100
  aria-label="Selector controls"
101
101
  class="pf-c-dual-list-selector__controls"
102
+ role="group"
102
103
  tabindex="0"
103
104
  >
104
105
  <div
@@ -248,11 +249,7 @@ exports[`DualListSelector basic 1`] = `
248
249
  tabindex="0"
249
250
  >
250
251
  <ul
251
- aria-activedescendant=""
252
- aria-labelledby="firstTest-chosen-pane-status"
253
- aria-multiselectable="true"
254
252
  class="pf-c-dual-list-selector__list"
255
- role="listbox"
256
253
  />
257
254
  </div>
258
255
  </div>
@@ -360,6 +357,7 @@ exports[`DualListSelector basic with disabled controls 1`] = `
360
357
  <div
361
358
  aria-label="Selector controls"
362
359
  class="pf-c-dual-list-selector__controls"
360
+ role="group"
363
361
  tabindex="0"
364
362
  >
365
363
  <div
@@ -510,12 +508,8 @@ exports[`DualListSelector basic with disabled controls 1`] = `
510
508
  tabindex="0"
511
509
  >
512
510
  <ul
513
- aria-activedescendant=""
514
511
  aria-disabled="true"
515
- aria-labelledby="disabledTest-chosen-pane-status"
516
- aria-multiselectable="true"
517
512
  class="pf-c-dual-list-selector__list"
518
- role="listbox"
519
513
  />
520
514
  </div>
521
515
  </div>
@@ -633,6 +627,7 @@ exports[`DualListSelector with actions 1`] = `
633
627
  <div
634
628
  aria-label="Selector controls"
635
629
  class="pf-c-dual-list-selector__controls"
630
+ role="group"
636
631
  tabindex="0"
637
632
  >
638
633
  <div
@@ -954,6 +949,7 @@ exports[`DualListSelector with custom status 1`] = `
954
949
  <div
955
950
  aria-label="Selector controls"
956
951
  class="pf-c-dual-list-selector__controls"
952
+ role="group"
957
953
  tabindex="0"
958
954
  >
959
955
  <div
@@ -1103,11 +1099,7 @@ exports[`DualListSelector with custom status 1`] = `
1103
1099
  tabindex="0"
1104
1100
  >
1105
1101
  <ul
1106
- aria-activedescendant=""
1107
- aria-labelledby="thirdTest-chosen-pane-status"
1108
- aria-multiselectable="true"
1109
1102
  class="pf-c-dual-list-selector__list"
1110
- role="listbox"
1111
1103
  />
1112
1104
  </div>
1113
1105
  </div>
@@ -1227,6 +1219,7 @@ exports[`DualListSelector with search inputs 1`] = `
1227
1219
  <div
1228
1220
  aria-label="Selector controls"
1229
1221
  class="pf-c-dual-list-selector__controls"
1222
+ role="group"
1230
1223
  tabindex="0"
1231
1224
  >
1232
1225
  <div
@@ -1389,11 +1382,7 @@ exports[`DualListSelector with search inputs 1`] = `
1389
1382
  tabindex="0"
1390
1383
  >
1391
1384
  <ul
1392
- aria-activedescendant=""
1393
- aria-labelledby="secondTest-chosen-pane-status"
1394
- aria-multiselectable="true"
1395
1385
  class="pf-c-dual-list-selector__list"
1396
- role="listbox"
1397
1386
  />
1398
1387
  </div>
1399
1388
  </div>
@@ -1577,6 +1566,7 @@ exports[`DualListSelector with tree 1`] = `
1577
1566
  <div
1578
1567
  aria-label="Selector controls"
1579
1568
  class="pf-c-dual-list-selector__controls"
1569
+ role="group"
1580
1570
  tabindex="0"
1581
1571
  >
1582
1572
  <div
@@ -1726,11 +1716,7 @@ exports[`DualListSelector with tree 1`] = `
1726
1716
  tabindex="0"
1727
1717
  >
1728
1718
  <ul
1729
- aria-activedescendant=""
1730
- aria-labelledby="tree-test-chosen-pane-status"
1731
- aria-multiselectable="true"
1732
1719
  class="pf-c-dual-list-selector__list"
1733
- role="tree"
1734
1720
  />
1735
1721
  </div>
1736
1722
  </div>
@@ -8,6 +8,8 @@ propComponents:
8
8
  'DualListSelectorPane',
9
9
  'DualListSelectorControl',
10
10
  'DualListSelectorControlsWrapper',
11
+ 'DualListSelectorList',
12
+ 'DualListSelectorListItem',
11
13
  'DualListSelectorTree',
12
14
  'DualListSelectorTreeItemData',
13
15
  ]
@@ -44,7 +46,7 @@ import PficonSortCommonAscIcon from '@patternfly/react-icons/dist/esm/icons/pfic
44
46
 
45
47
  ### With tree
46
48
 
47
- ```ts file="./DualListSelectorTree.tsx"
49
+ ```ts file="./DualListSelectorTreeExample.tsx"
48
50
  ```
49
51
 
50
52
  ### Composable dual list selector
@@ -151,7 +151,7 @@ export const DualListSelectorComposable: React.FunctionComponent = () => {
151
151
  )}
152
152
  </DualListSelectorList>
153
153
  </DualListSelectorPane>
154
- <DualListSelectorControlsWrapper aria-label="Selector controls">
154
+ <DualListSelectorControlsWrapper>
155
155
  <DualListSelectorControl
156
156
  isDisabled={!availableOptions.some(option => option.selected)}
157
157
  onClick={() => moveSelected(true)}
@@ -121,7 +121,7 @@ export const DualListSelectorComposableDragDrop: React.FunctionComponent = () =>
121
121
  )}
122
122
  </DualListSelectorList>
123
123
  </DualListSelectorPane>
124
- <DualListSelectorControlsWrapper aria-label="Selector controls">
124
+ <DualListSelectorControlsWrapper>
125
125
  <DualListSelectorControl
126
126
  isDisabled={!availableOptions.some(option => option.selected)}
127
127
  onClick={() => moveSelected(true)}