@patternfly/react-core 4.263.0 → 4.264.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +22 -0
- package/dist/esm/components/Tabs/Tab.d.ts +4 -2
- package/dist/esm/components/Tabs/Tab.d.ts.map +1 -1
- package/dist/esm/components/Tabs/Tab.js +6 -7
- package/dist/esm/components/Tabs/Tab.js.map +1 -1
- package/dist/esm/components/Tabs/TabAction.d.ts +20 -0
- package/dist/esm/components/Tabs/TabAction.d.ts.map +1 -0
- package/dist/esm/components/Tabs/TabAction.js +17 -0
- package/dist/esm/components/Tabs/TabAction.js.map +1 -0
- package/dist/esm/components/Tabs/Tabs.d.ts +1 -1
- package/dist/esm/components/Tabs/Tabs.d.ts.map +1 -1
- package/dist/esm/components/Tabs/index.d.ts +1 -0
- package/dist/esm/components/Tabs/index.d.ts.map +1 -1
- package/dist/esm/components/Tabs/index.js +1 -0
- package/dist/esm/components/Tabs/index.js.map +1 -1
- package/dist/js/components/Tabs/Tab.d.ts +4 -2
- package/dist/js/components/Tabs/Tab.d.ts.map +1 -1
- package/dist/js/components/Tabs/Tab.js +6 -7
- package/dist/js/components/Tabs/Tab.js.map +1 -1
- package/dist/js/components/Tabs/TabAction.d.ts +20 -0
- package/dist/js/components/Tabs/TabAction.d.ts.map +1 -0
- package/dist/js/components/Tabs/TabAction.js +20 -0
- package/dist/js/components/Tabs/TabAction.js.map +1 -0
- package/dist/js/components/Tabs/Tabs.d.ts +1 -1
- package/dist/js/components/Tabs/Tabs.d.ts.map +1 -1
- package/dist/js/components/Tabs/index.d.ts +1 -0
- package/dist/js/components/Tabs/index.d.ts.map +1 -1
- package/dist/js/components/Tabs/index.js +1 -0
- package/dist/js/components/Tabs/index.js.map +1 -1
- package/dist/styles/assets/pficon/pficon.scss +12 -0
- package/dist/styles/assets/pficon/pficon.woff +0 -0
- package/dist/styles/assets/pficon/pficon.woff2 +0 -0
- package/dist/styles/base-no-reset.css +10 -0
- package/dist/styles/base.css +10 -0
- package/dist/umd/react-core.min.css +1063 -894
- package/dist/umd/react-core.min.js +1 -1
- package/package.json +14 -7
- package/src/components/Tabs/Tab.tsx +17 -16
- package/src/components/Tabs/TabAction.tsx +57 -0
- package/src/components/Tabs/Tabs.tsx +1 -1
- package/src/components/Tabs/__tests__/Tab.test.tsx +10 -0
- package/src/components/Tabs/__tests__/__snapshots__/Tab.test.tsx.snap +45 -0
- package/src/components/Tabs/examples/Tabs.md +64 -20
- package/src/components/Tabs/examples/TabsHelp.tsx +61 -0
- package/src/components/Tabs/examples/TabsHelpAndClose.tsx +84 -0
- package/src/components/Tabs/index.ts +1 -0
- package/src/components/Tooltip/examples/Tooltip.md +5 -285
- package/src/components/Tooltip/examples/TooltipBasic.tsx +16 -0
- package/src/components/Tooltip/examples/TooltipIcon.tsx +24 -0
- package/src/components/Tooltip/examples/TooltipOptions.tsx +197 -0
- package/src/components/Tooltip/examples/TooltipReactRef.tsx +22 -0
- package/src/components/Tooltip/examples/TooltipSelectorRef.tsx +19 -0
- package/src/demos/Tabs.md +0 -10
- package/src/demos/examples/DashboardWrapper.js +1 -0
- package/src/demos/examples/Tabs/ModalTabs.tsx +3 -3
- package/src/demos/examples/Tabs/NestedTabs.tsx +11 -3
- package/src/demos/examples/Tabs/NestedUnindentedTabs.tsx +25 -40
- package/src/demos/examples/Tabs/TabsAndTable.tsx +9 -52
- package/dist/esm/components/Button/__mocks__/Button.d.ts +0 -8
- package/dist/esm/components/Button/__mocks__/Button.d.ts.map +0 -1
- package/dist/esm/components/Button/__mocks__/Button.js +0 -14
- package/dist/esm/components/Button/__mocks__/Button.js.map +0 -1
- package/dist/esm/components/Button/__mocks__/index.d.ts +0 -2
- package/dist/esm/components/Button/__mocks__/index.d.ts.map +0 -1
- package/dist/esm/components/Button/__mocks__/index.js +0 -2
- package/dist/esm/components/Button/__mocks__/index.js.map +0 -1
- package/dist/esm/components/HelperText/__mocks__/HelperText.d.ts +0 -4
- package/dist/esm/components/HelperText/__mocks__/HelperText.d.ts.map +0 -1
- package/dist/esm/components/HelperText/__mocks__/HelperText.js +0 -5
- package/dist/esm/components/HelperText/__mocks__/HelperText.js.map +0 -1
- package/dist/esm/components/HelperText/__mocks__/HelperTextItem.d.ts +0 -4
- package/dist/esm/components/HelperText/__mocks__/HelperTextItem.d.ts.map +0 -1
- package/dist/esm/components/HelperText/__mocks__/HelperTextItem.js +0 -5
- package/dist/esm/components/HelperText/__mocks__/HelperTextItem.js.map +0 -1
- package/dist/esm/components/HelperText/__mocks__/index.d.ts +0 -3
- package/dist/esm/components/HelperText/__mocks__/index.d.ts.map +0 -1
- package/dist/esm/components/HelperText/__mocks__/index.js +0 -3
- package/dist/esm/components/HelperText/__mocks__/index.js.map +0 -1
- package/dist/js/components/Button/__mocks__/Button.d.ts +0 -8
- package/dist/js/components/Button/__mocks__/Button.d.ts.map +0 -1
- package/dist/js/components/Button/__mocks__/Button.js +0 -18
- package/dist/js/components/Button/__mocks__/Button.js.map +0 -1
- package/dist/js/components/Button/__mocks__/index.d.ts +0 -2
- package/dist/js/components/Button/__mocks__/index.d.ts.map +0 -1
- package/dist/js/components/Button/__mocks__/index.js +0 -5
- package/dist/js/components/Button/__mocks__/index.js.map +0 -1
- package/dist/js/components/HelperText/__mocks__/HelperText.d.ts +0 -4
- package/dist/js/components/HelperText/__mocks__/HelperText.d.ts.map +0 -1
- package/dist/js/components/HelperText/__mocks__/HelperText.js +0 -10
- package/dist/js/components/HelperText/__mocks__/HelperText.js.map +0 -1
- package/dist/js/components/HelperText/__mocks__/HelperTextItem.d.ts +0 -4
- package/dist/js/components/HelperText/__mocks__/HelperTextItem.d.ts.map +0 -1
- package/dist/js/components/HelperText/__mocks__/HelperTextItem.js +0 -10
- package/dist/js/components/HelperText/__mocks__/HelperTextItem.js.map +0 -1
- package/dist/js/components/HelperText/__mocks__/index.d.ts +0 -3
- package/dist/js/components/HelperText/__mocks__/index.d.ts.map +0 -1
- package/dist/js/components/HelperText/__mocks__/index.js +0 -6
- package/dist/js/components/HelperText/__mocks__/index.js.map +0 -1
- package/src/demos/examples/Tabs/GrayTabs.tsx +0 -152
- package/src/demos/examples/Tabs/TabsAndTablesAutoWidthTabs.tsx +0 -442
package/package.json
CHANGED
|
@@ -1,10 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@patternfly/react-core",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.264.1",
|
|
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",
|
|
7
7
|
"types": "dist/esm/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": "./dist/esm/index.js",
|
|
10
|
+
"./dist/*": "./dist/*",
|
|
11
|
+
"./next": "./dist/esm/next",
|
|
12
|
+
"./deprecated": "./dist/esm/deprecated",
|
|
13
|
+
"./package.json": "./package.json"
|
|
14
|
+
},
|
|
8
15
|
"typesVersions": {
|
|
9
16
|
"*": {
|
|
10
17
|
"next": [
|
|
@@ -44,18 +51,18 @@
|
|
|
44
51
|
"generate": "node scripts/copyStyles.js"
|
|
45
52
|
},
|
|
46
53
|
"dependencies": {
|
|
47
|
-
"@patternfly/react-icons": "^4.
|
|
48
|
-
"@patternfly/react-styles": "^4.
|
|
49
|
-
"@patternfly/react-tokens": "^4.
|
|
54
|
+
"@patternfly/react-icons": "^4.93.0",
|
|
55
|
+
"@patternfly/react-styles": "^4.92.0",
|
|
56
|
+
"@patternfly/react-tokens": "^4.94.0",
|
|
50
57
|
"focus-trap": "6.9.2",
|
|
51
58
|
"react-dropzone": "9.0.0",
|
|
52
59
|
"tippy.js": "5.1.2",
|
|
53
60
|
"tslib": "^2.0.0"
|
|
54
61
|
},
|
|
55
62
|
"devDependencies": {
|
|
56
|
-
"@patternfly/patternfly": "4.
|
|
63
|
+
"@patternfly/patternfly": "4.221.2",
|
|
57
64
|
"@rollup/plugin-commonjs": "^21.0.0",
|
|
58
|
-
"@rollup/plugin-node-resolve": "^
|
|
65
|
+
"@rollup/plugin-node-resolve": "^15.0.1",
|
|
59
66
|
"@rollup/plugin-replace": "^3.0.0",
|
|
60
67
|
"css": "^2.2.3",
|
|
61
68
|
"fs-extra": "^6.0.1",
|
|
@@ -70,5 +77,5 @@
|
|
|
70
77
|
"react": "^16.8 || ^17 || ^18",
|
|
71
78
|
"react-dom": "^16.8 || ^17 || ^18"
|
|
72
79
|
},
|
|
73
|
-
"gitHead": "
|
|
80
|
+
"gitHead": "3c9dd17f7327ffafa0b9751074b188ea19eaeee6"
|
|
74
81
|
}
|
|
@@ -5,10 +5,12 @@ import { TabButton } from './TabButton';
|
|
|
5
5
|
import { TabsContext } from './TabsContext';
|
|
6
6
|
import { css } from '@patternfly/react-styles';
|
|
7
7
|
import { Tooltip } from '../Tooltip';
|
|
8
|
-
import { Button } from '../Button';
|
|
9
8
|
import TimesIcon from '@patternfly/react-icons/dist/esm/icons/times-icon';
|
|
9
|
+
import { TabAction } from './TabAction';
|
|
10
10
|
|
|
11
|
-
export interface TabProps
|
|
11
|
+
export interface TabProps
|
|
12
|
+
extends Omit<React.HTMLProps<HTMLAnchorElement | HTMLButtonElement>, 'title' | 'action'>,
|
|
13
|
+
OUIAProps {
|
|
12
14
|
/** content rendered inside the Tab content area. */
|
|
13
15
|
children?: React.ReactNode;
|
|
14
16
|
/** additional classes added to the Tab */
|
|
@@ -39,6 +41,8 @@ export interface TabProps extends Omit<React.HTMLProps<HTMLAnchorElement | HTMLB
|
|
|
39
41
|
closeButtonAriaLabel?: string;
|
|
40
42
|
/** @beta Flag indicating the close button should be disabled */
|
|
41
43
|
isCloseDisabled?: boolean;
|
|
44
|
+
/** @beta Actions rendered beside the tab content */
|
|
45
|
+
actions?: React.ReactNode;
|
|
42
46
|
/** Value to set the data-ouia-component-id for the tab button.*/
|
|
43
47
|
ouiaId?: number | string;
|
|
44
48
|
}
|
|
@@ -59,6 +63,7 @@ const TabBase: React.FunctionComponent<TabProps> = ({
|
|
|
59
63
|
tooltip,
|
|
60
64
|
closeButtonAriaLabel,
|
|
61
65
|
isCloseDisabled = false,
|
|
66
|
+
actions,
|
|
62
67
|
...props
|
|
63
68
|
}: TabProps) => {
|
|
64
69
|
const preventedEvents = inoperableEvents.reduce(
|
|
@@ -117,26 +122,22 @@ const TabBase: React.FunctionComponent<TabProps> = ({
|
|
|
117
122
|
className={css(
|
|
118
123
|
styles.tabsItem,
|
|
119
124
|
eventKey === localActiveKey && styles.modifiers.current,
|
|
120
|
-
handleTabClose && styles.modifiers.action,
|
|
121
|
-
|
|
125
|
+
(handleTabClose || actions) && styles.modifiers.action,
|
|
126
|
+
(isDisabled || isAriaDisabled) && styles.modifiers.disabled,
|
|
122
127
|
childClassName
|
|
123
128
|
)}
|
|
124
129
|
role="presentation"
|
|
125
130
|
>
|
|
126
131
|
{tooltip ? <Tooltip {...tooltip.props}>{tabButton}</Tooltip> : tabButton}
|
|
132
|
+
{actions && actions}
|
|
127
133
|
{handleTabClose !== undefined && (
|
|
128
|
-
<
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
<span className={css(styles.tabsItemCloseIcon)}>
|
|
136
|
-
<TimesIcon />
|
|
137
|
-
</span>
|
|
138
|
-
</Button>
|
|
139
|
-
</span>
|
|
134
|
+
<TabAction
|
|
135
|
+
aria-label={closeButtonAriaLabel || 'Close tab'}
|
|
136
|
+
onClick={(event: any) => handleTabClose(event, eventKey, tabContentRef)}
|
|
137
|
+
isDisabled={isCloseDisabled}
|
|
138
|
+
>
|
|
139
|
+
<TimesIcon />
|
|
140
|
+
</TabAction>
|
|
140
141
|
)}
|
|
141
142
|
</li>
|
|
142
143
|
);
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { css } from '@patternfly/react-styles';
|
|
3
|
+
import styles from '@patternfly/react-styles/css/components/Tabs/tabs';
|
|
4
|
+
import { Button } from '../Button';
|
|
5
|
+
import { getOUIAProps, OUIAProps } from '../../helpers';
|
|
6
|
+
|
|
7
|
+
export interface TabActionProps extends Omit<React.HTMLProps<HTMLButtonElement>, 'ref' | 'type'>, OUIAProps {
|
|
8
|
+
/** Content rendered in the tab action */
|
|
9
|
+
children?: React.ReactNode;
|
|
10
|
+
/** Additional classes added to the tab action span */
|
|
11
|
+
className?: string;
|
|
12
|
+
/** Click callback for tab action button */
|
|
13
|
+
onClick?: (event: React.MouseEvent<HTMLElement, MouseEvent>) => void;
|
|
14
|
+
/** Flag indicating if the tab action is a help action */
|
|
15
|
+
isHelpAction?: boolean;
|
|
16
|
+
/** Flag indicating if the tab action is disabled */
|
|
17
|
+
isDisabled?: boolean;
|
|
18
|
+
/** Accessible label for the tab action */
|
|
19
|
+
'aria-label'?: string;
|
|
20
|
+
/** @hide Callback for the section ref */
|
|
21
|
+
innerRef?: React.Ref<any>;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const TabActionBase: React.FunctionComponent<TabActionProps> = ({
|
|
25
|
+
children,
|
|
26
|
+
className,
|
|
27
|
+
onClick,
|
|
28
|
+
isHelpAction,
|
|
29
|
+
isDisabled,
|
|
30
|
+
'aria-label': ariaLabel = 'Tab action',
|
|
31
|
+
innerRef,
|
|
32
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
33
|
+
ouiaId,
|
|
34
|
+
ouiaSafe,
|
|
35
|
+
...props
|
|
36
|
+
}: TabActionProps) => (
|
|
37
|
+
<span className={css(styles.tabsItemAction, isHelpAction && styles.modifiers.help, className)}>
|
|
38
|
+
<Button
|
|
39
|
+
ref={innerRef}
|
|
40
|
+
type="button"
|
|
41
|
+
variant="plain"
|
|
42
|
+
aria-label={ariaLabel}
|
|
43
|
+
onClick={onClick}
|
|
44
|
+
isDisabled={isDisabled}
|
|
45
|
+
{...getOUIAProps(TabAction.displayName, ouiaId, ouiaSafe)}
|
|
46
|
+
{...props}
|
|
47
|
+
>
|
|
48
|
+
<span className={css(styles.tabsItemActionIcon)}>{children}</span>
|
|
49
|
+
</Button>
|
|
50
|
+
</span>
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
export const TabAction = React.forwardRef((props: TabActionProps, ref: React.Ref<HTMLElement>) => (
|
|
54
|
+
<TabActionBase {...props} innerRef={ref} />
|
|
55
|
+
));
|
|
56
|
+
|
|
57
|
+
TabAction.displayName = 'TabAction';
|
|
@@ -42,7 +42,7 @@ export interface TabsProps extends Omit<React.HTMLProps<HTMLElement | HTMLDivEle
|
|
|
42
42
|
defaultActiveKey?: number | string;
|
|
43
43
|
/** Callback to handle tab selection */
|
|
44
44
|
onSelect?: (event: React.MouseEvent<HTMLElement, MouseEvent>, eventKey: number | string) => void;
|
|
45
|
-
/** @beta Callback to handle tab closing */
|
|
45
|
+
/** @beta Callback to handle tab closing and adds a basic close button to all tabs. This is overridden by the tab actions property. */
|
|
46
46
|
onClose?: (event: React.MouseEvent<HTMLElement, MouseEvent>, eventKey: number | string) => void;
|
|
47
47
|
/** @beta Callback for the add button. Passing this property inserts the add button */
|
|
48
48
|
onAdd?: () => void;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { render } from '@testing-library/react';
|
|
3
3
|
import { Tab } from '../Tab';
|
|
4
|
+
import { TabAction } from '../TabAction';
|
|
4
5
|
import { TabTitleText } from '../TabTitleText';
|
|
5
6
|
|
|
6
7
|
test('should not render anything', () => {
|
|
@@ -11,3 +12,12 @@ test('should not render anything', () => {
|
|
|
11
12
|
);
|
|
12
13
|
expect(asFragment()).toMatchSnapshot();
|
|
13
14
|
});
|
|
15
|
+
|
|
16
|
+
test('renders tab action', () => {
|
|
17
|
+
const { asFragment } = render(
|
|
18
|
+
<Tab eventKey={1} title={<TabTitleText>"Tab item 2"</TabTitleText>} actions={<TabAction>test</TabAction>}>
|
|
19
|
+
Tab 2 section
|
|
20
|
+
</Tab>
|
|
21
|
+
);
|
|
22
|
+
expect(asFragment()).toMatchSnapshot();
|
|
23
|
+
});
|
|
@@ -1,5 +1,50 @@
|
|
|
1
1
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
2
2
|
|
|
3
|
+
exports[`renders tab action 1`] = `
|
|
4
|
+
<DocumentFragment>
|
|
5
|
+
<li
|
|
6
|
+
class="pf-c-tabs__item pf-m-action"
|
|
7
|
+
role="presentation"
|
|
8
|
+
>
|
|
9
|
+
<button
|
|
10
|
+
aria-controls="pf-tab-section-1-"
|
|
11
|
+
aria-selected="false"
|
|
12
|
+
class="pf-c-tabs__link"
|
|
13
|
+
data-ouia-component-type="PF4/TabButton"
|
|
14
|
+
data-ouia-safe="true"
|
|
15
|
+
id="pf-tab-1-"
|
|
16
|
+
role="tab"
|
|
17
|
+
type="button"
|
|
18
|
+
>
|
|
19
|
+
<span
|
|
20
|
+
class="pf-c-tabs__item-text"
|
|
21
|
+
>
|
|
22
|
+
"Tab item 2"
|
|
23
|
+
</span>
|
|
24
|
+
</button>
|
|
25
|
+
<span
|
|
26
|
+
class="pf-c-tabs__item-action"
|
|
27
|
+
>
|
|
28
|
+
<button
|
|
29
|
+
aria-disabled="false"
|
|
30
|
+
aria-label="Tab action"
|
|
31
|
+
class="pf-c-button pf-m-plain"
|
|
32
|
+
data-ouia-component-id="OUIA-Generated-Button-plain-1"
|
|
33
|
+
data-ouia-component-type="PF4/Button"
|
|
34
|
+
data-ouia-safe="true"
|
|
35
|
+
type="button"
|
|
36
|
+
>
|
|
37
|
+
<span
|
|
38
|
+
class="pf-c-tabs__item-action-icon"
|
|
39
|
+
>
|
|
40
|
+
test
|
|
41
|
+
</span>
|
|
42
|
+
</button>
|
|
43
|
+
</span>
|
|
44
|
+
</li>
|
|
45
|
+
</DocumentFragment>
|
|
46
|
+
`;
|
|
47
|
+
|
|
3
48
|
exports[`should not render anything 1`] = `
|
|
4
49
|
<DocumentFragment>
|
|
5
50
|
<li
|
|
@@ -12,6 +12,8 @@ import DatabaseIcon from '@patternfly/react-icons/dist/esm/icons/database-icon';
|
|
|
12
12
|
import ServerIcon from '@patternfly/react-icons/dist/esm/icons/server-icon';
|
|
13
13
|
import LaptopIcon from '@patternfly/react-icons/dist/esm/icons/laptop-icon';
|
|
14
14
|
import ProjectDiagramIcon from '@patternfly/react-icons/dist/esm/icons/project-diagram-icon';
|
|
15
|
+
import HelpIcon from '@patternfly/react-icons/dist/esm/icons/help-icon';
|
|
16
|
+
import TimesIcon from '@patternfly/react-icons/dist/esm/icons/times-icon';
|
|
15
17
|
|
|
16
18
|
Most tab variations are available as open (default) or box style tabs. Select the 'isBox' checkbox to preview an example with box styled tabs.
|
|
17
19
|
The Tabs items background can be also toggled with 'Tab light variation' checkbox.
|
|
@@ -458,7 +460,15 @@ class VerticalTabs extends React.Component {
|
|
|
458
460
|
aria-label="Tabs in the vertical example"
|
|
459
461
|
role="region"
|
|
460
462
|
>
|
|
461
|
-
<Tab
|
|
463
|
+
<Tab
|
|
464
|
+
eventKey={0}
|
|
465
|
+
title={
|
|
466
|
+
<TabTitleText aria-label="vertical" role="region">
|
|
467
|
+
Users
|
|
468
|
+
</TabTitleText>
|
|
469
|
+
}
|
|
470
|
+
aria-label="Vertical example content users"
|
|
471
|
+
>
|
|
462
472
|
Users
|
|
463
473
|
</Tab>
|
|
464
474
|
<Tab eventKey={1} title={<TabTitleText>Containers</TabTitleText>}>
|
|
@@ -591,7 +601,11 @@ class VerticalExpandableUncontrolledTabs extends React.Component {
|
|
|
591
601
|
aria-label="Tabs in the vertical expandable uncontrolled example"
|
|
592
602
|
role="region"
|
|
593
603
|
>
|
|
594
|
-
<Tab
|
|
604
|
+
<Tab
|
|
605
|
+
eventKey={0}
|
|
606
|
+
title={<TabTitleText>Users</TabTitleText>}
|
|
607
|
+
aria-label="Vertical expandable uncontrolled content users"
|
|
608
|
+
>
|
|
595
609
|
Users
|
|
596
610
|
</Tab>
|
|
597
611
|
<Tab eventKey={1} title={<TabTitleText>Containers</TabTitleText>}>
|
|
@@ -1206,7 +1220,12 @@ class TabsNav extends React.Component {
|
|
|
1206
1220
|
component={TabsComponent.nav}
|
|
1207
1221
|
aria-label="Tabs in the nav element example"
|
|
1208
1222
|
>
|
|
1209
|
-
<Tab
|
|
1223
|
+
<Tab
|
|
1224
|
+
eventKey={0}
|
|
1225
|
+
title={<TabTitleText>Users</TabTitleText>}
|
|
1226
|
+
href="#users"
|
|
1227
|
+
aria-label="Nav element content users"
|
|
1228
|
+
>
|
|
1210
1229
|
Users
|
|
1211
1230
|
</Tab>
|
|
1212
1231
|
<Tab eventKey={1} title={<TabTitleText>Containers</TabTitleText>} href="#containers">
|
|
@@ -1267,7 +1286,12 @@ class SecondaryTabsNav extends React.Component {
|
|
|
1267
1286
|
component={TabsComponent.nav}
|
|
1268
1287
|
aria-label="Tabs in the sub tabs with nav element example"
|
|
1269
1288
|
>
|
|
1270
|
-
<Tab
|
|
1289
|
+
<Tab
|
|
1290
|
+
eventKey={0}
|
|
1291
|
+
title={<TabTitleText>Users</TabTitleText>}
|
|
1292
|
+
href="#"
|
|
1293
|
+
aria-label="Subtabs with nav content users"
|
|
1294
|
+
>
|
|
1271
1295
|
<Tabs
|
|
1272
1296
|
activeKey={this.state.activeTabKey2}
|
|
1273
1297
|
isSecondary
|
|
@@ -1423,7 +1447,12 @@ const TabContentWithBody = () => {
|
|
|
1423
1447
|
|
|
1424
1448
|
return (
|
|
1425
1449
|
<React.Fragment>
|
|
1426
|
-
<Tabs
|
|
1450
|
+
<Tabs
|
|
1451
|
+
activeKey={activeTabKey}
|
|
1452
|
+
onSelect={handleTabClick}
|
|
1453
|
+
aria-label="Tabs in the body and padding example"
|
|
1454
|
+
role="region"
|
|
1455
|
+
>
|
|
1427
1456
|
<Tab
|
|
1428
1457
|
eventKey={0}
|
|
1429
1458
|
title={<TabTitleText>Tab item 1</TabTitleText>}
|
|
@@ -1447,20 +1476,10 @@ const TabContentWithBody = () => {
|
|
|
1447
1476
|
<TabContent eventKey={0} id="tab1SectionBodyPadding" ref={contentRef1}>
|
|
1448
1477
|
<TabContentBody hasPadding> Tab 1 section with body and padding </TabContentBody>
|
|
1449
1478
|
</TabContent>
|
|
1450
|
-
<TabContent
|
|
1451
|
-
eventKey={1}
|
|
1452
|
-
id="tab2SectionBodyPadding"
|
|
1453
|
-
ref={contentRef2}
|
|
1454
|
-
hidden
|
|
1455
|
-
>
|
|
1479
|
+
<TabContent eventKey={1} id="tab2SectionBodyPadding" ref={contentRef2} hidden>
|
|
1456
1480
|
<TabContentBody hasPadding> Tab 2 section with body and padding </TabContentBody>
|
|
1457
1481
|
</TabContent>
|
|
1458
|
-
<TabContent
|
|
1459
|
-
eventKey={2}
|
|
1460
|
-
id="tab3SectionBodyPadding"
|
|
1461
|
-
ref={contentRef3}
|
|
1462
|
-
hidden
|
|
1463
|
-
>
|
|
1482
|
+
<TabContent eventKey={2} id="tab3SectionBodyPadding" ref={contentRef3} hidden>
|
|
1464
1483
|
<TabContentBody hasPadding> Tab 3 section with body and padding </TabContentBody>
|
|
1465
1484
|
</TabContent>
|
|
1466
1485
|
</div>
|
|
@@ -1597,11 +1616,26 @@ class ToggledSeparateContent extends React.Component {
|
|
|
1597
1616
|
aria-label="Tabs in the toggled separate content example"
|
|
1598
1617
|
role="region"
|
|
1599
1618
|
>
|
|
1600
|
-
<Tab
|
|
1619
|
+
<Tab
|
|
1620
|
+
eventKey={0}
|
|
1621
|
+
title="Tab item 1"
|
|
1622
|
+
tabContentId="tab1SectionSeparateContent"
|
|
1623
|
+
tabContentRef={this.contentRef1}
|
|
1624
|
+
/>
|
|
1601
1625
|
{!isTab2Hidden && (
|
|
1602
|
-
<Tab
|
|
1626
|
+
<Tab
|
|
1627
|
+
eventKey={1}
|
|
1628
|
+
title="Tab item 2"
|
|
1629
|
+
tabContentId="tab2SectionSeparateContent"
|
|
1630
|
+
tabContentRef={this.contentRef2}
|
|
1631
|
+
/>
|
|
1603
1632
|
)}
|
|
1604
|
-
<Tab
|
|
1633
|
+
<Tab
|
|
1634
|
+
eventKey={2}
|
|
1635
|
+
title="Tab item 3"
|
|
1636
|
+
tabContentId="tab3SectionSeparateContent"
|
|
1637
|
+
tabContentRef={this.contentRef3}
|
|
1638
|
+
/>
|
|
1605
1639
|
</Tabs>
|
|
1606
1640
|
<div>
|
|
1607
1641
|
<TabContent
|
|
@@ -1645,3 +1679,13 @@ To enable closeable tabs, pass the `onClose` property to `Tabs`, and to enable t
|
|
|
1645
1679
|
|
|
1646
1680
|
```ts file="./TabsDynamic.tsx" isBeta
|
|
1647
1681
|
```
|
|
1682
|
+
|
|
1683
|
+
### Help action
|
|
1684
|
+
|
|
1685
|
+
```ts file="./TabsHelp.tsx" isBeta
|
|
1686
|
+
```
|
|
1687
|
+
|
|
1688
|
+
### Help and close actions
|
|
1689
|
+
|
|
1690
|
+
```ts file="./TabsHelpAndClose.tsx" isBeta
|
|
1691
|
+
```
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Tabs, Tab, TabTitleText, TabAction, Popover } from '@patternfly/react-core';
|
|
3
|
+
import HelpIcon from '@patternfly/react-icons/dist/esm/icons/help-icon';
|
|
4
|
+
|
|
5
|
+
export const TabsHelp: React.FunctionComponent = () => {
|
|
6
|
+
const [activeTabKey, setActiveTabKey] = React.useState<number>(0);
|
|
7
|
+
|
|
8
|
+
const tabs = ['Users', 'Containers', 'Database', 'Disabled', 'ARIA disabled', 'Help disabled'];
|
|
9
|
+
|
|
10
|
+
const helpPopover = (header: string, popoverRef: React.RefObject<any>) => (
|
|
11
|
+
<Popover
|
|
12
|
+
headerContent={<div>{header}</div>}
|
|
13
|
+
bodyContent={
|
|
14
|
+
<div>
|
|
15
|
+
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam id feugiat augue, nec fringilla turpis.
|
|
16
|
+
</div>
|
|
17
|
+
}
|
|
18
|
+
footerContent="Popover footer"
|
|
19
|
+
reference={popoverRef}
|
|
20
|
+
/>
|
|
21
|
+
);
|
|
22
|
+
|
|
23
|
+
return (
|
|
24
|
+
<Tabs
|
|
25
|
+
activeKey={activeTabKey}
|
|
26
|
+
onSelect={(event: any, tabIndex: string | number) => setActiveTabKey(tabIndex as number)}
|
|
27
|
+
aria-label="Tabs in the help action example"
|
|
28
|
+
role="region"
|
|
29
|
+
>
|
|
30
|
+
{tabs.map((tab, index) => {
|
|
31
|
+
const ref = React.createRef<HTMLElement>();
|
|
32
|
+
|
|
33
|
+
return (
|
|
34
|
+
<Tab
|
|
35
|
+
key={index}
|
|
36
|
+
eventKey={index}
|
|
37
|
+
aria-label={`Help action content - ${tab}`}
|
|
38
|
+
title={<TabTitleText>{tab}</TabTitleText>}
|
|
39
|
+
{...(tab === 'Disabled' && { isDisabled: true })}
|
|
40
|
+
{...(tab === 'ARIA disabled' && { isAriaDisabled: true })}
|
|
41
|
+
actions={
|
|
42
|
+
<>
|
|
43
|
+
<TabAction
|
|
44
|
+
isHelpAction
|
|
45
|
+
aria-label={`Help action for ${tab}`}
|
|
46
|
+
ref={ref}
|
|
47
|
+
{...(tab === 'Help disabled' && { isDisabled: true })}
|
|
48
|
+
>
|
|
49
|
+
<HelpIcon />
|
|
50
|
+
</TabAction>
|
|
51
|
+
{helpPopover(`Help popover for ${tab}`, ref)}
|
|
52
|
+
</>
|
|
53
|
+
}
|
|
54
|
+
>
|
|
55
|
+
{tab}
|
|
56
|
+
</Tab>
|
|
57
|
+
);
|
|
58
|
+
})}
|
|
59
|
+
</Tabs>
|
|
60
|
+
);
|
|
61
|
+
};
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Tabs, Tab, TabTitleText, Popover, TabAction } from '@patternfly/react-core';
|
|
3
|
+
import HelpIcon from '@patternfly/react-icons/dist/esm/icons/help-icon';
|
|
4
|
+
import TimesIcon from '@patternfly/react-icons/dist/esm/icons/times-icon';
|
|
5
|
+
|
|
6
|
+
export const TabsHelpAndClose: React.FunctionComponent = () => {
|
|
7
|
+
const [activeTabKey, setActiveTabKey] = React.useState<number>(0);
|
|
8
|
+
const [tabs, setTabs] = React.useState<string[]>(['Terminal 1', 'Terminal 2', 'Terminal 3']);
|
|
9
|
+
const tabComponentRef = React.useRef<any>();
|
|
10
|
+
const firstMount = React.useRef(true);
|
|
11
|
+
|
|
12
|
+
const onClose = (event: any, tabIndex: string | number) => {
|
|
13
|
+
const tabIndexNum = tabIndex as number;
|
|
14
|
+
let nextTabIndex = activeTabKey;
|
|
15
|
+
if (tabIndexNum < activeTabKey) {
|
|
16
|
+
// if a preceding tab is closing, keep focus on the new index of the current tab
|
|
17
|
+
nextTabIndex = activeTabKey - 1 > 0 ? activeTabKey - 1 : 0;
|
|
18
|
+
} else if (activeTabKey === tabs.length - 1) {
|
|
19
|
+
// if the closing tab is the last tab, focus the preceding tab
|
|
20
|
+
nextTabIndex = tabs.length - 2 > 0 ? tabs.length - 2 : 0;
|
|
21
|
+
}
|
|
22
|
+
setActiveTabKey(nextTabIndex);
|
|
23
|
+
setTabs(tabs.filter((tab, index) => index !== tabIndex));
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
const helpPopover = (header: string, popoverRef: React.RefObject<any>) => (
|
|
27
|
+
<Popover
|
|
28
|
+
headerContent={<div>{header}</div>}
|
|
29
|
+
bodyContent={
|
|
30
|
+
<div>
|
|
31
|
+
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam id feugiat augue, nec fringilla turpis.
|
|
32
|
+
</div>
|
|
33
|
+
}
|
|
34
|
+
footerContent="Popover footer"
|
|
35
|
+
reference={popoverRef}
|
|
36
|
+
/>
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
React.useEffect(() => {
|
|
40
|
+
if (firstMount.current) {
|
|
41
|
+
firstMount.current = false;
|
|
42
|
+
return;
|
|
43
|
+
} else {
|
|
44
|
+
const first = tabComponentRef.current.tabList.current.childNodes[activeTabKey];
|
|
45
|
+
first && first.firstChild.focus();
|
|
46
|
+
}
|
|
47
|
+
}, [tabs]);
|
|
48
|
+
|
|
49
|
+
return (
|
|
50
|
+
<Tabs
|
|
51
|
+
activeKey={activeTabKey}
|
|
52
|
+
onSelect={(event: any, tabIndex: string | number) => setActiveTabKey(tabIndex as number)}
|
|
53
|
+
aria-label="Tabs in the help enabled and closeable example"
|
|
54
|
+
role="region"
|
|
55
|
+
ref={tabComponentRef}
|
|
56
|
+
>
|
|
57
|
+
{tabs.map((tab, index) => {
|
|
58
|
+
const ref = React.createRef<HTMLElement>();
|
|
59
|
+
|
|
60
|
+
return (
|
|
61
|
+
<Tab
|
|
62
|
+
key={index}
|
|
63
|
+
eventKey={index}
|
|
64
|
+
aria-label={`Help action and closable content - ${tab}`}
|
|
65
|
+
title={<TabTitleText>{tab}</TabTitleText>}
|
|
66
|
+
actions={
|
|
67
|
+
<>
|
|
68
|
+
<TabAction isHelpAction aria-label={`Help for ${tab}`} ref={ref}>
|
|
69
|
+
<HelpIcon />
|
|
70
|
+
</TabAction>
|
|
71
|
+
<TabAction aria-label={`Close ${tab}`} onClick={e => onClose(e, index)} isDisabled={tabs.length === 1}>
|
|
72
|
+
<TimesIcon />
|
|
73
|
+
</TabAction>
|
|
74
|
+
{helpPopover(`Help popover for ${tab}`, ref)}
|
|
75
|
+
</>
|
|
76
|
+
}
|
|
77
|
+
>
|
|
78
|
+
{tab}
|
|
79
|
+
</Tab>
|
|
80
|
+
);
|
|
81
|
+
})}
|
|
82
|
+
</Tabs>
|
|
83
|
+
);
|
|
84
|
+
};
|