@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.
Files changed (88) 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 +1 -1
  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 +6 -6
  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 +68 -0
  16. package/dist/components/header-navigation/header-navigation-stacked.stories.js.map +1 -0
  17. package/dist/components/header-navigation/header-navigation-stories.module.less +6 -0
  18. package/dist/components/header-navigation/header-navigation.d.ts +32 -55
  19. package/dist/components/header-navigation/header-navigation.d.ts.map +1 -1
  20. package/dist/components/header-navigation/header-navigation.js +41 -48
  21. package/dist/components/header-navigation/header-navigation.js.map +1 -1
  22. package/dist/components/header-navigation/header-navigation.module.less +171 -95
  23. package/dist/components/header-navigation/header-navigation.stories.d.ts.map +1 -1
  24. package/dist/components/header-navigation/header-navigation.stories.js +6 -4
  25. package/dist/components/header-navigation/header-navigation.stories.js.map +1 -1
  26. package/dist/components/header-navigation/index.d.ts +3 -0
  27. package/dist/components/header-navigation/index.d.ts.map +1 -0
  28. package/dist/components/header-navigation/index.js +3 -0
  29. package/dist/components/header-navigation/index.js.map +1 -0
  30. package/dist/components/logo/logo-titan-text.d.ts +21 -5
  31. package/dist/components/logo/logo-titan-text.d.ts.map +1 -1
  32. package/dist/components/logo/logo-titan-text.js +9 -3
  33. package/dist/components/logo/logo-titan-text.js.map +1 -1
  34. package/dist/components/logo/logo-titan-text.module.less +12 -9
  35. package/dist/components/logo/logo-titan.d.ts +2 -2
  36. package/dist/components/logo/logo-titan.d.ts.map +1 -1
  37. package/dist/components/logo/logo-titan.js +1 -1
  38. package/dist/components/logo/logo-titan.js.map +1 -1
  39. package/dist/components/logo/logo.stories.d.ts +2 -1
  40. package/dist/components/logo/logo.stories.d.ts.map +1 -1
  41. package/dist/components/logo/logo.stories.js +7 -5
  42. package/dist/components/logo/logo.stories.js.map +1 -1
  43. package/dist/components/profile-dropdown/profile-dropdown-stacked.stories.d.ts +15 -0
  44. package/dist/components/profile-dropdown/profile-dropdown-stacked.stories.d.ts.map +1 -0
  45. package/dist/components/profile-dropdown/profile-dropdown-stacked.stories.js +51 -0
  46. package/dist/components/profile-dropdown/profile-dropdown-stacked.stories.js.map +1 -0
  47. package/dist/components/profile-dropdown/profile-dropdown.d.ts +1 -0
  48. package/dist/components/profile-dropdown/profile-dropdown.d.ts.map +1 -1
  49. package/dist/components/profile-dropdown/profile-dropdown.js +3 -3
  50. package/dist/components/profile-dropdown/profile-dropdown.js.map +1 -1
  51. package/dist/components/profile-dropdown/profile-dropdown.module.less +0 -2
  52. package/dist/components/profile-dropdown/profile-dropdown.stories.js +1 -1
  53. package/dist/components/profile-dropdown/profile-dropdown.stories.js.map +1 -1
  54. package/dist/components/profile-dropdown/profile-icon.d.ts +1 -1
  55. package/dist/components/profile-dropdown/profile-icon.d.ts.map +1 -1
  56. package/dist/components/profile-dropdown/profile-icon.js +1 -1
  57. package/dist/components/profile-dropdown/profile-icon.js.map +1 -1
  58. package/dist/index.d.ts +2 -1
  59. package/dist/index.d.ts.map +1 -1
  60. package/dist/index.js +2 -1
  61. package/dist/index.js.map +1 -1
  62. package/dist/utils/with-tooltip.d.ts +3 -0
  63. package/dist/utils/with-tooltip.d.ts.map +1 -0
  64. package/dist/utils/with-tooltip.js +4 -0
  65. package/dist/utils/with-tooltip.js.map +1 -0
  66. package/package.json +2 -2
  67. package/src/components/header-navigation/header-navigation-content.tsx +118 -0
  68. package/src/components/header-navigation/header-navigation-extra.stories.tsx +12 -12
  69. package/src/components/header-navigation/header-navigation-links.tsx +143 -0
  70. package/src/components/header-navigation/header-navigation-stacked.stories.tsx +187 -0
  71. package/src/components/header-navigation/header-navigation-stories.module.less +6 -0
  72. package/src/components/header-navigation/header-navigation-stories.module.less.d.ts +3 -0
  73. package/src/components/header-navigation/header-navigation.module.less +171 -95
  74. package/src/components/header-navigation/header-navigation.module.less.d.ts +14 -9
  75. package/src/components/header-navigation/header-navigation.stories.tsx +25 -16
  76. package/src/components/header-navigation/header-navigation.tsx +151 -266
  77. package/src/components/header-navigation/index.ts +2 -0
  78. package/src/components/logo/logo-titan-text.module.less +12 -9
  79. package/src/components/logo/logo-titan-text.tsx +62 -20
  80. package/src/components/logo/logo-titan.tsx +2 -2
  81. package/src/components/logo/logo.stories.tsx +13 -4
  82. package/src/components/profile-dropdown/profile-dropdown-stacked.stories.tsx +178 -0
  83. package/src/components/profile-dropdown/profile-dropdown.module.less +0 -2
  84. package/src/components/profile-dropdown/profile-dropdown.stories.tsx +1 -1
  85. package/src/components/profile-dropdown/profile-dropdown.tsx +5 -3
  86. package/src/components/profile-dropdown/profile-icon.tsx +2 -1
  87. package/src/index.ts +2 -1
  88. 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
- HeaderNavigation,
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
- <div onClick={() => setOpen(true)}>
118
- <HeaderNavigationItemContent iconName="help_outline" />
119
- </div>
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 fw-bold p-x-1">
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
- iconName="search"
170
+ iconComponent={SearchIcon}
164
171
  hint="Search: for all the questions"
165
172
  />
166
173
 
167
- <HeaderNavigationTriggerCustom id="help-center">
168
- <HelpCenterButton />
169
- </HeaderNavigationTriggerCustom>
170
- <HeaderNavigationTrigger id="titanAdvisor" iconName="rocket" />
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
- DefaultNavLinkComponent,
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
- contentClassName?: string;
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(Styles.navigationItems, 'd-if')}>
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
- contentClassName
181
+ rightClassName
439
182
  )}
440
183
  ref={rightRef}
441
- data-cy="navigation-content"
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
+ };
@@ -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
  );