@servicetitan/navigation 11.0.0-canary.237.0c461af.0 → 11.0.0-canary.237.1127df0.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/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.module.less +2 -0
- package/dist/components/titan-layout/layout-context.js +1 -1
- package/dist/components/titan-layout/layout-context.js.map +1 -1
- package/dist/components/titan-layout/layout-header.d.ts +2 -0
- package/dist/components/titan-layout/layout-header.d.ts.map +1 -1
- package/dist/components/titan-layout/layout-header.js +3 -4
- package/dist/components/titan-layout/layout-header.js.map +1 -1
- package/dist/components/titan-layout/layout-header.module.less +55 -36
- package/dist/components/titan-layout/layout-logo.d.ts.map +1 -1
- package/dist/components/titan-layout/layout-logo.js +2 -1
- package/dist/components/titan-layout/layout-logo.js.map +1 -1
- package/dist/components/titan-layout/layout-profile.d.ts.map +1 -1
- package/dist/components/titan-layout/layout-profile.js +29 -15
- package/dist/components/titan-layout/layout-profile.js.map +1 -1
- package/dist/components/titan-layout/layout-sidebar-links-internal.d.ts +2 -2
- package/dist/components/titan-layout/layout-sidebar-links-internal.d.ts.map +1 -1
- package/dist/components/titan-layout/layout-sidebar-links-internal.js +2 -2
- package/dist/components/titan-layout/layout-sidebar-links-internal.js.map +1 -1
- package/dist/components/titan-layout/layout-sidebar-links.d.ts.map +1 -1
- package/dist/components/titan-layout/layout-sidebar-links.js +10 -3
- package/dist/components/titan-layout/layout-sidebar-links.js.map +1 -1
- package/dist/components/titan-layout/layout-sidebar.d.ts +2 -0
- package/dist/components/titan-layout/layout-sidebar.d.ts.map +1 -1
- package/dist/components/titan-layout/layout-sidebar.js +6 -4
- package/dist/components/titan-layout/layout-sidebar.js.map +1 -1
- package/dist/components/titan-layout/layout-sidebar.module.less +25 -5
- 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 +5 -3
- package/dist/components/titan-layout/titan-layout.d.ts.map +1 -1
- package/dist/components/titan-layout/titan-layout.js +73 -28
- package/dist/components/titan-layout/titan-layout.js.map +1 -1
- package/dist/components/titan-layout/titan-layout.module.less +9 -6
- package/dist/components/titan-layout/titan-layout.stories.d.ts +2 -0
- package/dist/components/titan-layout/titan-layout.stories.d.ts.map +1 -1
- package/dist/components/titan-layout/titan-layout.stories.js +8 -5
- package/dist/components/titan-layout/titan-layout.stories.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 +2 -3
- package/dist/test/data.js.map +1 -1
- package/dist/utils/use-breakpoint.d.ts +1 -0
- package/dist/utils/use-breakpoint.d.ts.map +1 -1
- package/dist/utils/use-breakpoint.js +3 -2
- package/dist/utils/use-breakpoint.js.map +1 -1
- package/package.json +2 -2
- package/src/components/badge-tag.tsx +1 -1
- package/src/components/logo/logo-titan-text.tsx +1 -1
- package/src/components/profile-dropdown/profile-dropdown.module.less +2 -0
- package/src/components/titan-layout/layout-context.tsx +1 -1
- package/src/components/titan-layout/layout-header.module.less +55 -36
- package/src/components/titan-layout/layout-header.module.less.d.ts +2 -0
- package/src/components/titan-layout/layout-header.tsx +12 -5
- package/src/components/titan-layout/layout-logo.tsx +13 -6
- package/src/components/titan-layout/layout-profile.tsx +71 -32
- package/src/components/titan-layout/layout-sidebar-links-internal.tsx +6 -3
- package/src/components/titan-layout/layout-sidebar-links.tsx +16 -3
- package/src/components/titan-layout/layout-sidebar.module.less +25 -5
- package/src/components/titan-layout/layout-sidebar.module.less.d.ts +1 -0
- package/src/components/titan-layout/layout-sidebar.tsx +14 -5
- package/src/components/titan-layout/notifications-context.tsx +44 -0
- package/src/components/titan-layout/titan-layout.module.less +9 -6
- package/src/components/titan-layout/titan-layout.module.less.d.ts +1 -0
- package/src/components/titan-layout/titan-layout.stories.tsx +13 -4
- package/src/components/titan-layout/titan-layout.tsx +203 -107
- package/src/test/data.tsx +2 -3
- package/src/utils/use-breakpoint.ts +3 -1
|
@@ -3,10 +3,11 @@ import { useMemo } from 'react';
|
|
|
3
3
|
export const useTitanBreakpoint = () => {
|
|
4
4
|
const breakpoint = useBreakpoint();
|
|
5
5
|
return useMemo(() => {
|
|
6
|
-
var _a;
|
|
6
|
+
var _a, _b;
|
|
7
7
|
return ({
|
|
8
8
|
name: (_a = breakpoint === null || breakpoint === void 0 ? void 0 : breakpoint.name) !== null && _a !== void 0 ? _a : 'xl',
|
|
9
|
-
isMobile: breakpoint ? breakpoint.innerWidth
|
|
9
|
+
isMobile: breakpoint ? breakpoint.innerWidth < 768 : false,
|
|
10
|
+
width: (_b = breakpoint === null || breakpoint === void 0 ? void 0 : breakpoint.innerWidth) !== null && _b !== void 0 ? _b : 0,
|
|
10
11
|
});
|
|
11
12
|
}, [breakpoint]);
|
|
12
13
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-breakpoint.js","sourceRoot":"","sources":["../../src/utils/use-breakpoint.ts"],"names":[],"mappings":"AAAA,OAAO,EAAyB,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAC5E,OAAO,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"use-breakpoint.js","sourceRoot":"","sources":["../../src/utils/use-breakpoint.ts"],"names":[],"mappings":"AAAA,OAAO,EAAyB,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAC5E,OAAO,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAQhC,MAAM,CAAC,MAAM,kBAAkB,GAAG,GAAoB,EAAE;IACpD,MAAM,UAAU,GAAG,aAAa,EAAE,CAAC;IAEnC,OAAO,OAAO,CACV,GAAG,EAAE;;QAAC,OAAA,CAAC;YACH,IAAI,EAAE,MAAA,UAAU,aAAV,UAAU,uBAAV,UAAU,CAAE,IAAI,mCAAI,IAAI;YAC9B,QAAQ,EAAE,UAAU,CAAC,CAAC,CAAC,UAAU,CAAC,UAAU,GAAG,GAAG,CAAC,CAAC,CAAC,KAAK;YAC1D,KAAK,EAAE,MAAA,UAAU,aAAV,UAAU,uBAAV,UAAU,CAAE,UAAU,mCAAI,CAAC;SACrC,CAAC,CAAA;KAAA,EACF,CAAC,UAAU,CAAC,CACf,CAAC;AACN,CAAC,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@servicetitan/navigation",
|
|
3
|
-
"version": "11.0.0-canary.237.
|
|
3
|
+
"version": "11.0.0-canary.237.1127df0.0",
|
|
4
4
|
"description": "Navigation components",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -42,5 +42,5 @@
|
|
|
42
42
|
"less": true,
|
|
43
43
|
"webpack": false
|
|
44
44
|
},
|
|
45
|
-
"gitHead": "
|
|
45
|
+
"gitHead": "1127df0cf95ea4e6e4b074bf79895bed386049c9"
|
|
46
46
|
}
|
|
@@ -3,7 +3,7 @@ import { CSSProperties, FC, ReactNode } from 'react';
|
|
|
3
3
|
import { LogoTitanSvg } from './logo-titan';
|
|
4
4
|
import * as Styles from './logo-titan-text.module.less';
|
|
5
5
|
|
|
6
|
-
export type WrapperProps = FC<{ className
|
|
6
|
+
export type WrapperProps = FC<{ className?: string; children: ReactNode; style?: CSSProperties }>;
|
|
7
7
|
|
|
8
8
|
export interface LogoTitanProps {
|
|
9
9
|
mantleFill?: string;
|
|
@@ -19,7 +19,7 @@ export interface TitanLayoutContextType {
|
|
|
19
19
|
|
|
20
20
|
export const LayoutContext = createContext<TitanLayoutContextType>({
|
|
21
21
|
NavigationComponent: DefaultNavLinkComponent,
|
|
22
|
-
breakpoint: { name: 'lg', isMobile: false },
|
|
22
|
+
breakpoint: { name: 'lg', isMobile: false, width: 0 },
|
|
23
23
|
isTitanLayout: false,
|
|
24
24
|
sidebar: { styles: { popoverContent: {} } },
|
|
25
25
|
});
|
|
@@ -4,12 +4,14 @@
|
|
|
4
4
|
@size-links-tiny: 24px;
|
|
5
5
|
|
|
6
6
|
.header {
|
|
7
|
+
--nav-top-content-height: 32px;
|
|
7
8
|
display: flex;
|
|
8
9
|
justify-content: space-between;
|
|
9
10
|
|
|
10
11
|
background-color: @color-white;
|
|
11
12
|
color: @color-black;
|
|
12
|
-
|
|
13
|
+
box-sizing: border-box;
|
|
14
|
+
outline: 1px solid @color-neutral-60;
|
|
13
15
|
|
|
14
16
|
& > * {
|
|
15
17
|
overflow-y: hidden;
|
|
@@ -20,6 +22,10 @@
|
|
|
20
22
|
align-items: center;
|
|
21
23
|
}
|
|
22
24
|
|
|
25
|
+
.he-top-center {
|
|
26
|
+
overflow: hidden;
|
|
27
|
+
}
|
|
28
|
+
|
|
23
29
|
.he-top-right {
|
|
24
30
|
& > * {
|
|
25
31
|
color: @color-black;
|
|
@@ -84,29 +90,59 @@
|
|
|
84
90
|
}
|
|
85
91
|
}
|
|
86
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
|
+
|
|
87
119
|
// desktop
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
padding: 6px 6px;
|
|
94
|
-
}
|
|
120
|
+
.header-desktop {
|
|
121
|
+
height: var(--nav-offset-top);
|
|
122
|
+
.navigation-link {
|
|
123
|
+
margin: 6px 2px;
|
|
124
|
+
padding: 6px 6px;
|
|
95
125
|
|
|
96
|
-
.
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
.he-top-center {
|
|
100
|
-
flex: 1;
|
|
101
|
-
margin-left: @spacing-2;
|
|
102
|
-
margin-right: @spacing-2;
|
|
103
|
-
max-width: 400px;
|
|
126
|
+
.navigation-item-counter {
|
|
127
|
+
min-width: 12px !important;
|
|
128
|
+
height: 12px !important;
|
|
104
129
|
}
|
|
105
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
|
+
}
|
|
106
141
|
}
|
|
142
|
+
|
|
107
143
|
// desktop wide
|
|
108
144
|
@media only screen and (min-width: 1200px) {
|
|
109
|
-
.header {
|
|
145
|
+
.header-desktop {
|
|
110
146
|
display: grid;
|
|
111
147
|
grid-template-columns: repeat(3, 1fr);
|
|
112
148
|
grid-template-rows: 48px;
|
|
@@ -123,24 +159,6 @@
|
|
|
123
159
|
}
|
|
124
160
|
}
|
|
125
161
|
|
|
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
162
|
.navigation-link {
|
|
145
163
|
// styles specific to extra nav links
|
|
146
164
|
color: @color-black;
|
|
@@ -154,7 +172,8 @@
|
|
|
154
172
|
color: @color-white;
|
|
155
173
|
font-weight: @font-weight-semibold;
|
|
156
174
|
font-size: 8px !important;
|
|
157
|
-
min-width:
|
|
175
|
+
min-width: 16px !important;
|
|
176
|
+
height: 16px !important;
|
|
158
177
|
position: absolute;
|
|
159
178
|
top: 4px;
|
|
160
179
|
right: -2px;
|
|
@@ -4,6 +4,8 @@ export const heTopLeft: string;
|
|
|
4
4
|
export const heTopRight: string;
|
|
5
5
|
export const heTopRightText: string;
|
|
6
6
|
export const header: string;
|
|
7
|
+
export const headerDesktop: string;
|
|
8
|
+
export const headerMobile: string;
|
|
7
9
|
export const navigationIcon: string;
|
|
8
10
|
export const navigationIconActive: string;
|
|
9
11
|
export const navigationItemActive: string;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import SvgBurgerMenu from '@servicetitan/anvil2/assets/icons/material/round/menu.svg';
|
|
2
2
|
import classNames from 'classnames';
|
|
3
3
|
import { ComponentPropsWithoutRef, FC, ReactElement, ReactNode } from 'react';
|
|
4
|
-
import { LayoutPlacementContext
|
|
4
|
+
import { LayoutPlacementContext } from './layout-context';
|
|
5
5
|
import { LayoutHeaderNavigationTrigger } from './layout-header-links';
|
|
6
6
|
import * as Styles from './layout-header.module.less';
|
|
7
7
|
import { TitanLayoutLogoProps } from './layout-logo';
|
|
@@ -25,6 +25,8 @@ export type LayoutHeaderProps = Omit<ComponentPropsWithoutRef<'div'>, 'children'
|
|
|
25
25
|
logo: ReactElement<TitanLayoutLogoProps>;
|
|
26
26
|
profile?: ReactElement;
|
|
27
27
|
|
|
28
|
+
isMobile: boolean;
|
|
29
|
+
hasNotifications: boolean;
|
|
28
30
|
onBurgerClick?: (e: MouseEvent) => void;
|
|
29
31
|
};
|
|
30
32
|
|
|
@@ -35,22 +37,26 @@ export const LayoutHeader: FC<LayoutHeaderProps> = ({
|
|
|
35
37
|
rightClassName,
|
|
36
38
|
center,
|
|
37
39
|
centerClassName,
|
|
40
|
+
isMobile,
|
|
41
|
+
hasNotifications,
|
|
38
42
|
logo,
|
|
39
43
|
profile,
|
|
40
44
|
onBurgerClick,
|
|
41
45
|
...rest
|
|
42
46
|
}) => {
|
|
43
|
-
const { breakpoint } = useTitanLayoutContext();
|
|
44
|
-
|
|
45
47
|
return (
|
|
46
48
|
<LayoutPlacementContext.Provider value="top">
|
|
47
49
|
<div
|
|
48
|
-
className={classNames(
|
|
50
|
+
className={classNames(
|
|
51
|
+
Styles.header,
|
|
52
|
+
isMobile ? Styles.headerMobile : Styles.headerDesktop,
|
|
53
|
+
className
|
|
54
|
+
)}
|
|
49
55
|
{...rest}
|
|
50
56
|
data-cy="header-navigation"
|
|
51
57
|
>
|
|
52
58
|
<div className={classNames(Styles.heTopLeft)} data-cy="navigation-left">
|
|
53
|
-
{
|
|
59
|
+
{isMobile && (
|
|
54
60
|
<LayoutHeaderNavigationTrigger
|
|
55
61
|
id="burger"
|
|
56
62
|
title=""
|
|
@@ -58,6 +64,7 @@ export const LayoutHeader: FC<LayoutHeaderProps> = ({
|
|
|
58
64
|
iconActive={SvgBurgerMenu}
|
|
59
65
|
className="m-r-1"
|
|
60
66
|
onClick={onBurgerClick}
|
|
67
|
+
tag={{ value: hasNotifications }}
|
|
61
68
|
/>
|
|
62
69
|
)}
|
|
63
70
|
{logo}
|
|
@@ -33,20 +33,27 @@ export const TitanLayoutLogo: FC<TitanLayoutLogoProps> = ({
|
|
|
33
33
|
const Wrapper = logoWrapper;
|
|
34
34
|
const logoSize = isMobile ? 44 : 56;
|
|
35
35
|
const logoCompanySize = 48;
|
|
36
|
+
const showCompanyTitle = title === true && !isMobile;
|
|
36
37
|
|
|
37
38
|
return (
|
|
38
|
-
<div
|
|
39
|
-
{
|
|
39
|
+
<div
|
|
40
|
+
className={classNames(
|
|
41
|
+
'd-f align-items-center',
|
|
42
|
+
{ 'p-t-half': showCompanyTitle },
|
|
43
|
+
className
|
|
44
|
+
)}
|
|
45
|
+
>
|
|
46
|
+
{showCompanyTitle ? (
|
|
47
|
+
<Wrapper>
|
|
48
|
+
<LogoCompanyTitle height={logoCompanySize} />
|
|
49
|
+
</Wrapper>
|
|
50
|
+
) : typeof title === 'string' ? (
|
|
40
51
|
<Fragment>
|
|
41
52
|
<LogoTitan size={logoSize} mantleFill={mantleFill} logoWrapper={Wrapper} />
|
|
42
53
|
{!isMobile && (
|
|
43
54
|
<LogoTitanTitle className="c-inherit m-l-1">{title}</LogoTitanTitle>
|
|
44
55
|
)}
|
|
45
56
|
</Fragment>
|
|
46
|
-
) : title === true && !isMobile ? (
|
|
47
|
-
<Wrapper className="">
|
|
48
|
-
<LogoCompanyTitle height={logoCompanySize} />
|
|
49
|
-
</Wrapper>
|
|
50
57
|
) : (
|
|
51
58
|
<LogoTitan size={logoSize} mantleFill={mantleFill} logoWrapper={Wrapper} />
|
|
52
59
|
)}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import SvgAccountActive from '@servicetitan/anvil2/assets/icons/st/gnav_account_active.svg';
|
|
2
2
|
import SvgAccountInactive from '@servicetitan/anvil2/assets/icons/st/gnav_account_inactive.svg';
|
|
3
3
|
|
|
4
|
-
import { FC, useState } from 'react';
|
|
4
|
+
import { FC, MouseEvent, useEffect, useState } from 'react';
|
|
5
5
|
import { NavLinkComponentProps, NavigationComponentContext } from '../../utils/navigation-context';
|
|
6
6
|
import {
|
|
7
7
|
ProfileDropdown as DesktopProfileDropdown,
|
|
@@ -17,6 +17,7 @@ import {
|
|
|
17
17
|
InternalSideNavigationGroupLink,
|
|
18
18
|
InternalSideNavigationGroupTrigger,
|
|
19
19
|
} from './layout-sidebar-links-internal';
|
|
20
|
+
import { useNotificationsContext, useNotificationsState } from './notifications-context';
|
|
20
21
|
|
|
21
22
|
export type {
|
|
22
23
|
ProfileDropdownProps,
|
|
@@ -24,8 +25,16 @@ export type {
|
|
|
24
25
|
ProfileDropdownLinkProps,
|
|
25
26
|
} from '../profile-dropdown/profile-dropdown';
|
|
26
27
|
|
|
27
|
-
const ExternalNavComponent: FC<NavLinkComponentProps> = ({
|
|
28
|
-
|
|
28
|
+
const ExternalNavComponent: FC<NavLinkComponentProps> = ({
|
|
29
|
+
children,
|
|
30
|
+
isActive,
|
|
31
|
+
to,
|
|
32
|
+
activeClassName,
|
|
33
|
+
...props
|
|
34
|
+
}) => (
|
|
35
|
+
<a {...props} href={to}>
|
|
36
|
+
{children}
|
|
37
|
+
</a>
|
|
29
38
|
);
|
|
30
39
|
|
|
31
40
|
const ProfileDropdownContent: FC<ProfileDropdownProps> = props => {
|
|
@@ -44,24 +53,37 @@ const MobileProfileDropdown: FC<ProfileDropdownProps & NavigationComponentProps>
|
|
|
44
53
|
children,
|
|
45
54
|
...props
|
|
46
55
|
}) => {
|
|
56
|
+
const id = '__profile';
|
|
47
57
|
const [expanded, setExpanded] = useState(false);
|
|
48
|
-
const
|
|
58
|
+
const { hasNotifications, NotificationsContextProvider } = useNotificationsState();
|
|
59
|
+
const { onNotificationsUpdate } = useNotificationsContext();
|
|
60
|
+
const onExpandToggle = (e: MouseEvent<never>) => {
|
|
61
|
+
e.stopPropagation();
|
|
62
|
+
setExpanded(!expanded);
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
useEffect(() => {
|
|
66
|
+
onNotificationsUpdate(id, hasNotifications);
|
|
67
|
+
}, [hasNotifications, onNotificationsUpdate]);
|
|
68
|
+
|
|
49
69
|
return (
|
|
50
|
-
<
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
70
|
+
<NotificationsContextProvider>
|
|
71
|
+
<InternalSideNavigationGroup
|
|
72
|
+
id={id}
|
|
73
|
+
to={undefined}
|
|
74
|
+
title="Profile"
|
|
75
|
+
icon={SvgAccountInactive}
|
|
76
|
+
iconActive={SvgAccountActive}
|
|
77
|
+
isActive={expanded}
|
|
78
|
+
{...props}
|
|
79
|
+
submenuExpanded={expanded}
|
|
80
|
+
onExpandToggle={onExpandToggle}
|
|
81
|
+
onClick={onExpandToggle}
|
|
82
|
+
tag={{ value: hasNotifications }}
|
|
83
|
+
>
|
|
84
|
+
{children}
|
|
85
|
+
</InternalSideNavigationGroup>
|
|
86
|
+
</NotificationsContextProvider>
|
|
65
87
|
);
|
|
66
88
|
};
|
|
67
89
|
|
|
@@ -74,13 +96,13 @@ const ProfileDropdownDivider: FC = () => {
|
|
|
74
96
|
);
|
|
75
97
|
};
|
|
76
98
|
|
|
77
|
-
const getText = (
|
|
78
|
-
if (typeof
|
|
79
|
-
return
|
|
99
|
+
const getText = (children: any, text: any): string | undefined => {
|
|
100
|
+
if (typeof children === 'string') {
|
|
101
|
+
return children;
|
|
80
102
|
}
|
|
81
103
|
|
|
82
|
-
if (typeof
|
|
83
|
-
return
|
|
104
|
+
if (typeof text === 'string') {
|
|
105
|
+
return text;
|
|
84
106
|
}
|
|
85
107
|
|
|
86
108
|
return undefined;
|
|
@@ -94,10 +116,19 @@ const ProfileDropdownSection: FC<ProfileDropdownSectionProps> = props => {
|
|
|
94
116
|
<DesktopProfileDropdown.Section {...props} />
|
|
95
117
|
);
|
|
96
118
|
};
|
|
97
|
-
const MobileProfileDropdownSection: FC<ProfileDropdownSectionProps> =
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
119
|
+
const MobileProfileDropdownSection: FC<ProfileDropdownSectionProps> = ({
|
|
120
|
+
children,
|
|
121
|
+
text,
|
|
122
|
+
tooltip,
|
|
123
|
+
...props
|
|
124
|
+
}) => {
|
|
125
|
+
const sectionText = getText(children, text);
|
|
126
|
+
return sectionText ? (
|
|
127
|
+
<InternalSideNavigationGroupTrigger
|
|
128
|
+
id={props.id}
|
|
129
|
+
title={sectionText}
|
|
130
|
+
onClick={props.onClick}
|
|
131
|
+
/>
|
|
101
132
|
) : null;
|
|
102
133
|
};
|
|
103
134
|
|
|
@@ -110,17 +141,25 @@ const ProfileDropdownLink: FC<ProfileDropdownLinkProps> = props => {
|
|
|
110
141
|
);
|
|
111
142
|
};
|
|
112
143
|
const MobileProfileDropdownLink: FC<ProfileDropdownLinkProps & NavigationComponentProps> = ({
|
|
144
|
+
external,
|
|
113
145
|
to,
|
|
146
|
+
tooltip,
|
|
147
|
+
text,
|
|
148
|
+
children,
|
|
114
149
|
navigationComponent,
|
|
115
150
|
...props
|
|
116
151
|
}) => {
|
|
117
|
-
const
|
|
118
|
-
|
|
152
|
+
const { onNotificationsUpdate } = useNotificationsContext();
|
|
153
|
+
const linkText = getText(children, text);
|
|
154
|
+
const isExternalLink = external ?? to?.startsWith('http');
|
|
155
|
+
onNotificationsUpdate(props.id, !!props.tag?.value);
|
|
156
|
+
|
|
157
|
+
return linkText ? (
|
|
119
158
|
<InternalSideNavigationGroupLink
|
|
120
159
|
{...props}
|
|
121
160
|
to={to}
|
|
122
|
-
title={
|
|
123
|
-
navigationComponent={
|
|
161
|
+
title={linkText}
|
|
162
|
+
navigationComponent={isExternalLink ? ExternalNavComponent : navigationComponent}
|
|
124
163
|
/>
|
|
125
164
|
) : null;
|
|
126
165
|
};
|
|
@@ -156,7 +156,9 @@ export const InternalSideNavigationLink: FC<InternalSideNavigationLinkProps> = (
|
|
|
156
156
|
|
|
157
157
|
/** Side Navigation menu trigger (for internal usage) */
|
|
158
158
|
export const InternalSideNavigationTrigger: FC<
|
|
159
|
-
Omit<InternalSideNavigationLinkProps, 'to' | 'navigationComponent'> & {
|
|
159
|
+
Omit<InternalSideNavigationLinkProps, 'to' | 'navigationComponent'> & {
|
|
160
|
+
onClick?: (e: MouseEvent<never>) => void;
|
|
161
|
+
}
|
|
160
162
|
> = ({ className, dataPrefix, isActive, submenuExpanded, onExpandToggle, onClick, ...props }) => {
|
|
161
163
|
return (
|
|
162
164
|
<div
|
|
@@ -211,12 +213,13 @@ export const InternalSideNavigationGroupLink: FC<
|
|
|
211
213
|
|
|
212
214
|
export const InternalSideNavigationGroupTrigger: FC<
|
|
213
215
|
Omit<NavigationSubmenuItemData, 'to'> & { onClick?: (e: MouseEvent<any>) => void }
|
|
214
|
-
> = ({ id, counter, onClick, tag, title, isActive }) => {
|
|
216
|
+
> = ({ id, counter, onClick, tag, title, isActive, ...rest }) => {
|
|
215
217
|
return (
|
|
216
218
|
<div
|
|
217
219
|
data-cy={`navigation-item-${id}`}
|
|
218
220
|
data-pendo={`navigation-item-${id}`}
|
|
219
221
|
key={id}
|
|
222
|
+
{...rest}
|
|
220
223
|
className={classNames(Styles.submenuItem, {
|
|
221
224
|
[Styles.submenuLink]: !!onClick,
|
|
222
225
|
[Styles.submenuLinkActive]: isActive === true,
|
|
@@ -241,7 +244,7 @@ export const InternalSideNavigationGroup: FC<
|
|
|
241
244
|
onExpandToggle?: (e: MouseEvent<never>) => void;
|
|
242
245
|
tag: BadgeTagProps | undefined;
|
|
243
246
|
to: NavigationItemData['to'] | undefined;
|
|
244
|
-
onClick?: () => void;
|
|
247
|
+
onClick?: (e: MouseEvent<never>) => void;
|
|
245
248
|
}
|
|
246
249
|
> = ({ children, submenuExpanded, to, onExpandToggle, onClick, ...props }) => {
|
|
247
250
|
return (
|
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
InternalSideNavigationLink,
|
|
7
7
|
InternalSideNavigationTrigger,
|
|
8
8
|
} from './layout-sidebar-links-internal';
|
|
9
|
+
import { useNotificationsContext } from './notifications-context';
|
|
9
10
|
|
|
10
11
|
const WrappedLink: FC<{
|
|
11
12
|
children: ReactElement<any>;
|
|
@@ -21,6 +22,10 @@ export function TitanLayoutSidebarLink({ wrapper, ...props }: TitanLayoutSidebar
|
|
|
21
22
|
NavigationComponent,
|
|
22
23
|
breakpoint: { isMobile },
|
|
23
24
|
} = useTitanLayoutContext();
|
|
25
|
+
const { onNotificationsUpdate } = useNotificationsContext();
|
|
26
|
+
const tag = getCounterTag(props.counter, props.tag);
|
|
27
|
+
|
|
28
|
+
onNotificationsUpdate(props.id, !!tag);
|
|
24
29
|
|
|
25
30
|
const element = (
|
|
26
31
|
<InternalSideNavigationLink
|
|
@@ -28,7 +33,7 @@ export function TitanLayoutSidebarLink({ wrapper, ...props }: TitanLayoutSidebar
|
|
|
28
33
|
navigationComponent={NavigationComponent}
|
|
29
34
|
submenuExpanded={undefined}
|
|
30
35
|
dataPrefix="navigation-link"
|
|
31
|
-
tag={
|
|
36
|
+
tag={tag}
|
|
32
37
|
/>
|
|
33
38
|
);
|
|
34
39
|
|
|
@@ -45,15 +50,23 @@ export function TitanLayoutSidebarTrigger({
|
|
|
45
50
|
const {
|
|
46
51
|
breakpoint: { isMobile },
|
|
47
52
|
} = useTitanLayoutContext();
|
|
53
|
+
const { onNotificationsUpdate } = useNotificationsContext();
|
|
54
|
+
const tag = getCounterTag(props.counter, props.tag);
|
|
55
|
+
|
|
56
|
+
onNotificationsUpdate(props.id, !!tag);
|
|
48
57
|
|
|
49
58
|
const element = (
|
|
50
59
|
<InternalSideNavigationTrigger
|
|
51
60
|
{...props}
|
|
52
61
|
submenuExpanded={undefined}
|
|
53
62
|
dataPrefix="navigation-trigger"
|
|
54
|
-
tag={
|
|
63
|
+
tag={tag}
|
|
55
64
|
onClick={isMobile && !!onMobileClick ? onMobileClick : onClick}
|
|
56
65
|
/>
|
|
57
66
|
);
|
|
58
|
-
return wrapper && !isMobile
|
|
67
|
+
return wrapper && (!isMobile || !onMobileClick) ? (
|
|
68
|
+
<WrappedLink wrapper={wrapper}>{element}</WrappedLink>
|
|
69
|
+
) : (
|
|
70
|
+
element
|
|
71
|
+
);
|
|
59
72
|
}
|
|
@@ -17,15 +17,20 @@
|
|
|
17
17
|
|
|
18
18
|
// mobile version
|
|
19
19
|
.nav-drawer {
|
|
20
|
-
display: none;
|
|
20
|
+
// display: none;
|
|
21
21
|
position: fixed;
|
|
22
22
|
max-width: 400px;
|
|
23
23
|
width: 0;
|
|
24
|
+
height: 100vh;
|
|
24
25
|
top: 0;
|
|
25
|
-
|
|
26
|
-
left: 0;
|
|
26
|
+
left: -100vh;
|
|
27
27
|
z-index: 991;
|
|
28
28
|
|
|
29
|
+
-webkit-transition: width 200ms ease-in-out;
|
|
30
|
+
-moz-transition: width 200ms ease-in-out;
|
|
31
|
+
-o-transition: width 200ms ease-in-out;
|
|
32
|
+
transition: width 200ms ease-in-out;
|
|
33
|
+
|
|
29
34
|
.nav-main {
|
|
30
35
|
padding-left: @spacing-2;
|
|
31
36
|
padding-right: @spacing-2;
|
|
@@ -39,6 +44,7 @@
|
|
|
39
44
|
padding-top: @spacing-2;
|
|
40
45
|
padding-left: @spacing-2;
|
|
41
46
|
padding-right: @spacing-2;
|
|
47
|
+
cursor: pointer;
|
|
42
48
|
}
|
|
43
49
|
}
|
|
44
50
|
|
|
@@ -61,10 +67,21 @@
|
|
|
61
67
|
}
|
|
62
68
|
}
|
|
63
69
|
|
|
70
|
+
.nav-drawer-backdrop {
|
|
71
|
+
position: fixed;
|
|
72
|
+
height: 100vh;
|
|
73
|
+
width: 100vw;
|
|
74
|
+
top: 0;
|
|
75
|
+
left: 0;
|
|
76
|
+
z-index: 991;
|
|
77
|
+
background-color: rgba(0, 0, 0, 0.5);
|
|
78
|
+
}
|
|
79
|
+
|
|
64
80
|
// mobile version opened
|
|
65
81
|
.nav-drawer-opened {
|
|
66
82
|
display: flex;
|
|
67
83
|
width: 90vw;
|
|
84
|
+
left: 0;
|
|
68
85
|
}
|
|
69
86
|
|
|
70
87
|
@media only screen and (min-width: 361px) {
|
|
@@ -142,6 +159,11 @@
|
|
|
142
159
|
.nav-wide {
|
|
143
160
|
width: var(--nav-offset-left);
|
|
144
161
|
|
|
162
|
+
.nav-item {
|
|
163
|
+
margin-left: @spacing-1;
|
|
164
|
+
margin-right: @spacing-1;
|
|
165
|
+
}
|
|
166
|
+
|
|
145
167
|
.toggle {
|
|
146
168
|
.toggle-content {
|
|
147
169
|
margin: @spacing-2;
|
|
@@ -171,8 +193,6 @@
|
|
|
171
193
|
.nav-wide {
|
|
172
194
|
.nav-item {
|
|
173
195
|
flex-direction: row;
|
|
174
|
-
margin-left: @spacing-1;
|
|
175
|
-
margin-right: @spacing-1;
|
|
176
196
|
|
|
177
197
|
.nav-item-icon-wrapper {
|
|
178
198
|
flex: 1;
|
|
@@ -5,6 +5,7 @@ export const navBottom: string;
|
|
|
5
5
|
export const navClose: string;
|
|
6
6
|
export const navCloseWrapper: string;
|
|
7
7
|
export const navDrawer: string;
|
|
8
|
+
export const navDrawerBackdrop: string;
|
|
8
9
|
export const navDrawerOpened: string;
|
|
9
10
|
export const navFooter: string;
|
|
10
11
|
export const navGroupItem: string;
|