@servicetitan/navigation 10.6.1 → 11.0.0-canary.237.0c461af.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/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/left-navigation/interface.d.ts +1 -1
- package/dist/components/left-navigation/interface.d.ts.map +1 -1
- package/dist/components/left-navigation/side-navigation-links-internal.d.ts +3 -1
- package/dist/components/left-navigation/side-navigation-links-internal.d.ts.map +1 -1
- package/dist/components/left-navigation/side-navigation-links-internal.js +3 -3
- package/dist/components/left-navigation/side-navigation-links-internal.js.map +1 -1
- package/dist/components/left-navigation/side-navigation.d.ts.map +1 -1
- package/dist/components/left-navigation/side-navigation.js +8 -7
- package/dist/components/left-navigation/side-navigation.js.map +1 -1
- package/dist/components/left-navigation/side-navigation.module.less +21 -19
- 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/profile-dropdown/profile-dropdown.d.ts +15 -9
- package/dist/components/profile-dropdown/profile-dropdown.d.ts.map +1 -1
- package/dist/components/profile-dropdown/profile-dropdown.js +7 -8
- package/dist/components/profile-dropdown/profile-dropdown.js.map +1 -1
- package/dist/components/profile-dropdown/profile-dropdown.module.less +4 -0
- 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 +20 -0
- package/dist/components/titan-layout/layout-header.d.ts.map +1 -0
- package/dist/components/titan-layout/layout-header.js +11 -0
- package/dist/components/titan-layout/layout-header.js.map +1 -0
- package/dist/components/titan-layout/layout-header.module.less +174 -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 +15 -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 +54 -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 +21 -0
- package/dist/components/titan-layout/layout-sidebar-links.js.map +1 -0
- package/dist/components/titan-layout/layout-sidebar.d.ts +17 -0
- package/dist/components/titan-layout/layout-sidebar.d.ts.map +1 -0
- package/dist/components/titan-layout/layout-sidebar.js +65 -0
- package/dist/components/titan-layout/layout-sidebar.js.map +1 -0
- package/dist/components/titan-layout/layout-sidebar.module.less +516 -0
- package/dist/components/titan-layout/titan-layout.d.ts +38 -0
- package/dist/components/titan-layout/titan-layout.d.ts.map +1 -0
- package/dist/components/titan-layout/titan-layout.js +147 -0
- package/dist/components/titan-layout/titan-layout.js.map +1 -0
- package/dist/components/titan-layout/titan-layout.module.less +103 -0
- package/dist/components/titan-layout/titan-layout.stories.d.ts +20 -0
- package/dist/components/titan-layout/titan-layout.stories.d.ts.map +1 -0
- package/dist/components/titan-layout/titan-layout.stories.js +80 -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.map +1 -1
- package/dist/test/data.js +3 -3
- 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 +7 -0
- package/dist/utils/use-breakpoint.d.ts.map +1 -0
- package/dist/utils/use-breakpoint.js +13 -0
- package/dist/utils/use-breakpoint.js.map +1 -0
- package/package.json +5 -6
- 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/interface.ts +2 -2
- package/src/components/left-navigation/side-navigation-links-internal.tsx +21 -6
- package/src/components/left-navigation/side-navigation-links.tsx +1 -1
- package/src/components/left-navigation/side-navigation.module.less +21 -19
- package/src/components/left-navigation/side-navigation.module.less.d.ts +2 -1
- package/src/components/left-navigation/side-navigation.tsx +15 -8
- package/src/components/links.tsx +33 -13
- package/src/components/logo/logo-company-title.tsx +8 -6
- package/src/components/profile-dropdown/profile-dropdown.module.less +4 -0
- package/src/components/profile-dropdown/profile-dropdown.stories.tsx +4 -4
- package/src/components/profile-dropdown/profile-dropdown.tsx +55 -51
- 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 +144 -0
- package/src/components/titan-layout/layout-header.module.less +174 -0
- package/src/components/titan-layout/layout-header.module.less.d.ts +16 -0
- package/src/components/titan-layout/layout-header.tsx +90 -0
- package/src/components/titan-layout/layout-logo.stories.tsx +31 -0
- package/src/components/titan-layout/layout-logo.tsx +57 -0
- package/src/components/titan-layout/layout-profile.stories.tsx +46 -0
- package/src/components/titan-layout/layout-profile.tsx +132 -0
- package/src/components/titan-layout/layout-sidebar-links-internal.tsx +275 -0
- package/src/components/titan-layout/layout-sidebar-links.tsx +59 -0
- package/src/components/titan-layout/layout-sidebar.module.less +516 -0
- package/src/components/titan-layout/layout-sidebar.module.less.d.ts +48 -0
- package/src/components/titan-layout/layout-sidebar.tsx +295 -0
- package/src/components/titan-layout/titan-layout.module.less +103 -0
- package/src/components/titan-layout/titan-layout.module.less.d.ts +15 -0
- package/src/components/titan-layout/titan-layout.stories.tsx +332 -0
- package/src/components/titan-layout/titan-layout.tsx +365 -0
- package/src/components/titan-layout/with-tooltip.tsx +16 -0
- package/src/index.ts +2 -1
- package/src/test/data.tsx +3 -2
- package/src/utils/navigation-legacy.ts +3 -1
- package/src/utils/use-breakpoint.ts +19 -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,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
|
-
|
|
157
|
-
|
|
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
|
-
|
|
209
|
+
tooltip?: string;
|
|
210
|
+
to: string;
|
|
197
211
|
tag?: CounterTagData;
|
|
198
212
|
counter?: CounterTagValue;
|
|
199
|
-
onClick?: () => void;
|
|
200
213
|
}
|
|
201
214
|
|
|
202
|
-
export
|
|
203
|
-
|
|
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
|
|
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
|
-
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,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
|
+
};
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
/* stylelint-disable no-descending-specificity */
|
|
2
|
+
@import (reference) '@servicetitan/tokens/core/tokens.less';
|
|
3
|
+
|
|
4
|
+
@size-links-tiny: 24px;
|
|
5
|
+
|
|
6
|
+
.header {
|
|
7
|
+
display: flex;
|
|
8
|
+
justify-content: space-between;
|
|
9
|
+
|
|
10
|
+
background-color: @color-white;
|
|
11
|
+
color: @color-black;
|
|
12
|
+
border-bottom: 1px solid @color-neutral-60;
|
|
13
|
+
|
|
14
|
+
& > * {
|
|
15
|
+
overflow-y: hidden;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
.he-top-left {
|
|
19
|
+
display: flex;
|
|
20
|
+
align-items: center;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
.he-top-right {
|
|
24
|
+
& > * {
|
|
25
|
+
color: @color-black;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
.he-top-right-text {
|
|
29
|
+
font-size: @typescale-2;
|
|
30
|
+
font-weight: @font-weight-bold;
|
|
31
|
+
font-family: @base-font-family;
|
|
32
|
+
margin-right: @spacing-1;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
:global(.profile-dropdown-image) {
|
|
37
|
+
height: 24px;
|
|
38
|
+
width: 24px;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
:global(.profile-dropdown-trigger) {
|
|
42
|
+
height: 32px;
|
|
43
|
+
font-size: @size-links-tiny;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
.navigation-link {
|
|
47
|
+
border-radius: 12px;
|
|
48
|
+
font-size: @size-links-tiny;
|
|
49
|
+
color: inherit;
|
|
50
|
+
|
|
51
|
+
&.navigation-item-active:not(.navigation-item-overflow) {
|
|
52
|
+
background-color: @color-blue-100 !important;
|
|
53
|
+
color: @color-blue-500 !important;
|
|
54
|
+
}
|
|
55
|
+
&:hover:not(.navigation-item-active):not(.navigation-item-overflow) {
|
|
56
|
+
background-color: rgba(0, 0, 0, 0.12) !important;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
&.navigation-item-icon-state.navigation-item-active {
|
|
60
|
+
.navigation-icon:not(.navigation-icon-active) {
|
|
61
|
+
display: none;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
.navigation-icon.navigation-icon-active[data-anv][data-anv] {
|
|
65
|
+
display: block;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
.navigation-icon[data-anv][data-anv] {
|
|
71
|
+
display: inline-block;
|
|
72
|
+
color: inherit;
|
|
73
|
+
height: 24px;
|
|
74
|
+
width: 24px;
|
|
75
|
+
|
|
76
|
+
> svg {
|
|
77
|
+
height: @size-links-tiny;
|
|
78
|
+
width: @size-links-tiny;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
&.navigation-icon-active {
|
|
82
|
+
display: none;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// desktop
|
|
88
|
+
@media only screen and (min-width: 768px) {
|
|
89
|
+
.header {
|
|
90
|
+
height: var(--nav-offset-top);
|
|
91
|
+
.navigation-link {
|
|
92
|
+
margin: 6px 2px;
|
|
93
|
+
padding: 6px 6px;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
.he-top-left {
|
|
97
|
+
padding-left: @spacing-1;
|
|
98
|
+
}
|
|
99
|
+
.he-top-center {
|
|
100
|
+
flex: 1;
|
|
101
|
+
margin-left: @spacing-2;
|
|
102
|
+
margin-right: @spacing-2;
|
|
103
|
+
max-width: 400px;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
// desktop wide
|
|
108
|
+
@media only screen and (min-width: 1200px) {
|
|
109
|
+
.header {
|
|
110
|
+
display: grid;
|
|
111
|
+
grid-template-columns: repeat(3, 1fr);
|
|
112
|
+
grid-template-rows: 48px;
|
|
113
|
+
|
|
114
|
+
.he-top-left,
|
|
115
|
+
.he-top-center,
|
|
116
|
+
.he-top-right {
|
|
117
|
+
grid-column: span 1;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
.he-top-center {
|
|
121
|
+
max-width: unset;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// mobile
|
|
127
|
+
@media only screen and (max-width: 768px) {
|
|
128
|
+
.header {
|
|
129
|
+
padding: @spacing-1 @spacing-half;
|
|
130
|
+
|
|
131
|
+
.navigation-link {
|
|
132
|
+
padding: 10px;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
.he-top-center {
|
|
136
|
+
max-width: unset;
|
|
137
|
+
flex: 1;
|
|
138
|
+
margin-left: @spacing-3;
|
|
139
|
+
margin-right: @spacing-3;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
.navigation-link {
|
|
145
|
+
// styles specific to extra nav links
|
|
146
|
+
color: @color-black;
|
|
147
|
+
position: relative;
|
|
148
|
+
display: flex;
|
|
149
|
+
align-items: center;
|
|
150
|
+
flex-wrap: nowrap;
|
|
151
|
+
text-wrap: nowrap;
|
|
152
|
+
|
|
153
|
+
.navigation-item-counter {
|
|
154
|
+
color: @color-white;
|
|
155
|
+
font-weight: @font-weight-semibold;
|
|
156
|
+
font-size: 8px !important;
|
|
157
|
+
min-width: 12px;
|
|
158
|
+
position: absolute;
|
|
159
|
+
top: 4px;
|
|
160
|
+
right: -2px;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
.navigation-item-label {
|
|
164
|
+
color: inherit;
|
|
165
|
+
font-size: @typescale-1;
|
|
166
|
+
font-family: @base-font-family;
|
|
167
|
+
font-weight: @font-weight-semibold;
|
|
168
|
+
margin-left: @spacing-half;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
&.navigation-item-counter-long {
|
|
172
|
+
right: -8px;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
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 navigationIcon: string;
|
|
8
|
+
export const navigationIconActive: string;
|
|
9
|
+
export const navigationItemActive: string;
|
|
10
|
+
export const navigationItemCounter: string;
|
|
11
|
+
export const navigationItemCounterLong: string;
|
|
12
|
+
export const navigationItemIconState: string;
|
|
13
|
+
export const navigationItemLabel: string;
|
|
14
|
+
export const navigationItemOverflow: string;
|
|
15
|
+
export const navigationLink: string;
|
|
16
|
+
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import SvgBurgerMenu from '@servicetitan/anvil2/assets/icons/material/round/menu.svg';
|
|
2
|
+
import classNames from 'classnames';
|
|
3
|
+
import { ComponentPropsWithoutRef, FC, ReactElement, ReactNode } from 'react';
|
|
4
|
+
import { LayoutPlacementContext, useTitanLayoutContext } from './layout-context';
|
|
5
|
+
import { LayoutHeaderNavigationTrigger } from './layout-header-links';
|
|
6
|
+
import * as Styles from './layout-header.module.less';
|
|
7
|
+
import { TitanLayoutLogoProps } from './layout-logo';
|
|
8
|
+
|
|
9
|
+
export interface TitanLayoutHeaderLogoProps {
|
|
10
|
+
title?: true | string;
|
|
11
|
+
mantleFill?: string;
|
|
12
|
+
to?: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export type LayoutHeaderProps = Omit<ComponentPropsWithoutRef<'div'>, 'children'> & {
|
|
16
|
+
right?: ReactNode;
|
|
17
|
+
rightText?: string;
|
|
18
|
+
rightClassName?: string;
|
|
19
|
+
|
|
20
|
+
id?: string;
|
|
21
|
+
|
|
22
|
+
center?: ReactElement;
|
|
23
|
+
centerClassName?: string;
|
|
24
|
+
|
|
25
|
+
logo: ReactElement<TitanLayoutLogoProps>;
|
|
26
|
+
profile?: ReactElement;
|
|
27
|
+
|
|
28
|
+
onBurgerClick?: (e: MouseEvent) => void;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export const LayoutHeader: FC<LayoutHeaderProps> = ({
|
|
32
|
+
className,
|
|
33
|
+
right,
|
|
34
|
+
rightText,
|
|
35
|
+
rightClassName,
|
|
36
|
+
center,
|
|
37
|
+
centerClassName,
|
|
38
|
+
logo,
|
|
39
|
+
profile,
|
|
40
|
+
onBurgerClick,
|
|
41
|
+
...rest
|
|
42
|
+
}) => {
|
|
43
|
+
const { breakpoint } = useTitanLayoutContext();
|
|
44
|
+
|
|
45
|
+
return (
|
|
46
|
+
<LayoutPlacementContext.Provider value="top">
|
|
47
|
+
<div
|
|
48
|
+
className={classNames(Styles.header, className)}
|
|
49
|
+
{...rest}
|
|
50
|
+
data-cy="header-navigation"
|
|
51
|
+
>
|
|
52
|
+
<div className={classNames(Styles.heTopLeft)} data-cy="navigation-left">
|
|
53
|
+
{breakpoint.isMobile && (
|
|
54
|
+
<LayoutHeaderNavigationTrigger
|
|
55
|
+
id="burger"
|
|
56
|
+
title=""
|
|
57
|
+
icon={SvgBurgerMenu}
|
|
58
|
+
iconActive={SvgBurgerMenu}
|
|
59
|
+
className="m-r-1"
|
|
60
|
+
onClick={onBurgerClick}
|
|
61
|
+
/>
|
|
62
|
+
)}
|
|
63
|
+
{logo}
|
|
64
|
+
</div>
|
|
65
|
+
<div
|
|
66
|
+
className={classNames(
|
|
67
|
+
Styles.heTopCenter,
|
|
68
|
+
'd-f align-items-center justify-content-center',
|
|
69
|
+
centerClassName
|
|
70
|
+
)}
|
|
71
|
+
data-cy="navigation-center"
|
|
72
|
+
>
|
|
73
|
+
{center}
|
|
74
|
+
</div>
|
|
75
|
+
<div
|
|
76
|
+
className={classNames(
|
|
77
|
+
'd-f flex-row justify-content-end align-items-center',
|
|
78
|
+
Styles.heTopRight,
|
|
79
|
+
rightClassName
|
|
80
|
+
)}
|
|
81
|
+
data-cy="navigation-right"
|
|
82
|
+
>
|
|
83
|
+
{!!rightText && <div className={Styles.heTopRightText}>{rightText}</div>}
|
|
84
|
+
{right}
|
|
85
|
+
{profile}
|
|
86
|
+
</div>
|
|
87
|
+
</div>
|
|
88
|
+
</LayoutPlacementContext.Provider>
|
|
89
|
+
);
|
|
90
|
+
};
|