@servicetitan/navigation 2.0.0 → 2.2.0
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/dist/components/header-navigation/header-navigation-content.d.ts +30 -0
- package/dist/components/header-navigation/header-navigation-content.d.ts.map +1 -0
- package/dist/components/header-navigation/header-navigation-content.js +21 -0
- package/dist/components/header-navigation/header-navigation-content.js.map +1 -0
- package/dist/components/header-navigation/header-navigation-extra.stories.d.ts +1 -1
- package/dist/components/header-navigation/header-navigation-extra.stories.d.ts.map +1 -1
- package/dist/components/header-navigation/header-navigation-extra.stories.js +6 -6
- package/dist/components/header-navigation/header-navigation-extra.stories.js.map +1 -1
- package/dist/components/header-navigation/header-navigation-links.d.ts +38 -0
- package/dist/components/header-navigation/header-navigation-links.d.ts.map +1 -0
- package/dist/components/header-navigation/header-navigation-links.js +38 -0
- package/dist/components/header-navigation/header-navigation-links.js.map +1 -0
- package/dist/components/header-navigation/header-navigation-stacked.stories.d.ts +11 -0
- package/dist/components/header-navigation/header-navigation-stacked.stories.d.ts.map +1 -0
- package/dist/components/header-navigation/header-navigation-stacked.stories.js +68 -0
- package/dist/components/header-navigation/header-navigation-stacked.stories.js.map +1 -0
- package/dist/components/header-navigation/header-navigation-stories.module.less +6 -0
- package/dist/components/header-navigation/header-navigation.d.ts +32 -55
- package/dist/components/header-navigation/header-navigation.d.ts.map +1 -1
- package/dist/components/header-navigation/header-navigation.js +41 -48
- package/dist/components/header-navigation/header-navigation.js.map +1 -1
- package/dist/components/header-navigation/header-navigation.module.less +171 -95
- package/dist/components/header-navigation/header-navigation.stories.d.ts.map +1 -1
- package/dist/components/header-navigation/header-navigation.stories.js +6 -4
- package/dist/components/header-navigation/header-navigation.stories.js.map +1 -1
- package/dist/components/header-navigation/index.d.ts +3 -0
- package/dist/components/header-navigation/index.d.ts.map +1 -0
- package/dist/components/header-navigation/index.js +3 -0
- package/dist/components/header-navigation/index.js.map +1 -0
- package/dist/components/logo/logo-titan-text.d.ts +21 -5
- package/dist/components/logo/logo-titan-text.d.ts.map +1 -1
- package/dist/components/logo/logo-titan-text.js +9 -3
- package/dist/components/logo/logo-titan-text.js.map +1 -1
- package/dist/components/logo/logo-titan-text.module.less +12 -9
- package/dist/components/logo/logo-titan.d.ts +2 -2
- package/dist/components/logo/logo-titan.d.ts.map +1 -1
- package/dist/components/logo/logo-titan.js +1 -1
- package/dist/components/logo/logo-titan.js.map +1 -1
- package/dist/components/logo/logo.stories.d.ts +2 -1
- package/dist/components/logo/logo.stories.d.ts.map +1 -1
- package/dist/components/logo/logo.stories.js +7 -5
- package/dist/components/logo/logo.stories.js.map +1 -1
- package/dist/components/profile-dropdown/profile-dropdown-stacked.stories.d.ts +15 -0
- package/dist/components/profile-dropdown/profile-dropdown-stacked.stories.d.ts.map +1 -0
- package/dist/components/profile-dropdown/profile-dropdown-stacked.stories.js +51 -0
- package/dist/components/profile-dropdown/profile-dropdown-stacked.stories.js.map +1 -0
- package/dist/components/profile-dropdown/profile-dropdown.d.ts +1 -0
- package/dist/components/profile-dropdown/profile-dropdown.d.ts.map +1 -1
- package/dist/components/profile-dropdown/profile-dropdown.js +3 -3
- package/dist/components/profile-dropdown/profile-dropdown.js.map +1 -1
- package/dist/components/profile-dropdown/profile-dropdown.module.less +0 -2
- package/dist/components/profile-dropdown/profile-dropdown.stories.js +1 -1
- package/dist/components/profile-dropdown/profile-dropdown.stories.js.map +1 -1
- package/dist/components/profile-dropdown/profile-icon.d.ts +1 -1
- package/dist/components/profile-dropdown/profile-icon.d.ts.map +1 -1
- package/dist/components/profile-dropdown/profile-icon.js +1 -1
- package/dist/components/profile-dropdown/profile-icon.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/utils/with-tooltip.d.ts +3 -0
- package/dist/utils/with-tooltip.d.ts.map +1 -0
- package/dist/utils/with-tooltip.js +4 -0
- package/dist/utils/with-tooltip.js.map +1 -0
- package/package.json +2 -2
- package/src/components/header-navigation/header-navigation-content.tsx +118 -0
- package/src/components/header-navigation/header-navigation-extra.stories.tsx +12 -12
- package/src/components/header-navigation/header-navigation-links.tsx +143 -0
- package/src/components/header-navigation/header-navigation-stacked.stories.tsx +187 -0
- package/src/components/header-navigation/header-navigation-stories.module.less +6 -0
- package/src/components/header-navigation/header-navigation-stories.module.less.d.ts +3 -0
- package/src/components/header-navigation/header-navigation.module.less +171 -95
- package/src/components/header-navigation/header-navigation.module.less.d.ts +14 -9
- package/src/components/header-navigation/header-navigation.stories.tsx +25 -16
- package/src/components/header-navigation/header-navigation.tsx +151 -266
- package/src/components/header-navigation/index.ts +2 -0
- package/src/components/logo/logo-titan-text.module.less +12 -9
- package/src/components/logo/logo-titan-text.tsx +62 -20
- package/src/components/logo/logo-titan.tsx +2 -2
- package/src/components/logo/logo.stories.tsx +13 -4
- package/src/components/profile-dropdown/profile-dropdown-stacked.stories.tsx +178 -0
- package/src/components/profile-dropdown/profile-dropdown.module.less +0 -2
- package/src/components/profile-dropdown/profile-dropdown.stories.tsx +1 -1
- package/src/components/profile-dropdown/profile-dropdown.tsx +5 -3
- package/src/components/profile-dropdown/profile-icon.tsx +2 -1
- package/src/index.ts +2 -1
- package/src/utils/with-tooltip.tsx +11 -0
|
@@ -4,13 +4,8 @@ import { HeaderNavigationItemData, NavLinkComponentProps } from '../../utils/nav
|
|
|
4
4
|
import { LogoCompanyTitle } from '../logo/logo-company-title';
|
|
5
5
|
import { LogoTitanText } from '../logo/logo-titan-text';
|
|
6
6
|
import { ProfileDropdown } from '../profile-dropdown/profile-dropdown';
|
|
7
|
-
import
|
|
8
|
-
|
|
9
|
-
HeaderNavigationItemContent,
|
|
10
|
-
HeaderNavigationLink,
|
|
11
|
-
HeaderNavigationTrigger,
|
|
12
|
-
HeaderNavigationTriggerCustom,
|
|
13
|
-
} from './header-navigation';
|
|
7
|
+
import * as Styles from './header-navigation-stories.module.less';
|
|
8
|
+
import { HeaderNavigation, HeaderNavigationLink, HeaderNavigationTrigger } from './';
|
|
14
9
|
|
|
15
10
|
export default {
|
|
16
11
|
title: 'Navigation/HeaderNavigation',
|
|
@@ -36,6 +31,16 @@ const InventoryIcon = () => (
|
|
|
36
31
|
</svg>
|
|
37
32
|
);
|
|
38
33
|
|
|
34
|
+
const SearchIcon = () => (
|
|
35
|
+
<svg width="24" height="24" viewBox="-4 0 28 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
36
|
+
<path
|
|
37
|
+
d="M0 15.7992V13.9992H12V15.7992H0ZM0 9.49922V7.69922H6V9.49922H0ZM0 3.19922V1.39922H6V3.19922H0ZM22.74 15.7992L17.94 10.9992C17.42 11.3992 16.86 11.6992 16.26 11.8992C15.66 12.0992 15.04 12.1992 14.4 12.1992C12.74 12.1992 11.325 11.6142 10.155 10.4442C8.985 9.27422 8.4 7.85922 8.4 6.19922C8.4 4.53922 8.985 3.12422 10.155 1.95422C11.325 0.784219 12.74 0.199219 14.4 0.199219C16.06 0.199219 17.475 0.784219 18.645 1.95422C19.815 3.12422 20.4 4.53922 20.4 6.19922C20.4 6.83922 20.3 7.45922 20.1 8.05922C19.9 8.65922 19.6 9.21922 19.2 9.73922L24 14.5392L22.74 15.7992ZM14.393 10.3992C15.5577 10.3992 16.55 9.99157 17.37 9.17627C18.19 8.36099 18.6 7.37099 18.6 6.20627C18.6 5.04157 18.1923 4.04922 17.377 3.22922C16.5618 2.40922 15.5718 1.99922 14.407 1.99922C13.2423 1.99922 12.25 2.40687 11.43 3.22217C10.61 4.03745 10.2 5.02745 10.2 6.19217C10.2 7.35687 10.6077 8.34922 11.423 9.16922C12.2382 9.98922 13.2282 10.3992 14.393 10.3992Z"
|
|
38
|
+
fill="white"
|
|
39
|
+
style={{ fill: 'white', fillOpacity: 1 }}
|
|
40
|
+
/>
|
|
41
|
+
</svg>
|
|
42
|
+
);
|
|
43
|
+
|
|
39
44
|
const items = {
|
|
40
45
|
calendar: getItem('calendar', { iconName: 'event' }),
|
|
41
46
|
calls: getItem('calls', { iconName: 'local_phone', isActive: true, counter: 12 }),
|
|
@@ -114,9 +119,11 @@ const HelpCenterButton = () => {
|
|
|
114
119
|
direction="bl"
|
|
115
120
|
width="xs"
|
|
116
121
|
trigger={
|
|
117
|
-
<
|
|
118
|
-
|
|
119
|
-
|
|
122
|
+
<HeaderNavigationTrigger
|
|
123
|
+
id="help"
|
|
124
|
+
iconName="help_outline"
|
|
125
|
+
onClick={() => setOpen(true)}
|
|
126
|
+
/>
|
|
120
127
|
}
|
|
121
128
|
portal
|
|
122
129
|
>
|
|
@@ -126,7 +133,7 @@ const HelpCenterButton = () => {
|
|
|
126
133
|
};
|
|
127
134
|
|
|
128
135
|
const TimeZoneOffset: FC = () => (
|
|
129
|
-
<div className="fs-2
|
|
136
|
+
<div className="fs-2 ff-default p-r-2">
|
|
130
137
|
<span>EST (-9 hrs)</span>
|
|
131
138
|
</div>
|
|
132
139
|
);
|
|
@@ -160,14 +167,16 @@ export const withAllMonolithData = () => (
|
|
|
160
167
|
id="search"
|
|
161
168
|
to="https://google.com"
|
|
162
169
|
target="_blank"
|
|
163
|
-
|
|
170
|
+
iconComponent={SearchIcon}
|
|
164
171
|
hint="Search: for all the questions"
|
|
165
172
|
/>
|
|
166
173
|
|
|
167
|
-
<
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
174
|
+
<HelpCenterButton />
|
|
175
|
+
<HeaderNavigationTrigger
|
|
176
|
+
id="titanAdvisor"
|
|
177
|
+
iconName="rocket"
|
|
178
|
+
iconClassName={Styles.rocketIcon}
|
|
179
|
+
/>
|
|
171
180
|
|
|
172
181
|
<HeaderNavigationLink
|
|
173
182
|
id="settings"
|
|
@@ -1,29 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
Icon,
|
|
3
|
-
IconPropsStrict,
|
|
4
|
-
Popover,
|
|
5
|
-
PopoverPropsStrict,
|
|
6
|
-
Tooltip,
|
|
7
|
-
} from '@servicetitan/design-system';
|
|
1
|
+
import { Icon, Popover, PopoverPropsStrict } from '@servicetitan/design-system';
|
|
8
2
|
import classNames from 'classnames';
|
|
9
|
-
import {
|
|
10
|
-
FC,
|
|
11
|
-
Fragment,
|
|
12
|
-
HTMLAttributeAnchorTarget,
|
|
13
|
-
ReactElement,
|
|
14
|
-
ReactNode,
|
|
15
|
-
useCallback,
|
|
16
|
-
useEffect,
|
|
17
|
-
useRef,
|
|
18
|
-
useState,
|
|
19
|
-
} from 'react';
|
|
3
|
+
import { FC, ReactElement, ReactNode, useCallback, useEffect, useRef, useState } from 'react';
|
|
20
4
|
import { HeaderNavigationItemData, NavLinkComponentProps } from '../../utils/navigation';
|
|
21
|
-
import {
|
|
22
|
-
|
|
23
|
-
NavLinkContext,
|
|
24
|
-
useNavLink,
|
|
25
|
-
} from '../../utils/navigation-context';
|
|
26
|
-
import { CounterTag, CounterTagPropsType } from '../counter-tag';
|
|
5
|
+
import { DefaultNavLinkComponent, NavLinkContext } from '../../utils/navigation-context';
|
|
6
|
+
import { HeaderNavigationItem } from './header-navigation-content';
|
|
27
7
|
import * as Styles from './header-navigation.module.less';
|
|
28
8
|
|
|
29
9
|
function useForceUpdate() {
|
|
@@ -33,242 +13,6 @@ function useForceUpdate() {
|
|
|
33
13
|
}, []);
|
|
34
14
|
}
|
|
35
15
|
|
|
36
|
-
interface HeaderNavigationItemContentPropsStrict {
|
|
37
|
-
/** item text */
|
|
38
|
-
title?: string;
|
|
39
|
-
/** counter shown for item */
|
|
40
|
-
counter?: CounterTagPropsType;
|
|
41
|
-
/** icon component class name */
|
|
42
|
-
iconClassName?: string;
|
|
43
|
-
/** IconComponent custom icon component */
|
|
44
|
-
iconComponent?: FC;
|
|
45
|
-
/** iconName name of anvil icon */
|
|
46
|
-
iconName?: IconPropsStrict['name'];
|
|
47
|
-
/** iconSize size of anvil icon */
|
|
48
|
-
iconSize?: IconPropsStrict['size'];
|
|
49
|
-
}
|
|
50
|
-
export interface HeaderNavigationTriggerPropsStrict
|
|
51
|
-
extends Omit<HeaderNavigationItemContentPropsStrict, 'title'> {
|
|
52
|
-
/** unique identifier */
|
|
53
|
-
id: string;
|
|
54
|
-
/** tooltip text */
|
|
55
|
-
tooltip?: string;
|
|
56
|
-
/** item description */
|
|
57
|
-
hint?: string;
|
|
58
|
-
/** container class name */
|
|
59
|
-
className?: string;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
interface HeaderNavigationTriggerProps extends HeaderNavigationTriggerPropsStrict {
|
|
63
|
-
/** unstrict props */
|
|
64
|
-
[key: string]: any;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
export interface HeaderNavigationLinkPropsStrict extends HeaderNavigationTriggerPropsStrict {
|
|
68
|
-
/** link href */
|
|
69
|
-
to: string;
|
|
70
|
-
/** isActive */
|
|
71
|
-
isActive?: boolean | ((pathname: string) => boolean);
|
|
72
|
-
/** link html target */
|
|
73
|
-
target?: HTMLAttributeAnchorTarget;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
export interface HeaderNavigationLinkProps extends HeaderNavigationLinkPropsStrict {
|
|
77
|
-
/** unstrict props */
|
|
78
|
-
[key: string]: any;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
/** Content for navigation items */
|
|
82
|
-
export const HeaderNavigationItemContent: FC<HeaderNavigationItemContentPropsStrict> = ({
|
|
83
|
-
title,
|
|
84
|
-
counter,
|
|
85
|
-
iconClassName,
|
|
86
|
-
iconComponent: IconComponent,
|
|
87
|
-
iconName,
|
|
88
|
-
iconSize = '24px',
|
|
89
|
-
}) => (
|
|
90
|
-
<Fragment>
|
|
91
|
-
{IconComponent ? (
|
|
92
|
-
<i className={classNames(Styles.icon, iconClassName)}>
|
|
93
|
-
<IconComponent />
|
|
94
|
-
</i>
|
|
95
|
-
) : iconName ? (
|
|
96
|
-
<Icon
|
|
97
|
-
size={iconSize}
|
|
98
|
-
name={iconName}
|
|
99
|
-
className={classNames(Styles.icon, iconClassName)}
|
|
100
|
-
/>
|
|
101
|
-
) : (
|
|
102
|
-
<i className={classNames(Styles.icon, iconClassName)} />
|
|
103
|
-
)}
|
|
104
|
-
|
|
105
|
-
{!!title && <ins>{title}</ins>}
|
|
106
|
-
|
|
107
|
-
{!!counter && (
|
|
108
|
-
<CounterTag
|
|
109
|
-
data={counter}
|
|
110
|
-
className={Styles.counter}
|
|
111
|
-
longClassName={Styles.counterLong}
|
|
112
|
-
/>
|
|
113
|
-
)}
|
|
114
|
-
</Fragment>
|
|
115
|
-
);
|
|
116
|
-
|
|
117
|
-
const withTooltip = (element: ReactNode, tooltip?: string) =>
|
|
118
|
-
tooltip ? (
|
|
119
|
-
<Tooltip el="div" direction="b" text={tooltip}>
|
|
120
|
-
{element}
|
|
121
|
-
</Tooltip>
|
|
122
|
-
) : (
|
|
123
|
-
element
|
|
124
|
-
);
|
|
125
|
-
|
|
126
|
-
/** Navigation extra item with link */
|
|
127
|
-
export const HeaderNavigationLink: FC<HeaderNavigationLinkProps> = ({
|
|
128
|
-
id,
|
|
129
|
-
to,
|
|
130
|
-
hint,
|
|
131
|
-
tooltip,
|
|
132
|
-
counter,
|
|
133
|
-
className,
|
|
134
|
-
iconClassName,
|
|
135
|
-
iconComponent,
|
|
136
|
-
iconName,
|
|
137
|
-
isActive,
|
|
138
|
-
target,
|
|
139
|
-
...rest
|
|
140
|
-
}) => {
|
|
141
|
-
const NavigationComponent = useNavLink();
|
|
142
|
-
|
|
143
|
-
return withTooltip(
|
|
144
|
-
<NavigationComponent
|
|
145
|
-
data-cy={`navigation-link-${id}`}
|
|
146
|
-
data-pendo={`navigation-link-${id}`}
|
|
147
|
-
{...rest}
|
|
148
|
-
key={id}
|
|
149
|
-
to={to}
|
|
150
|
-
title={hint}
|
|
151
|
-
className={classNames(Styles.link, className, {
|
|
152
|
-
[Styles.active]: isActive === true,
|
|
153
|
-
})}
|
|
154
|
-
isActive={typeof isActive === 'function' ? isActive : undefined}
|
|
155
|
-
activeClassName={Styles.active}
|
|
156
|
-
target={target}
|
|
157
|
-
>
|
|
158
|
-
<HeaderNavigationItemContent
|
|
159
|
-
counter={counter}
|
|
160
|
-
iconComponent={iconComponent}
|
|
161
|
-
iconClassName={iconClassName}
|
|
162
|
-
iconName={iconName}
|
|
163
|
-
/>
|
|
164
|
-
</NavigationComponent>,
|
|
165
|
-
tooltip
|
|
166
|
-
);
|
|
167
|
-
};
|
|
168
|
-
|
|
169
|
-
interface HeaderNavigationItemPropsStrict extends HeaderNavigationItemData {
|
|
170
|
-
minimized: boolean;
|
|
171
|
-
main: boolean;
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
/** Navigation main menu item */
|
|
175
|
-
const HeaderNavigationItem: FC<HeaderNavigationItemPropsStrict> = ({
|
|
176
|
-
id,
|
|
177
|
-
to,
|
|
178
|
-
title,
|
|
179
|
-
hint,
|
|
180
|
-
counter,
|
|
181
|
-
className,
|
|
182
|
-
iconClassName,
|
|
183
|
-
iconComponent,
|
|
184
|
-
iconName,
|
|
185
|
-
isActive,
|
|
186
|
-
main,
|
|
187
|
-
minimized,
|
|
188
|
-
}) => {
|
|
189
|
-
const NavigationComponent = useNavLink();
|
|
190
|
-
|
|
191
|
-
return withTooltip(
|
|
192
|
-
<NavigationComponent
|
|
193
|
-
data-cy={`navigation-item-${id}`}
|
|
194
|
-
data-pendo={`navigation-item-${id}`}
|
|
195
|
-
key={id}
|
|
196
|
-
to={to}
|
|
197
|
-
title={hint}
|
|
198
|
-
className={classNames(
|
|
199
|
-
Styles.link,
|
|
200
|
-
className,
|
|
201
|
-
main ? Styles.linkMain : Styles.linkOverflow,
|
|
202
|
-
{
|
|
203
|
-
[Styles.active]: isActive === true,
|
|
204
|
-
}
|
|
205
|
-
)}
|
|
206
|
-
isActive={typeof isActive === 'function' ? isActive : undefined}
|
|
207
|
-
activeClassName={Styles.active}
|
|
208
|
-
>
|
|
209
|
-
<HeaderNavigationItemContent
|
|
210
|
-
title={minimized ? undefined : title}
|
|
211
|
-
counter={counter}
|
|
212
|
-
iconComponent={iconComponent}
|
|
213
|
-
iconClassName={iconClassName}
|
|
214
|
-
iconName={iconName}
|
|
215
|
-
iconSize="20px"
|
|
216
|
-
/>
|
|
217
|
-
</NavigationComponent>,
|
|
218
|
-
minimized ? title : undefined
|
|
219
|
-
);
|
|
220
|
-
};
|
|
221
|
-
|
|
222
|
-
/** Navigation extra item with icon button */
|
|
223
|
-
export const HeaderNavigationTrigger: FC<HeaderNavigationTriggerProps> = ({
|
|
224
|
-
id,
|
|
225
|
-
className,
|
|
226
|
-
counter,
|
|
227
|
-
iconClassName,
|
|
228
|
-
iconComponent,
|
|
229
|
-
iconName,
|
|
230
|
-
hint,
|
|
231
|
-
tooltip,
|
|
232
|
-
...rest
|
|
233
|
-
}) =>
|
|
234
|
-
withTooltip(
|
|
235
|
-
<div
|
|
236
|
-
data-cy={`navigation-trigger-${id}`}
|
|
237
|
-
data-pendo={`navigation-trigger-${id}`}
|
|
238
|
-
{...rest}
|
|
239
|
-
title={hint}
|
|
240
|
-
className={classNames(Styles.link, 'cursor-pointer', className)}
|
|
241
|
-
>
|
|
242
|
-
<HeaderNavigationItemContent
|
|
243
|
-
counter={counter}
|
|
244
|
-
iconComponent={iconComponent}
|
|
245
|
-
iconClassName={iconClassName}
|
|
246
|
-
iconName={iconName}
|
|
247
|
-
/>
|
|
248
|
-
</div>,
|
|
249
|
-
tooltip
|
|
250
|
-
);
|
|
251
|
-
|
|
252
|
-
/** Navigation extra item with custom content */
|
|
253
|
-
export const HeaderNavigationTriggerCustom: FC<
|
|
254
|
-
Omit<
|
|
255
|
-
HeaderNavigationTriggerProps,
|
|
256
|
-
'counter' | 'iconSize' | 'iconName' | 'iconComponent' | 'iconClassName'
|
|
257
|
-
> & { children: ReactNode }
|
|
258
|
-
> = ({ children, id, className, tooltip, title, ...rest }) =>
|
|
259
|
-
withTooltip(
|
|
260
|
-
<div
|
|
261
|
-
data-cy={`navigation-custom-${id}`}
|
|
262
|
-
data-pendo={`navigation-custom-${id}`}
|
|
263
|
-
{...rest}
|
|
264
|
-
title={title}
|
|
265
|
-
className={classNames(Styles.link, 'cursor-pointer', className)}
|
|
266
|
-
>
|
|
267
|
-
{children}
|
|
268
|
-
</div>,
|
|
269
|
-
tooltip
|
|
270
|
-
);
|
|
271
|
-
|
|
272
16
|
export interface HeaderNavigationOverflowProps {
|
|
273
17
|
direction: PopoverPropsStrict['direction'];
|
|
274
18
|
width: PopoverPropsStrict['width'];
|
|
@@ -321,7 +65,7 @@ export interface HeaderNavigationProps {
|
|
|
321
65
|
/** container class name */
|
|
322
66
|
className?: string;
|
|
323
67
|
/** extra navigation container class name */
|
|
324
|
-
|
|
68
|
+
rightClassName?: string;
|
|
325
69
|
/** container id */
|
|
326
70
|
id?: string;
|
|
327
71
|
/** left content (usually used for logo) */
|
|
@@ -349,12 +93,12 @@ enum MinimizedState {
|
|
|
349
93
|
export const HeaderNavigation: FC<HeaderNavigationProps> = ({
|
|
350
94
|
children,
|
|
351
95
|
className,
|
|
352
|
-
contentClassName,
|
|
353
96
|
id,
|
|
354
97
|
items,
|
|
355
98
|
itemsOverflow,
|
|
356
99
|
left,
|
|
357
100
|
leftClassName,
|
|
101
|
+
rightClassName,
|
|
358
102
|
minWidth = 800,
|
|
359
103
|
navigationComponent = DefaultNavLinkComponent,
|
|
360
104
|
overflow,
|
|
@@ -399,7 +143,6 @@ export const HeaderNavigation: FC<HeaderNavigationProps> = ({
|
|
|
399
143
|
<NavLinkContext.Provider value={navigationComponent}>
|
|
400
144
|
<div
|
|
401
145
|
className={classNames(Styles.header, className, {
|
|
402
|
-
[Styles.minimized]: minimized === MinimizedState.Minimized,
|
|
403
146
|
[Styles.calculating]: minimized === MinimizedState.Calculating,
|
|
404
147
|
})}
|
|
405
148
|
style={{ minWidth: `${minWidth}px` }}
|
|
@@ -417,7 +160,7 @@ export const HeaderNavigation: FC<HeaderNavigationProps> = ({
|
|
|
417
160
|
)}
|
|
418
161
|
data-cy="navigation-items"
|
|
419
162
|
>
|
|
420
|
-
<div ref={navigationRef} className={classNames(
|
|
163
|
+
<div ref={navigationRef} className={classNames('d-if')}>
|
|
421
164
|
{items?.map(item => (
|
|
422
165
|
<HeaderNavigationItem
|
|
423
166
|
{...item}
|
|
@@ -435,10 +178,10 @@ export const HeaderNavigation: FC<HeaderNavigationProps> = ({
|
|
|
435
178
|
className={classNames(
|
|
436
179
|
'd-f flex-row justify-content-end align-items-center',
|
|
437
180
|
Styles.right,
|
|
438
|
-
|
|
181
|
+
rightClassName
|
|
439
182
|
)}
|
|
440
183
|
ref={rightRef}
|
|
441
|
-
data-cy="navigation-
|
|
184
|
+
data-cy="navigation-right"
|
|
442
185
|
>
|
|
443
186
|
{children}
|
|
444
187
|
</div>
|
|
@@ -446,3 +189,145 @@ export const HeaderNavigation: FC<HeaderNavigationProps> = ({
|
|
|
446
189
|
</NavLinkContext.Provider>
|
|
447
190
|
);
|
|
448
191
|
};
|
|
192
|
+
|
|
193
|
+
export interface HeaderNavigationStackedProps {
|
|
194
|
+
/** container class name */
|
|
195
|
+
className?: string;
|
|
196
|
+
/** extra navigation */
|
|
197
|
+
right?: ReactNode;
|
|
198
|
+
/** extra navigation container class name */
|
|
199
|
+
rightClassName?: string;
|
|
200
|
+
/** container id */
|
|
201
|
+
id?: string;
|
|
202
|
+
/** left content (usually used for logo) */
|
|
203
|
+
left?: ReactElement;
|
|
204
|
+
/** left container class name */
|
|
205
|
+
leftClassName?: string;
|
|
206
|
+
/** center content */
|
|
207
|
+
center?: ReactElement;
|
|
208
|
+
/** center container class name */
|
|
209
|
+
centerClassName?: string;
|
|
210
|
+
/** minimal width for navigation bar */
|
|
211
|
+
minWidth?: number;
|
|
212
|
+
/** main navigation items */
|
|
213
|
+
items?: HeaderNavigationItemData[];
|
|
214
|
+
/** main navigation overflow items */
|
|
215
|
+
itemsOverflow?: HeaderNavigationItemData[];
|
|
216
|
+
/** navigation component used for routing */
|
|
217
|
+
navigationComponent?: FC<NavLinkComponentProps>;
|
|
218
|
+
/** props for main items overflow component */
|
|
219
|
+
overflow?: HeaderNavigationOverflowProps;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
export const HeaderNavigationStacked: FC<HeaderNavigationStackedProps> = ({
|
|
223
|
+
className,
|
|
224
|
+
id,
|
|
225
|
+
items,
|
|
226
|
+
itemsOverflow,
|
|
227
|
+
left,
|
|
228
|
+
leftClassName,
|
|
229
|
+
right,
|
|
230
|
+
rightClassName,
|
|
231
|
+
center,
|
|
232
|
+
centerClassName,
|
|
233
|
+
minWidth = 800,
|
|
234
|
+
navigationComponent = DefaultNavLinkComponent,
|
|
235
|
+
overflow,
|
|
236
|
+
}) => {
|
|
237
|
+
const bottomRef = useRef<HTMLDivElement>(null);
|
|
238
|
+
const navigationRef = useRef<HTMLDivElement>(null);
|
|
239
|
+
const forceUpdate = useForceUpdate();
|
|
240
|
+
const [minimized, setMinimized] = useState(MinimizedState.Calculating);
|
|
241
|
+
|
|
242
|
+
useEffect(() => {
|
|
243
|
+
const handleResize = () => {
|
|
244
|
+
setMinimized(MinimizedState.Calculating);
|
|
245
|
+
forceUpdate();
|
|
246
|
+
};
|
|
247
|
+
|
|
248
|
+
window.addEventListener('resize', handleResize);
|
|
249
|
+
return () => window.removeEventListener('resize', handleResize);
|
|
250
|
+
}, [forceUpdate]);
|
|
251
|
+
|
|
252
|
+
useEffect(() => {
|
|
253
|
+
setMinimized(MinimizedState.Calculating);
|
|
254
|
+
forceUpdate();
|
|
255
|
+
}, [items, itemsOverflow, forceUpdate]);
|
|
256
|
+
|
|
257
|
+
const updateIsMinimized = () => {
|
|
258
|
+
if (bottomRef.current && navigationRef.current) {
|
|
259
|
+
if (navigationRef.current.clientWidth + 16 > bottomRef.current.clientWidth) {
|
|
260
|
+
setMinimized(MinimizedState.Minimized);
|
|
261
|
+
} else if (minimized === MinimizedState.Calculating) {
|
|
262
|
+
setMinimized(MinimizedState.Full);
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
};
|
|
266
|
+
|
|
267
|
+
useEffect(() => {
|
|
268
|
+
updateIsMinimized();
|
|
269
|
+
});
|
|
270
|
+
|
|
271
|
+
return (
|
|
272
|
+
<NavLinkContext.Provider value={navigationComponent}>
|
|
273
|
+
<div
|
|
274
|
+
className={classNames(
|
|
275
|
+
Styles.headerStacked,
|
|
276
|
+
{
|
|
277
|
+
[Styles.calculating]: minimized === MinimizedState.Calculating,
|
|
278
|
+
},
|
|
279
|
+
className
|
|
280
|
+
)}
|
|
281
|
+
style={{ minWidth: `${minWidth}px` }}
|
|
282
|
+
id={id}
|
|
283
|
+
data-cy="header-navigation"
|
|
284
|
+
>
|
|
285
|
+
<div
|
|
286
|
+
className={classNames(Styles.heTopLeft, leftClassName)}
|
|
287
|
+
data-cy="navigation-left"
|
|
288
|
+
>
|
|
289
|
+
{left}
|
|
290
|
+
</div>
|
|
291
|
+
<div
|
|
292
|
+
className={classNames(Styles.heTopCenter, centerClassName)}
|
|
293
|
+
data-cy="navigation-center"
|
|
294
|
+
>
|
|
295
|
+
{center}
|
|
296
|
+
</div>
|
|
297
|
+
<div
|
|
298
|
+
className={classNames(
|
|
299
|
+
'd-f flex-row justify-content-end align-items-center',
|
|
300
|
+
Styles.heTopRight,
|
|
301
|
+
rightClassName
|
|
302
|
+
)}
|
|
303
|
+
data-cy="navigation-right"
|
|
304
|
+
>
|
|
305
|
+
{right}
|
|
306
|
+
</div>
|
|
307
|
+
<div
|
|
308
|
+
ref={bottomRef}
|
|
309
|
+
className={classNames(
|
|
310
|
+
Styles.heBottom,
|
|
311
|
+
'd-if flex-grow-1 flex-basis-0 justify-content-center',
|
|
312
|
+
Styles.center
|
|
313
|
+
)}
|
|
314
|
+
data-cy="navigation-items"
|
|
315
|
+
>
|
|
316
|
+
<div ref={navigationRef} className={classNames('d-if')}>
|
|
317
|
+
{items?.map(item => (
|
|
318
|
+
<HeaderNavigationItem
|
|
319
|
+
{...item}
|
|
320
|
+
minimized={minimized === MinimizedState.Minimized}
|
|
321
|
+
main
|
|
322
|
+
key={item.id}
|
|
323
|
+
/>
|
|
324
|
+
))}
|
|
325
|
+
{!!itemsOverflow?.length && (
|
|
326
|
+
<HeaderNavigationOverflow items={itemsOverflow} overflow={overflow} />
|
|
327
|
+
)}
|
|
328
|
+
</div>
|
|
329
|
+
</div>
|
|
330
|
+
</div>
|
|
331
|
+
</NavLinkContext.Provider>
|
|
332
|
+
);
|
|
333
|
+
};
|
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
@import (reference) '@servicetitan/tokens/core/tokens.less';
|
|
2
2
|
|
|
3
|
+
.logo-text-title {
|
|
4
|
+
font-weight: @font-weight-semibold;
|
|
5
|
+
font-size: 21px;
|
|
6
|
+
line-height: 24px;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
.logo-text-description {
|
|
10
|
+
font-size: @typescale-1;
|
|
11
|
+
line-height: 16px;
|
|
12
|
+
}
|
|
13
|
+
|
|
3
14
|
.container {
|
|
4
15
|
height: 56px;
|
|
5
16
|
max-width: 200px;
|
|
@@ -13,16 +24,8 @@
|
|
|
13
24
|
}
|
|
14
25
|
}
|
|
15
26
|
|
|
16
|
-
.logo-text-title
|
|
17
|
-
font-weight: @font-weight-semibold;
|
|
18
|
-
font-size: 21px;
|
|
19
|
-
max-width: 140px;
|
|
20
|
-
line-height: 24px;
|
|
21
|
-
}
|
|
22
|
-
|
|
27
|
+
.logo-text-title,
|
|
23
28
|
.logo-text-description {
|
|
24
|
-
font-size: @typescale-1;
|
|
25
29
|
max-width: 140px;
|
|
26
|
-
line-height: 16px;
|
|
27
30
|
}
|
|
28
31
|
}
|
|
@@ -1,43 +1,85 @@
|
|
|
1
1
|
import classNames from 'classnames';
|
|
2
|
-
import { FC, ReactNode } from 'react';
|
|
3
|
-
import {
|
|
2
|
+
import { CSSProperties, FC, ReactNode } from 'react';
|
|
3
|
+
import { LogoTitanSvg } from './logo-titan';
|
|
4
4
|
import * as Styles from './logo-titan-text.module.less';
|
|
5
5
|
|
|
6
|
+
export type WrapperProps = FC<{ className: string; children: ReactNode; style?: CSSProperties }>;
|
|
7
|
+
|
|
8
|
+
export interface LogoTitanProps {
|
|
9
|
+
mantleFill?: string;
|
|
10
|
+
className?: string;
|
|
11
|
+
logoWrapper?: WrapperProps;
|
|
12
|
+
size?: number;
|
|
13
|
+
innerSize?: number;
|
|
14
|
+
}
|
|
15
|
+
|
|
6
16
|
export interface LogoTitanTextProps {
|
|
7
17
|
mantleFill?: string;
|
|
8
18
|
className?: string;
|
|
9
19
|
title: string;
|
|
10
20
|
description: string;
|
|
11
|
-
logoWrapper?:
|
|
21
|
+
logoWrapper?: WrapperProps;
|
|
12
22
|
}
|
|
13
23
|
|
|
14
|
-
|
|
15
|
-
className
|
|
16
|
-
children
|
|
17
|
-
}
|
|
18
|
-
|
|
24
|
+
export interface LogoTitanTitleProps {
|
|
25
|
+
className?: string;
|
|
26
|
+
children: ReactNode;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const DefaultLogoWrapper: WrapperProps = ({ className, children, style }) => (
|
|
30
|
+
<div className={className} style={style}>
|
|
31
|
+
{children}
|
|
32
|
+
</div>
|
|
33
|
+
);
|
|
34
|
+
|
|
35
|
+
export const LogoTitan: FC<LogoTitanProps> = ({
|
|
19
36
|
className,
|
|
20
|
-
description,
|
|
21
37
|
logoWrapper: LogoWrapper = DefaultLogoWrapper,
|
|
22
38
|
mantleFill,
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
39
|
+
size = 56,
|
|
40
|
+
innerSize,
|
|
41
|
+
}) => {
|
|
42
|
+
const is = innerSize ? Math.min(innerSize, size) : Math.round(size * 0.7);
|
|
43
|
+
|
|
44
|
+
return (
|
|
26
45
|
<LogoWrapper
|
|
27
46
|
className={classNames(
|
|
28
47
|
'bg-white d-if justify-content-center align-items-center',
|
|
29
|
-
|
|
48
|
+
className
|
|
30
49
|
)}
|
|
50
|
+
style={{ height: `${size}px`, width: `${size}px` }}
|
|
31
51
|
>
|
|
32
|
-
<
|
|
52
|
+
<LogoTitanSvg width={is} height={is} mantleFill={mantleFill} />
|
|
33
53
|
</LogoWrapper>
|
|
54
|
+
);
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
export const LogoTitanTitle: FC<LogoTitanTitleProps> = ({ className, children }) => (
|
|
58
|
+
<div className={classNames(Styles.logoTextTitle, 'ff-display', className)}>{children}</div>
|
|
59
|
+
);
|
|
60
|
+
|
|
61
|
+
export const LogoTitanDescription: FC<LogoTitanTitleProps> = ({ className, children }) => (
|
|
62
|
+
<div className={classNames(Styles.logoTextDescription, 'ff-default', className)}>
|
|
63
|
+
{children}
|
|
64
|
+
</div>
|
|
65
|
+
);
|
|
66
|
+
|
|
67
|
+
export const LogoTitanText: FC<LogoTitanTextProps> = ({
|
|
68
|
+
className,
|
|
69
|
+
description,
|
|
70
|
+
logoWrapper,
|
|
71
|
+
mantleFill,
|
|
72
|
+
title,
|
|
73
|
+
}) => (
|
|
74
|
+
<div className={classNames('d-f', Styles.container, className)}>
|
|
75
|
+
<LogoTitan
|
|
76
|
+
className={Styles.logoWrapper}
|
|
77
|
+
logoWrapper={logoWrapper}
|
|
78
|
+
mantleFill={mantleFill}
|
|
79
|
+
/>
|
|
34
80
|
<div className="d-if p-l-1 c-white flex-column justify-content-center align-items-start">
|
|
35
|
-
<
|
|
36
|
-
|
|
37
|
-
</span>
|
|
38
|
-
<span className={classNames(Styles.logoTextDescription, 'ff-default t-truncate')}>
|
|
39
|
-
{description}
|
|
40
|
-
</span>
|
|
81
|
+
<LogoTitanTitle className="t-truncate p-b-half">{title}</LogoTitanTitle>
|
|
82
|
+
<LogoTitanDescription className="t-truncate">{description}</LogoTitanDescription>
|
|
41
83
|
</div>
|
|
42
84
|
</div>
|
|
43
85
|
);
|