@patternfly/react-core 4.224.9 → 4.224.12

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 (110) hide show
  1. package/CHANGELOG.md +24 -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/DragDrop/DragDrop.d.ts +1 -1
  10. package/dist/esm/components/DragDrop/DragDrop.d.ts.map +1 -1
  11. package/dist/esm/components/DualListSelector/DualListSelector.d.ts.map +1 -1
  12. package/dist/esm/components/DualListSelector/DualListSelector.js +6 -6
  13. package/dist/esm/components/DualListSelector/DualListSelector.js.map +1 -1
  14. package/dist/esm/components/DualListSelector/DualListSelectorControlsWrapper.js +1 -1
  15. package/dist/esm/components/DualListSelector/DualListSelectorControlsWrapper.js.map +1 -1
  16. package/dist/esm/components/DualListSelector/DualListSelectorList.d.ts +1 -0
  17. package/dist/esm/components/DualListSelector/DualListSelectorList.d.ts.map +1 -1
  18. package/dist/esm/components/DualListSelector/DualListSelectorList.js +7 -1
  19. package/dist/esm/components/DualListSelector/DualListSelectorList.js.map +1 -1
  20. package/dist/esm/components/DualListSelector/DualListSelectorTree.d.ts +3 -2
  21. package/dist/esm/components/DualListSelector/DualListSelectorTree.d.ts.map +1 -1
  22. package/dist/esm/components/DualListSelector/DualListSelectorTree.js.map +1 -1
  23. package/dist/esm/components/SearchInput/SearchInput.d.ts +7 -0
  24. package/dist/esm/components/SearchInput/SearchInput.d.ts.map +1 -1
  25. package/dist/esm/components/SearchInput/SearchInput.js +9 -4
  26. package/dist/esm/components/SearchInput/SearchInput.js.map +1 -1
  27. package/dist/js/components/ContextSelector/ContextSelector.d.ts +2 -0
  28. package/dist/js/components/ContextSelector/ContextSelector.d.ts.map +1 -1
  29. package/dist/js/components/ContextSelector/ContextSelector.js +7 -10
  30. package/dist/js/components/ContextSelector/ContextSelector.js.map +1 -1
  31. package/dist/js/components/ContextSelector/ContextSelectorMenuList.d.ts.map +1 -1
  32. package/dist/js/components/ContextSelector/ContextSelectorMenuList.js +2 -1
  33. package/dist/js/components/ContextSelector/ContextSelectorMenuList.js.map +1 -1
  34. package/dist/js/components/DragDrop/DragDrop.d.ts +1 -1
  35. package/dist/js/components/DragDrop/DragDrop.d.ts.map +1 -1
  36. package/dist/js/components/DualListSelector/DualListSelector.d.ts.map +1 -1
  37. package/dist/js/components/DualListSelector/DualListSelector.js +5 -5
  38. package/dist/js/components/DualListSelector/DualListSelector.js.map +1 -1
  39. package/dist/js/components/DualListSelector/DualListSelectorControlsWrapper.js +1 -1
  40. package/dist/js/components/DualListSelector/DualListSelectorControlsWrapper.js.map +1 -1
  41. package/dist/js/components/DualListSelector/DualListSelectorList.d.ts +1 -0
  42. package/dist/js/components/DualListSelector/DualListSelectorList.d.ts.map +1 -1
  43. package/dist/js/components/DualListSelector/DualListSelectorList.js +7 -1
  44. package/dist/js/components/DualListSelector/DualListSelectorList.js.map +1 -1
  45. package/dist/js/components/DualListSelector/DualListSelectorTree.d.ts +3 -2
  46. package/dist/js/components/DualListSelector/DualListSelectorTree.d.ts.map +1 -1
  47. package/dist/js/components/DualListSelector/DualListSelectorTree.js.map +1 -1
  48. package/dist/js/components/SearchInput/SearchInput.d.ts +7 -0
  49. package/dist/js/components/SearchInput/SearchInput.d.ts.map +1 -1
  50. package/dist/js/components/SearchInput/SearchInput.js +9 -4
  51. package/dist/js/components/SearchInput/SearchInput.js.map +1 -1
  52. package/dist/styles/base-no-reset.css +10 -10
  53. package/dist/styles/base.css +10 -10
  54. package/dist/umd/react-core.css +39 -209
  55. package/dist/umd/react-core.js +709 -726
  56. package/dist/umd/react-core.min.css +141 -311
  57. package/dist/umd/react-core.min.js +4 -4
  58. package/package.json +6 -6
  59. package/src/components/Accordion/examples/AccordionBordered.tsx +21 -21
  60. package/src/components/Accordion/examples/AccordionDefinitionList.tsx +21 -21
  61. package/src/components/ActionList/__tests__/ActionList.test.tsx +46 -11
  62. package/src/components/ActionList/__tests__/ActionListGroup.test.tsx +34 -7
  63. package/src/components/ActionList/__tests__/ActionListItem.test.tsx +34 -7
  64. package/src/components/ActionList/__tests__/__snapshots__/ActionList.test.tsx.snap +1 -11
  65. package/src/components/ActionList/__tests__/__snapshots__/ActionListGroup.test.tsx.snap +1 -1
  66. package/src/components/ActionList/__tests__/__snapshots__/ActionListItem.test.tsx.snap +1 -1
  67. package/src/components/ActionList/examples/ActionListMultipleGroups.tsx +4 -4
  68. package/src/components/ActionList/examples/ActionListSingleGroup.tsx +4 -4
  69. package/src/components/ActionList/examples/ActionListWithCancelButton.tsx +5 -5
  70. package/src/components/ActionList/examples/ActionListWithIcons.tsx +2 -2
  71. package/src/components/Card/examples/CardSelectableA11yHighlight.tsx +4 -4
  72. package/src/components/CodeBlock/examples/CodeBlockBasic.tsx +1 -1
  73. package/src/components/CodeBlock/examples/CodeBlockExpandable.tsx +1 -1
  74. package/src/components/ContextSelector/ContextSelector.tsx +11 -10
  75. package/src/components/ContextSelector/ContextSelectorMenuList.tsx +2 -1
  76. package/src/components/ContextSelector/__tests__/ContextSelector.test.tsx +2 -2
  77. package/src/components/ContextSelector/__tests__/__snapshots__/ContextSelector.test.tsx.snap +11 -7
  78. package/src/components/ContextSelector/__tests__/__snapshots__/ContextSelectorMenuList.test.tsx.snap +10 -0
  79. package/src/components/DataList/examples/DataListCompact.tsx +4 -4
  80. package/src/components/DataList/examples/DataListControllingText.tsx +3 -3
  81. package/src/components/DataList/examples/DataListDraggable.tsx +14 -7
  82. package/src/components/DataList/examples/DataListExpandable.tsx +3 -3
  83. package/src/components/DataList/examples/DataListSmGridBreakpoint.tsx +3 -3
  84. package/src/components/DragDrop/DragDrop.tsx +1 -1
  85. package/src/components/DualListSelector/DualListSelector.tsx +93 -89
  86. package/src/components/DualListSelector/DualListSelectorControlsWrapper.tsx +1 -1
  87. package/src/components/DualListSelector/DualListSelectorList.tsx +10 -4
  88. package/src/components/DualListSelector/DualListSelectorTree.tsx +3 -2
  89. package/src/components/DualListSelector/__tests__/__snapshots__/DualListSelector.test.tsx.snap +6 -20
  90. package/src/components/DualListSelector/examples/DualListSelector.md +3 -1
  91. package/src/components/DualListSelector/examples/DualListSelectorComposable.tsx +1 -1
  92. package/src/components/DualListSelector/examples/DualListSelectorComposableDragDrop.tsx +1 -1
  93. package/src/components/DualListSelector/examples/DualListSelectorComposableTree.tsx +1 -1
  94. package/src/components/DualListSelector/examples/{DualListSelectorTree.tsx → DualListSelectorTreeExample.tsx} +1 -1
  95. package/src/components/FileUpload/examples/FileUploadCustomUpload.tsx +1 -1
  96. package/src/components/FileUpload/examples/FileUploadSimpleText.tsx +1 -1
  97. package/src/components/FileUpload/examples/FileUploadTextWithEdits.tsx +1 -1
  98. package/src/components/FileUpload/examples/FileUploadTextWithRestrictions.tsx +2 -2
  99. package/src/components/InputGroup/examples/InputGroupBasic.tsx +3 -3
  100. package/src/components/InputGroup/examples/InputGroupWithDropdown.tsx +1 -1
  101. package/src/components/InputGroup/examples/InputGroupWithPopover.tsx +12 -2
  102. package/src/components/InputGroup/examples/InputGroupWithSiblings.tsx +7 -2
  103. package/src/components/InputGroup/examples/InputGroupWithTextarea.tsx +1 -1
  104. package/src/components/LoginPage/examples/LoginPage.md +2 -325
  105. package/src/components/LoginPage/examples/LoginPageBasic.tsx +144 -0
  106. package/src/components/LoginPage/examples/LoginPageShowHidePassword.tsx +145 -0
  107. package/src/components/NotificationDrawer/examples/NotificationDrawer.md +69 -68
  108. package/src/components/SearchInput/SearchInput.tsx +32 -5
  109. package/src/components/SearchInput/__tests__/SearchInput.test.tsx +37 -0
  110. package/src/components/SearchInput/__tests__/__snapshots__/SearchInput.test.tsx.snap +193 -4
@@ -9,15 +9,11 @@ import { Button, ButtonVariant } from '../Button';
9
9
  import { TextInput } from '../TextInput';
10
10
  import { InputGroup } from '../InputGroup';
11
11
  import { KEY_CODES } from '../../helpers/constants';
12
- import { FocusTrap } from '../../helpers';
12
+ import { FocusTrap, getUniqueId } from '../../helpers';
13
13
  import { ToggleMenuBaseProps } from '../../helpers/Popper/Popper';
14
14
  import { Popper } from '../../helpers/Popper/Popper';
15
15
  import { getOUIAProps, OUIAProps, getDefaultOUIAId } from '../../helpers';
16
16
 
17
- // seed for the aria-labelledby ID
18
- let currentId = 0;
19
- const newId = currentId++;
20
-
21
17
  export interface ContextSelectorProps extends Omit<ToggleMenuBaseProps, 'menuAppendTo'>, OUIAProps {
22
18
  /** content rendered inside the Context Selector */
23
19
  children?: React.ReactNode;
@@ -66,6 +62,8 @@ export interface ContextSelectorProps extends Omit<ToggleMenuBaseProps, 'menuApp
66
62
  * appended inline, e.g. `menuAppendTo="parent"`
67
63
  */
68
64
  isFlipEnabled?: boolean;
65
+ /** Id of the context selector */
66
+ id?: string;
69
67
  }
70
68
 
71
69
  export class ContextSelector extends React.Component<ContextSelectorProps, { ouiaStateId: string }> {
@@ -108,9 +106,6 @@ export class ContextSelector extends React.Component<ContextSelectorProps, { oui
108
106
  };
109
107
 
110
108
  render() {
111
- const toggleId = `pf-context-selector-toggle-id-${newId}`;
112
- const screenReaderLabelId = `pf-context-selector-label-id-${newId}`;
113
- const searchButtonId = `pf-context-selector-search-button-id-${newId}`;
114
109
  const {
115
110
  children,
116
111
  className,
@@ -133,14 +128,21 @@ export class ContextSelector extends React.Component<ContextSelectorProps, { oui
133
128
  footer,
134
129
  disableFocusTrap,
135
130
  isFlipEnabled,
131
+ id,
136
132
  ...props
137
133
  } = this.props;
134
+
135
+ const uniqueId = id || getUniqueId();
136
+ const toggleId = `pf-context-selector-toggle-id-${uniqueId}`;
137
+ const screenReaderLabelId = `pf-context-selector-label-id-${uniqueId}`;
138
+
138
139
  const menuContainer = (
139
140
  <div
140
141
  className={css(styles.contextSelectorMenu)}
141
142
  // This removes the `position: absolute`styling from the `.pf-c-context-selector__menu`
142
143
  // allowing the menu to flip correctly
143
144
  {...(isFlipEnabled && { style: { position: 'revert' } })}
145
+ id={uniqueId}
144
146
  >
145
147
  {isOpen && (
146
148
  <FocusTrap
@@ -155,12 +157,11 @@ export class ContextSelector extends React.Component<ContextSelectorProps, { oui
155
157
  placeholder={searchInputPlaceholder}
156
158
  onChange={onSearchInputChange}
157
159
  onKeyPress={this.onEnterPressed}
158
- aria-labelledby={searchButtonId}
160
+ aria-label={searchButtonAriaLabel}
159
161
  />
160
162
  <Button
161
163
  variant={ButtonVariant.control}
162
164
  aria-label={searchButtonAriaLabel}
163
- id={searchButtonId}
164
165
  onClick={onSearchButtonClick}
165
166
  >
166
167
  <SearchIcon aria-hidden="true" />
@@ -29,7 +29,8 @@ export class ContextSelectorMenuList extends React.Component<ContextSelectorMenu
29
29
  return React.Children.map(this.props.children, (child, index) =>
30
30
  React.cloneElement(child as React.ReactElement<any>, {
31
31
  sendRef: this.sendRef,
32
- index
32
+ index,
33
+ role: 'menuitem'
33
34
  })
34
35
  );
35
36
  }
@@ -16,12 +16,12 @@ const items = [
16
16
 
17
17
  describe('ContextSelector', () => {
18
18
  test('Renders ContextSelector', () => {
19
- const { asFragment } = render(<ContextSelector>{items}</ContextSelector>);
19
+ const { asFragment } = render(<ContextSelector id="render">{items}</ContextSelector>);
20
20
  expect(asFragment()).toMatchSnapshot();
21
21
  });
22
22
 
23
23
  test('Renders ContextSelector open', () => {
24
- const { asFragment } = render(<ContextSelector isOpen>{items}</ContextSelector>);
24
+ const { asFragment } = render(<ContextSelector isOpen id="render-open">{items}</ContextSelector>);
25
25
  expect(asFragment()).toMatchSnapshot();
26
26
  });
27
27
 
@@ -10,9 +10,9 @@ exports[`ContextSelector Renders ContextSelector 1`] = `
10
10
  >
11
11
  <button
12
12
  aria-expanded="false"
13
- aria-labelledby="pf-context-selector-label-id-0 pf-context-selector-toggle-id-0"
13
+ aria-labelledby="pf-context-selector-label-id-render pf-context-selector-toggle-id-render"
14
14
  class="pf-c-context-selector__toggle"
15
- id="pf-context-selector-toggle-id-0"
15
+ id="pf-context-selector-toggle-id-render"
16
16
  type="button"
17
17
  >
18
18
  <span
@@ -50,9 +50,9 @@ exports[`ContextSelector Renders ContextSelector open 1`] = `
50
50
  >
51
51
  <button
52
52
  aria-expanded="true"
53
- aria-labelledby="pf-context-selector-label-id-0 pf-context-selector-toggle-id-0"
53
+ aria-labelledby="pf-context-selector-label-id-render-open pf-context-selector-toggle-id-render-open"
54
54
  class="pf-c-context-selector__toggle"
55
- id="pf-context-selector-toggle-id-0"
55
+ id="pf-context-selector-toggle-id-render-open"
56
56
  type="button"
57
57
  >
58
58
  <span
@@ -78,6 +78,7 @@ exports[`ContextSelector Renders ContextSelector open 1`] = `
78
78
  </button>
79
79
  <div
80
80
  class="pf-c-context-selector__menu"
81
+ id="render-open"
81
82
  >
82
83
  <div>
83
84
  <div
@@ -87,9 +88,8 @@ exports[`ContextSelector Renders ContextSelector open 1`] = `
87
88
  class="pf-c-input-group"
88
89
  >
89
90
  <input
90
- aria-describedby="pf-context-selector-search-button-id-0"
91
91
  aria-invalid="false"
92
- aria-labelledby="pf-context-selector-search-button-id-0"
92
+ aria-label="Search menu items"
93
93
  class="pf-c-form-control"
94
94
  data-ouia-component-id="OUIA-Generated-TextInputBase-1"
95
95
  data-ouia-component-type="PF4/TextInput"
@@ -105,7 +105,6 @@ exports[`ContextSelector Renders ContextSelector open 1`] = `
105
105
  data-ouia-component-id="OUIA-Generated-Button-control-1"
106
106
  data-ouia-component-type="PF4/Button"
107
107
  data-ouia-safe="true"
108
- id="pf-context-selector-search-button-id-0"
109
108
  type="button"
110
109
  >
111
110
  <svg
@@ -133,6 +132,7 @@ exports[`ContextSelector Renders ContextSelector open 1`] = `
133
132
  >
134
133
  <button
135
134
  class="pf-c-context-selector__menu-list-item"
135
+ role="menuitem"
136
136
  >
137
137
  My Project
138
138
  </button>
@@ -142,6 +142,7 @@ exports[`ContextSelector Renders ContextSelector open 1`] = `
142
142
  >
143
143
  <button
144
144
  class="pf-c-context-selector__menu-list-item"
145
+ role="menuitem"
145
146
  >
146
147
  OpenShift Cluster
147
148
  </button>
@@ -151,6 +152,7 @@ exports[`ContextSelector Renders ContextSelector open 1`] = `
151
152
  >
152
153
  <button
153
154
  class="pf-c-context-selector__menu-list-item"
155
+ role="menuitem"
154
156
  >
155
157
  Production Ansible
156
158
  </button>
@@ -160,6 +162,7 @@ exports[`ContextSelector Renders ContextSelector open 1`] = `
160
162
  >
161
163
  <button
162
164
  class="pf-c-context-selector__menu-list-item"
165
+ role="menuitem"
163
166
  >
164
167
  AWS
165
168
  </button>
@@ -169,6 +172,7 @@ exports[`ContextSelector Renders ContextSelector open 1`] = `
169
172
  >
170
173
  <button
171
174
  class="pf-c-context-selector__menu-list-item"
175
+ role="menuitem"
172
176
  >
173
177
  Azure
174
178
  </button>
@@ -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
@@ -1,6 +1,6 @@
1
1
  import * as React from 'react';
2
2
 
3
- interface DraggableItemPosition {
3
+ export interface DraggableItemPosition {
4
4
  /** Parent droppableId */
5
5
  droppableId: string;
6
6
  /** Index of item in parent Droppable */
@@ -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