@servicetitan/navigation 10.6.1 → 11.0.0-canary.237.0ce6038.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (164) hide show
  1. package/dist/components/header-navigation/header-navigation-extra.stories.d.ts.map +1 -1
  2. package/dist/components/header-navigation/header-navigation-extra.stories.js +5 -5
  3. package/dist/components/header-navigation/header-navigation-extra.stories.js.map +1 -1
  4. package/dist/components/header-navigation/header-navigation-links.d.ts.map +1 -1
  5. package/dist/components/header-navigation/header-navigation-links.js +2 -2
  6. package/dist/components/header-navigation/header-navigation-links.js.map +1 -1
  7. package/dist/components/header-navigation/header-navigation-stacked.stories.d.ts.map +1 -1
  8. package/dist/components/header-navigation/header-navigation-stacked.stories.js +1 -1
  9. package/dist/components/header-navigation/header-navigation-stacked.stories.js.map +1 -1
  10. package/dist/components/header-navigation/header-navigation.stories.d.ts.map +1 -1
  11. package/dist/components/header-navigation/header-navigation.stories.js +2 -2
  12. package/dist/components/header-navigation/header-navigation.stories.js.map +1 -1
  13. package/dist/components/header-navigation/with-tooltip.d.ts +1 -1
  14. package/dist/components/header-navigation/with-tooltip.d.ts.map +1 -1
  15. package/dist/components/left-navigation/header-navigation-tiny.stories.d.ts.map +1 -1
  16. package/dist/components/left-navigation/header-navigation-tiny.stories.js +2 -2
  17. package/dist/components/left-navigation/header-navigation-tiny.stories.js.map +1 -1
  18. package/dist/components/left-navigation/interface.d.ts +1 -1
  19. package/dist/components/left-navigation/interface.d.ts.map +1 -1
  20. package/dist/components/left-navigation/side-navigation-links-internal.d.ts +3 -1
  21. package/dist/components/left-navigation/side-navigation-links-internal.d.ts.map +1 -1
  22. package/dist/components/left-navigation/side-navigation-links-internal.js +3 -3
  23. package/dist/components/left-navigation/side-navigation-links-internal.js.map +1 -1
  24. package/dist/components/left-navigation/side-navigation.d.ts.map +1 -1
  25. package/dist/components/left-navigation/side-navigation.js +8 -7
  26. package/dist/components/left-navigation/side-navigation.js.map +1 -1
  27. package/dist/components/left-navigation/side-navigation.module.less +21 -19
  28. package/dist/components/links.d.ts.map +1 -1
  29. package/dist/components/links.js +7 -7
  30. package/dist/components/links.js.map +1 -1
  31. package/dist/components/logo/logo-company-title.d.ts +1 -0
  32. package/dist/components/logo/logo-company-title.d.ts.map +1 -1
  33. package/dist/components/logo/logo-company-title.js +2 -2
  34. package/dist/components/logo/logo-company-title.js.map +1 -1
  35. package/dist/components/profile-dropdown/profile-dropdown.d.ts +6 -3
  36. package/dist/components/profile-dropdown/profile-dropdown.d.ts.map +1 -1
  37. package/dist/components/profile-dropdown/profile-dropdown.js +7 -8
  38. package/dist/components/profile-dropdown/profile-dropdown.js.map +1 -1
  39. package/dist/components/profile-dropdown/profile-dropdown.module.less +4 -0
  40. package/dist/components/profile-dropdown/profile-dropdown.stories.js +2 -2
  41. package/dist/components/profile-dropdown/profile-dropdown.stories.js.map +1 -1
  42. package/dist/components/titan-layout/index.d.ts +6 -0
  43. package/dist/components/titan-layout/index.d.ts.map +1 -0
  44. package/dist/components/titan-layout/index.js +6 -0
  45. package/dist/components/titan-layout/index.js.map +1 -0
  46. package/dist/components/titan-layout/interface-internal.d.ts +6 -0
  47. package/dist/components/titan-layout/interface-internal.d.ts.map +1 -0
  48. package/dist/components/titan-layout/interface-internal.js +2 -0
  49. package/dist/components/titan-layout/interface-internal.js.map +1 -0
  50. package/dist/components/titan-layout/interface.d.ts +21 -0
  51. package/dist/components/titan-layout/interface.d.ts.map +1 -0
  52. package/dist/components/titan-layout/interface.js +2 -0
  53. package/dist/components/titan-layout/interface.js.map +1 -0
  54. package/dist/components/titan-layout/layout-context.d.ts +20 -0
  55. package/dist/components/titan-layout/layout-context.d.ts.map +1 -0
  56. package/dist/components/titan-layout/layout-context.js +12 -0
  57. package/dist/components/titan-layout/layout-context.js.map +1 -0
  58. package/dist/components/titan-layout/layout-header-links.d.ts +7 -0
  59. package/dist/components/titan-layout/layout-header-links.d.ts.map +1 -0
  60. package/dist/components/titan-layout/layout-header-links.js +32 -0
  61. package/dist/components/titan-layout/layout-header-links.js.map +1 -0
  62. package/dist/components/titan-layout/layout-header.d.ts +20 -0
  63. package/dist/components/titan-layout/layout-header.d.ts.map +1 -0
  64. package/dist/components/titan-layout/layout-header.js +11 -0
  65. package/dist/components/titan-layout/layout-header.js.map +1 -0
  66. package/dist/components/titan-layout/layout-header.module.less +154 -0
  67. package/dist/components/titan-layout/layout-logo.d.ts +12 -0
  68. package/dist/components/titan-layout/layout-logo.d.ts.map +1 -0
  69. package/dist/components/titan-layout/layout-logo.js +15 -0
  70. package/dist/components/titan-layout/layout-logo.js.map +1 -0
  71. package/dist/components/titan-layout/layout-logo.stories.d.ts +13 -0
  72. package/dist/components/titan-layout/layout-logo.stories.d.ts.map +1 -0
  73. package/dist/components/titan-layout/layout-logo.stories.js +17 -0
  74. package/dist/components/titan-layout/layout-logo.stories.js.map +1 -0
  75. package/dist/components/titan-layout/layout-profile.d.ts +9 -0
  76. package/dist/components/titan-layout/layout-profile.d.ts.map +1 -0
  77. package/dist/components/titan-layout/layout-profile.js +44 -0
  78. package/dist/components/titan-layout/layout-profile.js.map +1 -0
  79. package/dist/components/titan-layout/layout-profile.stories.d.ts +13 -0
  80. package/dist/components/titan-layout/layout-profile.stories.d.ts.map +1 -0
  81. package/dist/components/titan-layout/layout-profile.stories.js +13 -0
  82. package/dist/components/titan-layout/layout-profile.stories.js.map +1 -0
  83. package/dist/components/titan-layout/layout-sidebar-links-internal.d.ts +46 -0
  84. package/dist/components/titan-layout/layout-sidebar-links-internal.d.ts.map +1 -0
  85. package/dist/components/titan-layout/layout-sidebar-links-internal.js +61 -0
  86. package/dist/components/titan-layout/layout-sidebar-links-internal.js.map +1 -0
  87. package/dist/components/titan-layout/layout-sidebar-links.d.ts +6 -0
  88. package/dist/components/titan-layout/layout-sidebar-links.d.ts.map +1 -0
  89. package/dist/components/titan-layout/layout-sidebar-links.js +21 -0
  90. package/dist/components/titan-layout/layout-sidebar-links.js.map +1 -0
  91. package/dist/components/titan-layout/layout-sidebar.d.ts +17 -0
  92. package/dist/components/titan-layout/layout-sidebar.d.ts.map +1 -0
  93. package/dist/components/titan-layout/layout-sidebar.js +65 -0
  94. package/dist/components/titan-layout/layout-sidebar.js.map +1 -0
  95. package/dist/components/titan-layout/layout-sidebar.module.less +513 -0
  96. package/dist/components/titan-layout/titan-layout.d.ts +36 -0
  97. package/dist/components/titan-layout/titan-layout.d.ts.map +1 -0
  98. package/dist/components/titan-layout/titan-layout.js +109 -0
  99. package/dist/components/titan-layout/titan-layout.js.map +1 -0
  100. package/dist/components/titan-layout/titan-layout.module.less +76 -0
  101. package/dist/components/titan-layout/titan-layout.stories.d.ts +18 -0
  102. package/dist/components/titan-layout/titan-layout.stories.d.ts.map +1 -0
  103. package/dist/components/titan-layout/titan-layout.stories.js +62 -0
  104. package/dist/components/titan-layout/titan-layout.stories.js.map +1 -0
  105. package/dist/components/titan-layout/with-tooltip.d.ts +4 -0
  106. package/dist/components/titan-layout/with-tooltip.d.ts.map +1 -0
  107. package/dist/components/titan-layout/with-tooltip.js +4 -0
  108. package/dist/components/titan-layout/with-tooltip.js.map +1 -0
  109. package/dist/index.d.ts +2 -1
  110. package/dist/index.d.ts.map +1 -1
  111. package/dist/index.js +2 -1
  112. package/dist/index.js.map +1 -1
  113. package/dist/test/data.d.ts.map +1 -1
  114. package/dist/test/data.js +3 -3
  115. package/dist/test/data.js.map +1 -1
  116. package/dist/utils/navigation-legacy.d.ts +3 -1
  117. package/dist/utils/navigation-legacy.d.ts.map +1 -1
  118. package/dist/utils/use-breakpoint.d.ts +7 -0
  119. package/dist/utils/use-breakpoint.d.ts.map +1 -0
  120. package/dist/utils/use-breakpoint.js +13 -0
  121. package/dist/utils/use-breakpoint.js.map +1 -0
  122. package/package.json +5 -6
  123. package/src/components/header-navigation/header-navigation-extra.stories.tsx +7 -0
  124. package/src/components/header-navigation/header-navigation-links.tsx +2 -0
  125. package/src/components/header-navigation/header-navigation-stacked.stories.tsx +4 -0
  126. package/src/components/header-navigation/header-navigation.stories.tsx +5 -0
  127. package/src/components/left-navigation/header-navigation-tiny.stories.tsx +6 -0
  128. package/src/components/left-navigation/interface.ts +2 -2
  129. package/src/components/left-navigation/side-navigation-links-internal.tsx +21 -6
  130. package/src/components/left-navigation/side-navigation-links.tsx +1 -1
  131. package/src/components/left-navigation/side-navigation.module.less +21 -19
  132. package/src/components/left-navigation/side-navigation.module.less.d.ts +2 -1
  133. package/src/components/left-navigation/side-navigation.tsx +15 -8
  134. package/src/components/links.tsx +33 -13
  135. package/src/components/logo/logo-company-title.tsx +8 -6
  136. package/src/components/profile-dropdown/profile-dropdown.module.less +4 -0
  137. package/src/components/profile-dropdown/profile-dropdown.stories.tsx +4 -4
  138. package/src/components/profile-dropdown/profile-dropdown.tsx +43 -46
  139. package/src/components/titan-layout/index.ts +5 -0
  140. package/src/components/titan-layout/interface-internal.ts +6 -0
  141. package/src/components/titan-layout/interface.ts +26 -0
  142. package/src/components/titan-layout/layout-context.tsx +30 -0
  143. package/src/components/titan-layout/layout-header-links.tsx +144 -0
  144. package/src/components/titan-layout/layout-header.module.less +154 -0
  145. package/src/components/titan-layout/layout-header.module.less.d.ts +16 -0
  146. package/src/components/titan-layout/layout-header.tsx +86 -0
  147. package/src/components/titan-layout/layout-logo.stories.tsx +31 -0
  148. package/src/components/titan-layout/layout-logo.tsx +57 -0
  149. package/src/components/titan-layout/layout-profile.stories.tsx +37 -0
  150. package/src/components/titan-layout/layout-profile.tsx +116 -0
  151. package/src/components/titan-layout/layout-sidebar-links-internal.tsx +265 -0
  152. package/src/components/titan-layout/layout-sidebar-links.tsx +56 -0
  153. package/src/components/titan-layout/layout-sidebar.module.less +513 -0
  154. package/src/components/titan-layout/layout-sidebar.module.less.d.ts +48 -0
  155. package/src/components/titan-layout/layout-sidebar.tsx +295 -0
  156. package/src/components/titan-layout/titan-layout.module.less +76 -0
  157. package/src/components/titan-layout/titan-layout.module.less.d.ts +13 -0
  158. package/src/components/titan-layout/titan-layout.stories.tsx +194 -0
  159. package/src/components/titan-layout/titan-layout.tsx +272 -0
  160. package/src/components/titan-layout/with-tooltip.tsx +16 -0
  161. package/src/index.ts +2 -1
  162. package/src/test/data.tsx +3 -2
  163. package/src/utils/navigation-legacy.ts +3 -1
  164. package/src/utils/use-breakpoint.ts +19 -0
@@ -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,154 @@
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
+ border-bottom: 1px solid @color-neutral-60;
12
+
13
+ & > * {
14
+ overflow-y: hidden;
15
+ }
16
+
17
+ .he-top-left {
18
+ grid-column: span 1;
19
+ display: flex;
20
+ align-items: center;
21
+ }
22
+
23
+ .he-top-center {
24
+ grid-column: span 1;
25
+ }
26
+
27
+ .he-top-right {
28
+ grid-column: span 1;
29
+
30
+ & > * {
31
+ color: @color-black;
32
+ }
33
+
34
+ .he-top-right-text {
35
+ font-size: @typescale-2;
36
+ font-weight: @font-weight-bold;
37
+ font-family: @base-font-family;
38
+ margin-right: @spacing-1;
39
+ }
40
+ }
41
+
42
+ :global(.profile-dropdown-image) {
43
+ height: 24px;
44
+ width: 24px;
45
+ }
46
+
47
+ :global(.profile-dropdown-trigger) {
48
+ height: 32px;
49
+ font-size: @size-links-tiny;
50
+ }
51
+
52
+ .navigation-link {
53
+ border-radius: 12px;
54
+ font-size: @size-links-tiny;
55
+ color: inherit;
56
+
57
+ &.navigation-item-active:not(.navigation-item-overflow) {
58
+ background-color: @color-blue-100 !important;
59
+ color: @color-blue-500 !important;
60
+ }
61
+ &:hover:not(.navigation-item-active):not(.navigation-item-overflow) {
62
+ background-color: rgba(0, 0, 0, 0.12) !important;
63
+ }
64
+
65
+ &.navigation-item-icon-state.navigation-item-active {
66
+ .navigation-icon:not(.navigation-icon-active) {
67
+ display: none;
68
+ }
69
+
70
+ .navigation-icon.navigation-icon-active[data-anv][data-anv] {
71
+ display: block;
72
+ }
73
+ }
74
+ }
75
+
76
+ .navigation-icon[data-anv][data-anv] {
77
+ display: inline-block;
78
+ color: inherit;
79
+ height: 24px;
80
+ width: 24px;
81
+
82
+ > svg {
83
+ height: @size-links-tiny;
84
+ width: @size-links-tiny;
85
+ }
86
+
87
+ &.navigation-icon-active {
88
+ display: none;
89
+ }
90
+ }
91
+ }
92
+
93
+ // desktop
94
+ @media only screen and (min-width: 768px) {
95
+ .header {
96
+ grid-template-columns: repeat(3, 1fr);
97
+ grid-template-rows: 48px;
98
+
99
+ .navigation-link {
100
+ margin: 6px 2px;
101
+ padding: 6px 6px;
102
+ }
103
+ }
104
+
105
+ .he-top-left {
106
+ padding-left: @spacing-1;
107
+ }
108
+ }
109
+
110
+ // mobile
111
+ @media only screen and (max-width: 768px) {
112
+ .header {
113
+ grid-template-columns: repeat(3, 1fr);
114
+ grid-template-rows: 44px;
115
+
116
+ padding: @spacing-1 @spacing-half;
117
+
118
+ .navigation-link {
119
+ padding: 10px;
120
+ }
121
+ }
122
+ }
123
+
124
+ .navigation-link {
125
+ // styles specific to extra nav links
126
+ color: @color-black;
127
+ position: relative;
128
+ display: flex;
129
+ align-items: center;
130
+ flex-wrap: nowrap;
131
+ text-wrap: nowrap;
132
+
133
+ .navigation-item-counter {
134
+ color: @color-white;
135
+ font-weight: @font-weight-semibold;
136
+ font-size: 8px !important;
137
+ min-width: 12px;
138
+ position: absolute;
139
+ top: 4px;
140
+ right: -2px;
141
+ }
142
+
143
+ .navigation-item-label {
144
+ color: inherit;
145
+ font-size: @typescale-1;
146
+ font-family: @base-font-family;
147
+ font-weight: @font-weight-semibold;
148
+ margin-left: @spacing-half;
149
+ }
150
+
151
+ &.navigation-item-counter-long {
152
+ right: -8px;
153
+ }
154
+ }
@@ -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,86 @@
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(Styles.heTopCenter, centerClassName)}
67
+ data-cy="navigation-center"
68
+ >
69
+ {center}
70
+ </div>
71
+ <div
72
+ className={classNames(
73
+ 'd-f flex-row justify-content-end align-items-center',
74
+ Styles.heTopRight,
75
+ rightClassName
76
+ )}
77
+ data-cy="navigation-right"
78
+ >
79
+ {!!rightText && <div className={Styles.heTopRightText}>{rightText}</div>}
80
+ {right}
81
+ {profile}
82
+ </div>
83
+ </div>
84
+ </LayoutPlacementContext.Provider>
85
+ );
86
+ };
@@ -0,0 +1,31 @@
1
+ import { Chip } from '@servicetitan/anvil2';
2
+ import { ReactElement } from 'react';
3
+ import { withAnvil, withDefaultRedirects, withMemoryRouter } from '../../test/data';
4
+ import { TitanLayoutLogo, TitanLayoutLogoProps } from './layout-logo';
5
+ import { TitanLayout } from './titan-layout';
6
+
7
+ const withTitanLayout = (element: ReactElement<TitanLayoutLogoProps>) => () => (
8
+ <TitanLayout navigationMainItems={[]}>
9
+ {element}
10
+ <TitanLayout.Content>logo</TitanLayout.Content>
11
+ </TitanLayout>
12
+ );
13
+
14
+ export default {
15
+ title: 'Navigation/TitanLayoutLogo',
16
+ component: TitanLayoutLogo,
17
+ decorators: [withDefaultRedirects, withMemoryRouter, withAnvil],
18
+ parameters: {},
19
+ };
20
+
21
+ export const LogoDefault = withTitanLayout(<TitanLayoutLogo />);
22
+
23
+ export const LogoCompanyTitle = withTitanLayout(<TitanLayoutLogo title />);
24
+
25
+ export const LogoCommercial = withTitanLayout(
26
+ <TitanLayoutLogo title="Commercial" mantleFill="#2270EE" />
27
+ );
28
+
29
+ export const LogoWithPostfix = withTitanLayout(
30
+ <TitanLayoutLogo title postfix={<Chip className="m-l-2-i" label="demo" />} />
31
+ );
@@ -0,0 +1,57 @@
1
+ import classNames from 'classnames';
2
+ import { FC, Fragment, ReactNode } from 'react';
3
+ import { LogoCompanyTitle } from '../logo/logo-company-title';
4
+ import { LogoTitan, LogoTitanTitle, WrapperProps } from '../logo/logo-titan-text';
5
+ import { useTitanLayoutContext } from './layout-context';
6
+
7
+ export interface TitanLayoutLogoProps {
8
+ /** container class name */
9
+ className?: string;
10
+
11
+ title?: string | boolean;
12
+
13
+ postfix?: ReactNode;
14
+
15
+ logoWrapper?: WrapperProps;
16
+
17
+ mantleFill?: string;
18
+ }
19
+
20
+ const EmptyWrapper: FC<any> = ({ children }) => children;
21
+
22
+ export const TitanLayoutLogo: FC<TitanLayoutLogoProps> = ({
23
+ className,
24
+ mantleFill,
25
+ postfix,
26
+ title,
27
+ logoWrapper = EmptyWrapper,
28
+ }) => {
29
+ const {
30
+ breakpoint: { isMobile },
31
+ } = useTitanLayoutContext();
32
+
33
+ const Wrapper = logoWrapper;
34
+ const logoSize = isMobile ? 44 : 56;
35
+ const logoCompanySize = 48;
36
+
37
+ return (
38
+ <div className={classNames('d-f align-items-center', className)}>
39
+ {typeof title === 'string' ? (
40
+ <Fragment>
41
+ <LogoTitan size={logoSize} mantleFill={mantleFill} logoWrapper={Wrapper} />
42
+ {!isMobile && (
43
+ <LogoTitanTitle className="c-inherit m-l-1">{title}</LogoTitanTitle>
44
+ )}
45
+ </Fragment>
46
+ ) : title === true && !isMobile ? (
47
+ <Wrapper className="">
48
+ <LogoCompanyTitle height={logoCompanySize} />
49
+ </Wrapper>
50
+ ) : (
51
+ <LogoTitan size={logoSize} mantleFill={mantleFill} logoWrapper={Wrapper} />
52
+ )}
53
+
54
+ {!isMobile && postfix}
55
+ </div>
56
+ );
57
+ };
@@ -0,0 +1,37 @@
1
+ import { ReactElement } from 'react';
2
+ import { withAnvil, withDefaultRedirects, withMemoryRouter } from '../../test/data';
3
+ import { ProfileDropdown } from './layout-profile';
4
+ import { TitanLayout } from './titan-layout';
5
+
6
+ const withTitanLayout = (element: ReactElement) => () => (
7
+ <TitanLayout navigationMainItems={[]} profile={element}>
8
+ <TitanLayout.Content>profile</TitanLayout.Content>
9
+ </TitanLayout>
10
+ );
11
+
12
+ export default {
13
+ title: 'Navigation/TitanLayoutProfile',
14
+ component: ProfileDropdown,
15
+ decorators: [withDefaultRedirects, withMemoryRouter, withAnvil],
16
+ parameters: {},
17
+ };
18
+
19
+ export const ProfileDefault = withTitanLayout(
20
+ <ProfileDropdown>
21
+ <ProfileDropdown.Link id="first" to="https://google.com">
22
+ first link
23
+ </ProfileDropdown.Link>
24
+ <ProfileDropdown.Section id="second" onClick={() => alert('second click')}>
25
+ second link
26
+ </ProfileDropdown.Section>
27
+ <ProfileDropdown.Divider />
28
+ <ProfileDropdown.Section id="content">some content</ProfileDropdown.Section>
29
+ <ProfileDropdown.Divider />
30
+ <ProfileDropdown.Divider />
31
+ <ProfileDropdown.Divider />
32
+ <ProfileDropdown.Link id="third" to="third">
33
+ third link
34
+ </ProfileDropdown.Link>
35
+ <ProfileDropdown.Divider />
36
+ </ProfileDropdown>
37
+ );
@@ -0,0 +1,116 @@
1
+ import SvgAccountActive from '@servicetitan/anvil2/assets/icons/st/gnav_account_active.svg';
2
+ import SvgAccountInactive from '@servicetitan/anvil2/assets/icons/st/gnav_account_inactive.svg';
3
+
4
+ import { FC, useState } from 'react';
5
+ import { NavigationComponentContext } from '../../utils/navigation-context';
6
+ import {
7
+ ProfileDropdown as DesktopProfileDropdown,
8
+ ProfileDropdownLinkProps,
9
+ ProfileDropdownProps,
10
+ ProfileDropdownSectionProps,
11
+ } from '../profile-dropdown/profile-dropdown';
12
+ import { NavigationComponentProps } from './interface-internal';
13
+ import { useTitanLayoutContext } from './layout-context';
14
+ import {
15
+ InternalSideNavigationGroup,
16
+ InternalSideNavigationGroupDivider,
17
+ InternalSideNavigationGroupLink,
18
+ InternalSideNavigationGroupTrigger,
19
+ } from './layout-sidebar-links-internal';
20
+
21
+ export type {
22
+ ProfileDropdownProps,
23
+ ProfileDropdownSectionProps,
24
+ ProfileDropdownLinkProps,
25
+ } from '../profile-dropdown/profile-dropdown';
26
+
27
+ const ProfileDropdownContent: FC<ProfileDropdownProps> = props => {
28
+ const { breakpoint, NavigationComponent } = useTitanLayoutContext();
29
+ return breakpoint.isMobile ? (
30
+ <MobileProfileDropdown {...props} navigationComponent={NavigationComponent} />
31
+ ) : (
32
+ <NavigationComponentContext.Provider value={NavigationComponent}>
33
+ <DesktopProfileDropdown {...props} />
34
+ </NavigationComponentContext.Provider>
35
+ );
36
+ };
37
+ ProfileDropdownContent.displayName = 'ProfileDropdown';
38
+
39
+ const MobileProfileDropdown: FC<ProfileDropdownProps & NavigationComponentProps> = ({
40
+ children,
41
+ ...props
42
+ }) => {
43
+ const [expanded, setExpanded] = useState(false);
44
+ const onExpandToggle = () => setExpanded(!expanded);
45
+ return (
46
+ <InternalSideNavigationGroup
47
+ id="__profile"
48
+ to={undefined}
49
+ title="Profile"
50
+ icon={SvgAccountInactive}
51
+ iconActive={SvgAccountActive}
52
+ isActive={expanded}
53
+ {...props}
54
+ submenuExpanded={expanded}
55
+ onExpandToggle={onExpandToggle}
56
+ onClick={onExpandToggle}
57
+ tag={undefined}
58
+ >
59
+ {children}
60
+ </InternalSideNavigationGroup>
61
+ );
62
+ };
63
+
64
+ const ProfileDropdownDivider: FC = () => {
65
+ const { breakpoint } = useTitanLayoutContext();
66
+ return breakpoint.isMobile ? (
67
+ <InternalSideNavigationGroupDivider />
68
+ ) : (
69
+ <DesktopProfileDropdown.Divider />
70
+ );
71
+ };
72
+
73
+ const ProfileDropdownSection: FC<ProfileDropdownSectionProps> = props => {
74
+ const { breakpoint } = useTitanLayoutContext();
75
+ return breakpoint.isMobile ? (
76
+ <MobileProfileDropdownSection {...props} />
77
+ ) : (
78
+ <DesktopProfileDropdown.Section {...props} />
79
+ );
80
+ };
81
+ const MobileProfileDropdownSection: FC<ProfileDropdownSectionProps> = props => {
82
+ const title = typeof props.children === 'string' ? props.children : undefined;
83
+ return title ? (
84
+ <InternalSideNavigationGroupTrigger id={props.id} title={title} onClick={props.onClick} />
85
+ ) : null;
86
+ };
87
+
88
+ const ProfileDropdownLink: FC<ProfileDropdownLinkProps> = props => {
89
+ const { breakpoint, NavigationComponent } = useTitanLayoutContext();
90
+ return breakpoint.isMobile ? (
91
+ <MobileProfileDropdownLink {...props} navigationComponent={NavigationComponent} />
92
+ ) : (
93
+ <DesktopProfileDropdown.Link {...props} />
94
+ );
95
+ };
96
+ const MobileProfileDropdownLink: FC<ProfileDropdownLinkProps & NavigationComponentProps> = ({
97
+ to,
98
+ navigationComponent,
99
+ ...props
100
+ }) => {
101
+ const title = typeof props.children === 'string' ? props.children : undefined;
102
+ return title ? (
103
+ <InternalSideNavigationGroupLink
104
+ {...props}
105
+ to={to}
106
+ title={title}
107
+ navigationComponent={navigationComponent}
108
+ />
109
+ ) : null;
110
+ };
111
+
112
+ export const ProfileDropdown = Object.assign(ProfileDropdownContent, {
113
+ Divider: ProfileDropdownDivider,
114
+ Link: ProfileDropdownLink,
115
+ Section: ProfileDropdownSection,
116
+ });