@servicetitan/navigation 2.0.0 → 2.1.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 +66 -0
- package/dist/components/header-navigation/header-navigation-stacked.stories.js.map +1 -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 +172 -95
- package/dist/components/header-navigation/header-navigation.stories.d.ts.map +1 -1
- package/dist/components/header-navigation/header-navigation.stories.js +7 -7
- 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 +172 -0
- package/src/components/header-navigation/header-navigation.module.less +172 -95
- package/src/components/header-navigation/header-navigation.module.less.d.ts +14 -9
- package/src/components/header-navigation/header-navigation.stories.tsx +11 -17
- 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,7 @@ 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
|
-
HeaderNavigation,
|
|
9
|
-
HeaderNavigationItemContent,
|
|
10
|
-
HeaderNavigationLink,
|
|
11
|
-
HeaderNavigationTrigger,
|
|
12
|
-
HeaderNavigationTriggerCustom,
|
|
13
|
-
} from './header-navigation';
|
|
7
|
+
import { HeaderNavigation, HeaderNavigationLink, HeaderNavigationTrigger } from './';
|
|
14
8
|
|
|
15
9
|
export default {
|
|
16
10
|
title: 'Navigation/HeaderNavigation',
|
|
@@ -114,9 +108,11 @@ const HelpCenterButton = () => {
|
|
|
114
108
|
direction="bl"
|
|
115
109
|
width="xs"
|
|
116
110
|
trigger={
|
|
117
|
-
<
|
|
118
|
-
|
|
119
|
-
|
|
111
|
+
<HeaderNavigationTrigger
|
|
112
|
+
id="help"
|
|
113
|
+
iconName="help_outline"
|
|
114
|
+
onClick={() => setOpen(true)}
|
|
115
|
+
/>
|
|
120
116
|
}
|
|
121
117
|
portal
|
|
122
118
|
>
|
|
@@ -139,15 +135,15 @@ export const withAllMonolithData = () => (
|
|
|
139
135
|
items.calendar,
|
|
140
136
|
items.calls,
|
|
141
137
|
items.accounting,
|
|
142
|
-
items.dispatch,
|
|
138
|
+
// items.dispatch,
|
|
143
139
|
|
|
144
140
|
items.fleet,
|
|
145
|
-
items.followUps,
|
|
141
|
+
// items.followUps,
|
|
146
142
|
items.inventory,
|
|
147
143
|
|
|
148
|
-
items.marketing,
|
|
144
|
+
// items.marketing,
|
|
149
145
|
items.priceBook,
|
|
150
|
-
items.pointOfSale,
|
|
146
|
+
// items.pointOfSale,
|
|
151
147
|
items.reports,
|
|
152
148
|
]}
|
|
153
149
|
navigationComponent={NavLinkMock}
|
|
@@ -164,9 +160,7 @@ export const withAllMonolithData = () => (
|
|
|
164
160
|
hint="Search: for all the questions"
|
|
165
161
|
/>
|
|
166
162
|
|
|
167
|
-
<
|
|
168
|
-
<HelpCenterButton />
|
|
169
|
-
</HeaderNavigationTriggerCustom>
|
|
163
|
+
<HelpCenterButton />
|
|
170
164
|
<HeaderNavigationTrigger id="titanAdvisor" iconName="rocket" />
|
|
171
165
|
|
|
172
166
|
<HeaderNavigationLink
|
|
@@ -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
|
);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { FC } from 'react';
|
|
2
2
|
|
|
3
|
-
export interface
|
|
3
|
+
export interface LogoTitanSvgProps {
|
|
4
4
|
height?: number;
|
|
5
5
|
width?: number;
|
|
6
6
|
fill?: string;
|
|
@@ -8,7 +8,7 @@ export interface LogoTitanProps {
|
|
|
8
8
|
}
|
|
9
9
|
|
|
10
10
|
/* tslint:disable: max-line-length */
|
|
11
|
-
export const
|
|
11
|
+
export const LogoTitanSvg: FC<LogoTitanSvgProps> = props => {
|
|
12
12
|
const dimensions = {
|
|
13
13
|
width: props.width ?? 116,
|
|
14
14
|
height: props.height ?? 106,
|