@servicetitan/navigation 10.7.0 → 11.0.0-canary.237.4d902dc.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/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 +6 -3
- 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 +153 -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 +44 -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 +18 -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 +528 -0
- package/dist/components/titan-layout/titan-layout.d.ts +36 -0
- package/dist/components/titan-layout/titan-layout.d.ts.map +1 -0
- package/dist/components/titan-layout/titan-layout.js +109 -0
- package/dist/components/titan-layout/titan-layout.js.map +1 -0
- package/dist/components/titan-layout/titan-layout.module.less +53 -0
- package/dist/components/titan-layout/titan-layout.stories.d.ts +18 -0
- package/dist/components/titan-layout/titan-layout.stories.d.ts.map +1 -0
- package/dist/components/titan-layout/titan-layout.stories.js +62 -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 +4 -0
- package/src/components/header-navigation/header-navigation.stories.tsx +5 -0
- package/src/components/left-navigation/header-navigation-tiny.stories.tsx +6 -0
- 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/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 +43 -46
- 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 +153 -0
- package/src/components/titan-layout/layout-header.module.less.d.ts +16 -0
- package/src/components/titan-layout/layout-header.tsx +86 -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 +37 -0
- package/src/components/titan-layout/layout-profile.tsx +116 -0
- package/src/components/titan-layout/layout-sidebar-links-internal.tsx +265 -0
- package/src/components/titan-layout/layout-sidebar-links.tsx +56 -0
- package/src/components/titan-layout/layout-sidebar.module.less +528 -0
- package/src/components/titan-layout/layout-sidebar.module.less.d.ts +50 -0
- package/src/components/titan-layout/layout-sidebar.tsx +298 -0
- package/src/components/titan-layout/titan-layout.module.less +53 -0
- package/src/components/titan-layout/titan-layout.module.less.d.ts +11 -0
- package/src/components/titan-layout/titan-layout.stories.tsx +194 -0
- package/src/components/titan-layout/titan-layout.tsx +270 -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
package/src/components/links.tsx
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { FC
|
|
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
|
-
|
|
13
|
-
|
|
14
|
-
} from './
|
|
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
|
|
21
|
+
const placement = useTitanLayoutPlacementContext();
|
|
18
22
|
|
|
19
|
-
return
|
|
20
|
-
<
|
|
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
|
-
<
|
|
35
|
+
<HeaderNavigationLinkLegacy {...props} />
|
|
23
36
|
);
|
|
24
37
|
};
|
|
25
38
|
|
|
26
39
|
export const HeaderNavigationTrigger: FC<HeaderNavigationTriggerProps> = props => {
|
|
27
|
-
const
|
|
40
|
+
const placement = useTitanLayoutPlacementContext();
|
|
28
41
|
|
|
29
|
-
return
|
|
30
|
-
<
|
|
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
|
-
<
|
|
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<{
|
|
5
|
-
className
|
|
6
|
-
fill
|
|
7
|
-
size
|
|
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
|
>
|
|
@@ -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.
|
|
24
|
+
<ProfileDropdown.Section id="second" onClick={() => alert('second click')}>
|
|
25
25
|
second link
|
|
26
|
-
</ProfileDropdown.
|
|
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.
|
|
48
|
+
<ProfileDropdown.Section id="second" onClick={() => alert('second click')}>
|
|
49
49
|
second link
|
|
50
|
-
</ProfileDropdown.
|
|
50
|
+
</ProfileDropdown.Section>
|
|
51
51
|
</ProfileDropdown>
|
|
52
52
|
);
|
|
53
53
|
|
|
@@ -25,6 +25,7 @@ import {
|
|
|
25
25
|
} from '../../utils/navigation-context';
|
|
26
26
|
import { getCounterTag } from '../../utils/side-nav';
|
|
27
27
|
import { CounterTag } from '../counter-tag';
|
|
28
|
+
import { withTooltip } from '../titan-layout/with-tooltip';
|
|
28
29
|
import * as Styles from './profile-dropdown.module.less';
|
|
29
30
|
import { ProfileLogo } from './profile-icon';
|
|
30
31
|
|
|
@@ -149,11 +150,12 @@ const ProfileDropdownTrigger: FC<ProfileDropdownTriggerProps> = ({
|
|
|
149
150
|
export interface ProfileDropdownSectionPropsStrict {
|
|
150
151
|
children: ReactNode;
|
|
151
152
|
id: string;
|
|
153
|
+
tooltip?: string;
|
|
152
154
|
className?: string;
|
|
153
155
|
onClick?(e: MouseEvent): void;
|
|
154
156
|
}
|
|
155
157
|
|
|
156
|
-
interface ProfileDropdownSectionProps extends ProfileDropdownSectionPropsStrict {
|
|
158
|
+
export interface ProfileDropdownSectionProps extends ProfileDropdownSectionPropsStrict {
|
|
157
159
|
[key: string]: any;
|
|
158
160
|
}
|
|
159
161
|
|
|
@@ -161,6 +163,7 @@ export const ProfileDropdownSection: FC<ProfileDropdownSectionProps> = ({
|
|
|
161
163
|
children,
|
|
162
164
|
className,
|
|
163
165
|
id,
|
|
166
|
+
tooltip,
|
|
164
167
|
onClick,
|
|
165
168
|
...rest
|
|
166
169
|
}) => {
|
|
@@ -172,16 +175,20 @@ export const ProfileDropdownSection: FC<ProfileDropdownSectionProps> = ({
|
|
|
172
175
|
}
|
|
173
176
|
};
|
|
174
177
|
|
|
175
|
-
return (
|
|
178
|
+
return withTooltip(
|
|
176
179
|
<div
|
|
177
|
-
className={classNames(Styles.dropdownSection, className
|
|
180
|
+
className={classNames(Styles.dropdownSection, className, {
|
|
181
|
+
'cursor-pointer': !!onClick,
|
|
182
|
+
})}
|
|
178
183
|
onClick={clickHandler}
|
|
179
184
|
data-cy={`profile-dropdown-section-${id}`}
|
|
180
185
|
data-pendo={`profile-dropdown-section-${id}`}
|
|
181
186
|
{...rest}
|
|
182
187
|
>
|
|
183
188
|
{children}
|
|
184
|
-
</div
|
|
189
|
+
</div>,
|
|
190
|
+
tooltip,
|
|
191
|
+
'left'
|
|
185
192
|
);
|
|
186
193
|
};
|
|
187
194
|
|
|
@@ -193,10 +200,10 @@ export interface ProfileDropdownLinkPropsStrict {
|
|
|
193
200
|
className?: string;
|
|
194
201
|
external?: boolean;
|
|
195
202
|
target?: HTMLAttributeAnchorTarget;
|
|
196
|
-
|
|
203
|
+
tooltip?: string;
|
|
204
|
+
to: string;
|
|
197
205
|
tag?: CounterTagData;
|
|
198
206
|
counter?: CounterTagValue;
|
|
199
|
-
onClick?: () => void;
|
|
200
207
|
}
|
|
201
208
|
|
|
202
209
|
export interface ProfileDropdownLinkProps extends ProfileDropdownLinkPropsStrict {
|
|
@@ -212,16 +219,12 @@ export const ProfileDropdownLink: FC<ProfileDropdownLinkProps> = ({
|
|
|
212
219
|
tag,
|
|
213
220
|
target,
|
|
214
221
|
to,
|
|
222
|
+
tooltip,
|
|
215
223
|
onClick,
|
|
216
224
|
...rest
|
|
217
225
|
}: ProfileDropdownLinkProps) => {
|
|
218
226
|
const NavigationComponent = useContext(NavigationComponentContext);
|
|
219
227
|
|
|
220
|
-
const clickHandler = (e: MouseEvent<any>) => {
|
|
221
|
-
e.preventDefault();
|
|
222
|
-
onClick?.();
|
|
223
|
-
};
|
|
224
|
-
|
|
225
228
|
const isExternalLink = external ?? to?.startsWith('http');
|
|
226
229
|
|
|
227
230
|
const tagElement = useMemo(
|
|
@@ -229,41 +232,34 @@ export const ProfileDropdownLink: FC<ProfileDropdownLinkProps> = ({
|
|
|
229
232
|
[counter, tag]
|
|
230
233
|
);
|
|
231
234
|
|
|
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>
|
|
235
|
+
return withTooltip(
|
|
236
|
+
isExternalLink ? (
|
|
237
|
+
<a
|
|
238
|
+
className={classNames(Styles.dropdownSection, Styles.dropdownLink, className)}
|
|
239
|
+
href={to}
|
|
240
|
+
target={target}
|
|
241
|
+
data-cy={`profile-dropdown-link-${id}`}
|
|
242
|
+
data-pendo={`profile-dropdown-link-${id}`}
|
|
243
|
+
{...rest}
|
|
244
|
+
>
|
|
245
|
+
{children}
|
|
246
|
+
{tagElement}
|
|
247
|
+
</a>
|
|
248
|
+
) : (
|
|
249
|
+
<NavigationComponent
|
|
250
|
+
className={classNames(Styles.dropdownSection, Styles.dropdownLink, className)}
|
|
251
|
+
target={target}
|
|
252
|
+
to={to}
|
|
253
|
+
data-cy={`profile-dropdown-link-${id}`}
|
|
254
|
+
data-pendo={`profile-dropdown-link-${id}`}
|
|
255
|
+
{...rest}
|
|
256
|
+
>
|
|
257
|
+
{children}
|
|
258
|
+
{tagElement}
|
|
259
|
+
</NavigationComponent>
|
|
260
|
+
),
|
|
261
|
+
tooltip,
|
|
262
|
+
'left'
|
|
267
263
|
);
|
|
268
264
|
};
|
|
269
265
|
|
|
@@ -291,6 +287,7 @@ export interface ProfileDropdownProps extends ProfileDropdownPropsStrict {
|
|
|
291
287
|
export interface ProfileDropdownType extends FC<ProfileDropdownProps> {
|
|
292
288
|
Divider: typeof ProfileDropdownDivider;
|
|
293
289
|
Link: typeof ProfileDropdownLink;
|
|
290
|
+
Trigger: typeof ProfileDropdownTrigger;
|
|
294
291
|
Section: typeof ProfileDropdownSection;
|
|
295
292
|
}
|
|
296
293
|
|
|
@@ -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,153 @@
|
|
|
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: grid;
|
|
8
|
+
|
|
9
|
+
background-color: @color-white;
|
|
10
|
+
color: @color-black;
|
|
11
|
+
|
|
12
|
+
& > * {
|
|
13
|
+
overflow-y: hidden;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
.he-top-left {
|
|
17
|
+
grid-column: span 1;
|
|
18
|
+
display: flex;
|
|
19
|
+
align-items: center;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
.he-top-center {
|
|
23
|
+
grid-column: span 1;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
.he-top-right {
|
|
27
|
+
grid-column: span 1;
|
|
28
|
+
|
|
29
|
+
& > * {
|
|
30
|
+
color: @color-black;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
.he-top-right-text {
|
|
34
|
+
font-size: @typescale-2;
|
|
35
|
+
font-weight: @font-weight-bold;
|
|
36
|
+
font-family: @base-font-family;
|
|
37
|
+
margin-right: @spacing-1;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
:global(.profile-dropdown-image) {
|
|
42
|
+
height: 24px;
|
|
43
|
+
width: 24px;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
:global(.profile-dropdown-trigger) {
|
|
47
|
+
height: 32px;
|
|
48
|
+
font-size: @size-links-tiny;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
.navigation-link {
|
|
52
|
+
border-radius: 12px;
|
|
53
|
+
font-size: @size-links-tiny;
|
|
54
|
+
color: inherit;
|
|
55
|
+
|
|
56
|
+
&.navigation-item-active:not(.navigation-item-overflow) {
|
|
57
|
+
background-color: @color-blue-100 !important;
|
|
58
|
+
color: @color-blue-500 !important;
|
|
59
|
+
}
|
|
60
|
+
&:hover:not(.navigation-item-active):not(.navigation-item-overflow) {
|
|
61
|
+
background-color: rgba(0, 0, 0, 0.12) !important;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
&.navigation-item-icon-state.navigation-item-active {
|
|
65
|
+
.navigation-icon:not(.navigation-icon-active) {
|
|
66
|
+
display: none;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
.navigation-icon.navigation-icon-active[data-anv][data-anv] {
|
|
70
|
+
display: block;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
.navigation-icon[data-anv][data-anv] {
|
|
76
|
+
display: inline-block;
|
|
77
|
+
color: inherit;
|
|
78
|
+
height: 24px;
|
|
79
|
+
width: 24px;
|
|
80
|
+
|
|
81
|
+
> svg {
|
|
82
|
+
height: @size-links-tiny;
|
|
83
|
+
width: @size-links-tiny;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
&.navigation-icon-active {
|
|
87
|
+
display: none;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// desktop
|
|
93
|
+
@media only screen and (min-width: 768px) {
|
|
94
|
+
.header {
|
|
95
|
+
grid-template-columns: repeat(3, 1fr);
|
|
96
|
+
grid-template-rows: 48px;
|
|
97
|
+
|
|
98
|
+
.navigation-link {
|
|
99
|
+
margin: 6px 2px;
|
|
100
|
+
padding: 6px 6px;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
.he-top-left {
|
|
105
|
+
padding-left: @spacing-1;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// mobile
|
|
110
|
+
@media only screen and (max-width: 768px) {
|
|
111
|
+
.header {
|
|
112
|
+
grid-template-columns: repeat(3, 1fr);
|
|
113
|
+
grid-template-rows: 44px;
|
|
114
|
+
|
|
115
|
+
padding: @spacing-1 @spacing-half;
|
|
116
|
+
|
|
117
|
+
.navigation-link {
|
|
118
|
+
padding: 10px;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
.navigation-link {
|
|
124
|
+
// styles specific to extra nav links
|
|
125
|
+
color: @color-black;
|
|
126
|
+
position: relative;
|
|
127
|
+
display: flex;
|
|
128
|
+
align-items: center;
|
|
129
|
+
flex-wrap: nowrap;
|
|
130
|
+
text-wrap: nowrap;
|
|
131
|
+
|
|
132
|
+
.navigation-item-counter {
|
|
133
|
+
color: @color-white;
|
|
134
|
+
font-weight: @font-weight-semibold;
|
|
135
|
+
font-size: 8px !important;
|
|
136
|
+
min-width: 12px;
|
|
137
|
+
position: absolute;
|
|
138
|
+
top: 4px;
|
|
139
|
+
right: -2px;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
.navigation-item-label {
|
|
143
|
+
color: inherit;
|
|
144
|
+
font-size: @typescale-1;
|
|
145
|
+
font-family: @base-font-family;
|
|
146
|
+
font-weight: @font-weight-semibold;
|
|
147
|
+
margin-left: @spacing-half;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
&.navigation-item-counter-long {
|
|
151
|
+
right: -8px;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
@@ -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
|
+
|