@servicetitan/navigation 10.7.0 → 11.0.0-canary.237.4786284.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 (149) hide show
  1. package/dist/components/header-navigation/header-navigation-extra.stories.d.ts.map +1 -1
  2. package/dist/components/header-navigation/header-navigation-extra.stories.js +5 -5
  3. package/dist/components/header-navigation/header-navigation-extra.stories.js.map +1 -1
  4. package/dist/components/header-navigation/header-navigation-links.d.ts.map +1 -1
  5. package/dist/components/header-navigation/header-navigation-links.js +2 -2
  6. package/dist/components/header-navigation/header-navigation-links.js.map +1 -1
  7. package/dist/components/header-navigation/header-navigation-stacked.stories.d.ts.map +1 -1
  8. package/dist/components/header-navigation/header-navigation-stacked.stories.js +1 -1
  9. package/dist/components/header-navigation/header-navigation-stacked.stories.js.map +1 -1
  10. package/dist/components/header-navigation/header-navigation.stories.d.ts.map +1 -1
  11. package/dist/components/header-navigation/header-navigation.stories.js +2 -2
  12. package/dist/components/header-navigation/header-navigation.stories.js.map +1 -1
  13. package/dist/components/header-navigation/with-tooltip.d.ts +1 -1
  14. package/dist/components/header-navigation/with-tooltip.d.ts.map +1 -1
  15. package/dist/components/left-navigation/header-navigation-tiny.stories.d.ts.map +1 -1
  16. package/dist/components/left-navigation/header-navigation-tiny.stories.js +2 -2
  17. package/dist/components/left-navigation/header-navigation-tiny.stories.js.map +1 -1
  18. package/dist/components/links.d.ts.map +1 -1
  19. package/dist/components/links.js +7 -7
  20. package/dist/components/links.js.map +1 -1
  21. package/dist/components/logo/logo-company-title.d.ts +1 -0
  22. package/dist/components/logo/logo-company-title.d.ts.map +1 -1
  23. package/dist/components/logo/logo-company-title.js +2 -2
  24. package/dist/components/logo/logo-company-title.js.map +1 -1
  25. package/dist/components/profile-dropdown/profile-dropdown.d.ts +15 -9
  26. package/dist/components/profile-dropdown/profile-dropdown.d.ts.map +1 -1
  27. package/dist/components/profile-dropdown/profile-dropdown.js +7 -8
  28. package/dist/components/profile-dropdown/profile-dropdown.js.map +1 -1
  29. package/dist/components/profile-dropdown/profile-dropdown.module.less +4 -0
  30. package/dist/components/profile-dropdown/profile-dropdown.stories.js +2 -2
  31. package/dist/components/profile-dropdown/profile-dropdown.stories.js.map +1 -1
  32. package/dist/components/titan-layout/index.d.ts +6 -0
  33. package/dist/components/titan-layout/index.d.ts.map +1 -0
  34. package/dist/components/titan-layout/index.js +6 -0
  35. package/dist/components/titan-layout/index.js.map +1 -0
  36. package/dist/components/titan-layout/interface-internal.d.ts +6 -0
  37. package/dist/components/titan-layout/interface-internal.d.ts.map +1 -0
  38. package/dist/components/titan-layout/interface-internal.js +2 -0
  39. package/dist/components/titan-layout/interface-internal.js.map +1 -0
  40. package/dist/components/titan-layout/interface.d.ts +21 -0
  41. package/dist/components/titan-layout/interface.d.ts.map +1 -0
  42. package/dist/components/titan-layout/interface.js +2 -0
  43. package/dist/components/titan-layout/interface.js.map +1 -0
  44. package/dist/components/titan-layout/layout-context.d.ts +20 -0
  45. package/dist/components/titan-layout/layout-context.d.ts.map +1 -0
  46. package/dist/components/titan-layout/layout-context.js +12 -0
  47. package/dist/components/titan-layout/layout-context.js.map +1 -0
  48. package/dist/components/titan-layout/layout-header-links.d.ts +7 -0
  49. package/dist/components/titan-layout/layout-header-links.d.ts.map +1 -0
  50. package/dist/components/titan-layout/layout-header-links.js +32 -0
  51. package/dist/components/titan-layout/layout-header-links.js.map +1 -0
  52. package/dist/components/titan-layout/layout-header.d.ts +20 -0
  53. package/dist/components/titan-layout/layout-header.d.ts.map +1 -0
  54. package/dist/components/titan-layout/layout-header.js +11 -0
  55. package/dist/components/titan-layout/layout-header.js.map +1 -0
  56. package/dist/components/titan-layout/layout-header.module.less +174 -0
  57. package/dist/components/titan-layout/layout-logo.d.ts +12 -0
  58. package/dist/components/titan-layout/layout-logo.d.ts.map +1 -0
  59. package/dist/components/titan-layout/layout-logo.js +15 -0
  60. package/dist/components/titan-layout/layout-logo.js.map +1 -0
  61. package/dist/components/titan-layout/layout-logo.stories.d.ts +13 -0
  62. package/dist/components/titan-layout/layout-logo.stories.d.ts.map +1 -0
  63. package/dist/components/titan-layout/layout-logo.stories.js +17 -0
  64. package/dist/components/titan-layout/layout-logo.stories.js.map +1 -0
  65. package/dist/components/titan-layout/layout-profile.d.ts +9 -0
  66. package/dist/components/titan-layout/layout-profile.d.ts.map +1 -0
  67. package/dist/components/titan-layout/layout-profile.js +54 -0
  68. package/dist/components/titan-layout/layout-profile.js.map +1 -0
  69. package/dist/components/titan-layout/layout-profile.stories.d.ts +13 -0
  70. package/dist/components/titan-layout/layout-profile.stories.d.ts.map +1 -0
  71. package/dist/components/titan-layout/layout-profile.stories.js +13 -0
  72. package/dist/components/titan-layout/layout-profile.stories.js.map +1 -0
  73. package/dist/components/titan-layout/layout-sidebar-links-internal.d.ts +46 -0
  74. package/dist/components/titan-layout/layout-sidebar-links-internal.d.ts.map +1 -0
  75. package/dist/components/titan-layout/layout-sidebar-links-internal.js +61 -0
  76. package/dist/components/titan-layout/layout-sidebar-links-internal.js.map +1 -0
  77. package/dist/components/titan-layout/layout-sidebar-links.d.ts +6 -0
  78. package/dist/components/titan-layout/layout-sidebar-links.d.ts.map +1 -0
  79. package/dist/components/titan-layout/layout-sidebar-links.js +21 -0
  80. package/dist/components/titan-layout/layout-sidebar-links.js.map +1 -0
  81. package/dist/components/titan-layout/layout-sidebar.d.ts +17 -0
  82. package/dist/components/titan-layout/layout-sidebar.d.ts.map +1 -0
  83. package/dist/components/titan-layout/layout-sidebar.js +65 -0
  84. package/dist/components/titan-layout/layout-sidebar.js.map +1 -0
  85. package/dist/components/titan-layout/layout-sidebar.module.less +516 -0
  86. package/dist/components/titan-layout/titan-layout.d.ts +38 -0
  87. package/dist/components/titan-layout/titan-layout.d.ts.map +1 -0
  88. package/dist/components/titan-layout/titan-layout.js +143 -0
  89. package/dist/components/titan-layout/titan-layout.js.map +1 -0
  90. package/dist/components/titan-layout/titan-layout.module.less +116 -0
  91. package/dist/components/titan-layout/titan-layout.stories.d.ts +20 -0
  92. package/dist/components/titan-layout/titan-layout.stories.d.ts.map +1 -0
  93. package/dist/components/titan-layout/titan-layout.stories.js +80 -0
  94. package/dist/components/titan-layout/titan-layout.stories.js.map +1 -0
  95. package/dist/components/titan-layout/with-tooltip.d.ts +4 -0
  96. package/dist/components/titan-layout/with-tooltip.d.ts.map +1 -0
  97. package/dist/components/titan-layout/with-tooltip.js +4 -0
  98. package/dist/components/titan-layout/with-tooltip.js.map +1 -0
  99. package/dist/index.d.ts +2 -1
  100. package/dist/index.d.ts.map +1 -1
  101. package/dist/index.js +2 -1
  102. package/dist/index.js.map +1 -1
  103. package/dist/test/data.d.ts.map +1 -1
  104. package/dist/test/data.js +3 -3
  105. package/dist/test/data.js.map +1 -1
  106. package/dist/utils/navigation-legacy.d.ts +3 -1
  107. package/dist/utils/navigation-legacy.d.ts.map +1 -1
  108. package/dist/utils/use-breakpoint.d.ts +7 -0
  109. package/dist/utils/use-breakpoint.d.ts.map +1 -0
  110. package/dist/utils/use-breakpoint.js +13 -0
  111. package/dist/utils/use-breakpoint.js.map +1 -0
  112. package/package.json +5 -6
  113. package/src/components/header-navigation/header-navigation-extra.stories.tsx +7 -0
  114. package/src/components/header-navigation/header-navigation-links.tsx +2 -0
  115. package/src/components/header-navigation/header-navigation-stacked.stories.tsx +5 -1
  116. package/src/components/header-navigation/header-navigation.stories.tsx +6 -1
  117. package/src/components/left-navigation/header-navigation-tiny.stories.tsx +8 -2
  118. package/src/components/left-navigation/side-navigation-links.tsx +1 -1
  119. package/src/components/links.tsx +33 -13
  120. package/src/components/logo/logo-company-title.tsx +8 -6
  121. package/src/components/profile-dropdown/profile-dropdown.module.less +4 -0
  122. package/src/components/profile-dropdown/profile-dropdown.stories.tsx +4 -4
  123. package/src/components/profile-dropdown/profile-dropdown.tsx +55 -51
  124. package/src/components/titan-layout/index.ts +5 -0
  125. package/src/components/titan-layout/interface-internal.ts +6 -0
  126. package/src/components/titan-layout/interface.ts +26 -0
  127. package/src/components/titan-layout/layout-context.tsx +30 -0
  128. package/src/components/titan-layout/layout-header-links.tsx +144 -0
  129. package/src/components/titan-layout/layout-header.module.less +174 -0
  130. package/src/components/titan-layout/layout-header.module.less.d.ts +16 -0
  131. package/src/components/titan-layout/layout-header.tsx +90 -0
  132. package/src/components/titan-layout/layout-logo.stories.tsx +31 -0
  133. package/src/components/titan-layout/layout-logo.tsx +57 -0
  134. package/src/components/titan-layout/layout-profile.stories.tsx +46 -0
  135. package/src/components/titan-layout/layout-profile.tsx +132 -0
  136. package/src/components/titan-layout/layout-sidebar-links-internal.tsx +275 -0
  137. package/src/components/titan-layout/layout-sidebar-links.tsx +59 -0
  138. package/src/components/titan-layout/layout-sidebar.module.less +516 -0
  139. package/src/components/titan-layout/layout-sidebar.module.less.d.ts +48 -0
  140. package/src/components/titan-layout/layout-sidebar.tsx +295 -0
  141. package/src/components/titan-layout/titan-layout.module.less +116 -0
  142. package/src/components/titan-layout/titan-layout.module.less.d.ts +16 -0
  143. package/src/components/titan-layout/titan-layout.stories.tsx +332 -0
  144. package/src/components/titan-layout/titan-layout.tsx +355 -0
  145. package/src/components/titan-layout/with-tooltip.tsx +16 -0
  146. package/src/index.ts +2 -1
  147. package/src/test/data.tsx +3 -2
  148. package/src/utils/navigation-legacy.ts +3 -1
  149. package/src/utils/use-breakpoint.ts +19 -0
@@ -64,6 +64,7 @@ const HelpCenterButton = () => {
64
64
  trigger={
65
65
  <HeaderNavigationTrigger
66
66
  id="help"
67
+ title="Help"
67
68
  iconName="help_outline"
68
69
  onClick={() => setOpen(true)}
69
70
  icon={SvgIcon}
@@ -107,6 +108,7 @@ export const WithAllMonolithData = () => (
107
108
 
108
109
  <HeaderNavigationTrigger
109
110
  id="dialpad"
111
+ title="Dialpad"
110
112
  iconName="phone"
111
113
  counter={2}
112
114
  icon={SvgIcon}
@@ -115,6 +117,7 @@ export const WithAllMonolithData = () => (
115
117
 
116
118
  <HeaderNavigationLink
117
119
  id="search"
120
+ title="Search"
118
121
  to="https://google.com"
119
122
  target="_blank"
120
123
  iconComponent={SearchIcon}
@@ -126,6 +129,7 @@ export const WithAllMonolithData = () => (
126
129
  <HelpCenterButton />
127
130
  <HeaderNavigationTrigger
128
131
  id="titanAdvisor"
132
+ title="Titan Advisor"
129
133
  iconName="rocket"
130
134
  iconClassName={Styles.rocketIcon}
131
135
  icon={SvgIcon}
@@ -134,6 +138,7 @@ export const WithAllMonolithData = () => (
134
138
 
135
139
  <HeaderNavigationLink
136
140
  id="settings"
141
+ title="Settings"
137
142
  to="https://google.com"
138
143
  target="_blank"
139
144
  iconName="settings"
@@ -149,7 +154,7 @@ export const WithAllMonolithData = () => (
149
154
  Task Management
150
155
  </ProfileDropdown.Link>
151
156
  <ProfileDropdown.Divider />
152
- <ProfileDropdown.Link id="sign-out" to="https://googgle.com">
157
+ <ProfileDropdown.Link id="sign-out" to="https://googgle.com" text="Sign Out">
153
158
  Sign Out <span className="c-neutral-100 m-l-half t-truncate">James Bond</span>
154
159
  </ProfileDropdown.Link>
155
160
  <ProfileDropdown.Section id="userid" className="c-neutral-100 fs-1">
@@ -54,6 +54,7 @@ export const WithAllMonolithData = () => (
54
54
 
55
55
  <HeaderNavigationLink
56
56
  id="search"
57
+ title="Search"
57
58
  to="https://google.com"
58
59
  target="_blank"
59
60
  iconComponent={SearchIcon}
@@ -67,6 +68,7 @@ export const WithAllMonolithData = () => (
67
68
 
68
69
  <HeaderNavigationLink
69
70
  id="titanAdvisor"
71
+ title="Titan Advisor"
70
72
  to="titanAdvisor"
71
73
  iconName="rocket"
72
74
  iconClassName={Styles.rocketIcon}
@@ -76,6 +78,7 @@ export const WithAllMonolithData = () => (
76
78
 
77
79
  <HeaderNavigationLink
78
80
  id="settings"
81
+ title="Settings"
79
82
  to="settings"
80
83
  target="_blank"
81
84
  iconName="settings"
@@ -90,7 +93,7 @@ export const WithAllMonolithData = () => (
90
93
  Task Management
91
94
  </ProfileDropdown.Link>
92
95
  <ProfileDropdown.Divider />
93
- <ProfileDropdown.Link id="sign-out" to="https://googgle.com">
96
+ <ProfileDropdown.Link id="sign-out" to="https://googgle.com" text="Sign Out">
94
97
  Sign Out{' '}
95
98
  <span className="c-neutral-100 m-l-half t-truncate">James Bond</span>
96
99
  </ProfileDropdown.Link>
@@ -121,6 +124,7 @@ export const WithAllMonolithDataCommercial = () => (
121
124
 
122
125
  <HeaderNavigationLink
123
126
  id="search"
127
+ title="Search"
124
128
  to="https://google.com"
125
129
  target="_blank"
126
130
  iconComponent={SearchIcon}
@@ -133,6 +137,7 @@ export const WithAllMonolithDataCommercial = () => (
133
137
 
134
138
  <HeaderNavigationLink
135
139
  id="titanAdvisor"
140
+ title="Titan Advisor"
136
141
  to="titanAdvisor"
137
142
  iconName="rocket"
138
143
  iconClassName={Styles.rocketIcon}
@@ -142,6 +147,7 @@ export const WithAllMonolithDataCommercial = () => (
142
147
 
143
148
  <HeaderNavigationLink
144
149
  id="settings"
150
+ title="Settings"
145
151
  to="settings"
146
152
  iconName="settings"
147
153
  aria-label="search"
@@ -156,7 +162,7 @@ export const WithAllMonolithDataCommercial = () => (
156
162
  Task Management
157
163
  </ProfileDropdown.Link>
158
164
  <ProfileDropdown.Divider />
159
- <ProfileDropdown.Link id="sign-out" to="https://googgle.com">
165
+ <ProfileDropdown.Link id="sign-out" to="https://googgle.com" text="Sign Out">
160
166
  Sign Out{' '}
161
167
  <span className="c-neutral-100 m-l-half t-truncate">James Bond</span>
162
168
  </ProfileDropdown.Link>
@@ -11,7 +11,7 @@ import {
11
11
  } from './side-navigation-links-internal';
12
12
 
13
13
  const WrappedLink: FC<{
14
- children: ReactElement;
14
+ children: ReactElement<any>;
15
15
  wrapper: NonNullable<SideNavigationLinkProps['wrapper']>;
16
16
  }> = ({ children, wrapper: WrapperComponent }) => {
17
17
  return (
@@ -1,5 +1,4 @@
1
- import { FC, useContext } from 'react';
2
- import { NavigationLegacyContext } from '../utils/navigation-context';
1
+ import { FC } from 'react';
3
2
  import {
4
3
  HeaderNavigationLinkProps,
5
4
  HeaderNavigationTriggerProps,
@@ -8,27 +7,48 @@ import {
8
7
  HeaderNavigationLink as HeaderNavigationLinkLegacy,
9
8
  HeaderNavigationTrigger as HeaderNavigationTriggerLegacy,
10
9
  } from './header-navigation/header-navigation-links';
10
+ import { useTitanLayoutPlacementContext } from './titan-layout';
11
11
  import {
12
- HeaderNavigationLink as HeaderNavigationLinkModern,
13
- HeaderNavigationTrigger as HeaderNavigationTriggerModern,
14
- } from './left-navigation/header-navigation-tiny-links';
12
+ LayoutHeaderNavigationLink,
13
+ LayoutHeaderNavigationTrigger,
14
+ } from './titan-layout/layout-header-links';
15
+ import {
16
+ TitanLayoutSidebarLink,
17
+ TitanLayoutSidebarTrigger,
18
+ } from './titan-layout/layout-sidebar-links';
15
19
 
16
20
  export const HeaderNavigationLink: FC<HeaderNavigationLinkProps> = props => {
17
- const isLegacy = useContext(NavigationLegacyContext);
21
+ const placement = useTitanLayoutPlacementContext();
18
22
 
19
- return isLegacy ? (
20
- <HeaderNavigationLinkLegacy {...props} />
23
+ return placement === 'top' ? (
24
+ <LayoutHeaderNavigationLink {...props} />
25
+ ) : placement === 'side' ? (
26
+ <TitanLayoutSidebarLink
27
+ id={props.id}
28
+ icon={props.icon}
29
+ iconActive={props.iconActive}
30
+ to={props.to}
31
+ title={props.title}
32
+ counter={props.counter}
33
+ />
21
34
  ) : (
22
- <HeaderNavigationLinkModern {...props} />
35
+ <HeaderNavigationLinkLegacy {...props} />
23
36
  );
24
37
  };
25
38
 
26
39
  export const HeaderNavigationTrigger: FC<HeaderNavigationTriggerProps> = props => {
27
- const isLegacy = useContext(NavigationLegacyContext);
40
+ const placement = useTitanLayoutPlacementContext();
28
41
 
29
- return isLegacy ? (
30
- <HeaderNavigationTriggerLegacy {...props} />
42
+ return placement === 'top' ? (
43
+ <LayoutHeaderNavigationTrigger {...props} />
44
+ ) : placement === 'side' ? (
45
+ <TitanLayoutSidebarTrigger
46
+ id={props.id}
47
+ title={props.title}
48
+ icon={props.icon}
49
+ iconActive={props.iconActive}
50
+ />
31
51
  ) : (
32
- <HeaderNavigationTriggerModern {...props} />
52
+ <HeaderNavigationTriggerLegacy {...props} />
33
53
  );
34
54
  };
@@ -1,15 +1,17 @@
1
1
  import { FC } from 'react';
2
2
 
3
3
  /* tslint:disable: max-line-length */
4
- export const LogoCompanyTitle: FC<{ className?: string; fill?: string; size?: string }> = ({
5
- className,
6
- fill = 'currentColor',
7
- size = '162',
8
- }) => {
4
+ export const LogoCompanyTitle: FC<{
5
+ className?: string;
6
+ fill?: string;
7
+ size?: string;
8
+ height?: string | number;
9
+ }> = ({ className, fill = 'currentColor', size = '162', height }) => {
9
10
  return (
10
11
  <svg
11
12
  className={className}
12
- width={size}
13
+ width={height ? undefined : size}
14
+ height={height}
13
15
  viewBox="0 0 322 80"
14
16
  xmlns="http://www.w3.org/2000/svg"
15
17
  >
@@ -105,6 +105,10 @@
105
105
  position: relative;
106
106
  }
107
107
 
108
+ .dropdown-content-wrapper > span {
109
+ display: block !important;
110
+ }
111
+
108
112
  .dropdown-content-bottom-left {
109
113
  .dropdown-content-wrapper::before {
110
114
  content: '';
@@ -21,9 +21,9 @@ export const ProfileDropdownDefault = () => (
21
21
  <ProfileDropdown.Link id="first" to="https://google.com">
22
22
  first link
23
23
  </ProfileDropdown.Link>
24
- <ProfileDropdown.Link id="second" onClick={() => alert('second click')}>
24
+ <ProfileDropdown.Section id="second" onClick={() => alert('second click')}>
25
25
  second link
26
- </ProfileDropdown.Link>
26
+ </ProfileDropdown.Section>
27
27
  <ProfileDropdown.Divider />
28
28
  <ProfileDropdown.Section id="content">some content</ProfileDropdown.Section>
29
29
  <ProfileDropdown.Divider />
@@ -45,9 +45,9 @@ export const ProfileDropdownWithLogo = () => (
45
45
  <ProfileDropdown.Link id="first" to="https://google.com">
46
46
  first link
47
47
  </ProfileDropdown.Link>
48
- <ProfileDropdown.Link id="second" onClick={() => alert('second click')}>
48
+ <ProfileDropdown.Section id="second" onClick={() => alert('second click')}>
49
49
  second link
50
- </ProfileDropdown.Link>
50
+ </ProfileDropdown.Section>
51
51
  </ProfileDropdown>
52
52
  );
53
53
 
@@ -6,6 +6,7 @@ import SvgAccountInactive from '@servicetitan/anvil2/assets/icons/st/gnav_accoun
6
6
  import { BodyText, Popover, PopoverPropsStrict } from '@servicetitan/design-system';
7
7
  import classNames from 'classnames';
8
8
  import {
9
+ ComponentPropsWithoutRef,
9
10
  FC,
10
11
  HTMLAttributeAnchorTarget,
11
12
  MouseEvent,
@@ -25,6 +26,7 @@ import {
25
26
  } from '../../utils/navigation-context';
26
27
  import { getCounterTag } from '../../utils/side-nav';
27
28
  import { CounterTag } from '../counter-tag';
29
+ import { withTooltip } from '../titan-layout/with-tooltip';
28
30
  import * as Styles from './profile-dropdown.module.less';
29
31
  import { ProfileLogo } from './profile-icon';
30
32
 
@@ -146,21 +148,28 @@ const ProfileDropdownTrigger: FC<ProfileDropdownTriggerProps> = ({
146
148
  );
147
149
  };
148
150
 
151
+ export type ProfileItemContent =
152
+ | { children: string; text?: string }
153
+ | { children: ReactNode; text: string };
154
+
149
155
  export interface ProfileDropdownSectionPropsStrict {
150
156
  children: ReactNode;
151
157
  id: string;
158
+ tooltip?: string;
152
159
  className?: string;
153
160
  onClick?(e: MouseEvent): void;
154
161
  }
155
162
 
156
- interface ProfileDropdownSectionProps extends ProfileDropdownSectionPropsStrict {
157
- [key: string]: any;
158
- }
163
+ export type ProfileDropdownSectionProps = Omit<ComponentPropsWithoutRef<'div'>, 'children'> &
164
+ ProfileDropdownSectionPropsStrict &
165
+ ProfileItemContent;
159
166
 
160
167
  export const ProfileDropdownSection: FC<ProfileDropdownSectionProps> = ({
161
168
  children,
162
169
  className,
163
170
  id,
171
+ text,
172
+ tooltip,
164
173
  onClick,
165
174
  ...rest
166
175
  }) => {
@@ -172,16 +181,20 @@ export const ProfileDropdownSection: FC<ProfileDropdownSectionProps> = ({
172
181
  }
173
182
  };
174
183
 
175
- return (
184
+ return withTooltip(
176
185
  <div
177
- className={classNames(Styles.dropdownSection, className)}
186
+ className={classNames(Styles.dropdownSection, className, {
187
+ 'cursor-pointer': !!onClick,
188
+ })}
178
189
  onClick={clickHandler}
179
190
  data-cy={`profile-dropdown-section-${id}`}
180
191
  data-pendo={`profile-dropdown-section-${id}`}
181
192
  {...rest}
182
193
  >
183
194
  {children}
184
- </div>
195
+ </div>,
196
+ tooltip,
197
+ 'left'
185
198
  );
186
199
  };
187
200
 
@@ -193,15 +206,15 @@ export interface ProfileDropdownLinkPropsStrict {
193
206
  className?: string;
194
207
  external?: boolean;
195
208
  target?: HTMLAttributeAnchorTarget;
196
- to?: string;
209
+ tooltip?: string;
210
+ to: string;
197
211
  tag?: CounterTagData;
198
212
  counter?: CounterTagValue;
199
- onClick?: () => void;
200
213
  }
201
214
 
202
- export interface ProfileDropdownLinkProps extends ProfileDropdownLinkPropsStrict {
203
- [key: string]: any;
204
- }
215
+ export type ProfileDropdownLinkProps = Omit<ComponentPropsWithoutRef<'a'>, 'children'> &
216
+ ProfileDropdownLinkPropsStrict &
217
+ ProfileItemContent;
205
218
 
206
219
  export const ProfileDropdownLink: FC<ProfileDropdownLinkProps> = ({
207
220
  children,
@@ -211,17 +224,14 @@ export const ProfileDropdownLink: FC<ProfileDropdownLinkProps> = ({
211
224
  counter,
212
225
  tag,
213
226
  target,
227
+ text,
214
228
  to,
229
+ tooltip,
215
230
  onClick,
216
231
  ...rest
217
232
  }: ProfileDropdownLinkProps) => {
218
233
  const NavigationComponent = useContext(NavigationComponentContext);
219
234
 
220
- const clickHandler = (e: MouseEvent<any>) => {
221
- e.preventDefault();
222
- onClick?.();
223
- };
224
-
225
235
  const isExternalLink = external ?? to?.startsWith('http');
226
236
 
227
237
  const tagElement = useMemo(
@@ -229,41 +239,34 @@ export const ProfileDropdownLink: FC<ProfileDropdownLinkProps> = ({
229
239
  [counter, tag]
230
240
  );
231
241
 
232
- return isExternalLink ? (
233
- <a
234
- className={classNames(Styles.dropdownSection, Styles.dropdownLink, className)}
235
- href={to}
236
- target={target}
237
- data-cy={`profile-dropdown-link-${id}`}
238
- data-pendo={`profile-dropdown-link-${id}`}
239
- {...rest}
240
- >
241
- {children}
242
- {tagElement}
243
- </a>
244
- ) : to ? (
245
- <NavigationComponent
246
- className={classNames(Styles.dropdownSection, Styles.dropdownLink, className)}
247
- target={target}
248
- to={to}
249
- data-cy={`profile-dropdown-link-${id}`}
250
- data-pendo={`profile-dropdown-link-${id}`}
251
- {...rest}
252
- >
253
- {children}
254
- {tagElement}
255
- </NavigationComponent>
256
- ) : (
257
- <a
258
- className={classNames(Styles.dropdownSection, Styles.dropdownLink, className)}
259
- onClick={clickHandler}
260
- data-cy={`profile-dropdown-link-${id}`}
261
- data-pendo={`profile-dropdown-link-${id}`}
262
- {...rest}
263
- >
264
- {children}
265
- {tagElement}
266
- </a>
242
+ return withTooltip(
243
+ isExternalLink ? (
244
+ <a
245
+ className={classNames(Styles.dropdownSection, Styles.dropdownLink, className)}
246
+ href={to}
247
+ target={target}
248
+ data-cy={`profile-dropdown-link-${id}`}
249
+ data-pendo={`profile-dropdown-link-${id}`}
250
+ {...rest}
251
+ >
252
+ {children}
253
+ {tagElement}
254
+ </a>
255
+ ) : (
256
+ <NavigationComponent
257
+ className={classNames(Styles.dropdownSection, Styles.dropdownLink, className)}
258
+ target={target}
259
+ to={to}
260
+ data-cy={`profile-dropdown-link-${id}`}
261
+ data-pendo={`profile-dropdown-link-${id}`}
262
+ {...rest}
263
+ >
264
+ {children}
265
+ {tagElement}
266
+ </NavigationComponent>
267
+ ),
268
+ tooltip,
269
+ 'left'
267
270
  );
268
271
  };
269
272
 
@@ -291,6 +294,7 @@ export interface ProfileDropdownProps extends ProfileDropdownPropsStrict {
291
294
  export interface ProfileDropdownType extends FC<ProfileDropdownProps> {
292
295
  Divider: typeof ProfileDropdownDivider;
293
296
  Link: typeof ProfileDropdownLink;
297
+ Trigger: typeof ProfileDropdownTrigger;
294
298
  Section: typeof ProfileDropdownSection;
295
299
  }
296
300
 
@@ -0,0 +1,5 @@
1
+ export * from './titan-layout';
2
+ export * from './layout-profile';
3
+ export * from './layout-context';
4
+ export * from './layout-logo';
5
+ export * from './interface';
@@ -0,0 +1,6 @@
1
+ import { FC } from 'react';
2
+ import { NavLinkComponentProps } from '../../utils/navigation-context';
3
+
4
+ export interface NavigationComponentProps {
5
+ navigationComponent: FC<NavLinkComponentProps>;
6
+ }
@@ -0,0 +1,26 @@
1
+ import { FC, ReactElement } from 'react';
2
+ import { NavigationItemData } from '../../utils/navigation';
3
+ import { TitanLayoutSidebarContextType } from './layout-context';
4
+
5
+ export interface TitanLayoutSidebarLinkWrapperProps {
6
+ children:
7
+ | ReactElement<TitanLayoutSidebarLinkProps>
8
+ | ReactElement<TitanLayoutSidebarTriggerProps>;
9
+ context: TitanLayoutSidebarContextType;
10
+ }
11
+
12
+ export interface TitanLayoutSidebarLinkProps extends Omit<NavigationItemData, 'submenu'> {
13
+ wrapper?: FC<TitanLayoutSidebarLinkWrapperProps>;
14
+ }
15
+ export interface TitanLayoutSidebarTriggerProps
16
+ extends Omit<TitanLayoutSidebarLinkProps, 'to' | 'isActive'> {
17
+ isActive?: boolean;
18
+ wrapper?: FC<TitanLayoutSidebarLinkWrapperProps>;
19
+ onClick?: () => void;
20
+ onMobileClick?: () => void;
21
+ }
22
+
23
+ export interface TitanLayoutState {
24
+ navCollapsed: boolean;
25
+ submenuExpanded?: string;
26
+ }
@@ -0,0 +1,30 @@
1
+ import { CSSProperties, FC, createContext, useContext } from 'react';
2
+ import { DefaultNavLinkComponent, NavLinkComponentProps } from '../../utils/navigation-context';
3
+ import { TitanBreakpoint } from '../../utils/use-breakpoint';
4
+
5
+ export interface TitanLayoutSidebarContextType {
6
+ styles: {
7
+ popoverContent: CSSProperties;
8
+ };
9
+ }
10
+
11
+ export type TitanLayoutPlacement = 'top' | 'side' | 'unset';
12
+
13
+ export interface TitanLayoutContextType {
14
+ NavigationComponent: FC<NavLinkComponentProps>;
15
+ breakpoint: TitanBreakpoint;
16
+ isTitanLayout: boolean;
17
+ sidebar: TitanLayoutSidebarContextType;
18
+ }
19
+
20
+ export const LayoutContext = createContext<TitanLayoutContextType>({
21
+ NavigationComponent: DefaultNavLinkComponent,
22
+ breakpoint: { name: 'lg', isMobile: false },
23
+ isTitanLayout: false,
24
+ sidebar: { styles: { popoverContent: {} } },
25
+ });
26
+
27
+ export const useTitanLayoutContext = () => useContext(LayoutContext);
28
+
29
+ export const LayoutPlacementContext = createContext<TitanLayoutPlacement | undefined>(undefined);
30
+ export const useTitanLayoutPlacementContext = () => useContext(LayoutPlacementContext);
@@ -0,0 +1,144 @@
1
+ import { Icon, IconProps } from '@servicetitan/anvil2';
2
+ import classNames from 'classnames';
3
+ import { FC, Fragment } from 'react';
4
+ import {
5
+ HeaderNavigationLinkProps,
6
+ HeaderNavigationTriggerProps,
7
+ } from '../../utils/navigation-legacy';
8
+ import { getCounterTag } from '../../utils/side-nav';
9
+ import { CounterTag, CounterTagProps } from '../counter-tag';
10
+ // use v1 tooltips due to bug with v2 in monolith
11
+ import { withTooltip } from '../header-navigation/with-tooltip';
12
+ import { useTitanLayoutContext } from './layout-context';
13
+ import * as Styles from './layout-header.module.less';
14
+
15
+ /** Content for navigation items */
16
+ const HeaderNavigationItemContent: FC<{
17
+ tag?: CounterTagProps;
18
+ counterClassName?: string;
19
+ icon: IconProps['svg'] | undefined;
20
+ iconActive?: IconProps['svg'];
21
+ label?: string;
22
+ labelClassName?: string;
23
+ }> = ({ counterClassName, icon, iconActive, label, labelClassName, tag }) => {
24
+ return (
25
+ <Fragment>
26
+ {!!icon && <Icon svg={icon} className={Styles.navigationIcon} />}
27
+ {!!iconActive && (
28
+ <Icon
29
+ svg={iconActive}
30
+ className={classNames(Styles.navigationIcon, Styles.navigationIconActive)}
31
+ />
32
+ )}
33
+
34
+ {!!label && (
35
+ <span className={classNames(Styles.navigationItemLabel, labelClassName)}>
36
+ {label}
37
+ </span>
38
+ )}
39
+
40
+ {!!tag && (
41
+ <CounterTag
42
+ data={tag}
43
+ className={classNames(Styles.navigationItemCounter, counterClassName)}
44
+ longClassName={Styles.navigationItemCounterLong}
45
+ />
46
+ )}
47
+ </Fragment>
48
+ );
49
+ };
50
+
51
+ /** Navigation extra item with link */
52
+ export const LayoutHeaderNavigationLink: FC<HeaderNavigationLinkProps> = ({
53
+ id,
54
+ to,
55
+ hint,
56
+ tooltip,
57
+ className,
58
+ counter,
59
+ icon,
60
+ iconActive,
61
+ iconClassName,
62
+ iconComponent,
63
+ iconName,
64
+ isActive,
65
+ label,
66
+ labelClassName,
67
+ tag,
68
+ target,
69
+ ...rest
70
+ }) => {
71
+ const { NavigationComponent } = useTitanLayoutContext();
72
+
73
+ return withTooltip(
74
+ <NavigationComponent
75
+ data-cy={`navigation-link-${id}`}
76
+ data-pendo={`navigation-link-${id}`}
77
+ {...rest}
78
+ key={id}
79
+ to={to}
80
+ title={hint}
81
+ className={classNames(Styles.navigationLink, className, {
82
+ [Styles.navigationItemActive]: isActive === true,
83
+ [Styles.navigationItemIconState]: !!icon && !!iconActive,
84
+ })}
85
+ isActive={typeof isActive === 'function' ? isActive : undefined}
86
+ activeClassName={Styles.navigationItemActive}
87
+ target={target}
88
+ >
89
+ <HeaderNavigationItemContent
90
+ tag={getCounterTag(counter, tag)}
91
+ icon={icon}
92
+ iconActive={iconActive}
93
+ label={label}
94
+ labelClassName={labelClassName}
95
+ />
96
+ </NavigationComponent>,
97
+ tooltip
98
+ );
99
+ };
100
+
101
+ /** Navigation extra item with icon button */
102
+ export const LayoutHeaderNavigationTrigger: FC<HeaderNavigationTriggerProps> = ({
103
+ id,
104
+ className,
105
+ counter,
106
+ icon,
107
+ iconActive,
108
+ iconName,
109
+ isActive,
110
+ hint,
111
+ label,
112
+ labelClassName,
113
+ tag,
114
+ tooltip,
115
+ title,
116
+ titleClassName,
117
+ ...rest
118
+ }) => {
119
+ return withTooltip(
120
+ <div
121
+ data-cy={`navigation-trigger-${id}`}
122
+ data-pendo={`navigation-trigger-${id}`}
123
+ {...rest}
124
+ title={hint}
125
+ className={classNames(
126
+ Styles.navigationLink,
127
+ {
128
+ [Styles.navigationItemActive]: isActive === true,
129
+ [Styles.navigationItemIconState]: !!icon && !!iconActive,
130
+ },
131
+ 'cursor-pointer',
132
+ className
133
+ )}
134
+ >
135
+ <HeaderNavigationItemContent
136
+ tag={getCounterTag(counter, tag)}
137
+ icon={isActive && iconActive ? iconActive : icon}
138
+ label={label}
139
+ labelClassName={labelClassName}
140
+ />
141
+ </div>,
142
+ tooltip
143
+ );
144
+ };