@servicetitan/navigation 1.6.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.
Files changed (85) hide show
  1. package/dist/components/header-navigation/header-navigation-content.d.ts +30 -0
  2. package/dist/components/header-navigation/header-navigation-content.d.ts.map +1 -0
  3. package/dist/components/header-navigation/header-navigation-content.js +21 -0
  4. package/dist/components/header-navigation/header-navigation-content.js.map +1 -0
  5. package/dist/components/header-navigation/header-navigation-extra.stories.d.ts +2 -2
  6. package/dist/components/header-navigation/header-navigation-extra.stories.d.ts.map +1 -1
  7. package/dist/components/header-navigation/header-navigation-extra.stories.js +7 -7
  8. package/dist/components/header-navigation/header-navigation-extra.stories.js.map +1 -1
  9. package/dist/components/header-navigation/header-navigation-links.d.ts +38 -0
  10. package/dist/components/header-navigation/header-navigation-links.d.ts.map +1 -0
  11. package/dist/components/header-navigation/header-navigation-links.js +38 -0
  12. package/dist/components/header-navigation/header-navigation-links.js.map +1 -0
  13. package/dist/components/header-navigation/header-navigation-stacked.stories.d.ts +11 -0
  14. package/dist/components/header-navigation/header-navigation-stacked.stories.d.ts.map +1 -0
  15. package/dist/components/header-navigation/header-navigation-stacked.stories.js +66 -0
  16. package/dist/components/header-navigation/header-navigation-stacked.stories.js.map +1 -0
  17. package/dist/components/header-navigation/header-navigation.d.ts +43 -36
  18. package/dist/components/header-navigation/header-navigation.d.ts.map +1 -1
  19. package/dist/components/header-navigation/header-navigation.js +41 -81
  20. package/dist/components/header-navigation/header-navigation.js.map +1 -1
  21. package/dist/components/header-navigation/header-navigation.module.less +172 -95
  22. package/dist/components/header-navigation/header-navigation.stories.d.ts.map +1 -1
  23. package/dist/components/header-navigation/header-navigation.stories.js +8 -8
  24. package/dist/components/header-navigation/header-navigation.stories.js.map +1 -1
  25. package/dist/components/header-navigation/index.d.ts +3 -0
  26. package/dist/components/header-navigation/index.d.ts.map +1 -0
  27. package/dist/components/header-navigation/index.js +3 -0
  28. package/dist/components/header-navigation/index.js.map +1 -0
  29. package/dist/components/logo/logo-titan-text.d.ts +21 -5
  30. package/dist/components/logo/logo-titan-text.d.ts.map +1 -1
  31. package/dist/components/logo/logo-titan-text.js +9 -3
  32. package/dist/components/logo/logo-titan-text.js.map +1 -1
  33. package/dist/components/logo/logo-titan-text.module.less +12 -9
  34. package/dist/components/logo/logo-titan.d.ts +2 -2
  35. package/dist/components/logo/logo-titan.d.ts.map +1 -1
  36. package/dist/components/logo/logo-titan.js +1 -1
  37. package/dist/components/logo/logo-titan.js.map +1 -1
  38. package/dist/components/logo/logo.stories.d.ts +2 -1
  39. package/dist/components/logo/logo.stories.d.ts.map +1 -1
  40. package/dist/components/logo/logo.stories.js +7 -5
  41. package/dist/components/logo/logo.stories.js.map +1 -1
  42. package/dist/components/profile-dropdown/profile-dropdown-stacked.stories.d.ts +15 -0
  43. package/dist/components/profile-dropdown/profile-dropdown-stacked.stories.d.ts.map +1 -0
  44. package/dist/components/profile-dropdown/profile-dropdown-stacked.stories.js +51 -0
  45. package/dist/components/profile-dropdown/profile-dropdown-stacked.stories.js.map +1 -0
  46. package/dist/components/profile-dropdown/profile-dropdown.d.ts +1 -0
  47. package/dist/components/profile-dropdown/profile-dropdown.d.ts.map +1 -1
  48. package/dist/components/profile-dropdown/profile-dropdown.js +3 -3
  49. package/dist/components/profile-dropdown/profile-dropdown.js.map +1 -1
  50. package/dist/components/profile-dropdown/profile-dropdown.module.less +0 -2
  51. package/dist/components/profile-dropdown/profile-dropdown.stories.js +1 -1
  52. package/dist/components/profile-dropdown/profile-dropdown.stories.js.map +1 -1
  53. package/dist/components/profile-dropdown/profile-icon.d.ts +1 -1
  54. package/dist/components/profile-dropdown/profile-icon.d.ts.map +1 -1
  55. package/dist/components/profile-dropdown/profile-icon.js +1 -1
  56. package/dist/components/profile-dropdown/profile-icon.js.map +1 -1
  57. package/dist/index.d.ts +2 -1
  58. package/dist/index.d.ts.map +1 -1
  59. package/dist/index.js +2 -1
  60. package/dist/index.js.map +1 -1
  61. package/dist/utils/with-tooltip.d.ts +3 -0
  62. package/dist/utils/with-tooltip.d.ts.map +1 -0
  63. package/dist/utils/with-tooltip.js +4 -0
  64. package/dist/utils/with-tooltip.js.map +1 -0
  65. package/package.json +2 -2
  66. package/src/components/header-navigation/header-navigation-content.tsx +118 -0
  67. package/src/components/header-navigation/header-navigation-extra.stories.tsx +23 -17
  68. package/src/components/header-navigation/header-navigation-links.tsx +143 -0
  69. package/src/components/header-navigation/header-navigation-stacked.stories.tsx +172 -0
  70. package/src/components/header-navigation/header-navigation.module.less +172 -95
  71. package/src/components/header-navigation/header-navigation.module.less.d.ts +14 -9
  72. package/src/components/header-navigation/header-navigation.stories.tsx +11 -19
  73. package/src/components/header-navigation/header-navigation.tsx +163 -283
  74. package/src/components/header-navigation/index.ts +2 -0
  75. package/src/components/logo/logo-titan-text.module.less +12 -9
  76. package/src/components/logo/logo-titan-text.tsx +62 -20
  77. package/src/components/logo/logo-titan.tsx +2 -2
  78. package/src/components/logo/logo.stories.tsx +13 -4
  79. package/src/components/profile-dropdown/profile-dropdown-stacked.stories.tsx +178 -0
  80. package/src/components/profile-dropdown/profile-dropdown.module.less +0 -2
  81. package/src/components/profile-dropdown/profile-dropdown.stories.tsx +1 -1
  82. package/src/components/profile-dropdown/profile-dropdown.tsx +5 -3
  83. package/src/components/profile-dropdown/profile-icon.tsx +2 -1
  84. package/src/index.ts +2 -1
  85. package/src/utils/with-tooltip.tsx +11 -0
@@ -1,31 +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
- useLayoutEffect,
18
- useMemo,
19
- useRef,
20
- useState,
21
- } from 'react';
3
+ import { FC, ReactElement, ReactNode, useCallback, useEffect, useRef, useState } from 'react';
22
4
  import { HeaderNavigationItemData, NavLinkComponentProps } from '../../utils/navigation';
23
- import {
24
- DefaultNavLinkComponent,
25
- NavLinkContext,
26
- useNavLink,
27
- } from '../../utils/navigation-context';
28
- import { CounterTag, CounterTagPropsType } from '../counter-tag';
5
+ import { DefaultNavLinkComponent, NavLinkContext } from '../../utils/navigation-context';
6
+ import { HeaderNavigationItem } from './header-navigation-content';
29
7
  import * as Styles from './header-navigation.module.less';
30
8
 
31
9
  function useForceUpdate() {
@@ -35,205 +13,6 @@ function useForceUpdate() {
35
13
  }, []);
36
14
  }
37
15
 
38
- interface HeaderNavigationItemContentPropsStrict {
39
- title?: string;
40
- counter?: CounterTagPropsType;
41
- iconClassName?: string;
42
- iconComponent?: FC;
43
- iconName?: IconPropsStrict['name'];
44
- }
45
- export interface HeaderNavigationTriggerPropsStrict extends HeaderNavigationItemContentPropsStrict {
46
- id: string;
47
- hint?: string;
48
- className?: string;
49
- }
50
-
51
- interface HeaderNavigationTriggerProps extends HeaderNavigationTriggerPropsStrict {
52
- [key: string]: any;
53
- }
54
-
55
- export interface HeaderNavigationLinkPropsStrict extends HeaderNavigationTriggerPropsStrict {
56
- to: string;
57
- isActive?: boolean | ((pathname: string) => boolean);
58
- target?: HTMLAttributeAnchorTarget;
59
- }
60
-
61
- export interface HeaderNavigationLinkProps extends HeaderNavigationLinkPropsStrict {
62
- [key: string]: any;
63
- }
64
-
65
- export const HeaderNavigationItemContent: FC<HeaderNavigationItemContentPropsStrict> = ({
66
- title,
67
- counter,
68
- iconClassName,
69
- iconComponent: IconComponent,
70
- iconName,
71
- }) => (
72
- <Fragment>
73
- {IconComponent ? (
74
- <i className={classNames(Styles.icon, iconClassName)}>
75
- <IconComponent />
76
- </i>
77
- ) : iconName ? (
78
- <Icon size="20px" name={iconName} className={classNames(Styles.icon, iconClassName)} />
79
- ) : (
80
- <i className={classNames(Styles.icon, iconClassName)} />
81
- )}
82
-
83
- {!!title && <ins>{title}</ins>}
84
-
85
- {!!counter && (
86
- <CounterTag
87
- data={counter}
88
- className={Styles.counter}
89
- longClassName={Styles.counterLong}
90
- />
91
- )}
92
- </Fragment>
93
- );
94
-
95
- export const HeaderNavigationLink: FC<HeaderNavigationLinkProps> = ({
96
- id,
97
- to,
98
- title,
99
- hint,
100
- counter,
101
- className,
102
- iconClassName,
103
- iconComponent,
104
- iconName,
105
- isActive,
106
- target,
107
- ...rest
108
- }) => {
109
- const NavigationComponent = useNavLink();
110
-
111
- return (
112
- <NavigationComponent
113
- data-cy={`navigation-link-${id}`}
114
- data-pendo={`navigation-link-${id}`}
115
- {...rest}
116
- key={id}
117
- to={to}
118
- title={hint}
119
- className={classNames(Styles.link, className, {
120
- [Styles.active]: isActive === true,
121
- })}
122
- isActive={typeof isActive === 'function' ? isActive : undefined}
123
- activeClassName={Styles.active}
124
- target={target}
125
- >
126
- <HeaderNavigationItemContent
127
- title={title}
128
- counter={counter}
129
- iconComponent={iconComponent}
130
- iconClassName={iconClassName}
131
- iconName={iconName}
132
- />
133
- </NavigationComponent>
134
- );
135
- };
136
-
137
- interface HeaderNavigationItemPropsStrict extends HeaderNavigationItemData {
138
- minimized: boolean;
139
- main: boolean;
140
- }
141
-
142
- const HeaderNavigationItem: FC<HeaderNavigationItemPropsStrict> = ({
143
- id,
144
- to,
145
- title,
146
- hint,
147
- counter,
148
- className,
149
- iconClassName,
150
- iconComponent,
151
- iconName,
152
- isActive,
153
- main,
154
- minimized,
155
- }) => {
156
- const NavigationComponent = useNavLink();
157
-
158
- const trigger = (
159
- <NavigationComponent
160
- data-cy={`navigation-item-${id}`}
161
- data-pendo={`navigation-item-${id}`}
162
- key={id}
163
- to={to}
164
- title={hint}
165
- className={classNames(
166
- Styles.link,
167
- className,
168
- main ? Styles.linkMain : Styles.linkOverflow,
169
- {
170
- [Styles.active]: isActive === true,
171
- }
172
- )}
173
- isActive={typeof isActive === 'function' ? isActive : undefined}
174
- activeClassName={Styles.active}
175
- >
176
- <HeaderNavigationItemContent
177
- title={minimized ? undefined : title}
178
- counter={counter}
179
- iconComponent={iconComponent}
180
- iconClassName={iconClassName}
181
- iconName={iconName}
182
- />
183
- </NavigationComponent>
184
- );
185
-
186
- return minimized && title ? (
187
- <Tooltip el="div" direction="b" text={title}>
188
- {trigger}
189
- </Tooltip>
190
- ) : (
191
- trigger
192
- );
193
- };
194
-
195
- export const HeaderNavigationTrigger: FC<HeaderNavigationTriggerProps> = ({
196
- id,
197
- hint,
198
- className,
199
- counter,
200
- iconClassName,
201
- iconComponent,
202
- iconName,
203
- title,
204
- ...rest
205
- }) => (
206
- <div
207
- data-cy={`navigation-trigger-${id}`}
208
- data-pendo={`navigation-trigger-${id}`}
209
- {...rest}
210
- title={hint}
211
- className={classNames(Styles.link, 'cursor-pointer', className)}
212
- >
213
- <HeaderNavigationItemContent
214
- counter={counter}
215
- iconComponent={iconComponent}
216
- iconClassName={iconClassName}
217
- iconName={iconName}
218
- title={title}
219
- />
220
- </div>
221
- );
222
-
223
- export const HeaderNavigationTriggerCustom: FC<
224
- Omit<HeaderNavigationTriggerProps, 'title'> & { children: ReactNode }
225
- > = ({ children, id, hint, className, iconClassName, iconComponent, iconName, ...rest }) => (
226
- <div
227
- data-cy={`navigation-custom-${id}`}
228
- data-pendo={`navigation-custom-${id}`}
229
- {...rest}
230
- title={hint}
231
- className={classNames(Styles.link, 'cursor-pointer', className)}
232
- >
233
- {children}
234
- </div>
235
- );
236
-
237
16
  export interface HeaderNavigationOverflowProps {
238
17
  direction: PopoverPropsStrict['direction'];
239
18
  width: PopoverPropsStrict['width'];
@@ -281,23 +60,30 @@ const HeaderNavigationOverflow: FC<{
281
60
  };
282
61
 
283
62
  export interface HeaderNavigationProps {
63
+ /** extra navigation */
284
64
  children?: ReactNode;
65
+ /** container class name */
285
66
  className?: string;
286
- contentClassName?: string;
67
+ /** extra navigation container class name */
68
+ rightClassName?: string;
69
+ /** container id */
287
70
  id?: string;
71
+ /** left content (usually used for logo) */
288
72
  left?: ReactElement;
73
+ /** left container class name */
289
74
  leftClassName?: string;
75
+ /** minimal width for navigation bar */
290
76
  minWidth?: number;
77
+ /** main navigation items */
291
78
  items?: HeaderNavigationItemData[];
79
+ /** main navigation overflow items */
292
80
  itemsOverflow?: HeaderNavigationItemData[];
81
+ /** navigation component used for routing */
293
82
  navigationComponent?: FC<NavLinkComponentProps>;
294
- align?: 'left' | 'right' | 'center';
295
- alignMinimized?: 'left' | 'right' | 'center';
83
+ /** props for main items overflow component */
296
84
  overflow?: HeaderNavigationOverflowProps;
297
85
  }
298
86
 
299
- const shortItemWidth = 44;
300
-
301
87
  enum MinimizedState {
302
88
  Calculating,
303
89
  Minimized,
@@ -305,16 +91,14 @@ enum MinimizedState {
305
91
  }
306
92
 
307
93
  export const HeaderNavigation: FC<HeaderNavigationProps> = ({
308
- align,
309
- alignMinimized,
310
94
  children,
311
95
  className,
312
- contentClassName,
313
96
  id,
314
97
  items,
315
98
  itemsOverflow,
316
99
  left,
317
100
  leftClassName,
101
+ rightClassName,
318
102
  minWidth = 800,
319
103
  navigationComponent = DefaultNavLinkComponent,
320
104
  overflow,
@@ -326,45 +110,6 @@ export const HeaderNavigation: FC<HeaderNavigationProps> = ({
326
110
  const forceUpdate = useForceUpdate();
327
111
  const [minimized, setMinimized] = useState(MinimizedState.Calculating);
328
112
 
329
- const navigationAlign = useMemo(() => {
330
- if (alignMinimized && minimized === MinimizedState.Minimized) {
331
- return alignMinimized;
332
- }
333
-
334
- return align ?? 'left';
335
- }, [align, alignMinimized, minimized]);
336
-
337
- const navigationAlignClass = useMemo(() => {
338
- switch (navigationAlign) {
339
- case 'center':
340
- return 'justify-content-center';
341
- case 'right':
342
- return 'justify-content-end';
343
- default:
344
- return 'justify-content-start';
345
- }
346
- }, [navigationAlign]);
347
-
348
- const calculatePaddings = useCallback(() => {
349
- if (leftRef.current && rightRef.current && centerRef.current) {
350
- let diff = leftRef.current.clientWidth - rightRef.current.clientWidth;
351
- const margin = 8;
352
-
353
- // if no enough space to show navigation links in the middle of page
354
- if (centerRef.current.clientWidth < (items?.length ?? 0) * shortItemWidth) {
355
- // show them in the middle of available space
356
- diff = 0;
357
- }
358
-
359
- if (navigationAlign !== 'center') {
360
- diff = 0;
361
- }
362
-
363
- centerRef.current.style.marginLeft = `${margin + (diff < 0 ? -diff : 0)}px`;
364
- centerRef.current.style.marginRight = `${margin + (diff > 0 ? diff : 0)}px`;
365
- }
366
- }, [items, navigationAlign]);
367
-
368
113
  useEffect(() => {
369
114
  const handleResize = () => {
370
115
  setMinimized(MinimizedState.Calculating);
@@ -380,15 +125,10 @@ export const HeaderNavigation: FC<HeaderNavigationProps> = ({
380
125
  forceUpdate();
381
126
  }, [items, itemsOverflow, forceUpdate]);
382
127
 
383
- useLayoutEffect(() => {
384
- calculatePaddings();
385
- }, [calculatePaddings]);
386
-
387
128
  const updateIsMinimized = () => {
388
129
  if (centerRef.current && navigationRef.current) {
389
130
  if (navigationRef.current.clientWidth > centerRef.current.clientWidth) {
390
131
  setMinimized(MinimizedState.Minimized);
391
- calculatePaddings();
392
132
  } else if (minimized === MinimizedState.Calculating) {
393
133
  setMinimized(MinimizedState.Full);
394
134
  }
@@ -403,7 +143,6 @@ export const HeaderNavigation: FC<HeaderNavigationProps> = ({
403
143
  <NavLinkContext.Provider value={navigationComponent}>
404
144
  <div
405
145
  className={classNames(Styles.header, className, {
406
- [Styles.minimized]: minimized === MinimizedState.Minimized,
407
146
  [Styles.calculating]: minimized === MinimizedState.Calculating,
408
147
  })}
409
148
  style={{ minWidth: `${minWidth}px` }}
@@ -416,13 +155,12 @@ export const HeaderNavigation: FC<HeaderNavigationProps> = ({
416
155
  <div
417
156
  ref={centerRef}
418
157
  className={classNames(
419
- 'd-if flex-grow-1 flex-basis-0',
420
- navigationAlignClass,
158
+ 'd-if flex-grow-1 flex-basis-0 justify-content-center',
421
159
  Styles.center
422
160
  )}
423
161
  data-cy="navigation-items"
424
162
  >
425
- <div ref={navigationRef} className={classNames(Styles.navigationItems, 'd-if')}>
163
+ <div ref={navigationRef} className={classNames('d-if')}>
426
164
  {items?.map(item => (
427
165
  <HeaderNavigationItem
428
166
  {...item}
@@ -440,10 +178,10 @@ export const HeaderNavigation: FC<HeaderNavigationProps> = ({
440
178
  className={classNames(
441
179
  'd-f flex-row justify-content-end align-items-center',
442
180
  Styles.right,
443
- contentClassName
181
+ rightClassName
444
182
  )}
445
183
  ref={rightRef}
446
- data-cy="navigation-content"
184
+ data-cy="navigation-right"
447
185
  >
448
186
  {children}
449
187
  </div>
@@ -451,3 +189,145 @@ export const HeaderNavigation: FC<HeaderNavigationProps> = ({
451
189
  </NavLinkContext.Provider>
452
190
  );
453
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
+ };
@@ -0,0 +1,2 @@
1
+ export * from './header-navigation';
2
+ export * from './header-navigation-links';
@@ -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 { LogoTitan } from './logo-titan';
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?: FC<{ className: string; children: ReactNode }>;
21
+ logoWrapper?: WrapperProps;
12
22
  }
13
23
 
14
- const DefaultLogoWrapper: FC<{ className: string; children: ReactNode }> = ({
15
- className,
16
- children,
17
- }) => <div className={className}>{children}</div>;
18
- export const LogoTitanText: FC<LogoTitanTextProps> = ({
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
- title,
24
- }) => (
25
- <div className={classNames('d-f', Styles.container, className)}>
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
- Styles.logoWrapper
48
+ className
30
49
  )}
50
+ style={{ height: `${size}px`, width: `${size}px` }}
31
51
  >
32
- <LogoTitan width={40} height={40} mantleFill={mantleFill} />
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
- <span className={classNames(Styles.logoTextTitle, 'ff-display t-truncate p-b-half')}>
36
- {title}
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 LogoTitanProps {
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 LogoTitan: FC<LogoTitanProps> = (props: LogoTitanProps) => {
11
+ export const LogoTitanSvg: FC<LogoTitanSvgProps> = props => {
12
12
  const dimensions = {
13
13
  width: props.width ?? 116,
14
14
  height: props.height ?? 106,