@patternfly/react-core 4.198.12 → 4.198.15

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 (129) hide show
  1. package/CHANGELOG.md +30 -0
  2. package/dist/esm/components/Form/FormFieldGroup.d.ts +1 -1
  3. package/dist/esm/components/Form/FormFieldGroupExpandable.d.ts +2 -2
  4. package/dist/esm/components/Form/FormFieldGroupHeader.d.ts +3 -1
  5. package/dist/esm/components/Form/FormFieldGroupHeader.d.ts.map +1 -1
  6. package/dist/esm/components/Form/FormFieldGroupHeader.js.map +1 -1
  7. package/dist/esm/components/Form/InternalFormFieldGroup.d.ts +2 -2
  8. package/dist/esm/components/Label/Label.d.ts.map +1 -1
  9. package/dist/esm/components/Label/Label.js +5 -2
  10. package/dist/esm/components/Label/Label.js.map +1 -1
  11. package/dist/esm/components/Menu/MenuItem.d.ts +3 -1
  12. package/dist/esm/components/Menu/MenuItem.d.ts.map +1 -1
  13. package/dist/esm/components/Menu/MenuItem.js +4 -3
  14. package/dist/esm/components/Menu/MenuItem.js.map +1 -1
  15. package/dist/esm/components/Nav/NavGroup.d.ts +1 -1
  16. package/dist/esm/components/Nav/NavGroup.d.ts.map +1 -1
  17. package/dist/esm/components/Nav/NavGroup.js +7 -2
  18. package/dist/esm/components/Nav/NavGroup.js.map +1 -1
  19. package/dist/esm/components/NotificationDrawer/NotificationDrawer.d.ts +3 -1
  20. package/dist/esm/components/NotificationDrawer/NotificationDrawer.d.ts.map +1 -1
  21. package/dist/esm/components/NotificationDrawer/NotificationDrawer.js +4 -3
  22. package/dist/esm/components/NotificationDrawer/NotificationDrawer.js.map +1 -1
  23. package/dist/esm/components/Tabs/Tab.d.ts +3 -1
  24. package/dist/esm/components/Tabs/Tab.d.ts.map +1 -1
  25. package/dist/esm/components/Tabs/Tab.js +4 -3
  26. package/dist/esm/components/Tabs/Tab.js.map +1 -1
  27. package/dist/esm/components/Tabs/TabButton.d.ts +2 -0
  28. package/dist/esm/components/Tabs/TabButton.d.ts.map +1 -1
  29. package/dist/esm/components/Tabs/TabButton.js +2 -2
  30. package/dist/esm/components/Tabs/TabButton.js.map +1 -1
  31. package/dist/esm/components/Tile/Tile.d.ts.map +1 -1
  32. package/dist/esm/components/Tile/Tile.js +1 -1
  33. package/dist/esm/components/Tile/Tile.js.map +1 -1
  34. package/dist/esm/components/Toolbar/Toolbar.d.ts +3 -1
  35. package/dist/esm/components/Toolbar/Toolbar.d.ts.map +1 -1
  36. package/dist/esm/components/Toolbar/Toolbar.js +4 -3
  37. package/dist/esm/components/Toolbar/Toolbar.js.map +1 -1
  38. package/dist/esm/components/Toolbar/ToolbarChipGroupContent.d.ts +2 -0
  39. package/dist/esm/components/Toolbar/ToolbarChipGroupContent.d.ts.map +1 -1
  40. package/dist/esm/components/Toolbar/ToolbarChipGroupContent.js +4 -3
  41. package/dist/esm/components/Toolbar/ToolbarChipGroupContent.js.map +1 -1
  42. package/dist/esm/components/Toolbar/ToolbarExpandableContent.d.ts.map +1 -1
  43. package/dist/esm/components/Toolbar/ToolbarExpandableContent.js +4 -3
  44. package/dist/esm/components/Toolbar/ToolbarExpandableContent.js.map +1 -1
  45. package/dist/esm/components/Toolbar/ToolbarUtils.d.ts +1 -0
  46. package/dist/esm/components/Toolbar/ToolbarUtils.d.ts.map +1 -1
  47. package/dist/esm/components/Toolbar/ToolbarUtils.js.map +1 -1
  48. package/dist/js/components/Form/FormFieldGroup.d.ts +1 -1
  49. package/dist/js/components/Form/FormFieldGroupExpandable.d.ts +2 -2
  50. package/dist/js/components/Form/FormFieldGroupHeader.d.ts +3 -1
  51. package/dist/js/components/Form/FormFieldGroupHeader.d.ts.map +1 -1
  52. package/dist/js/components/Form/FormFieldGroupHeader.js.map +1 -1
  53. package/dist/js/components/Form/InternalFormFieldGroup.d.ts +2 -2
  54. package/dist/js/components/Label/Label.d.ts.map +1 -1
  55. package/dist/js/components/Label/Label.js +5 -2
  56. package/dist/js/components/Label/Label.js.map +1 -1
  57. package/dist/js/components/Menu/MenuItem.d.ts +3 -1
  58. package/dist/js/components/Menu/MenuItem.d.ts.map +1 -1
  59. package/dist/js/components/Menu/MenuItem.js +4 -4
  60. package/dist/js/components/Menu/MenuItem.js.map +1 -1
  61. package/dist/js/components/Nav/NavGroup.d.ts +1 -1
  62. package/dist/js/components/Nav/NavGroup.d.ts.map +1 -1
  63. package/dist/js/components/Nav/NavGroup.js +7 -2
  64. package/dist/js/components/Nav/NavGroup.js.map +1 -1
  65. package/dist/js/components/NotificationDrawer/NotificationDrawer.d.ts +3 -1
  66. package/dist/js/components/NotificationDrawer/NotificationDrawer.d.ts.map +1 -1
  67. package/dist/js/components/NotificationDrawer/NotificationDrawer.js +4 -4
  68. package/dist/js/components/NotificationDrawer/NotificationDrawer.js.map +1 -1
  69. package/dist/js/components/Tabs/Tab.d.ts +3 -1
  70. package/dist/js/components/Tabs/Tab.d.ts.map +1 -1
  71. package/dist/js/components/Tabs/Tab.js +4 -3
  72. package/dist/js/components/Tabs/Tab.js.map +1 -1
  73. package/dist/js/components/Tabs/TabButton.d.ts +2 -0
  74. package/dist/js/components/Tabs/TabButton.d.ts.map +1 -1
  75. package/dist/js/components/Tabs/TabButton.js +2 -2
  76. package/dist/js/components/Tabs/TabButton.js.map +1 -1
  77. package/dist/js/components/Tile/Tile.d.ts.map +1 -1
  78. package/dist/js/components/Tile/Tile.js +1 -1
  79. package/dist/js/components/Tile/Tile.js.map +1 -1
  80. package/dist/js/components/Toolbar/Toolbar.d.ts +3 -1
  81. package/dist/js/components/Toolbar/Toolbar.d.ts.map +1 -1
  82. package/dist/js/components/Toolbar/Toolbar.js +4 -3
  83. package/dist/js/components/Toolbar/Toolbar.js.map +1 -1
  84. package/dist/js/components/Toolbar/ToolbarChipGroupContent.d.ts +2 -0
  85. package/dist/js/components/Toolbar/ToolbarChipGroupContent.d.ts.map +1 -1
  86. package/dist/js/components/Toolbar/ToolbarChipGroupContent.js +4 -3
  87. package/dist/js/components/Toolbar/ToolbarChipGroupContent.js.map +1 -1
  88. package/dist/js/components/Toolbar/ToolbarExpandableContent.d.ts.map +1 -1
  89. package/dist/js/components/Toolbar/ToolbarExpandableContent.js +4 -3
  90. package/dist/js/components/Toolbar/ToolbarExpandableContent.js.map +1 -1
  91. package/dist/js/components/Toolbar/ToolbarUtils.d.ts +1 -0
  92. package/dist/js/components/Toolbar/ToolbarUtils.d.ts.map +1 -1
  93. package/dist/js/components/Toolbar/ToolbarUtils.js.map +1 -1
  94. package/dist/umd/react-core.js +38 -25
  95. package/dist/umd/react-core.min.js +1 -1
  96. package/package.json +5 -5
  97. package/src/components/Form/FormFieldGroup.tsx +1 -1
  98. package/src/components/Form/FormFieldGroupExpandable.tsx +2 -2
  99. package/src/components/Form/FormFieldGroupHeader.tsx +5 -1
  100. package/src/components/Form/InternalFormFieldGroup.tsx +2 -2
  101. package/src/components/Form/__tests__/FormFieldGroup.test.tsx +1 -1
  102. package/src/components/Form/__tests__/__snapshots__/FormFieldGroup.test.tsx.snap +1 -1
  103. package/src/components/Form/examples/Form.md +1 -1
  104. package/src/components/Label/Label.tsx +5 -2
  105. package/src/components/Menu/MenuItem.tsx +9 -1
  106. package/src/components/Menu/examples/Menu.md +57 -32
  107. package/src/components/Nav/NavGroup.tsx +20 -9
  108. package/src/components/Nav/examples/Nav.md +2 -0
  109. package/src/components/NotificationDrawer/NotificationDrawer.tsx +8 -2
  110. package/src/components/NotificationDrawer/__tests__/__snapshots__/NotificationDrawer.test.tsx.snap +1 -1
  111. package/src/components/Tabs/Tab.tsx +31 -24
  112. package/src/components/Tabs/TabButton.tsx +5 -1
  113. package/src/components/Tabs/examples/Tabs.md +527 -256
  114. package/src/components/Tile/Tile.tsx +3 -0
  115. package/src/components/Tile/__tests__/__snapshots__/Tile.test.tsx.snap +9 -0
  116. package/src/components/Tile/examples/Tile.md +41 -39
  117. package/src/components/Toolbar/Toolbar.tsx +7 -2
  118. package/src/components/Toolbar/ToolbarChipGroupContent.tsx +5 -1
  119. package/src/components/Toolbar/ToolbarExpandableContent.tsx +3 -2
  120. package/src/components/Toolbar/ToolbarUtils.tsx +1 -0
  121. package/src/components/Toolbar/__tests__/ToolbarToggleGroup.test.tsx +71 -1
  122. package/src/components/Toolbar/__tests__/__snapshots__/ToolbarToggleGroup.test.tsx.snap +394 -0
  123. package/src/components/Toolbar/examples/Toolbar.md +8 -1
  124. package/src/components/Toolbar/examples/ToolbarCustomChipGroupContent.tsx +166 -0
  125. package/src/demos/Nav.md +7 -3
  126. package/src/demos/NotificationDrawer/NotificationDrawer.md +31 -4
  127. package/src/demos/Page/Page.md +7 -3
  128. package/src/demos/TileDemo.md +17 -35
  129. package/src/demos/examples/DashboardHeader.js +2 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@patternfly/react-core",
3
- "version": "4.198.12",
3
+ "version": "4.198.15",
4
4
  "description": "This library provides a set of common React components for use with the PatternFly reference implementation.",
5
5
  "main": "dist/js/index.js",
6
6
  "module": "dist/esm/index.js",
@@ -34,9 +34,9 @@
34
34
  "generate": "node scripts/copyStyles.js"
35
35
  },
36
36
  "dependencies": {
37
- "@patternfly/react-icons": "^4.49.12",
38
- "@patternfly/react-styles": "^4.48.12",
39
- "@patternfly/react-tokens": "^4.50.12",
37
+ "@patternfly/react-icons": "^4.49.15",
38
+ "@patternfly/react-styles": "^4.48.15",
39
+ "@patternfly/react-tokens": "^4.50.15",
40
40
  "focus-trap": "6.2.2",
41
41
  "react-dropzone": "9.0.0",
42
42
  "tippy.js": "5.1.2",
@@ -60,5 +60,5 @@
60
60
  "react": "^16.8.0 || ^17.0.0",
61
61
  "react-dom": "^16.8.0 || ^17.0.0"
62
62
  },
63
- "gitHead": "2f37e9854ab448a91848398d42e93c6d31fb07d1"
63
+ "gitHead": "16259ba437f75ad2818da8ff55a1994340971e26"
64
64
  }
@@ -6,7 +6,7 @@ export interface FormFieldGroupProps extends Omit<React.HTMLProps<HTMLDivElement
6
6
  children?: React.ReactNode;
7
7
  /** Additional classes added to the form field group. */
8
8
  className?: string;
9
- /** Form filed group header */
9
+ /** Form field group header */
10
10
  header?: React.ReactNode;
11
11
  }
12
12
 
@@ -7,11 +7,11 @@ export interface FormFieldGroupExpandableProps extends React.HTMLProps<HTMLDivEl
7
7
  children?: React.ReactNode;
8
8
  /** Additional classes added to the form field group. */
9
9
  className?: string;
10
- /** Form filed group header */
10
+ /** Form field group header */
11
11
  header?: React.ReactNode;
12
12
  /** Flag indicating if the form field group is initially expanded */
13
13
  isExpanded?: boolean;
14
- /** Aria-label to use on the form filed group toggle button */
14
+ /** Aria-label to use on the form field group toggle button */
15
15
  toggleAriaLabel?: string;
16
16
  }
17
17
 
@@ -2,17 +2,21 @@ import * as React from 'react';
2
2
  import styles from '@patternfly/react-styles/css/components/Form/form';
3
3
  import { css } from '@patternfly/react-styles';
4
4
 
5
+ // typo - rename to FormFieldGroupHeaderTitleTextObject during breaking change release
5
6
  export interface FormFiledGroupHeaderTitleTextObject {
6
7
  /** Title text. */
7
8
  text: React.ReactNode;
8
9
  /** The applied to the title div for accessibility */
9
10
  id: string;
10
11
  }
12
+
13
+ export interface FormFieldGroupHeaderTitleTextObject extends FormFiledGroupHeaderTitleTextObject {}
14
+
11
15
  export interface FormFieldGroupHeaderProps extends React.HTMLProps<HTMLDivElement> {
12
16
  /** Additional classes added to the section */
13
17
  className?: string;
14
18
  /** Field group header title text */
15
- titleText?: FormFiledGroupHeaderTitleTextObject;
19
+ titleText?: FormFieldGroupHeaderTitleTextObject;
16
20
  /** Field group header title description */
17
21
  titleDescription?: React.ReactNode;
18
22
  /** Field group header actions */
@@ -9,7 +9,7 @@ export interface InternalFormFieldGroupProps extends Omit<React.HTMLProps<HTMLDi
9
9
  children?: React.ReactNode;
10
10
  /** Additional classes added to the form field group. */
11
11
  className?: string;
12
- /** Form filed group header */
12
+ /** Form field group header */
13
13
  header?: any;
14
14
  /** Flag indicating if the field group is expandable */
15
15
  isExpandable?: boolean;
@@ -17,7 +17,7 @@ export interface InternalFormFieldGroupProps extends Omit<React.HTMLProps<HTMLDi
17
17
  isExpanded?: boolean;
18
18
  /** Function callback called when user clicks toggle button */
19
19
  onToggle?: () => void;
20
- /** Aria-label to use on the form filed group toggle button */
20
+ /** Aria-label to use on the form field group toggle button */
21
21
  toggleAriaLabel?: string;
22
22
  }
23
23
 
@@ -5,7 +5,7 @@ import { FormFieldGroupHeader } from '../FormFieldGroupHeader';
5
5
  import { Button } from '../../Button';
6
6
  import { render } from '@testing-library/react';
7
7
 
8
- test('Check form filed group example against snapshot', () => {
8
+ test('Check form field group example against snapshot', () => {
9
9
  const FieldGroup = (
10
10
  <FormFieldGroup
11
11
  header={
@@ -85,7 +85,7 @@ exports[`Check expandable form field group example against snapshot 1`] = `
85
85
  </div>
86
86
  `;
87
87
 
88
- exports[`Check form filed group example against snapshot 1`] = `
88
+ exports[`Check form field group example against snapshot 1`] = `
89
89
  <div>
90
90
  <div
91
91
  class="pf-c-form__field-group"
@@ -12,7 +12,7 @@ propComponents:
12
12
  'FormFieldGroup',
13
13
  'FormFieldGroupExpandable',
14
14
  'FormFieldGroupHeader',
15
- 'FormFiledGroupHeaderTitleTextObject',
15
+ 'FormFieldGroupHeaderTitleTextObject',
16
16
  'Button',
17
17
  'Popover',
18
18
  ]
@@ -197,8 +197,11 @@ export const Label: React.FunctionComponent<LabelProps> = ({
197
197
  const componentRef = React.useRef();
198
198
  const [isTooltipVisible, setIsTooltipVisible] = React.useState(false);
199
199
  useIsomorphicLayoutEffect(() => {
200
- setIsTooltipVisible(textRef.current && textRef.current.offsetWidth < textRef.current.scrollWidth);
201
- }, []);
200
+ const currTextRef = isEditable ? editableButtonRef : textRef;
201
+ if (!isEditableActive) {
202
+ setIsTooltipVisible(currTextRef.current && currTextRef.current.offsetWidth < currTextRef.current.scrollWidth);
203
+ }
204
+ }, [isEditableActive]);
202
205
  const content = (
203
206
  <React.Fragment>
204
207
  {icon && <span className={css(styles.labelIcon)}>{icon}</span>}
@@ -58,13 +58,15 @@ export interface MenuItemProps extends Omit<React.HTMLProps<HTMLLIElement>, 'onC
58
58
  isOnPath?: boolean;
59
59
  /** Accessibility label */
60
60
  'aria-label'?: string;
61
+ /** @hide Forwarded ref */
62
+ innerRef?: React.Ref<HTMLAnchorElement | HTMLButtonElement>;
61
63
  }
62
64
 
63
65
  const FlyoutContext = React.createContext({
64
66
  direction: 'right' as 'left' | 'right'
65
67
  });
66
68
 
67
- export const MenuItem: React.FunctionComponent<MenuItemProps> = ({
69
+ const MenuItemBase: React.FunctionComponent<MenuItemProps> = ({
68
70
  children,
69
71
  className,
70
72
  itemId = null,
@@ -86,6 +88,7 @@ export const MenuItem: React.FunctionComponent<MenuItemProps> = ({
86
88
  onShowFlyout,
87
89
  drilldownMenu,
88
90
  isOnPath,
91
+ innerRef,
89
92
  ...props
90
93
  }: MenuItemProps) => {
91
94
  const {
@@ -293,6 +296,7 @@ export const MenuItem: React.FunctionComponent<MenuItemProps> = ({
293
296
  aria-current={getAriaCurrent()}
294
297
  disabled={isDisabled}
295
298
  role="menuitem"
299
+ ref={innerRef}
296
300
  onClick={(event: any) => {
297
301
  onItemSelect(event, onSelect);
298
302
  _drill && _drill();
@@ -352,4 +356,8 @@ export const MenuItem: React.FunctionComponent<MenuItemProps> = ({
352
356
  );
353
357
  };
354
358
 
359
+ export const MenuItem = React.forwardRef((props: MenuItemProps, ref: React.Ref<any>) => (
360
+ <MenuItemBase {...props} innerRef={ref} />
361
+ ));
362
+
355
363
  MenuItem.displayName = 'MenuItem';
@@ -1246,39 +1246,41 @@ class ViewMoreMenu extends React.Component {
1246
1246
  isLoading: false,
1247
1247
  numOptions: 3
1248
1248
  };
1249
+ this.activeItemRef = React.createRef();
1250
+ this.viewMoreRef = React.createRef();
1249
1251
 
1250
1252
  this.menuOptions = [
1251
- <MenuItem key={0} itemId={0}>
1253
+ <MenuItem key={0} itemId={'view-more-0'}>
1252
1254
  Action
1253
1255
  </MenuItem>,
1254
1256
  <MenuItem
1255
- key={2}
1256
- itemId={1}
1257
+ key={1}
1258
+ itemId={'view-more-1'}
1257
1259
  to="#default-link2"
1258
1260
  // just for demo so that navigation is not triggered
1259
1261
  onClick={event => event.preventDefault()}
1260
1262
  >
1261
1263
  Link
1262
1264
  </MenuItem>,
1263
- <MenuItem key={3} isDisabled>
1265
+ <MenuItem key={2} itemId="view-more-2" isDisabled>
1264
1266
  Disabled action
1265
1267
  </MenuItem>,
1266
- <MenuItem key={4} isDisabled to="#default-link4">
1268
+ <MenuItem key={3} itemId="view-more-3" isDisabled to="#default-link4">
1267
1269
  Disabled link
1268
1270
  </MenuItem>,
1269
- <MenuItem key={5} itemId={2}>
1271
+ <MenuItem key={4} itemId="view-more-4" ref={this.activeItemRef}>
1270
1272
  Action 2
1271
1273
  </MenuItem>,
1272
- <MenuItem key={6} itemId={3}>
1274
+ <MenuItem key={5} itemId="view-more-5">
1273
1275
  Action 3
1274
1276
  </MenuItem>,
1275
- <MenuItem key={7} itemId={4}>
1277
+ <MenuItem key={6} itemId="view-more-6">
1276
1278
  Action 4
1277
1279
  </MenuItem>,
1278
- <MenuItem key={8} itemId={5}>
1280
+ <MenuItem key={7} itemId="view-more-7">
1279
1281
  Action 5
1280
1282
  </MenuItem>,
1281
- <MenuItem key={9} itemId={6}>
1283
+ <MenuItem key={8} itemId="view-more-8">
1282
1284
  Final option
1283
1285
  </MenuItem>
1284
1286
  ];
@@ -1290,25 +1292,38 @@ class ViewMoreMenu extends React.Component {
1290
1292
  });
1291
1293
  };
1292
1294
 
1293
- this.simulateNetworkCall = callback => {
1294
- setTimeout(callback, 2000);
1295
+ this.simulateNetworkCall = networkCallback => {
1296
+ setTimeout(networkCallback, 2000);
1295
1297
  };
1296
1298
 
1297
- this.getNextValidRef = startingIndex => {
1298
- let index = startingIndex;
1299
- while (index < this.menuOptions.length && this.menuOptions[index].ref === null) {
1300
- index++;
1299
+ this.getNextValidItem = (startingIndex, maxLength) => {
1300
+ let validItem;
1301
+ for (let i = startingIndex; i < maxLength; i++) {
1302
+ if (this.menuOptions[i].props.isDisabled) {
1303
+ continue;
1304
+ } else {
1305
+ validItem = this.menuOptions[i];
1306
+ break;
1307
+ }
1301
1308
  }
1302
- return this.menuOptions[index].ref.current;
1309
+ return validItem;
1310
+ };
1311
+
1312
+ this.loadMoreOptions = stateCallback => {
1313
+ const newLength =
1314
+ this.state.numOptions + 3 <= this.menuOptions.length ? this.state.numOptions + 3 : this.menuOptions.length;
1315
+ const prevPosition = this.state.numOptions;
1316
+ const nextValidItem = this.getNextValidItem(prevPosition, newLength);
1317
+
1318
+ this.setState({ numOptions: newLength, isLoading: false, activeItem: nextValidItem.props.itemId }, stateCallback);
1303
1319
  };
1304
1320
 
1305
- this.onViewMoreClick = () => {
1321
+ this.onViewMoreClick = event => {
1306
1322
  this.setState({ isLoading: true });
1307
1323
  this.simulateNetworkCall(() => {
1308
- const newLength =
1309
- this.state.numOptions + 3 <= this.menuOptions.length ? this.state.numOptions + 3 : this.menuOptions.length;
1310
- const prevPosition = this.state.numOptions;
1311
- this.setState({ numOptions: newLength, isLoading: false });
1324
+ this.loadMoreOptions(() => {
1325
+ this.activeItemRef.current.focus();
1326
+ });
1312
1327
  });
1313
1328
  };
1314
1329
 
@@ -1321,15 +1336,14 @@ class ViewMoreMenu extends React.Component {
1321
1336
 
1322
1337
  this.setState({ isLoading: true });
1323
1338
  this.simulateNetworkCall(() => {
1324
- const newLength =
1325
- this.state.numOptions + 3 <= this.menuOptions.length ? this.state.numOptions + 3 : this.menuOptions.length;
1326
- const prevPosition = this.state.numOptions;
1327
-
1328
- this.setState({ numOptions: newLength, isLoading: false }, () => {
1329
- const nextFocus = this.getNextValidRef(prevPosition).querySelector('button, a');
1330
- this.getNextValidRef(0).querySelector('button, a').tabIndex = -1;
1331
- nextFocus.tabIndex = 0;
1332
- nextFocus.focus();
1339
+ this.loadMoreOptions(() => {
1340
+ if (this.viewMoreRef.current) {
1341
+ this.viewMoreRef.current.tabIndex = -1;
1342
+ }
1343
+ const firstMenuItem = this.activeItemRef.current.closest('ul').firstChild;
1344
+ firstMenuItem.querySelector('button, a').tabIndex = -1;
1345
+ this.activeItemRef.current.tabIndex = 0;
1346
+ this.activeItemRef.current.focus();
1333
1347
  });
1334
1348
  });
1335
1349
  };
@@ -1341,7 +1355,17 @@ class ViewMoreMenu extends React.Component {
1341
1355
  <Menu activeItemId={activeItem} onSelect={this.onSelect}>
1342
1356
  <MenuContent>
1343
1357
  <MenuList>
1344
- {this.menuOptions.slice(0, numOptions)}
1358
+ {this.menuOptions.slice(0, numOptions).map(option => {
1359
+ const props = option.props;
1360
+
1361
+ return (
1362
+ <MenuItem
1363
+ key={option.key}
1364
+ {...props}
1365
+ ref={props.itemId === this.state.activeItem ? this.activeItemRef : null}
1366
+ />
1367
+ );
1368
+ })}
1345
1369
  {numOptions !== this.menuOptions.length && (
1346
1370
  <MenuItem
1347
1371
  {...(!isLoading && { isLoadButton: true })}
@@ -1349,6 +1373,7 @@ class ViewMoreMenu extends React.Component {
1349
1373
  onKeyDown={this.onViewMoreKeyDown}
1350
1374
  onClick={this.onViewMoreClick}
1351
1375
  itemId="loader"
1376
+ ref={this.viewMoreRef}
1352
1377
  >
1353
1378
  {isLoading ? <Spinner size="lg" /> : 'View more'}
1354
1379
  </MenuItem>
@@ -5,7 +5,7 @@ import { getUniqueId } from '../../helpers/util';
5
5
 
6
6
  export interface NavGroupProps extends React.HTMLProps<HTMLDivElement> {
7
7
  /** Title shown for the group */
8
- title: string;
8
+ title?: string;
9
9
  /** Anything that can be rendered inside of the group */
10
10
  children?: React.ReactNode;
11
11
  /** Additional classes added to the container */
@@ -20,12 +20,23 @@ export const NavGroup: React.FunctionComponent<NavGroupProps> = ({
20
20
  className = '',
21
21
  id = getUniqueId(),
22
22
  ...props
23
- }: NavGroupProps) => (
24
- <section className={css(styles.navSection, className)} aria-labelledby={id} {...props}>
25
- <h2 className={css(styles.navSectionTitle)} id={id}>
26
- {title}
27
- </h2>
28
- <ul className={css(styles.navList, className)}>{children}</ul>
29
- </section>
30
- );
23
+ }: NavGroupProps) => {
24
+ if (!title && !props['aria-label']) {
25
+ // eslint-disable-next-line no-console
26
+ console.warn("For accessibility reasons an aria-label should be specified on nav groups if a title isn't");
27
+ }
28
+
29
+ const labelledBy = title ? id : undefined;
30
+
31
+ return (
32
+ <section className={css(styles.navSection, className)} aria-labelledby={labelledBy} {...props}>
33
+ {title && (
34
+ <h2 className={css(styles.navSectionTitle)} id={id}>
35
+ {title}
36
+ </h2>
37
+ )}
38
+ <ul className={css(styles.navList, className)}>{children}</ul>
39
+ </section>
40
+ );
41
+ };
31
42
  NavGroup.displayName = 'NavGroup';
@@ -55,6 +55,8 @@ class NavDefaultList extends React.Component {
55
55
 
56
56
  ### Grouped
57
57
 
58
+ Note: to keep nav groups accessible an `aria-label` should be supplied if the `title` prop is not passed.
59
+
58
60
  ```js
59
61
  import React from 'react';
60
62
  import { Nav, NavExpandable, NavItem, NavItemSeparator, NavList, NavGroup } from '@patternfly/react-core';
@@ -8,15 +8,21 @@ export interface NotificationDrawerProps extends React.HTMLProps<HTMLDivElement>
8
8
  children?: React.ReactNode;
9
9
  /** Additional classes added to the notification drawer */
10
10
  className?: string;
11
+ /** @hide Forwarded ref */
12
+ innerRef?: React.Ref<any>;
11
13
  }
12
14
 
13
- export const NotificationDrawer: React.FunctionComponent<NotificationDrawerProps> = ({
15
+ const NotificationDrawerBase: React.FunctionComponent<NotificationDrawerProps> = ({
14
16
  children,
15
17
  className = '',
18
+ innerRef,
16
19
  ...props
17
20
  }: NotificationDrawerProps) => (
18
- <div {...props} className={css(styles.notificationDrawer, className)}>
21
+ <div ref={innerRef} {...props} className={css(styles.notificationDrawer, className)}>
19
22
  {children}
20
23
  </div>
21
24
  );
25
+ export const NotificationDrawer = React.forwardRef((props: NotificationDrawerProps, ref: React.Ref<any>) => (
26
+ <NotificationDrawerBase innerRef={ref} {...props} />
27
+ ));
22
28
  NotificationDrawer.displayName = 'NotificationDrawer';
@@ -1,6 +1,6 @@
1
1
  // Jest Snapshot v1, https://goo.gl/fbAQLP
2
2
 
3
- exports[`className is added to the root element 1`] = `"pf-c-notification-drawer extra-class"`;
3
+ exports[`className is added to the root element 1`] = `"extra-class"`;
4
4
 
5
5
  exports[`renders with PatternFly Core styles 1`] = `
6
6
  <div>
@@ -4,6 +4,7 @@ import { OUIAProps } from '../../helpers';
4
4
  import { TabButton } from './TabButton';
5
5
  import { TabsContext } from './TabsContext';
6
6
  import { css } from '@patternfly/react-styles';
7
+ import { Tooltip } from '../Tooltip';
7
8
 
8
9
  export interface TabProps extends Omit<React.HTMLProps<HTMLAnchorElement | HTMLButtonElement>, 'title'>, OUIAProps {
9
10
  /** content rendered inside the Tab content area. */
@@ -30,6 +31,8 @@ export interface TabProps extends Omit<React.HTMLProps<HTMLAnchorElement | HTMLB
30
31
  inoperableEvents?: string[];
31
32
  /** Forwarded ref */
32
33
  innerRef?: React.Ref<any>;
34
+ /** Optional Tooltip rendered to a Tab. Should be <Tooltip> with appropriate props for proper rendering. */
35
+ tooltip?: React.ReactElement<any>;
33
36
  }
34
37
 
35
38
  const TabBase: React.FunctionComponent<TabProps> = ({
@@ -45,6 +48,7 @@ const TabBase: React.FunctionComponent<TabProps> = ({
45
48
  inoperableEvents = ['onClick', 'onKeyPress'],
46
49
  href,
47
50
  innerRef,
51
+ tooltip,
48
52
  ...props
49
53
  }: TabProps) => {
50
54
  const preventedEvents = inoperableEvents.reduce(
@@ -69,31 +73,34 @@ const TabBase: React.FunctionComponent<TabProps> = ({
69
73
  return null;
70
74
  }
71
75
  };
72
- return (
73
- <li
74
- className={css(styles.tabsItem, eventKey === localActiveKey && styles.modifiers.current, childClassName)}
75
- ref={innerRef}
76
+
77
+ const tabButton = (
78
+ <TabButton
79
+ parentInnerRef={innerRef}
80
+ className={css(
81
+ styles.tabsLink,
82
+ isDisabled && href && styles.modifiers.disabled,
83
+ isAriaDisabled && styles.modifiers.ariaDisabled
84
+ )}
85
+ disabled={isButtonElement ? isDisabled : null}
86
+ aria-disabled={isDisabled || isAriaDisabled}
87
+ tabIndex={getDefaultTabIdx()}
88
+ onClick={(event: any) => handleTabClick(event, eventKey, tabContentRef)}
89
+ {...(isAriaDisabled ? preventedEvents : null)}
90
+ id={`pf-tab-${eventKey}-${childId || uniqueId}`}
91
+ aria-controls={ariaControls}
92
+ tabContentRef={tabContentRef}
93
+ ouiaId={childOuiaId}
94
+ href={href}
95
+ {...props}
76
96
  >
77
- <TabButton
78
- className={css(
79
- styles.tabsLink,
80
- isDisabled && href && styles.modifiers.disabled,
81
- isAriaDisabled && styles.modifiers.ariaDisabled
82
- )}
83
- disabled={isButtonElement ? isDisabled : null}
84
- aria-disabled={isDisabled || isAriaDisabled}
85
- tabIndex={getDefaultTabIdx()}
86
- onClick={(event: any) => handleTabClick(event, eventKey, tabContentRef)}
87
- {...(isAriaDisabled ? preventedEvents : null)}
88
- id={`pf-tab-${eventKey}-${childId || uniqueId}`}
89
- aria-controls={ariaControls}
90
- tabContentRef={tabContentRef}
91
- ouiaId={childOuiaId}
92
- href={href}
93
- {...props}
94
- >
95
- {title}
96
- </TabButton>
97
+ {title}
98
+ </TabButton>
99
+ );
100
+
101
+ return (
102
+ <li className={css(styles.tabsItem, eventKey === localActiveKey && styles.modifiers.current, childClassName)}>
103
+ {tooltip ? <Tooltip {...tooltip.props}>{tabButton}</Tooltip> : tabButton}
97
104
  </li>
98
105
  );
99
106
  };
@@ -10,6 +10,8 @@ export interface TabButtonProps extends Omit<React.HTMLProps<HTMLAnchorElement |
10
10
  href?: string;
11
11
  /** child reference for case in which a TabContent section is defined outside of a Tabs component */
12
12
  tabContentRef?: React.Ref<any>;
13
+ /** Parents' innerRef passed down for properly displaying Tooltips */
14
+ parentInnerRef?: React.Ref<any>;
13
15
  }
14
16
 
15
17
  export const TabButton: React.FunctionComponent<TabButtonProps> = ({
@@ -17,12 +19,14 @@ export const TabButton: React.FunctionComponent<TabButtonProps> = ({
17
19
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
18
20
  tabContentRef,
19
21
  ouiaId,
22
+ parentInnerRef,
20
23
  ouiaSafe,
21
24
  ...props
22
25
  }: TabButtonProps) => {
23
26
  const Component = (props.href ? 'a' : 'button') as any;
27
+
24
28
  return (
25
- <Component {...getOUIAProps(TabButton.displayName, ouiaId, ouiaSafe)} {...props}>
29
+ <Component ref={parentInnerRef} {...getOUIAProps(TabButton.displayName, ouiaId, ouiaSafe)} {...props}>
26
30
  {children}
27
31
  </Component>
28
32
  );