@servicetitan/navigation 13.0.0-canary.256.b43c6d7.0 → 13.0.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 (116) hide show
  1. package/dist/components/counter-tag.d.ts +1 -1
  2. package/dist/components/counter-tag.d.ts.map +1 -1
  3. package/dist/components/counter-tag.js.map +1 -1
  4. package/dist/components/profile-dropdown/interface.d.ts +55 -0
  5. package/dist/components/profile-dropdown/interface.d.ts.map +1 -0
  6. package/dist/components/profile-dropdown/interface.js +3 -0
  7. package/dist/components/profile-dropdown/interface.js.map +1 -0
  8. package/dist/components/profile-dropdown/profile-dropdown-legacy.stories.d.ts +5 -1
  9. package/dist/components/profile-dropdown/profile-dropdown-legacy.stories.d.ts.map +1 -1
  10. package/dist/components/profile-dropdown/profile-dropdown-stacked.stories.d.ts +5 -1
  11. package/dist/components/profile-dropdown/profile-dropdown-stacked.stories.d.ts.map +1 -1
  12. package/dist/components/profile-dropdown/profile-dropdown.d.ts +9 -79
  13. package/dist/components/profile-dropdown/profile-dropdown.d.ts.map +1 -1
  14. package/dist/components/profile-dropdown/profile-dropdown.js +17 -14
  15. package/dist/components/profile-dropdown/profile-dropdown.js.map +1 -1
  16. package/dist/components/profile-dropdown/profile-dropdown.stories.d.ts +5 -1
  17. package/dist/components/profile-dropdown/profile-dropdown.stories.d.ts.map +1 -1
  18. package/dist/components/titan-layout/interface-internal.d.ts +12 -0
  19. package/dist/components/titan-layout/interface-internal.d.ts.map +1 -1
  20. package/dist/components/titan-layout/interface-internal.js.map +1 -1
  21. package/dist/components/titan-layout/interface.d.ts +60 -4
  22. package/dist/components/titan-layout/interface.d.ts.map +1 -1
  23. package/dist/components/titan-layout/interface.js.map +1 -1
  24. package/dist/components/titan-layout/layout-header-dark.d.ts.map +1 -1
  25. package/dist/components/titan-layout/layout-header-dark.js +24 -12
  26. package/dist/components/titan-layout/layout-header-dark.js.map +1 -1
  27. package/dist/components/titan-layout/layout-header-links-internal.d.ts +22 -3
  28. package/dist/components/titan-layout/layout-header-links-internal.d.ts.map +1 -1
  29. package/dist/components/titan-layout/layout-header-links-internal.js +15 -18
  30. package/dist/components/titan-layout/layout-header-links-internal.js.map +1 -1
  31. package/dist/components/titan-layout/layout-header-links.d.ts +2 -3
  32. package/dist/components/titan-layout/layout-header-links.d.ts.map +1 -1
  33. package/dist/components/titan-layout/layout-header-links.js +25 -5
  34. package/dist/components/titan-layout/layout-header-links.js.map +1 -1
  35. package/dist/components/titan-layout/layout-header.d.ts +2 -0
  36. package/dist/components/titan-layout/layout-header.d.ts.map +1 -1
  37. package/dist/components/titan-layout/layout-header.js +25 -16
  38. package/dist/components/titan-layout/layout-header.js.map +1 -1
  39. package/dist/components/titan-layout/layout-header.module.less +37 -1
  40. package/dist/components/titan-layout/layout-header.module.less.d.ts +3 -0
  41. package/dist/components/titan-layout/layout-profile.d.ts +8 -5
  42. package/dist/components/titan-layout/layout-profile.d.ts.map +1 -1
  43. package/dist/components/titan-layout/layout-profile.js +29 -21
  44. package/dist/components/titan-layout/layout-profile.js.map +1 -1
  45. package/dist/components/titan-layout/layout-sidebar-links-internal.d.ts +48 -24
  46. package/dist/components/titan-layout/layout-sidebar-links-internal.d.ts.map +1 -1
  47. package/dist/components/titan-layout/layout-sidebar-links-internal.js +62 -51
  48. package/dist/components/titan-layout/layout-sidebar-links-internal.js.map +1 -1
  49. package/dist/components/titan-layout/layout-sidebar-links.d.ts +2 -2
  50. package/dist/components/titan-layout/layout-sidebar-links.d.ts.map +1 -1
  51. package/dist/components/titan-layout/layout-sidebar-links.js +27 -14
  52. package/dist/components/titan-layout/layout-sidebar-links.js.map +1 -1
  53. package/dist/components/titan-layout/layout-sidebar.d.ts +1 -1
  54. package/dist/components/titan-layout/layout-sidebar.d.ts.map +1 -1
  55. package/dist/components/titan-layout/layout-sidebar.js +81 -104
  56. package/dist/components/titan-layout/layout-sidebar.js.map +1 -1
  57. package/dist/components/titan-layout/layout-sidebar.module.less +74 -22
  58. package/dist/components/titan-layout/titan-layout-default.stories.d.ts +16 -0
  59. package/dist/components/titan-layout/titan-layout-default.stories.d.ts.map +1 -0
  60. package/dist/components/titan-layout/titan-layout-legacy.stories.d.ts +10 -0
  61. package/dist/components/titan-layout/titan-layout-legacy.stories.d.ts.map +1 -0
  62. package/dist/components/titan-layout/titan-layout-stacked.stories.d.ts +10 -0
  63. package/dist/components/titan-layout/titan-layout-stacked.stories.d.ts.map +1 -0
  64. package/dist/components/titan-layout/titan-layout.d.ts +28 -1
  65. package/dist/components/titan-layout/titan-layout.d.ts.map +1 -1
  66. package/dist/components/titan-layout/titan-layout.js +30 -11
  67. package/dist/components/titan-layout/titan-layout.js.map +1 -1
  68. package/dist/index.d.ts +0 -1
  69. package/dist/index.d.ts.map +1 -1
  70. package/dist/index.js.map +1 -1
  71. package/dist/test/data.d.ts +0 -22
  72. package/dist/test/data.d.ts.map +1 -1
  73. package/dist/test/data.js +0 -197
  74. package/dist/test/data.js.map +1 -1
  75. package/dist/test/titan-layout.d.ts +16 -0
  76. package/dist/test/titan-layout.d.ts.map +1 -0
  77. package/dist/test/titan-layout.js +21 -0
  78. package/dist/test/titan-layout.js.map +1 -0
  79. package/dist/utils/navigation.d.ts +1 -4
  80. package/dist/utils/navigation.d.ts.map +1 -1
  81. package/dist/utils/navigation.js.map +1 -1
  82. package/package.json +4 -4
  83. package/src/components/counter-tag.tsx +1 -1
  84. package/src/components/profile-dropdown/interface.ts +47 -0
  85. package/src/components/profile-dropdown/profile-dropdown-legacy.stories.tsx +3 -3
  86. package/src/components/profile-dropdown/profile-dropdown-stacked.stories.tsx +3 -3
  87. package/src/components/profile-dropdown/profile-dropdown.stories.tsx +39 -39
  88. package/src/components/profile-dropdown/profile-dropdown.tsx +37 -104
  89. package/src/components/titan-layout/interface-internal.ts +13 -0
  90. package/src/components/titan-layout/interface.ts +64 -7
  91. package/src/components/titan-layout/layout-header-dark.tsx +21 -5
  92. package/src/components/titan-layout/layout-header-links-internal.tsx +41 -54
  93. package/src/components/titan-layout/layout-header-links.tsx +64 -8
  94. package/src/components/titan-layout/layout-header.module.less +37 -1
  95. package/src/components/titan-layout/layout-header.module.less.d.ts +3 -0
  96. package/src/components/titan-layout/layout-header.tsx +26 -13
  97. package/src/components/titan-layout/layout-profile.tsx +51 -28
  98. package/src/components/titan-layout/layout-sidebar-links-internal.tsx +155 -102
  99. package/src/components/titan-layout/layout-sidebar-links.tsx +45 -12
  100. package/src/components/titan-layout/layout-sidebar.module.less +74 -22
  101. package/src/components/titan-layout/layout-sidebar.tsx +55 -80
  102. package/src/components/titan-layout/{titan-layout.stories.tsx → titan-layout-default.stories.tsx} +100 -84
  103. package/src/components/titan-layout/titan-layout-legacy.stories.tsx +24 -0
  104. package/src/components/titan-layout/titan-layout-stacked.stories.tsx +30 -0
  105. package/src/components/titan-layout/titan-layout.tsx +67 -12
  106. package/src/index.ts +0 -1
  107. package/src/test/data.tsx +0 -165
  108. package/src/test/titan-layout.tsx +34 -0
  109. package/src/utils/navigation.ts +1 -6
  110. package/dist/components/titan-layout/titan-layout.stories.d.ts +0 -29
  111. package/dist/components/titan-layout/titan-layout.stories.d.ts.map +0 -1
  112. package/dist/utils/navigation-legacy.d.ts +0 -88
  113. package/dist/utils/navigation-legacy.d.ts.map +0 -1
  114. package/dist/utils/navigation-legacy.js +0 -3
  115. package/dist/utils/navigation-legacy.js.map +0 -1
  116. package/src/utils/navigation-legacy.ts +0 -106
@@ -3,15 +3,13 @@ import SvgExpandLess from '@servicetitan/anvil2/assets/icons/material/round/expa
3
3
  import SvgExpandMore from '@servicetitan/anvil2/assets/icons/material/round/expand_more.svg';
4
4
  import SvgAccountActive from '@servicetitan/anvil2/assets/icons/st/gnav_account_active.svg';
5
5
  import SvgAccountInactive from '@servicetitan/anvil2/assets/icons/st/gnav_account_inactive.svg';
6
- import { BodyText, Popover, PopoverPropsStrict } from '@servicetitan/design-system';
6
+ import { BodyText, Popover } from '@servicetitan/design-system';
7
7
  import classNames from 'classnames';
8
8
  import {
9
9
  ComponentPropsWithoutRef,
10
10
  FC,
11
- HTMLAttributeAnchorTarget,
12
11
  MouseEvent,
13
12
  MouseEventHandler,
14
- ReactNode,
15
13
  useCallback,
16
14
  useEffect,
17
15
  useMemo,
@@ -23,29 +21,21 @@ import { getCounterTag } from '../../utils/side-nav';
23
21
  import { CounterTag } from '../counter-tag';
24
22
  import { useTitanLayoutContext } from '../titan-layout';
25
23
  import { withTooltip } from '../titan-layout/with-tooltip';
24
+ import {
25
+ ProfileDropdownLinkProps,
26
+ ProfileDropdownProps,
27
+ ProfileDropdownSectionProps,
28
+ ProfileDropdownTriggerProps,
29
+ } from './interface';
26
30
  import * as Styles from './profile-dropdown.module.less';
27
31
 
28
- export interface ProfileDropdownTriggerProps {
29
- className?: string;
30
- info?: { title: string; text: string };
31
- imageSrc?: string | null;
32
- avatarBadge?: boolean | string;
33
- badge?: { content?: number | string; className: string };
34
- hintArrow?: boolean;
35
- open: boolean;
36
- onClick?(e: MouseEvent): void;
37
- }
38
-
39
- const ProfileDropdownTrigger: FC<ProfileDropdownTriggerProps> = ({
40
- avatarBadge,
41
- badge,
42
- className,
43
- hintArrow,
44
- imageSrc,
45
- info,
46
- onClick,
47
- open,
48
- }) => {
32
+ const ProfileDropdownTrigger: FC<
33
+ ProfileDropdownTriggerProps & {
34
+ hintArrow?: boolean;
35
+ open: boolean;
36
+ onClick: ComponentPropsWithoutRef<'div'>['onClick'];
37
+ }
38
+ > = ({ info, imageSrc, avatarBadge, badge, className, hintArrow, open, onClick, ...rest }) => {
49
39
  const [avatarSource, setAvatarSource] = useState(imageSrc ?? '');
50
40
  const [avatarSourceError, setAvatarSourceError] = useState(false);
51
41
 
@@ -66,6 +56,9 @@ const ProfileDropdownTrigger: FC<ProfileDropdownTriggerProps> = ({
66
56
 
67
57
  return (
68
58
  <div
59
+ data-cy="profile-dropdown-trigger"
60
+ data-pendo="profile-dropdown-trigger"
61
+ {...rest}
69
62
  className={classNames(
70
63
  'd-f align-items-center cursor-pointer position-relative p-x-1 p-y-half',
71
64
  'profile-dropdown-trigger',
@@ -76,8 +69,6 @@ const ProfileDropdownTrigger: FC<ProfileDropdownTriggerProps> = ({
76
69
  className
77
70
  )}
78
71
  onClick={onClick}
79
- data-cy="profile-dropdown-trigger"
80
- data-pendo="profile-dropdown-trigger"
81
72
  >
82
73
  {avatarSource && !avatarSourceError ? (
83
74
  <img
@@ -154,25 +145,7 @@ const useTag = (counter?: CounterTagValue, tag?: CounterTagData) =>
154
145
  ) : undefined;
155
146
  }, [counter, tag]);
156
147
 
157
- export type ProfileItemContent =
158
- | { children: string; text?: string }
159
- | { children: ReactNode; text: string };
160
-
161
- export interface ProfileDropdownSectionPropsStrict {
162
- children: ReactNode;
163
- id: string;
164
- tooltip?: string;
165
- className?: string;
166
- tag?: CounterTagData;
167
- counter?: CounterTagValue;
168
- onClick?(e: MouseEvent): void;
169
- }
170
-
171
- export type ProfileDropdownSectionProps = Omit<ComponentPropsWithoutRef<'div'>, 'children'> &
172
- ProfileDropdownSectionPropsStrict &
173
- ProfileItemContent;
174
-
175
- export const ProfileDropdownSection: FC<ProfileDropdownSectionProps> = ({
148
+ function DesktopProfileDropdownSection({
176
149
  children,
177
150
  className,
178
151
  counter,
@@ -182,7 +155,7 @@ export const ProfileDropdownSection: FC<ProfileDropdownSectionProps> = ({
182
155
  tooltip,
183
156
  onClick,
184
157
  ...rest
185
- }) => {
158
+ }: ProfileDropdownSectionProps) {
186
159
  const clickHandler: MouseEventHandler<never> = e => {
187
160
  if (onClick) {
188
161
  onClick(e);
@@ -212,27 +185,11 @@ export const ProfileDropdownSection: FC<ProfileDropdownSectionProps> = ({
212
185
  tooltip,
213
186
  { placement: 'left' }
214
187
  );
215
- };
216
-
217
- export const ProfileDropdownDivider: FC = Popover.Divider;
218
-
219
- export interface ProfileDropdownLinkPropsStrict {
220
- id: string;
221
- children: ReactNode;
222
- className?: string;
223
- external?: boolean;
224
- target?: HTMLAttributeAnchorTarget;
225
- tooltip?: string;
226
- to: string;
227
- tag?: CounterTagData;
228
- counter?: CounterTagValue;
229
188
  }
230
189
 
231
- export type ProfileDropdownLinkProps = Omit<ComponentPropsWithoutRef<'a'>, 'children'> &
232
- ProfileDropdownLinkPropsStrict &
233
- ProfileItemContent;
190
+ const DesktopProfileDropdownDivider: FC = Popover.Divider;
234
191
 
235
- export const ProfileDropdownLink: FC<ProfileDropdownLinkProps> = ({
192
+ function DesktopProfileDropdownLink({
236
193
  children,
237
194
  className,
238
195
  external,
@@ -245,7 +202,7 @@ export const ProfileDropdownLink: FC<ProfileDropdownLinkProps> = ({
245
202
  tooltip,
246
203
  onClick,
247
204
  ...rest
248
- }: ProfileDropdownLinkProps) => {
205
+ }: ProfileDropdownLinkProps) {
249
206
  const { NavigationComponent } = useTitanLayoutContext();
250
207
 
251
208
  const isExternalLink = external ?? to?.startsWith('http');
@@ -291,47 +248,21 @@ export const ProfileDropdownLink: FC<ProfileDropdownLinkProps> = ({
291
248
  tooltip,
292
249
  { placement: 'left' }
293
250
  );
294
- };
295
-
296
- export interface ProfileDropdownPropsStrict {
297
- children?: ReactNode;
298
- className?: string;
299
- direction?: PopoverPropsStrict['direction'];
300
- trigger?: Omit<ProfileDropdownTriggerProps, 'onClick' | 'open' | 'hintArrow'>;
301
- hintPopup?: {
302
- className?: string;
303
- content: FC<{ openProfile(): void }>;
304
- width?: PopoverPropsStrict['width'];
305
- onClose?: () => void;
306
- };
307
- portal?: boolean;
308
- width?: PopoverPropsStrict['width'];
309
- onClose?(): void;
310
- onOpen?(): void;
311
251
  }
312
252
 
313
- export interface ProfileDropdownProps extends ProfileDropdownPropsStrict {
314
- [key: string]: any;
315
- }
316
-
317
- export interface ProfileDropdownType extends FC<ProfileDropdownProps> {
318
- Divider: typeof ProfileDropdownDivider;
319
- Link: typeof ProfileDropdownLink;
320
- Trigger: typeof ProfileDropdownTrigger;
321
- Section: typeof ProfileDropdownSection;
322
- }
323
-
324
- export const ProfileDropdown: ProfileDropdownType = (({
253
+ function DesktopProfileDropdownComponent({
325
254
  children,
326
- className,
255
+
327
256
  direction,
257
+ trigger,
328
258
  hintPopup,
329
- onClose,
330
- onOpen,
331
259
  portal,
332
- trigger,
333
260
  width,
334
- }) => {
261
+ onClose,
262
+ onOpen,
263
+
264
+ ...rest
265
+ }: ProfileDropdownProps) {
335
266
  const [open, setOpen] = useState(false);
336
267
  const handleClose = useCallback(() => {
337
268
  setOpen(false);
@@ -367,7 +298,7 @@ export const ProfileDropdown: ProfileDropdownType = (({
367
298
  );
368
299
 
369
300
  return (
370
- <div className={className} data-cy="profile-dropdown">
301
+ <div data-cy="profile-dropdown" {...rest}>
371
302
  {!!hintPopup && hintShown && HintComponent ? (
372
303
  <Popover
373
304
  direction={direction ?? 'bl'}
@@ -406,8 +337,10 @@ export const ProfileDropdown: ProfileDropdownType = (({
406
337
  )}
407
338
  </div>
408
339
  );
409
- }) as ProfileDropdownType;
340
+ }
410
341
 
411
- ProfileDropdown.Divider = ProfileDropdownDivider;
412
- ProfileDropdown.Link = ProfileDropdownLink;
413
- ProfileDropdown.Section = ProfileDropdownSection;
342
+ export const DesktopProfileDropdown = Object.assign(DesktopProfileDropdownComponent, {
343
+ Divider: DesktopProfileDropdownDivider,
344
+ Link: DesktopProfileDropdownLink,
345
+ Section: DesktopProfileDropdownSection,
346
+ });
@@ -1,6 +1,19 @@
1
+ import { IconProps } from '@servicetitan/anvil2';
1
2
  import { FC } from 'react';
3
+ import { CounterTagData } from '../../utils/counter-tag';
2
4
  import { NavLinkComponentProps } from '../../utils/navigation-context';
3
5
 
4
6
  export interface NavigationComponentProps {
5
7
  navigationComponent: FC<NavLinkComponentProps>;
6
8
  }
9
+ export interface NavigationItemPropsStrict {
10
+ id: string;
11
+ to: string;
12
+ title: string;
13
+ isActive: boolean | ((pathname: string) => boolean) | undefined;
14
+ icon: IconProps['svg'] | undefined;
15
+ iconActive: IconProps['svg'] | undefined;
16
+
17
+ tag: CounterTagData | undefined;
18
+ className: string | undefined;
19
+ }
@@ -1,5 +1,6 @@
1
+ import { IconProps } from '@servicetitan/anvil2';
1
2
  import { ComponentPropsWithoutRef, FC, ReactNode } from 'react';
2
- import { NavigationItemData } from '../../utils/navigation';
3
+ import { CounterTagData, CounterTagValue } from '../../utils/counter-tag';
3
4
  import { TitanLayoutSidebarContextType } from './layout-context';
4
5
 
5
6
  export interface TitanLayoutLinkWrapperProps {
@@ -11,20 +12,76 @@ export interface TitanLayoutLinkWrapperProps {
11
12
  export type TitanLayoutLinkWrapper = FC<TitanLayoutLinkWrapperProps>;
12
13
 
13
14
  export interface TitanLayoutState {
15
+ /** flags if side nav is collapsed */
14
16
  navCollapsed: boolean;
15
- submenuExpanded?: string;
17
+ /** ;ost expanded submenu ids */
18
+ submenusExpanded?: string[];
16
19
  }
17
20
 
18
- export type TitanLayoutLinkProps = Omit<NavigationItemData, 'submenu' | 'isHidden'> & {
21
+ export interface TitanLayoutLinkExtraProps {
22
+ /** link's title should be shown (for extra links we show icon only by default) */
23
+ showTitle?: boolean;
24
+ /** link is flashing */
25
+ flashing?: boolean;
26
+ }
27
+
28
+ export interface TitanLayoutLinkSideProps {
29
+ /** counter value used only for side links */
30
+ counter: CounterTagValue;
31
+ }
32
+
33
+ export type TitanLayoutLinkProps = {
34
+ /** link id */
35
+ id: string;
36
+ /** link href */
37
+ to: string;
38
+ /** link title */
39
+ title: string;
40
+ /** callback to return active state. By default, it compares link href with current pathname */
41
+ isActive?: boolean | ((pathname: string) => boolean);
42
+ /** svg icon (anvil2) of inactive item */
43
+ icon: IconProps['svg'] | undefined;
44
+ /** svg icon (anvil2) of active item */
45
+ iconActive: IconProps['svg'] | undefined;
46
+ /** item tag (optional). shown if it is set and value is true or greater than 0 */
47
+ tag?: CounterTagData;
48
+ counter?: CounterTagValue;
49
+ /** class name of link item */
50
+ className?: string;
51
+
52
+ /** tooltip text (for extra links) */
19
53
  tooltip?: string;
54
+ /** wrapper component for link element (used for side links) */
20
55
  wrapper?: TitanLayoutLinkWrapper;
56
+ /** props for extra link element */
57
+ extra?: TitanLayoutLinkExtraProps;
58
+ /** props for side nav link element (mobile version) */
59
+ side?: TitanLayoutLinkSideProps;
21
60
  } & Omit<ComponentPropsWithoutRef<'a'>, 'children' | 'title'>;
22
61
 
23
- export type TitanLayoutTriggerProps = Omit<
24
- NavigationItemData,
25
- 'to' | 'isActive' | 'isHidden' | 'submenu'
26
- > & {
62
+ export type TitanLayoutTriggerProps = {
63
+ /** link id */
64
+ id: string;
65
+ /** link title */
66
+ title: string;
67
+ /** active state */
27
68
  isActive?: boolean;
69
+ /** svg icon (anvil2) of inactive item */
70
+ icon: IconProps['svg'] | undefined;
71
+ /** svg icon (anvil2) of active item */
72
+ iconActive: IconProps['svg'] | undefined;
73
+ /** item tag (optional). shown if it is set and value is true or greater than 0 */
74
+ tag?: CounterTagData;
75
+ counter?: CounterTagValue;
76
+ /** class name of link item */
77
+ className?: string;
78
+
79
+ /** tooltip text (for extra links) */
28
80
  tooltip?: string;
81
+ /** wrapper component for link element (used for side links) */
29
82
  wrapper?: TitanLayoutLinkWrapper;
83
+ /** props for extra link element */
84
+ extra?: TitanLayoutLinkExtraProps;
85
+ /** props for nav link element (mobile version) */
86
+ side?: TitanLayoutLinkSideProps;
30
87
  } & Omit<ComponentPropsWithoutRef<'div'>, 'children' | 'title'>;
@@ -3,6 +3,7 @@ import SvgMoreVert from '@servicetitan/anvil2/assets/icons/material/round/more_v
3
3
  import classNames from 'classnames';
4
4
  import { FC, useCallback, useEffect, useRef, useState } from 'react';
5
5
  import { NavigationItemData } from '../../utils/navigation';
6
+ import { getCounterTag } from '../../utils/side-nav';
6
7
  import { NavigationComponentProps } from './interface-internal';
7
8
  import { useTitanLayoutContext } from './layout-context';
8
9
  import { LayoutHeader, LayoutHeaderProps } from './layout-header';
@@ -34,7 +35,6 @@ export const LayoutHeaderDark: FC<LayoutHeaderStackedProps> = ({
34
35
  navigationMainItems,
35
36
  navigationOverflowItems,
36
37
  hasNotifications,
37
- onBurgerClick,
38
38
  logo,
39
39
  profile,
40
40
  right,
@@ -42,6 +42,8 @@ export const LayoutHeaderDark: FC<LayoutHeaderStackedProps> = ({
42
42
  rightClassName,
43
43
  center,
44
44
  centerClassName,
45
+ hasBurger,
46
+ onBurgerClick,
45
47
  ...rest
46
48
  }) => {
47
49
  return center ? (
@@ -62,6 +64,7 @@ export const LayoutHeaderDark: FC<LayoutHeaderStackedProps> = ({
62
64
  logo={logo}
63
65
  profile={profile}
64
66
  onBurgerClick={onBurgerClick}
67
+ hasBurger={hasBurger}
65
68
  data-cy="header-navigation-top"
66
69
  />
67
70
 
@@ -94,6 +97,7 @@ export const LayoutHeaderDark: FC<LayoutHeaderStackedProps> = ({
94
97
  logo={logo}
95
98
  profile={profile}
96
99
  onBurgerClick={onBurgerClick}
100
+ hasBurger={hasBurger}
97
101
  {...rest}
98
102
  />
99
103
  );
@@ -155,8 +159,14 @@ const LayoutHeaderNav: FC<LayoutHeaderNavProps> = ({ className, mainItems, overf
155
159
  {mainItems?.map(item =>
156
160
  withTooltip(
157
161
  <InternalLayoutHeaderNavigationLink
158
- {...item}
159
- label={isMinimized ? undefined : item.title}
162
+ id={item.id}
163
+ to={item.to}
164
+ title={isMinimized ? undefined : item.title}
165
+ isActive={item.isActive}
166
+ icon={item.icon}
167
+ iconActive={item.iconActive}
168
+ tag={getCounterTag(item.counter, item.tag)}
169
+ className={item.className}
160
170
  key={item.id}
161
171
  navigationComponent={NavigationComponent}
162
172
  />,
@@ -195,8 +205,14 @@ const LayoutHeaderNavOverflow: FC<
195
205
  <div data-cy="navigation-overflow-content" className={Styles.headerNavigationOverflow}>
196
206
  {items.map(item => (
197
207
  <InternalLayoutHeaderNavigationLink
198
- {...item}
199
- label={item.title}
208
+ id={item.id}
209
+ to={item.to}
210
+ title={item.title}
211
+ isActive={item.isActive}
212
+ icon={item.icon}
213
+ iconActive={item.iconActive}
214
+ tag={getCounterTag(item.counter, item.tag)}
215
+ className={item.className}
200
216
  key={item.id}
201
217
  navigationComponent={navigationComponent}
202
218
  isOverflow
@@ -1,13 +1,8 @@
1
1
  import { Icon, IconProps } from '@servicetitan/anvil2';
2
2
  import classNames from 'classnames';
3
3
  import { FC, Fragment } from 'react';
4
- import {
5
- HeaderNavigationLinkProps,
6
- HeaderNavigationTriggerProps,
7
- } from '../../utils/navigation-legacy';
8
- import { getCounterTag } from '../../utils/side-nav';
4
+ import { CounterTagData } from '../../utils/counter-tag';
9
5
  import { CounterTag, CounterTagProps } from '../counter-tag';
10
- // use v1 tooltips due to bug with v2 in monolith
11
6
  import { NavigationComponentProps } from './interface-internal';
12
7
  import * as Styles from './layout-header.module.less';
13
8
 
@@ -17,9 +12,8 @@ const InternalHeaderNavigationItemContent: FC<{
17
12
  counterClassName?: string;
18
13
  icon: IconProps['svg'] | undefined;
19
14
  iconActive?: IconProps['svg'];
20
- label?: string;
21
- labelClassName?: string;
22
- }> = ({ counterClassName, icon, iconActive, label, labelClassName, tag }) => {
15
+ title?: string;
16
+ }> = ({ counterClassName, icon, iconActive, title, tag }) => {
23
17
  return (
24
18
  <Fragment>
25
19
  {!!icon && <Icon svg={icon} className={Styles.navigationIcon} />}
@@ -30,12 +24,9 @@ const InternalHeaderNavigationItemContent: FC<{
30
24
  />
31
25
  )}
32
26
 
33
- {!!label && (
34
- <span
35
- className={classNames(Styles.navigationItemLabel, labelClassName)}
36
- data-cy="nav-item-label"
37
- >
38
- {label}
27
+ {!!title && (
28
+ <span className={Styles.navigationItemLabel} data-cy="nav-item-label">
29
+ {title}
39
30
  </span>
40
31
  )}
41
32
 
@@ -52,26 +43,30 @@ const InternalHeaderNavigationItemContent: FC<{
52
43
 
53
44
  /** Navigation extra item with link */
54
45
  export const InternalLayoutHeaderNavigationLink: FC<
55
- HeaderNavigationLinkProps & NavigationComponentProps & { isOverflow?: boolean }
46
+ NavigationComponentProps & {
47
+ id: string;
48
+ to: string;
49
+ title: string | undefined;
50
+ isActive: boolean | ((pathname: string) => boolean) | undefined;
51
+ icon: IconProps['svg'] | undefined;
52
+ iconActive: IconProps['svg'] | undefined;
53
+ tag: CounterTagData | undefined;
54
+ className: string | undefined;
55
+
56
+ isOverflow?: boolean;
57
+ flashing?: boolean;
58
+ }
56
59
  > = ({
57
60
  id,
58
61
  to,
59
- hint,
60
- tooltip,
61
- className,
62
- counter,
62
+ title,
63
+ isActive,
63
64
  icon,
64
65
  iconActive,
65
- iconClassName,
66
- iconName,
67
- iconComponent,
68
- isActive,
69
- isOverflow,
70
- label,
71
- labelClassName,
72
66
  tag,
73
- target,
74
- title,
67
+ className,
68
+ isOverflow,
69
+ flashing,
75
70
  navigationComponent: NavigationComponent,
76
71
  ...rest
77
72
  }) => {
@@ -88,63 +83,55 @@ export const InternalLayoutHeaderNavigationLink: FC<
88
83
  {
89
84
  [Styles.navigationItemActive]: isActive === true,
90
85
  [Styles.navigationItemIconState]: !!icon && !!iconActive,
86
+ [Styles.navigationItemFlashing]: flashing,
91
87
  }
92
88
  )}
93
89
  isActive={typeof isActive === 'function' ? isActive : undefined}
94
90
  activeClassName={Styles.navigationItemActive}
95
- target={target}
96
91
  >
97
92
  <InternalHeaderNavigationItemContent
98
- tag={getCounterTag(counter, tag)}
93
+ tag={tag}
99
94
  icon={icon}
100
95
  iconActive={iconActive}
101
- label={label}
102
- labelClassName={labelClassName}
96
+ title={title}
103
97
  />
104
98
  </NavigationComponent>
105
99
  );
106
100
  };
107
101
 
108
102
  /** Navigation extra item with icon button */
109
- export const InternalLayoutHeaderNavigationTrigger: FC<HeaderNavigationTriggerProps> = ({
110
- id,
111
- className,
112
- counter,
113
- icon,
114
- iconActive,
115
- iconName,
116
- isActive,
117
- hint,
118
- label,
119
- labelClassName,
120
- tag,
121
- tooltip,
122
- title,
123
- titleClassName,
124
- ...rest
125
- }) => {
103
+ export const InternalLayoutHeaderNavigationTrigger: FC<{
104
+ id: string;
105
+ title: string | undefined;
106
+ isActive: boolean | undefined;
107
+ icon: IconProps['svg'] | undefined;
108
+ iconActive: IconProps['svg'] | undefined;
109
+ tag: CounterTagData | undefined;
110
+ className: string | undefined;
111
+
112
+ flashing?: boolean;
113
+ }> = ({ id, className, flashing, icon, iconActive, isActive, tag, title, ...rest }) => {
126
114
  return (
127
115
  <div
128
116
  data-cy={`navigation-trigger-${id}`}
129
117
  data-pendo={`navigation-trigger-${id}`}
130
118
  {...rest}
131
- title={hint}
132
119
  className={classNames(
133
120
  Styles.navigationLink,
134
121
  {
135
122
  [Styles.navigationItemActive]: isActive === true,
136
123
  [Styles.navigationItemIconState]: !!icon && !!iconActive,
124
+ [Styles.navigationItemFlashing]: flashing,
137
125
  },
138
126
  'cursor-pointer',
139
127
  className
140
128
  )}
141
129
  >
142
130
  <InternalHeaderNavigationItemContent
143
- tag={getCounterTag(counter, tag)}
131
+ tag={tag}
144
132
  icon={icon}
145
133
  iconActive={iconActive}
146
- label={label}
147
- labelClassName={labelClassName}
134
+ title={title}
148
135
  />
149
136
  </div>
150
137
  );
@@ -1,4 +1,4 @@
1
- import { FC } from 'react';
1
+ import { getCounterTag } from '../../utils/side-nav';
2
2
  import { TitanLayoutLinkProps, TitanLayoutTriggerProps } from './interface';
3
3
  import { useTitanLayoutContext } from './layout-context';
4
4
  import {
@@ -8,19 +8,75 @@ import {
8
8
  import { withTooltip } from './with-tooltip';
9
9
 
10
10
  /** Navigation extra item with link */
11
- export const LayoutHeaderNavigationLink: FC<TitanLayoutLinkProps> = ({ tooltip, ...rest }) => {
11
+ export function LayoutHeaderNavigationLink({
12
+ id,
13
+ to,
14
+ title,
15
+ isActive,
16
+ icon,
17
+ iconActive,
18
+ counter,
19
+ tag,
20
+ className,
21
+
22
+ tooltip,
23
+ extra,
24
+ side,
25
+ wrapper,
26
+ ...rest
27
+ }: TitanLayoutLinkProps) {
12
28
  const { NavigationComponent } = useTitanLayoutContext();
29
+ const { showTitle, flashing } = extra ?? {};
13
30
 
14
31
  return withTooltip(
15
- <InternalLayoutHeaderNavigationLink {...rest} navigationComponent={NavigationComponent} />,
32
+ <InternalLayoutHeaderNavigationLink
33
+ id={id}
34
+ to={to}
35
+ title={showTitle ? title : undefined}
36
+ isActive={isActive}
37
+ icon={icon}
38
+ iconActive={iconActive}
39
+ tag={getCounterTag(counter, tag)}
40
+ className={className}
41
+ {...rest}
42
+ flashing={flashing}
43
+ navigationComponent={NavigationComponent}
44
+ />,
16
45
  tooltip
17
46
  );
18
- };
47
+ }
19
48
 
20
49
  /** Navigation extra item with icon button */
21
- export const LayoutHeaderNavigationTrigger: FC<TitanLayoutTriggerProps> = ({
50
+ export function LayoutHeaderNavigationTrigger({
51
+ id,
52
+ title,
53
+ isActive,
54
+ icon,
55
+ iconActive,
56
+ counter,
57
+ tag,
58
+ className,
59
+
22
60
  tooltip,
61
+ extra,
62
+ side,
63
+ wrapper,
23
64
  ...rest
24
- }) => {
25
- return withTooltip(<InternalLayoutHeaderNavigationTrigger {...rest} />, tooltip);
26
- };
65
+ }: TitanLayoutTriggerProps) {
66
+ const { showTitle, flashing } = extra ?? {};
67
+
68
+ return withTooltip(
69
+ <InternalLayoutHeaderNavigationTrigger
70
+ id={id}
71
+ title={showTitle ? title : undefined}
72
+ isActive={isActive}
73
+ icon={icon}
74
+ iconActive={iconActive}
75
+ tag={getCounterTag(counter, tag)}
76
+ className={className}
77
+ {...rest}
78
+ flashing={flashing}
79
+ />,
80
+ tooltip
81
+ );
82
+ }