@servicetitan/navigation 10.7.0 → 11.0.0-canary.237.0a4df1d.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/badge-tag.d.ts +1 -1
- package/dist/components/badge-tag.d.ts.map +1 -1
- package/dist/components/header-navigation/header-navigation-extra.stories.d.ts.map +1 -1
- package/dist/components/header-navigation/header-navigation-extra.stories.js +5 -5
- package/dist/components/header-navigation/header-navigation-extra.stories.js.map +1 -1
- package/dist/components/header-navigation/header-navigation-links.d.ts.map +1 -1
- package/dist/components/header-navigation/header-navigation-links.js +2 -2
- package/dist/components/header-navigation/header-navigation-links.js.map +1 -1
- package/dist/components/header-navigation/header-navigation-stacked.stories.d.ts.map +1 -1
- package/dist/components/header-navigation/header-navigation-stacked.stories.js +1 -1
- package/dist/components/header-navigation/header-navigation-stacked.stories.js.map +1 -1
- package/dist/components/header-navigation/header-navigation.stories.d.ts.map +1 -1
- package/dist/components/header-navigation/header-navigation.stories.js +2 -2
- package/dist/components/header-navigation/header-navigation.stories.js.map +1 -1
- package/dist/components/header-navigation/with-tooltip.d.ts +1 -1
- package/dist/components/header-navigation/with-tooltip.d.ts.map +1 -1
- package/dist/components/left-navigation/header-navigation-tiny.stories.d.ts.map +1 -1
- package/dist/components/left-navigation/header-navigation-tiny.stories.js +2 -2
- package/dist/components/left-navigation/header-navigation-tiny.stories.js.map +1 -1
- package/dist/components/links.d.ts.map +1 -1
- package/dist/components/links.js +7 -7
- package/dist/components/links.js.map +1 -1
- package/dist/components/logo/logo-company-title.d.ts +1 -0
- package/dist/components/logo/logo-company-title.d.ts.map +1 -1
- package/dist/components/logo/logo-company-title.js +2 -2
- package/dist/components/logo/logo-company-title.js.map +1 -1
- package/dist/components/logo/logo-titan-text.d.ts +1 -1
- package/dist/components/logo/logo-titan-text.d.ts.map +1 -1
- package/dist/components/profile-dropdown/profile-dropdown.d.ts +17 -9
- package/dist/components/profile-dropdown/profile-dropdown.d.ts.map +1 -1
- package/dist/components/profile-dropdown/profile-dropdown.js +11 -9
- package/dist/components/profile-dropdown/profile-dropdown.js.map +1 -1
- package/dist/components/profile-dropdown/profile-dropdown.module.less +24 -6
- package/dist/components/profile-dropdown/profile-dropdown.stories.js +2 -2
- package/dist/components/profile-dropdown/profile-dropdown.stories.js.map +1 -1
- package/dist/components/titan-layout/index.d.ts +6 -0
- package/dist/components/titan-layout/index.d.ts.map +1 -0
- package/dist/components/titan-layout/index.js +6 -0
- package/dist/components/titan-layout/index.js.map +1 -0
- package/dist/components/titan-layout/interface-internal.d.ts +6 -0
- package/dist/components/titan-layout/interface-internal.d.ts.map +1 -0
- package/dist/components/titan-layout/interface-internal.js +2 -0
- package/dist/components/titan-layout/interface-internal.js.map +1 -0
- package/dist/components/titan-layout/interface.d.ts +21 -0
- package/dist/components/titan-layout/interface.d.ts.map +1 -0
- package/dist/components/titan-layout/interface.js +2 -0
- package/dist/components/titan-layout/interface.js.map +1 -0
- package/dist/components/titan-layout/layout-context.d.ts +20 -0
- package/dist/components/titan-layout/layout-context.d.ts.map +1 -0
- package/dist/components/titan-layout/layout-context.js +12 -0
- package/dist/components/titan-layout/layout-context.js.map +1 -0
- package/dist/components/titan-layout/layout-header-links.d.ts +7 -0
- package/dist/components/titan-layout/layout-header-links.d.ts.map +1 -0
- package/dist/components/titan-layout/layout-header-links.js +32 -0
- package/dist/components/titan-layout/layout-header-links.js.map +1 -0
- package/dist/components/titan-layout/layout-header.d.ts +22 -0
- package/dist/components/titan-layout/layout-header.d.ts.map +1 -0
- package/dist/components/titan-layout/layout-header.js +10 -0
- package/dist/components/titan-layout/layout-header.js.map +1 -0
- package/dist/components/titan-layout/layout-header.module.less +193 -0
- package/dist/components/titan-layout/layout-logo.d.ts +12 -0
- package/dist/components/titan-layout/layout-logo.d.ts.map +1 -0
- package/dist/components/titan-layout/layout-logo.js +16 -0
- package/dist/components/titan-layout/layout-logo.js.map +1 -0
- package/dist/components/titan-layout/layout-logo.stories.d.ts +13 -0
- package/dist/components/titan-layout/layout-logo.stories.d.ts.map +1 -0
- package/dist/components/titan-layout/layout-logo.stories.js +17 -0
- package/dist/components/titan-layout/layout-logo.stories.js.map +1 -0
- package/dist/components/titan-layout/layout-profile.d.ts +9 -0
- package/dist/components/titan-layout/layout-profile.d.ts.map +1 -0
- package/dist/components/titan-layout/layout-profile.js +72 -0
- package/dist/components/titan-layout/layout-profile.js.map +1 -0
- package/dist/components/titan-layout/layout-profile.stories.d.ts +13 -0
- package/dist/components/titan-layout/layout-profile.stories.d.ts.map +1 -0
- package/dist/components/titan-layout/layout-profile.stories.js +13 -0
- package/dist/components/titan-layout/layout-profile.stories.js.map +1 -0
- package/dist/components/titan-layout/layout-sidebar-links-internal.d.ts +46 -0
- package/dist/components/titan-layout/layout-sidebar-links-internal.d.ts.map +1 -0
- package/dist/components/titan-layout/layout-sidebar-links-internal.js +61 -0
- package/dist/components/titan-layout/layout-sidebar-links-internal.js.map +1 -0
- package/dist/components/titan-layout/layout-sidebar-links.d.ts +6 -0
- package/dist/components/titan-layout/layout-sidebar-links.d.ts.map +1 -0
- package/dist/components/titan-layout/layout-sidebar-links.js +28 -0
- package/dist/components/titan-layout/layout-sidebar-links.js.map +1 -0
- package/dist/components/titan-layout/layout-sidebar.d.ts +19 -0
- package/dist/components/titan-layout/layout-sidebar.d.ts.map +1 -0
- package/dist/components/titan-layout/layout-sidebar.js +67 -0
- package/dist/components/titan-layout/layout-sidebar.js.map +1 -0
- package/dist/components/titan-layout/layout-sidebar.module.less +536 -0
- package/dist/components/titan-layout/notifications-context.d.ts +13 -0
- package/dist/components/titan-layout/notifications-context.d.ts.map +1 -0
- package/dist/components/titan-layout/notifications-context.js +23 -0
- package/dist/components/titan-layout/notifications-context.js.map +1 -0
- package/dist/components/titan-layout/titan-layout.d.ts +40 -0
- package/dist/components/titan-layout/titan-layout.d.ts.map +1 -0
- package/dist/components/titan-layout/titan-layout.js +192 -0
- package/dist/components/titan-layout/titan-layout.js.map +1 -0
- package/dist/components/titan-layout/titan-layout.module.less +106 -0
- package/dist/components/titan-layout/titan-layout.stories.d.ts +22 -0
- package/dist/components/titan-layout/titan-layout.stories.d.ts.map +1 -0
- package/dist/components/titan-layout/titan-layout.stories.js +83 -0
- package/dist/components/titan-layout/titan-layout.stories.js.map +1 -0
- package/dist/components/titan-layout/with-tooltip.d.ts +4 -0
- package/dist/components/titan-layout/with-tooltip.d.ts.map +1 -0
- package/dist/components/titan-layout/with-tooltip.js +4 -0
- package/dist/components/titan-layout/with-tooltip.js.map +1 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/test/data.d.ts +4 -1
- package/dist/test/data.d.ts.map +1 -1
- package/dist/test/data.js +5 -6
- package/dist/test/data.js.map +1 -1
- package/dist/utils/navigation-legacy.d.ts +3 -1
- package/dist/utils/navigation-legacy.d.ts.map +1 -1
- package/dist/utils/use-breakpoint.d.ts +8 -0
- package/dist/utils/use-breakpoint.d.ts.map +1 -0
- package/dist/utils/use-breakpoint.js +14 -0
- package/dist/utils/use-breakpoint.js.map +1 -0
- package/package.json +5 -6
- package/src/components/badge-tag.tsx +1 -1
- package/src/components/header-navigation/header-navigation-extra.stories.tsx +7 -0
- package/src/components/header-navigation/header-navigation-links.tsx +2 -0
- package/src/components/header-navigation/header-navigation-stacked.stories.tsx +5 -1
- package/src/components/header-navigation/header-navigation.stories.tsx +6 -1
- package/src/components/left-navigation/header-navigation-tiny.stories.tsx +8 -2
- package/src/components/left-navigation/side-navigation-links.tsx +1 -1
- package/src/components/links.tsx +33 -13
- package/src/components/logo/logo-company-title.tsx +8 -6
- package/src/components/logo/logo-titan-text.tsx +1 -1
- package/src/components/profile-dropdown/profile-dropdown.module.less +24 -6
- package/src/components/profile-dropdown/profile-dropdown.module.less.d.ts +2 -0
- package/src/components/profile-dropdown/profile-dropdown.stories.tsx +4 -4
- package/src/components/profile-dropdown/profile-dropdown.tsx +87 -55
- package/src/components/titan-layout/index.ts +5 -0
- package/src/components/titan-layout/interface-internal.ts +6 -0
- package/src/components/titan-layout/interface.ts +26 -0
- package/src/components/titan-layout/layout-context.tsx +30 -0
- package/src/components/titan-layout/layout-header-links.tsx +145 -0
- package/src/components/titan-layout/layout-header.module.less +193 -0
- package/src/components/titan-layout/layout-header.module.less.d.ts +18 -0
- package/src/components/titan-layout/layout-header.tsx +97 -0
- package/src/components/titan-layout/layout-logo.stories.tsx +31 -0
- package/src/components/titan-layout/layout-logo.tsx +64 -0
- package/src/components/titan-layout/layout-profile.stories.tsx +46 -0
- package/src/components/titan-layout/layout-profile.tsx +180 -0
- package/src/components/titan-layout/layout-sidebar-links-internal.tsx +278 -0
- package/src/components/titan-layout/layout-sidebar-links.tsx +72 -0
- package/src/components/titan-layout/layout-sidebar.module.less +536 -0
- package/src/components/titan-layout/layout-sidebar.module.less.d.ts +49 -0
- package/src/components/titan-layout/layout-sidebar.tsx +304 -0
- package/src/components/titan-layout/notifications-context.tsx +44 -0
- package/src/components/titan-layout/titan-layout.module.less +106 -0
- package/src/components/titan-layout/titan-layout.module.less.d.ts +16 -0
- package/src/components/titan-layout/titan-layout.stories.tsx +346 -0
- package/src/components/titan-layout/titan-layout.tsx +457 -0
- package/src/components/titan-layout/with-tooltip.tsx +16 -0
- package/src/index.ts +2 -1
- package/src/test/data.tsx +5 -5
- package/src/utils/navigation-legacy.ts +3 -1
- package/src/utils/use-breakpoint.ts +21 -0
|
@@ -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,43 @@ const ProfileDropdownTrigger: FC<ProfileDropdownTriggerProps> = ({
|
|
|
146
148
|
);
|
|
147
149
|
};
|
|
148
150
|
|
|
151
|
+
const useTag = (counter?: CounterTagValue, tag?: CounterTagData) =>
|
|
152
|
+
useMemo(() => {
|
|
153
|
+
const data = getCounterTag(counter, tag);
|
|
154
|
+
|
|
155
|
+
return data ? (
|
|
156
|
+
<div className={Styles.counterWrapper}>
|
|
157
|
+
<CounterTag className={Styles.counter} data={data} />
|
|
158
|
+
</div>
|
|
159
|
+
) : undefined;
|
|
160
|
+
}, [counter, tag]);
|
|
161
|
+
|
|
162
|
+
export type ProfileItemContent =
|
|
163
|
+
| { children: string; text?: string }
|
|
164
|
+
| { children: ReactNode; text: string };
|
|
165
|
+
|
|
149
166
|
export interface ProfileDropdownSectionPropsStrict {
|
|
150
167
|
children: ReactNode;
|
|
151
168
|
id: string;
|
|
169
|
+
tooltip?: string;
|
|
152
170
|
className?: string;
|
|
171
|
+
tag?: CounterTagData;
|
|
172
|
+
counter?: CounterTagValue;
|
|
153
173
|
onClick?(e: MouseEvent): void;
|
|
154
174
|
}
|
|
155
175
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
176
|
+
export type ProfileDropdownSectionProps = Omit<ComponentPropsWithoutRef<'div'>, 'children'> &
|
|
177
|
+
ProfileDropdownSectionPropsStrict &
|
|
178
|
+
ProfileItemContent;
|
|
159
179
|
|
|
160
180
|
export const ProfileDropdownSection: FC<ProfileDropdownSectionProps> = ({
|
|
161
181
|
children,
|
|
162
182
|
className,
|
|
183
|
+
counter,
|
|
163
184
|
id,
|
|
185
|
+
tag,
|
|
186
|
+
text,
|
|
187
|
+
tooltip,
|
|
164
188
|
onClick,
|
|
165
189
|
...rest
|
|
166
190
|
}) => {
|
|
@@ -172,16 +196,26 @@ export const ProfileDropdownSection: FC<ProfileDropdownSectionProps> = ({
|
|
|
172
196
|
}
|
|
173
197
|
};
|
|
174
198
|
|
|
175
|
-
|
|
199
|
+
const tagElement = useTag(counter, tag);
|
|
200
|
+
|
|
201
|
+
return withTooltip(
|
|
176
202
|
<div
|
|
177
|
-
className={classNames(
|
|
203
|
+
className={classNames(
|
|
204
|
+
Styles.dropdownSection,
|
|
205
|
+
tagElement && Styles.dropdownSectionWithCounter,
|
|
206
|
+
!!onClick && Styles.dropdownLink,
|
|
207
|
+
className
|
|
208
|
+
)}
|
|
178
209
|
onClick={clickHandler}
|
|
179
210
|
data-cy={`profile-dropdown-section-${id}`}
|
|
180
211
|
data-pendo={`profile-dropdown-section-${id}`}
|
|
181
212
|
{...rest}
|
|
182
213
|
>
|
|
183
214
|
{children}
|
|
184
|
-
|
|
215
|
+
{tagElement}
|
|
216
|
+
</div>,
|
|
217
|
+
tooltip,
|
|
218
|
+
'left'
|
|
185
219
|
);
|
|
186
220
|
};
|
|
187
221
|
|
|
@@ -193,15 +227,15 @@ export interface ProfileDropdownLinkPropsStrict {
|
|
|
193
227
|
className?: string;
|
|
194
228
|
external?: boolean;
|
|
195
229
|
target?: HTMLAttributeAnchorTarget;
|
|
196
|
-
|
|
230
|
+
tooltip?: string;
|
|
231
|
+
to: string;
|
|
197
232
|
tag?: CounterTagData;
|
|
198
233
|
counter?: CounterTagValue;
|
|
199
|
-
onClick?: () => void;
|
|
200
234
|
}
|
|
201
235
|
|
|
202
|
-
export
|
|
203
|
-
|
|
204
|
-
|
|
236
|
+
export type ProfileDropdownLinkProps = Omit<ComponentPropsWithoutRef<'a'>, 'children'> &
|
|
237
|
+
ProfileDropdownLinkPropsStrict &
|
|
238
|
+
ProfileItemContent;
|
|
205
239
|
|
|
206
240
|
export const ProfileDropdownLink: FC<ProfileDropdownLinkProps> = ({
|
|
207
241
|
children,
|
|
@@ -211,59 +245,56 @@ export const ProfileDropdownLink: FC<ProfileDropdownLinkProps> = ({
|
|
|
211
245
|
counter,
|
|
212
246
|
tag,
|
|
213
247
|
target,
|
|
248
|
+
text,
|
|
214
249
|
to,
|
|
250
|
+
tooltip,
|
|
215
251
|
onClick,
|
|
216
252
|
...rest
|
|
217
253
|
}: ProfileDropdownLinkProps) => {
|
|
218
254
|
const NavigationComponent = useContext(NavigationComponentContext);
|
|
219
255
|
|
|
220
|
-
const clickHandler = (e: MouseEvent<any>) => {
|
|
221
|
-
e.preventDefault();
|
|
222
|
-
onClick?.();
|
|
223
|
-
};
|
|
224
|
-
|
|
225
256
|
const isExternalLink = external ?? to?.startsWith('http');
|
|
226
257
|
|
|
227
|
-
const tagElement =
|
|
228
|
-
() => <CounterTag data={getCounterTag(counter, tag)} className={Styles.counter} />,
|
|
229
|
-
[counter, tag]
|
|
230
|
-
);
|
|
258
|
+
const tagElement = useTag(counter, tag);
|
|
231
259
|
|
|
232
|
-
return
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
260
|
+
return withTooltip(
|
|
261
|
+
isExternalLink ? (
|
|
262
|
+
<a
|
|
263
|
+
className={classNames(
|
|
264
|
+
Styles.dropdownSection,
|
|
265
|
+
tagElement && Styles.dropdownSectionWithCounter,
|
|
266
|
+
Styles.dropdownLink,
|
|
267
|
+
className
|
|
268
|
+
)}
|
|
269
|
+
href={to}
|
|
270
|
+
target={target}
|
|
271
|
+
data-cy={`profile-dropdown-link-${id}`}
|
|
272
|
+
data-pendo={`profile-dropdown-link-${id}`}
|
|
273
|
+
{...rest}
|
|
274
|
+
>
|
|
275
|
+
{children}
|
|
276
|
+
{tagElement}
|
|
277
|
+
</a>
|
|
278
|
+
) : (
|
|
279
|
+
<NavigationComponent
|
|
280
|
+
className={classNames(
|
|
281
|
+
Styles.dropdownSection,
|
|
282
|
+
Styles.dropdownLink,
|
|
283
|
+
{ [Styles.dropdownSectionWithCounter]: !!tagElement },
|
|
284
|
+
className
|
|
285
|
+
)}
|
|
286
|
+
target={target}
|
|
287
|
+
to={to}
|
|
288
|
+
data-cy={`profile-dropdown-link-${id}`}
|
|
289
|
+
data-pendo={`profile-dropdown-link-${id}`}
|
|
290
|
+
{...rest}
|
|
291
|
+
>
|
|
292
|
+
{children}
|
|
293
|
+
{tagElement}
|
|
294
|
+
</NavigationComponent>
|
|
295
|
+
),
|
|
296
|
+
tooltip,
|
|
297
|
+
'left'
|
|
267
298
|
);
|
|
268
299
|
};
|
|
269
300
|
|
|
@@ -291,6 +322,7 @@ export interface ProfileDropdownProps extends ProfileDropdownPropsStrict {
|
|
|
291
322
|
export interface ProfileDropdownType extends FC<ProfileDropdownProps> {
|
|
292
323
|
Divider: typeof ProfileDropdownDivider;
|
|
293
324
|
Link: typeof ProfileDropdownLink;
|
|
325
|
+
Trigger: typeof ProfileDropdownTrigger;
|
|
294
326
|
Section: typeof ProfileDropdownSection;
|
|
295
327
|
}
|
|
296
328
|
|
|
@@ -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, width: 0 },
|
|
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,145 @@
|
|
|
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={icon}
|
|
138
|
+
iconActive={iconActive}
|
|
139
|
+
label={label}
|
|
140
|
+
labelClassName={labelClassName}
|
|
141
|
+
/>
|
|
142
|
+
</div>,
|
|
143
|
+
tooltip
|
|
144
|
+
);
|
|
145
|
+
};
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
/* stylelint-disable no-descending-specificity */
|
|
2
|
+
@import (reference) '@servicetitan/tokens/core/tokens.less';
|
|
3
|
+
|
|
4
|
+
@size-links-tiny: 24px;
|
|
5
|
+
|
|
6
|
+
.header {
|
|
7
|
+
--nav-top-content-height: 32px;
|
|
8
|
+
display: flex;
|
|
9
|
+
justify-content: space-between;
|
|
10
|
+
|
|
11
|
+
background-color: @color-white;
|
|
12
|
+
color: @color-black;
|
|
13
|
+
box-sizing: border-box;
|
|
14
|
+
outline: 1px solid @color-neutral-60;
|
|
15
|
+
|
|
16
|
+
& > * {
|
|
17
|
+
overflow-y: hidden;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
.he-top-left {
|
|
21
|
+
display: flex;
|
|
22
|
+
align-items: center;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
.he-top-center {
|
|
26
|
+
overflow: hidden;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.he-top-right {
|
|
30
|
+
& > * {
|
|
31
|
+
color: @color-black;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.he-top-right-text {
|
|
35
|
+
font-size: @typescale-2;
|
|
36
|
+
font-weight: @font-weight-bold;
|
|
37
|
+
font-family: @base-font-family;
|
|
38
|
+
margin-right: @spacing-1;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
:global(.profile-dropdown-image) {
|
|
43
|
+
height: 24px;
|
|
44
|
+
width: 24px;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
:global(.profile-dropdown-trigger) {
|
|
48
|
+
height: 32px;
|
|
49
|
+
font-size: @size-links-tiny;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
.navigation-link {
|
|
53
|
+
border-radius: 12px;
|
|
54
|
+
font-size: @size-links-tiny;
|
|
55
|
+
color: inherit;
|
|
56
|
+
|
|
57
|
+
&.navigation-item-active:not(.navigation-item-overflow) {
|
|
58
|
+
background-color: @color-blue-100 !important;
|
|
59
|
+
color: @color-blue-500 !important;
|
|
60
|
+
}
|
|
61
|
+
&:hover:not(.navigation-item-active):not(.navigation-item-overflow) {
|
|
62
|
+
background-color: rgba(0, 0, 0, 0.12) !important;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
&.navigation-item-icon-state.navigation-item-active {
|
|
66
|
+
.navigation-icon[data-anv][data-anv]:not(.navigation-icon-active) {
|
|
67
|
+
display: none;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
.navigation-icon.navigation-icon-active[data-anv][data-anv] {
|
|
71
|
+
display: block;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
.navigation-icon[data-anv][data-anv] {
|
|
77
|
+
display: inline-block;
|
|
78
|
+
color: inherit;
|
|
79
|
+
height: 24px;
|
|
80
|
+
width: 24px;
|
|
81
|
+
|
|
82
|
+
> svg {
|
|
83
|
+
height: @size-links-tiny;
|
|
84
|
+
width: @size-links-tiny;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
&.navigation-icon-active {
|
|
88
|
+
display: none;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
.header-mobile {
|
|
94
|
+
padding: @spacing-2 @spacing-0;
|
|
95
|
+
height: var(--nav-offset-top);
|
|
96
|
+
|
|
97
|
+
--nav-top-content-height: 40px;
|
|
98
|
+
|
|
99
|
+
.navigation-link {
|
|
100
|
+
padding: 10px;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
.he-top-center {
|
|
104
|
+
max-width: unset;
|
|
105
|
+
flex: 1;
|
|
106
|
+
margin-left: @spacing-3;
|
|
107
|
+
margin-right: @spacing-3;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
.he-top-left {
|
|
111
|
+
margin-left: @spacing-half;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
.he-top-right {
|
|
115
|
+
margin-right: @spacing-half;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// desktop
|
|
120
|
+
.header-desktop {
|
|
121
|
+
height: var(--nav-offset-top);
|
|
122
|
+
.navigation-link {
|
|
123
|
+
margin: 6px 2px;
|
|
124
|
+
padding: 6px 6px;
|
|
125
|
+
|
|
126
|
+
.navigation-item-counter {
|
|
127
|
+
min-width: 12px !important;
|
|
128
|
+
height: 12px !important;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
.he-top-left {
|
|
133
|
+
padding-left: @spacing-1;
|
|
134
|
+
}
|
|
135
|
+
.he-top-center {
|
|
136
|
+
flex: 1;
|
|
137
|
+
margin-left: @spacing-2;
|
|
138
|
+
margin-right: @spacing-2;
|
|
139
|
+
max-width: 400px;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// desktop wide
|
|
144
|
+
@media only screen and (min-width: 1200px) {
|
|
145
|
+
.header-desktop {
|
|
146
|
+
display: grid;
|
|
147
|
+
grid-template-columns: repeat(3, 1fr);
|
|
148
|
+
grid-template-rows: 48px;
|
|
149
|
+
|
|
150
|
+
.he-top-left,
|
|
151
|
+
.he-top-center,
|
|
152
|
+
.he-top-right {
|
|
153
|
+
grid-column: span 1;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
.he-top-center {
|
|
157
|
+
max-width: unset;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
.navigation-link {
|
|
163
|
+
// styles specific to extra nav links
|
|
164
|
+
color: @color-black;
|
|
165
|
+
position: relative;
|
|
166
|
+
display: flex;
|
|
167
|
+
align-items: center;
|
|
168
|
+
flex-wrap: nowrap;
|
|
169
|
+
text-wrap: nowrap;
|
|
170
|
+
|
|
171
|
+
.navigation-item-counter {
|
|
172
|
+
color: @color-white;
|
|
173
|
+
font-weight: @font-weight-semibold;
|
|
174
|
+
font-size: 8px !important;
|
|
175
|
+
min-width: 16px !important;
|
|
176
|
+
height: 16px !important;
|
|
177
|
+
position: absolute;
|
|
178
|
+
top: 4px;
|
|
179
|
+
right: -2px;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
.navigation-item-label {
|
|
183
|
+
color: inherit;
|
|
184
|
+
font-size: @typescale-1;
|
|
185
|
+
font-family: @base-font-family;
|
|
186
|
+
font-weight: @font-weight-semibold;
|
|
187
|
+
margin-left: @spacing-half;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
&.navigation-item-counter-long {
|
|
191
|
+
right: -8px;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export const __esModule: true;
|
|
2
|
+
export const heTopCenter: string;
|
|
3
|
+
export const heTopLeft: string;
|
|
4
|
+
export const heTopRight: string;
|
|
5
|
+
export const heTopRightText: string;
|
|
6
|
+
export const header: string;
|
|
7
|
+
export const headerDesktop: string;
|
|
8
|
+
export const headerMobile: string;
|
|
9
|
+
export const navigationIcon: string;
|
|
10
|
+
export const navigationIconActive: string;
|
|
11
|
+
export const navigationItemActive: string;
|
|
12
|
+
export const navigationItemCounter: string;
|
|
13
|
+
export const navigationItemCounterLong: string;
|
|
14
|
+
export const navigationItemIconState: string;
|
|
15
|
+
export const navigationItemLabel: string;
|
|
16
|
+
export const navigationItemOverflow: string;
|
|
17
|
+
export const navigationLink: string;
|
|
18
|
+
|