forked from patternfly/patternfly-react
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathWizardNavItem.tsx
More file actions
139 lines (132 loc) · 5.19 KB
/
WizardNavItem.tsx
File metadata and controls
139 lines (132 loc) · 5.19 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
import { useEffect, useState } from 'react';
import { css } from '@patternfly/react-styles';
import styles from '@patternfly/react-styles/css/components/Wizard/wizard';
import AngleRightIcon from '@patternfly/react-icons/dist/esm/icons/angle-right-icon';
import ExclamationCircleIcon from '@patternfly/react-icons/dist/esm/icons/exclamation-circle-icon';
import CheckCircleIcon from '@patternfly/react-icons/dist/esm/icons/check-circle-icon';
import ExclamationTriangleIcon from '@patternfly/react-icons/dist/esm/icons/exclamation-triangle-icon';
import { OUIAProps, useOUIAProps } from '../../helpers';
import { WizardNavItemStatus } from './types';
export interface WizardNavItemProps
extends Omit<React.HTMLProps<HTMLLIElement>, 'onClick' | 'id' | 'content' | 'type'>,
OUIAProps {
/** Additional classes spread to the wizard nav item */
className?: string;
/** Can nest a WizardNav component for substeps */
children?: React.ReactNode;
/** The content to display in the navigation item */
content?: React.ReactNode;
/** Whether the navigation item is the currently active item */
isCurrent?: boolean;
/** Whether the navigation item is disabled */
isDisabled?: boolean;
/** Whether the navigation item has been visited */
isVisited?: boolean;
/** The step index passed into the onNavItemClick callback */
stepIndex: number;
/** Callback for when the navigation item is clicked */
onClick?: (event: React.MouseEvent<HTMLButtonElement> | React.MouseEvent<HTMLAnchorElement>, index: number) => any;
/** Component used to render WizardNavItem */
component?: 'button' | 'a';
/** An optional url to use for when using an anchor component */
href?: string;
/** Where to display the linked URL when using an anchor component */
target?: React.HTMLAttributeAnchorTarget;
/** Flag indicating that this NavItem has child steps and is expandable */
isExpandable?: boolean;
/** The id for the navigation item */
id?: string | number;
/** Used to determine the icon displayed next to content. Default has no icon. */
status?: 'default' | 'error' | 'success' | 'warning';
}
export const WizardNavItem = ({
children = null,
content = '',
isCurrent = false,
isDisabled = false,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
isVisited = false,
stepIndex,
onClick,
component: NavItemComponent = 'button',
href,
isExpandable = false,
id,
status = 'default',
target,
ouiaId,
ouiaSafe = true,
className,
...props
}: WizardNavItemProps) => {
const [isExpanded, setIsExpanded] = useState(false);
const ouiaProps = useOUIAProps(WizardNavItem.displayName, ouiaId, ouiaSafe);
useEffect(() => {
setIsExpanded(isCurrent);
}, [isCurrent]);
if (NavItemComponent === 'a' && !href && process.env.NODE_ENV !== 'production') {
// eslint-disable-next-line no-console
console.error('WizardNavItem: When using an anchor, please provide an href');
}
return (
<li
className={css(
styles.wizardNavItem,
isExpandable && styles.modifiers.expandable,
isExpandable && isExpanded && styles.modifiers.expanded,
className
)}
{...props}
>
<NavItemComponent
{...(NavItemComponent === 'a'
? { tabIndex: isDisabled ? -1 : undefined, href, target }
: { disabled: isDisabled })}
{...(id && { id: id.toString() })}
onClick={(e) => {
e.stopPropagation();
isExpandable ? setIsExpanded(!isExpanded || isCurrent) : onClick?.(e, stepIndex);
}}
className={css(
styles.wizardNavLink,
isCurrent && styles.modifiers.current,
isDisabled && styles.modifiers.disabled,
status === WizardNavItemStatus.Error && styles.modifiers.danger,
status === WizardNavItemStatus.Success && styles.modifiers.success,
status === WizardNavItemStatus.Warning && styles.modifiers.warning
)}
aria-disabled={isDisabled ? true : null}
aria-current={isCurrent && !children ? 'step' : false}
{...(isExpandable && { 'aria-expanded': isExpanded })}
{...ouiaProps}
>
{status !== WizardNavItemStatus.Default && (
<>
<span className="pf-v6-screen-reader">, {status}</span>
<span className={css(styles.wizardNavLinkStatusIcon)}>
{status === WizardNavItemStatus.Error && <ExclamationCircleIcon />}
{status === WizardNavItemStatus.Success && <CheckCircleIcon />}
{status === WizardNavItemStatus.Warning && <ExclamationTriangleIcon />}
</span>
</>
)}
<span className={css(styles.wizardNavLinkMain)}>
{isExpandable ? (
<>
<span className="pf-v6-c-wizard__nav-link-text">{content}</span>
<span className={css(styles.wizardNavLinkToggle)}>
<span className={css(styles.wizardNavLinkToggleIcon)}>
<AngleRightIcon aria-label={`${isCurrent ? 'Collapse' : 'Expand'} step icon`} />
</span>
</span>
</>
) : (
<>{content}</>
)}
</span>
</NavItemComponent>
{children}
</li>
);
};
WizardNavItem.displayName = 'WizardNavItem';