@patternfly/react-core 4.242.2 → 4.242.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@patternfly/react-core",
3
- "version": "4.242.2",
3
+ "version": "4.242.3",
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",
@@ -70,5 +70,5 @@
70
70
  "react": "^16.8 || ^17 || ^18",
71
71
  "react-dom": "^16.8 || ^17 || ^18"
72
72
  },
73
- "gitHead": "e35f87ea426d87511edcb2a98124e460fe80e9b7"
73
+ "gitHead": "5538c2f9925a8ac29505f1a4ec6003add9e14fa0"
74
74
  }
@@ -114,7 +114,14 @@ const variantStyle = {
114
114
  };
115
115
 
116
116
  interface TabsState {
117
+ /** Used to signal if the scroll buttons should be used */
118
+ enableScrollButtons: boolean;
119
+ /** Used to control if the scroll buttons should be shown to the user via the pf-m-scrollable class */
117
120
  showScrollButtons: boolean;
121
+ /** Used to control if the scroll buttons should be rendered. Rendering must occur before the scroll buttons are
122
+ * shown and rendering must be stopped after they stop being shown to preserve CSS transitions.
123
+ */
124
+ renderScrollButtons: boolean;
118
125
  disableLeftScrollButton: boolean;
119
126
  disableRightScrollButton: boolean;
120
127
  shownKeys: (string | number)[];
@@ -127,10 +134,13 @@ interface TabsState {
127
134
  export class Tabs extends React.Component<TabsProps, TabsState> {
128
135
  static displayName = 'Tabs';
129
136
  tabList = React.createRef<HTMLUListElement>();
137
+ leftScrollButtonRef = React.createRef<HTMLButtonElement>();
130
138
  constructor(props: TabsProps) {
131
139
  super(props);
132
140
  this.state = {
141
+ enableScrollButtons: false,
133
142
  showScrollButtons: false,
143
+ renderScrollButtons: false,
134
144
  disableLeftScrollButton: true,
135
145
  disableRightScrollButton: true,
136
146
  shownKeys: this.props.defaultActiveKey !== undefined ? [this.props.defaultActiveKey] : [this.props.activeKey], // only for mountOnEnter case
@@ -219,7 +229,7 @@ export class Tabs extends React.Component<TabsProps, TabsState> {
219
229
  const container = this.tabList.current;
220
230
  let disableLeftScrollButton = true;
221
231
  let disableRightScrollButton = true;
222
- let showScrollButtons = false;
232
+ let enableScrollButtons = false;
223
233
  let overflowingTabCount = 0;
224
234
 
225
235
  if (container && !this.props.isVertical && !isOverflowHorizontal) {
@@ -229,7 +239,7 @@ export class Tabs extends React.Component<TabsProps, TabsState> {
229
239
  // get last element and check if it is in view
230
240
  const overflowOnRight = !isElementInView(container, container.lastChild as HTMLElement, false);
231
241
 
232
- showScrollButtons = overflowOnLeft || overflowOnRight;
242
+ enableScrollButtons = overflowOnLeft || overflowOnRight;
233
243
 
234
244
  disableLeftScrollButton = !overflowOnLeft;
235
245
  disableRightScrollButton = !overflowOnRight;
@@ -240,7 +250,7 @@ export class Tabs extends React.Component<TabsProps, TabsState> {
240
250
  }
241
251
 
242
252
  this.setState({
243
- showScrollButtons,
253
+ enableScrollButtons,
244
254
  disableLeftScrollButton,
245
255
  disableRightScrollButton,
246
256
  overflowingTabCount
@@ -287,6 +297,13 @@ export class Tabs extends React.Component<TabsProps, TabsState> {
287
297
  }
288
298
  };
289
299
 
300
+ hideScrollButtons = () => {
301
+ const { enableScrollButtons, renderScrollButtons, showScrollButtons } = this.state;
302
+ if (!enableScrollButtons && !showScrollButtons && renderScrollButtons) {
303
+ this.setState({ renderScrollButtons: false });
304
+ }
305
+ };
306
+
290
307
  componentDidMount() {
291
308
  if (!this.props.isVertical) {
292
309
  if (canUseDOM) {
@@ -304,11 +321,12 @@ export class Tabs extends React.Component<TabsProps, TabsState> {
304
321
  }
305
322
  }
306
323
  clearTimeout(this.scrollTimeout);
324
+ this.leftScrollButtonRef.current?.removeEventListener('transitionend', this.hideScrollButtons);
307
325
  }
308
326
 
309
- componentDidUpdate(prevProps: TabsProps) {
327
+ componentDidUpdate(prevProps: TabsProps, prevState: TabsState) {
310
328
  const { activeKey, mountOnEnter, isOverflowHorizontal, children } = this.props;
311
- const { shownKeys, overflowingTabCount } = this.state;
329
+ const { shownKeys, overflowingTabCount, enableScrollButtons } = this.state;
312
330
  if (prevProps.activeKey !== activeKey && mountOnEnter && shownKeys.indexOf(activeKey) < 0) {
313
331
  this.setState({
314
332
  shownKeys: shownKeys.concat(activeKey)
@@ -327,6 +345,16 @@ export class Tabs extends React.Component<TabsProps, TabsState> {
327
345
  if (isOverflowHorizontal && currentOverflowingTabCount) {
328
346
  this.setState({ overflowingTabCount: currentOverflowingTabCount + overflowingTabCount });
329
347
  }
348
+
349
+ if (!prevState.enableScrollButtons && enableScrollButtons) {
350
+ this.setState({ renderScrollButtons: true });
351
+ setTimeout(() => {
352
+ this.leftScrollButtonRef.current?.addEventListener('transitionend', this.hideScrollButtons);
353
+ this.setState({ showScrollButtons: true });
354
+ }, 100);
355
+ } else if (prevState.enableScrollButtons && !enableScrollButtons) {
356
+ this.setState({ showScrollButtons: false });
357
+ }
330
358
  }
331
359
 
332
360
  render() {
@@ -367,6 +395,7 @@ export class Tabs extends React.Component<TabsProps, TabsState> {
367
395
  } = this.props;
368
396
  const {
369
397
  showScrollButtons,
398
+ renderScrollButtons,
370
399
  disableLeftScrollButton,
371
400
  disableRightScrollButton,
372
401
  shownKeys,
@@ -421,7 +450,7 @@ export class Tabs extends React.Component<TabsProps, TabsState> {
421
450
  isVertical && expandable && formatBreakpointMods(expandable, styles),
422
451
  isVertical && expandable && isExpandedLocal && styles.modifiers.expanded,
423
452
  isBox && styles.modifiers.box,
424
- showScrollButtons && !isVertical && styles.modifiers.scrollable,
453
+ showScrollButtons && styles.modifiers.scrollable,
425
454
  usePageInsets && styles.modifiers.pageInsets,
426
455
  !hasBorderBottom && styles.modifiers.noBorderBottom,
427
456
  hasSecondaryBorderBottom && styles.modifiers.borderBottom,
@@ -461,7 +490,7 @@ export class Tabs extends React.Component<TabsProps, TabsState> {
461
490
  )}
462
491
  </GenerateId>
463
492
  )}
464
- {showScrollButtons && (
493
+ {renderScrollButtons && (
465
494
  <button
466
495
  type="button"
467
496
  className={css(styles.tabsScrollButton, isSecondary && buttonStyles.modifiers.secondary)}
@@ -469,6 +498,7 @@ export class Tabs extends React.Component<TabsProps, TabsState> {
469
498
  onClick={this.scrollLeft}
470
499
  disabled={disableLeftScrollButton}
471
500
  aria-hidden={disableLeftScrollButton}
501
+ ref={this.leftScrollButtonRef}
472
502
  >
473
503
  <AngleLeftIcon />
474
504
  </button>
@@ -477,7 +507,7 @@ export class Tabs extends React.Component<TabsProps, TabsState> {
477
507
  {isOverflowHorizontal ? filteredChildrenWithoutOverflow : filteredChildren}
478
508
  {hasOverflowTab && <OverflowTab overflowingTabs={overflowingTabProps} {...overflowObjectProps} />}
479
509
  </ul>
480
- {showScrollButtons && (
510
+ {renderScrollButtons && (
481
511
  <button
482
512
  type="button"
483
513
  className={css(styles.tabsScrollButton, isSecondary && buttonStyles.modifiers.secondary)}
@@ -412,6 +412,25 @@ test('should render tabs with secondary border bottom when passed hasSecondaryBo
412
412
  expect(tabsContainer).toHaveClass('pf-m-border-bottom');
413
413
  });
414
414
 
415
+ test('should not render scroll buttons by default', () => {
416
+ render(
417
+ <Tabs>
418
+ <Tab id="tab1" eventKey={0} title={<TabTitleText>"Tab item 1"</TabTitleText>}>
419
+ Tab 1 section
420
+ </Tab>
421
+ <Tab id="tab2" eventKey={1} title={<TabTitleText>"Tab item 2"</TabTitleText>}>
422
+ Tab 2 section
423
+ </Tab>
424
+ <Tab id="tab3" eventKey={2} title={<TabTitleText>"Tab item 3"</TabTitleText>}>
425
+ Tab 3 section
426
+ </Tab>
427
+ </Tabs>
428
+ );
429
+
430
+ expect(screen.queryByLabelText('Scroll left')).not.toBeInTheDocument();
431
+ expect(screen.queryByLabelText('Scroll right')).not.toBeInTheDocument();
432
+ })
433
+
415
434
  test('should not render scroll buttons when isVertical is true', () => {
416
435
  render(
417
436
  <Tabs isVertical>