@servicetitan/navigation 13.0.0-canary.256.b43c6d7.0 → 13.0.0-canary.256.b93dc10.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 (116) hide show
  1. package/dist/components/counter-tag.d.ts +1 -1
  2. package/dist/components/counter-tag.d.ts.map +1 -1
  3. package/dist/components/counter-tag.js.map +1 -1
  4. package/dist/components/profile-dropdown/interface.d.ts +55 -0
  5. package/dist/components/profile-dropdown/interface.d.ts.map +1 -0
  6. package/dist/components/profile-dropdown/interface.js +3 -0
  7. package/dist/components/profile-dropdown/interface.js.map +1 -0
  8. package/dist/components/profile-dropdown/profile-dropdown-legacy.stories.d.ts +5 -1
  9. package/dist/components/profile-dropdown/profile-dropdown-legacy.stories.d.ts.map +1 -1
  10. package/dist/components/profile-dropdown/profile-dropdown-stacked.stories.d.ts +5 -1
  11. package/dist/components/profile-dropdown/profile-dropdown-stacked.stories.d.ts.map +1 -1
  12. package/dist/components/profile-dropdown/profile-dropdown.d.ts +9 -79
  13. package/dist/components/profile-dropdown/profile-dropdown.d.ts.map +1 -1
  14. package/dist/components/profile-dropdown/profile-dropdown.js +17 -14
  15. package/dist/components/profile-dropdown/profile-dropdown.js.map +1 -1
  16. package/dist/components/profile-dropdown/profile-dropdown.stories.d.ts +5 -1
  17. package/dist/components/profile-dropdown/profile-dropdown.stories.d.ts.map +1 -1
  18. package/dist/components/titan-layout/interface-internal.d.ts +12 -0
  19. package/dist/components/titan-layout/interface-internal.d.ts.map +1 -1
  20. package/dist/components/titan-layout/interface-internal.js.map +1 -1
  21. package/dist/components/titan-layout/interface.d.ts +55 -4
  22. package/dist/components/titan-layout/interface.d.ts.map +1 -1
  23. package/dist/components/titan-layout/interface.js.map +1 -1
  24. package/dist/components/titan-layout/layout-header-dark.d.ts.map +1 -1
  25. package/dist/components/titan-layout/layout-header-dark.js +24 -12
  26. package/dist/components/titan-layout/layout-header-dark.js.map +1 -1
  27. package/dist/components/titan-layout/layout-header-links-internal.d.ts +22 -3
  28. package/dist/components/titan-layout/layout-header-links-internal.d.ts.map +1 -1
  29. package/dist/components/titan-layout/layout-header-links-internal.js +15 -18
  30. package/dist/components/titan-layout/layout-header-links-internal.js.map +1 -1
  31. package/dist/components/titan-layout/layout-header-links.d.ts +2 -3
  32. package/dist/components/titan-layout/layout-header-links.d.ts.map +1 -1
  33. package/dist/components/titan-layout/layout-header-links.js +25 -5
  34. package/dist/components/titan-layout/layout-header-links.js.map +1 -1
  35. package/dist/components/titan-layout/layout-header.d.ts +2 -0
  36. package/dist/components/titan-layout/layout-header.d.ts.map +1 -1
  37. package/dist/components/titan-layout/layout-header.js +25 -16
  38. package/dist/components/titan-layout/layout-header.js.map +1 -1
  39. package/dist/components/titan-layout/layout-header.module.less +37 -1
  40. package/dist/components/titan-layout/layout-header.module.less.d.ts +3 -0
  41. package/dist/components/titan-layout/layout-profile.d.ts +8 -5
  42. package/dist/components/titan-layout/layout-profile.d.ts.map +1 -1
  43. package/dist/components/titan-layout/layout-profile.js +29 -21
  44. package/dist/components/titan-layout/layout-profile.js.map +1 -1
  45. package/dist/components/titan-layout/layout-sidebar-links-internal.d.ts +48 -24
  46. package/dist/components/titan-layout/layout-sidebar-links-internal.d.ts.map +1 -1
  47. package/dist/components/titan-layout/layout-sidebar-links-internal.js +62 -51
  48. package/dist/components/titan-layout/layout-sidebar-links-internal.js.map +1 -1
  49. package/dist/components/titan-layout/layout-sidebar-links.d.ts +2 -2
  50. package/dist/components/titan-layout/layout-sidebar-links.d.ts.map +1 -1
  51. package/dist/components/titan-layout/layout-sidebar-links.js +27 -14
  52. package/dist/components/titan-layout/layout-sidebar-links.js.map +1 -1
  53. package/dist/components/titan-layout/layout-sidebar.d.ts +1 -1
  54. package/dist/components/titan-layout/layout-sidebar.d.ts.map +1 -1
  55. package/dist/components/titan-layout/layout-sidebar.js +81 -104
  56. package/dist/components/titan-layout/layout-sidebar.js.map +1 -1
  57. package/dist/components/titan-layout/layout-sidebar.module.less +74 -22
  58. package/dist/components/titan-layout/titan-layout-default.stories.d.ts +16 -0
  59. package/dist/components/titan-layout/titan-layout-default.stories.d.ts.map +1 -0
  60. package/dist/components/titan-layout/titan-layout-legacy.stories.d.ts +10 -0
  61. package/dist/components/titan-layout/titan-layout-legacy.stories.d.ts.map +1 -0
  62. package/dist/components/titan-layout/titan-layout-stacked.stories.d.ts +10 -0
  63. package/dist/components/titan-layout/titan-layout-stacked.stories.d.ts.map +1 -0
  64. package/dist/components/titan-layout/titan-layout.d.ts +3 -1
  65. package/dist/components/titan-layout/titan-layout.d.ts.map +1 -1
  66. package/dist/components/titan-layout/titan-layout.js +30 -11
  67. package/dist/components/titan-layout/titan-layout.js.map +1 -1
  68. package/dist/index.d.ts +0 -1
  69. package/dist/index.d.ts.map +1 -1
  70. package/dist/index.js.map +1 -1
  71. package/dist/test/data.d.ts +0 -22
  72. package/dist/test/data.d.ts.map +1 -1
  73. package/dist/test/data.js +0 -197
  74. package/dist/test/data.js.map +1 -1
  75. package/dist/test/titan-layout.d.ts +16 -0
  76. package/dist/test/titan-layout.d.ts.map +1 -0
  77. package/dist/test/titan-layout.js +21 -0
  78. package/dist/test/titan-layout.js.map +1 -0
  79. package/dist/utils/navigation.d.ts +0 -2
  80. package/dist/utils/navigation.d.ts.map +1 -1
  81. package/dist/utils/navigation.js.map +1 -1
  82. package/package.json +4 -4
  83. package/src/components/counter-tag.tsx +1 -1
  84. package/src/components/profile-dropdown/interface.ts +47 -0
  85. package/src/components/profile-dropdown/profile-dropdown-legacy.stories.tsx +3 -3
  86. package/src/components/profile-dropdown/profile-dropdown-stacked.stories.tsx +3 -3
  87. package/src/components/profile-dropdown/profile-dropdown.stories.tsx +39 -39
  88. package/src/components/profile-dropdown/profile-dropdown.tsx +37 -104
  89. package/src/components/titan-layout/interface-internal.ts +13 -0
  90. package/src/components/titan-layout/interface.ts +59 -7
  91. package/src/components/titan-layout/layout-header-dark.tsx +21 -5
  92. package/src/components/titan-layout/layout-header-links-internal.tsx +41 -54
  93. package/src/components/titan-layout/layout-header-links.tsx +64 -8
  94. package/src/components/titan-layout/layout-header.module.less +37 -1
  95. package/src/components/titan-layout/layout-header.module.less.d.ts +3 -0
  96. package/src/components/titan-layout/layout-header.tsx +26 -13
  97. package/src/components/titan-layout/layout-profile.tsx +51 -28
  98. package/src/components/titan-layout/layout-sidebar-links-internal.tsx +155 -102
  99. package/src/components/titan-layout/layout-sidebar-links.tsx +45 -12
  100. package/src/components/titan-layout/layout-sidebar.module.less +74 -22
  101. package/src/components/titan-layout/layout-sidebar.tsx +55 -80
  102. package/src/components/titan-layout/{titan-layout.stories.tsx → titan-layout-default.stories.tsx} +100 -84
  103. package/src/components/titan-layout/titan-layout-legacy.stories.tsx +24 -0
  104. package/src/components/titan-layout/titan-layout-stacked.stories.tsx +30 -0
  105. package/src/components/titan-layout/titan-layout.tsx +35 -12
  106. package/src/index.ts +0 -1
  107. package/src/test/data.tsx +0 -165
  108. package/src/test/titan-layout.tsx +34 -0
  109. package/src/utils/navigation.ts +0 -3
  110. package/dist/components/titan-layout/titan-layout.stories.d.ts +0 -29
  111. package/dist/components/titan-layout/titan-layout.stories.d.ts.map +0 -1
  112. package/dist/utils/navigation-legacy.d.ts +0 -88
  113. package/dist/utils/navigation-legacy.d.ts.map +0 -1
  114. package/dist/utils/navigation-legacy.js +0 -3
  115. package/dist/utils/navigation-legacy.js.map +0 -1
  116. package/src/utils/navigation-legacy.ts +0 -106
@@ -1,7 +1,5 @@
1
1
  import { Icon, Popover, Text, ThemeProvider } from '@servicetitan/anvil2';
2
2
  import SvgClose from '@servicetitan/anvil2/assets/icons/material/round/close.svg';
3
- import SvgCollapse from '@servicetitan/anvil2/assets/icons/st/gnav_menu_collapse.svg';
4
- import SvgExpand from '@servicetitan/anvil2/assets/icons/st/gnav_menu_expand.svg';
5
3
  import classNames from 'classnames';
6
4
  import {
7
5
  Children,
@@ -24,15 +22,13 @@ import {
24
22
  } from './layout-sidebar-links-internal';
25
23
  import * as Styles from './layout-sidebar.module.less';
26
24
 
27
- import { withTooltip } from './with-tooltip';
28
-
29
25
  export interface LayoutSidebarProps {
30
26
  className?: string;
31
27
  top?: ReactElement[];
32
28
  bottom?: ReactElement;
33
29
  mainItems?: NavigationItemData[];
34
30
  barExpanded: boolean;
35
- submenuExpanded: string | undefined;
31
+ submenusExpanded: string[] | undefined;
36
32
  drawerOpened: boolean;
37
33
  mobile: boolean;
38
34
  navigationComponent: FC<NavLinkComponentProps>;
@@ -45,7 +41,7 @@ export const LayoutSidebar: FC<LayoutSidebarProps> = ({
45
41
  className,
46
42
  mobile,
47
43
  barExpanded,
48
- submenuExpanded,
44
+ submenusExpanded,
49
45
  drawerOpened,
50
46
  onBarExpandChange,
51
47
  onSubmenuExpandChange,
@@ -95,22 +91,29 @@ export const LayoutSidebar: FC<LayoutSidebarProps> = ({
95
91
  item.submenu ? (
96
92
  <SideNavigationGroupItem
97
93
  key={item.id}
94
+ item={item}
98
95
  barExpanded={mobile ? drawerOpened : barExpanded}
99
- submenuExpanded={!!item.id && submenuExpanded === item.id}
96
+ submenuExpanded={
97
+ !!item.id && !!submenusExpanded?.includes(item.id)
98
+ }
100
99
  onSubmenuExpand={onSubmenuExpandChange}
101
100
  navigationComponent={navigationComponent}
102
- {...item}
103
101
  />
104
102
  ) : (
105
103
  <InternalSideNavigationLink
106
- {...item}
107
104
  key={item.id}
108
- submenuExpanded={undefined}
109
- navigationComponent={navigationComponent}
105
+ id={item.id}
106
+ to={item.to}
107
+ title={item.title}
108
+ isActive={item.isActive}
109
+ icon={item.icon}
110
+ iconActive={item.iconActive}
111
+ className={item.className}
110
112
  tag={getSubmenuGroupTag(
111
113
  item.submenu,
112
114
  getCounterTag(item.counter, item.tag)
113
115
  )}
116
+ navigationComponent={navigationComponent}
114
117
  />
115
118
  )
116
119
  )}
@@ -118,76 +121,30 @@ export const LayoutSidebar: FC<LayoutSidebarProps> = ({
118
121
 
119
122
  {!!bottom && <SidebarBottom>{bottom}</SidebarBottom>}
120
123
  </ThemeProvider>
121
-
122
- {!mobile && (
123
- <div className={Styles.navFooter}>
124
- <div className={Styles.divider} />
125
- <div className={Styles.toggleWrapper}>
126
- <SideNavigationOptionsToggle
127
- appearance={barExpanded ? 'collapse-button' : 'expand'}
128
- onExpandedChange={() => onBarExpandChange(!barExpanded)}
129
- />
130
- </div>
131
- </div>
132
- )}
133
124
  </div>
134
125
  </LayoutPlacementContext.Provider>
135
126
  );
136
127
  };
137
128
  LayoutSidebar.displayName = 'LayoutSidebar';
138
129
 
139
- /** Side Navigation options toggle */
140
- const SideNavigationOptionsToggle: FC<{
141
- appearance: 'expand' | 'collapse' | 'collapse-button';
142
- onExpandedChange?(expanded: boolean): void;
143
- }> = ({ appearance, onExpandedChange }) =>
144
- withTooltip(
145
- <div
146
- data-cy="navigation-left-options"
147
- data-pendo="navigation-left-options"
148
- className={classNames(Styles.toggle)}
149
- onClick={() => onExpandedChange?.(appearance === 'expand')}
150
- >
151
- <div className={Styles.toggleContent}>
152
- <div className={Styles.toggleIconWrapper}>
153
- <Icon
154
- className={Styles.toggleIcon}
155
- svg={appearance === 'expand' ? SvgExpand : SvgCollapse}
156
- />
157
- </div>
158
-
159
- {appearance === 'collapse-button' && (
160
- <span className={Styles.toggleText}>Collapse Menu</span>
161
- )}
162
- </div>
163
- </div>,
164
- appearance === 'expand'
165
- ? 'Expand Menu'
166
- : appearance === 'collapse'
167
- ? 'Collapse Menu'
168
- : undefined,
169
- { placement: 'right' }
170
- );
171
-
172
130
  /** Side Navigation menu item */
173
- const SideNavigationGroupItem: FC<
174
- NavigationItemData & {
175
- navigationComponent: FC<NavLinkComponentProps>;
176
- barExpanded: boolean;
177
- submenuExpanded: boolean;
178
- onSubmenuExpand: undefined | ((id: string, expanded: boolean) => void);
179
- }
180
- > = ({ onSubmenuExpand, barExpanded, submenuExpanded, ...props }) => {
131
+ const SideNavigationGroupItem: FC<{
132
+ item: NavigationItemData;
133
+ navigationComponent: FC<NavLinkComponentProps>;
134
+ barExpanded: boolean;
135
+ submenuExpanded: boolean;
136
+ onSubmenuExpand: undefined | ((id: string, expanded: boolean) => void);
137
+ }> = ({ item, onSubmenuExpand, barExpanded, submenuExpanded, navigationComponent }) => {
181
138
  const onExpandToggle = useCallback(
182
139
  (e: MouseEvent<never>) => {
183
140
  e.preventDefault();
184
141
  e.stopPropagation();
185
142
 
186
- if (props.id) {
187
- onSubmenuExpand?.(props.id, !submenuExpanded);
143
+ if (item.id) {
144
+ onSubmenuExpand?.(item.id, !submenuExpanded);
188
145
  }
189
146
  },
190
- [props.id, submenuExpanded, onSubmenuExpand]
147
+ [item.id, submenuExpanded, onSubmenuExpand]
191
148
  );
192
149
  const {
193
150
  sidebar: {
@@ -195,19 +152,26 @@ const SideNavigationGroupItem: FC<
195
152
  },
196
153
  } = useTitanLayoutContext();
197
154
 
198
- const tag = getSubmenuGroupTag(props.submenu, getCounterTag(props.counter, props.tag));
155
+ const tag = getSubmenuGroupTag(item.submenu, getCounterTag(item.counter, item.tag));
199
156
 
200
157
  return barExpanded ? (
201
158
  <InternalSideNavigationGroup
202
- {...props}
159
+ id={item.id}
160
+ to={item.to}
161
+ title={item.title}
162
+ isActive={item.isActive}
163
+ icon={item.icon}
164
+ iconActive={item.iconActive}
165
+ className={item.className}
166
+ tag={tag}
203
167
  submenuExpanded={submenuExpanded}
204
168
  onExpandToggle={onExpandToggle}
205
- tag={tag}
169
+ navigationComponent={navigationComponent}
206
170
  >
207
171
  <SideNavigationGroupContent
208
- parentId={props.id}
209
- groups={props.submenu?.groups ?? []}
210
- navigationComponent={props.navigationComponent}
172
+ parentId={item.id}
173
+ groups={item.submenu?.groups ?? []}
174
+ navigationComponent={navigationComponent}
211
175
  />
212
176
  </InternalSideNavigationGroup>
213
177
  ) : (
@@ -216,9 +180,15 @@ const SideNavigationGroupItem: FC<
216
180
  {(triggerProps: any) => (
217
181
  <div {...triggerProps}>
218
182
  <InternalSideNavigationLink
219
- {...props}
220
- submenuExpanded={undefined}
183
+ id={item.id}
184
+ to={item.to}
185
+ title={item.title}
186
+ isActive={item.isActive}
187
+ icon={item.icon}
188
+ iconActive={item.iconActive}
189
+ className={item.className}
221
190
  tag={tag}
191
+ navigationComponent={navigationComponent}
222
192
  />
223
193
  </div>
224
194
  )}
@@ -231,12 +201,12 @@ const SideNavigationGroupItem: FC<
231
201
  size="small"
232
202
  className="c-white m-b-half-i m-t-1"
233
203
  >
234
- {props.title}
204
+ {item.title}
235
205
  </Text>
236
206
  <SideNavigationGroupContent
237
- parentId={props.id}
238
- groups={props.submenu?.groups ?? []}
239
- navigationComponent={props.navigationComponent}
207
+ parentId={item.id}
208
+ groups={item.submenu?.groups ?? []}
209
+ navigationComponent={navigationComponent}
240
210
  />
241
211
  </div>
242
212
  </Popover.Content>
@@ -270,7 +240,12 @@ const SideNavigationGroupContent: FC<
270
240
  ...group.links.map((link, index) => (
271
241
  <InternalSideNavigationGroupLink
272
242
  key={`:${parentId}:${link.id}:${index}`}
273
- {...link}
243
+ id={link.id}
244
+ to={link.to}
245
+ title={link.title}
246
+ isActive={link.isActive}
247
+ className={undefined}
248
+ tag={getCounterTag(link.counter, link.tag)}
274
249
  parentId={parentId}
275
250
  navigationComponent={navigationComponent}
276
251
  />
@@ -6,7 +6,7 @@ import SvgSettings from '@servicetitan/anvil2/assets/icons/st/gnav_settings_inac
6
6
  import SvgRocketActive from '@servicetitan/anvil2/assets/icons/st/gnav_titan_advisor_active.svg';
7
7
  import SvgRocket from '@servicetitan/anvil2/assets/icons/st/gnav_titan_advisor_inactive.svg';
8
8
  import { Page as Anvil1Page } from '@servicetitan/design-system';
9
- import { Fragment, useState } from 'react';
9
+ import { Fragment, useEffect, useState } from 'react';
10
10
  import {
11
11
  CallsNavigationTrigger,
12
12
  LocationInfo,
@@ -16,6 +16,12 @@ import {
16
16
  withDefaultRedirects,
17
17
  withMemoryRouter,
18
18
  } from '../../test/data';
19
+ import {
20
+ LayoutContentArgs,
21
+ getDefaultArgs,
22
+ useDefaultLayoutProps,
23
+ withDefaultLayoutProps,
24
+ } from '../../test/titan-layout';
19
25
  import {
20
26
  ProfileDropdown,
21
27
  TitanLayout,
@@ -24,32 +30,17 @@ import {
24
30
  TitanLayoutState,
25
31
  } from './';
26
32
 
27
- interface LayoutContentArgs {
28
- header: boolean;
29
- sideTop: boolean;
30
- extraText: boolean;
31
- search: boolean;
32
- longContent: boolean;
33
- wideContent: boolean;
34
- minWidth: boolean;
35
- emptyNav: boolean;
36
- }
37
-
38
33
  export default {
39
- title: 'Navigation/TitanLayout',
40
- decorators: [withDefaultRedirects, withMemoryRouter, withAnvil],
34
+ title: 'Navigation/TitanLayout/Default',
35
+ decorators: [
36
+ withDefaultLayoutProps({ navVariant: 'left' }),
37
+ withDefaultRedirects,
38
+ withMemoryRouter,
39
+ withAnvil,
40
+ ],
41
41
  parameters: {},
42
42
  argTypes: {},
43
- args: {
44
- header: true,
45
- sideTop: true,
46
- extraText: true,
47
- search: true,
48
- longContent: true,
49
- wideContent: false,
50
- minWidth: false,
51
- emptyNav: false,
52
- } as LayoutContentArgs,
43
+ args: getDefaultArgs(),
53
44
  };
54
45
 
55
46
  const mainNavItems = [
@@ -60,8 +51,8 @@ const mainNavItems = [
60
51
  navItems.dispatch,
61
52
 
62
53
  navItems.fleet,
63
- navItems.followUps,
64
- navItems.inventory,
54
+ navItems.followUpsWithSubmenu,
55
+ navItems.purchasingWithSubmenu,
65
56
 
66
57
  navItems.marketing,
67
58
  navItems.priceBook,
@@ -105,6 +96,15 @@ const profile = (
105
96
  </ProfileDropdown>
106
97
  );
107
98
 
99
+ const profileEmpty = (
100
+ <ProfileDropdown>
101
+ <ProfileDropdown.Link id="sign-out" to="/sign-out">
102
+ sign out
103
+ </ProfileDropdown.Link>
104
+ <ProfileDropdown.Divider />
105
+ </ProfileDropdown>
106
+ );
107
+
108
108
  const extraLinks = (
109
109
  <Fragment>
110
110
  <TitanLayout.Link
@@ -205,7 +205,7 @@ const useLayoutProps = (args: LayoutContentArgs): TitanLayoutProps => {
205
205
 
206
206
  navigationComponent: NavLinkMock,
207
207
  navigationMainItems: args.emptyNav ? [] : mainNavItems,
208
- navigationOverflowItems: args.emptyNav ? [] : overflowNavItems,
208
+ navigationOverflowItems: args.emptyNav || !args.overflowItems ? [] : overflowNavItems,
209
209
 
210
210
  profile,
211
211
  top: args.search ? <SearchBar /> : undefined,
@@ -224,10 +224,15 @@ const useLayoutProps = (args: LayoutContentArgs): TitanLayoutProps => {
224
224
  };
225
225
 
226
226
  const Content = (args: LayoutContentArgs) => {
227
+ const [info, setInfo] = useState('');
228
+ useEffect(() => {
229
+ setInfo(new Date().toLocaleTimeString());
230
+ }, []);
227
231
  return (
228
232
  <Fragment>
229
233
  <LocationInfo className="m-b-3" />
230
- <div className="m-b-3">rendered - {new Date().toLocaleTimeString()}</div>
234
+ <div className="m-b-3">component rendered - {info}</div>
235
+ <div className="m-b-3">rerendered - {new Date().toLocaleTimeString()}</div>
231
236
  {args.wideContent && (
232
237
  <div style={{ width: '1200px' }}>
233
238
  Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor
@@ -316,30 +321,8 @@ const Content = (args: LayoutContentArgs) => {
316
321
  );
317
322
  };
318
323
 
319
- export const TitanLayoutLegacy = (args: LayoutContentArgs) => (
320
- <TitanLayout {...useLayoutProps(args)} appearance="legacy">
321
- <div
322
- className="p-3"
323
- style={{ position: 'absolute', width: 'calc(100% - var(--nav-offset-left))' }}
324
- >
325
- <Content {...args} />
326
- </div>
327
- </TitanLayout>
328
- );
329
-
330
- export const TitanLayoutLegacyTopNav = (args: LayoutContentArgs) => (
331
- <TitanLayout {...useLayoutProps(args)} appearance="legacy" navVariant="top">
332
- <div
333
- className="p-3"
334
- style={{ position: 'absolute', width: 'calc(100% - var(--nav-offset-left))' }}
335
- >
336
- <Content {...args} />
337
- </div>
338
- </TitanLayout>
339
- );
340
-
341
- export const TitanLayoutLegacyTop = (args: LayoutContentArgs) => (
342
- <TitanLayout {...useLayoutProps(args)} appearance="legacy" navVariant="top" top={undefined}>
324
+ export const ContentLegacy = (args: LayoutContentArgs) => (
325
+ <TitanLayout {...useLayoutProps(args)} appearance="legacy" {...useDefaultLayoutProps()}>
343
326
  <div
344
327
  className="p-3"
345
328
  style={{ position: 'absolute', width: 'calc(100% - var(--nav-offset-left))' }}
@@ -349,46 +332,43 @@ export const TitanLayoutLegacyTop = (args: LayoutContentArgs) => (
349
332
  </TitanLayout>
350
333
  );
351
334
 
352
- export const TitanLayoutAnvil1 = (args: LayoutContentArgs) => (
353
- <TitanLayout {...useLayoutProps(args)} appearance="anvil1">
335
+ export const ContentAnvil1 = (args: LayoutContentArgs) => (
336
+ <TitanLayout {...useLayoutProps(args)} appearance="anvil1" {...useDefaultLayoutProps()}>
354
337
  <Anvil1Page>
355
338
  <Content {...args} />
356
339
  </Anvil1Page>
357
340
  </TitanLayout>
358
341
  );
359
342
 
360
- export const TitanLayoutAnvil1TopNav = (args: LayoutContentArgs) => (
361
- <TitanLayout {...useLayoutProps(args)} appearance="anvil1" navVariant="top">
362
- <Anvil1Page>
363
- <Content {...args} />
364
- </Anvil1Page>
343
+ export const ContentAnvil2 = (args: LayoutContentArgs) => (
344
+ <TitanLayout {...useLayoutProps(args)} appearance="anvil2" {...useDefaultLayoutProps()}>
345
+ <Anvil2Page>
346
+ <Anvil2Page.Content>
347
+ <Content {...args} />
348
+ </Anvil2Page.Content>
349
+ </Anvil2Page>
365
350
  </TitanLayout>
366
351
  );
367
352
 
368
- export const TitanLayoutAnvil1Top = (args: LayoutContentArgs) => (
353
+ export const ExtraWithTitle = (args: LayoutContentArgs) => (
369
354
  <TitanLayout
370
355
  {...useLayoutProps(args)}
371
- appearance="anvil1"
372
- navVariant="top"
373
- top={undefined}
374
- navigationOverflowItems={undefined}
356
+ appearance="anvil2"
357
+ profile={profileEmpty}
358
+ sideTop={undefined}
359
+ navigationMainItems={[navItems.projects]}
360
+ extraLinks={
361
+ <TitanLayout.Link
362
+ id="search"
363
+ to="/search"
364
+ title="Search"
365
+ icon={SvgSearch}
366
+ iconActive={SvgSearch}
367
+ extra={{ showTitle: true }}
368
+ />
369
+ }
370
+ {...useDefaultLayoutProps()}
375
371
  >
376
- <Anvil1Page>
377
- <Content {...args} />
378
- </Anvil1Page>
379
- </TitanLayout>
380
- );
381
-
382
- export const TitanLayoutAnvil1TopOverflow = (args: LayoutContentArgs) => (
383
- <TitanLayout {...useLayoutProps(args)} appearance="anvil1" navVariant="top" top={undefined}>
384
- <Anvil1Page>
385
- <Content {...args} />
386
- </Anvil1Page>
387
- </TitanLayout>
388
- );
389
-
390
- export const TitanLayoutAnvil2 = (args: LayoutContentArgs) => (
391
- <TitanLayout {...useLayoutProps(args)} appearance="anvil2">
392
372
  <Anvil2Page>
393
373
  <Anvil2Page.Content>
394
374
  <Content {...args} />
@@ -397,8 +377,26 @@ export const TitanLayoutAnvil2 = (args: LayoutContentArgs) => (
397
377
  </TitanLayout>
398
378
  );
399
379
 
400
- export const TitanLayoutAnvil2TopNav = (args: LayoutContentArgs) => (
401
- <TitanLayout {...useLayoutProps(args)} appearance="anvil2" navVariant="top">
380
+ export const ExtraWithFlashing = (args: LayoutContentArgs) => (
381
+ <TitanLayout
382
+ {...useLayoutProps(args)}
383
+ appearance="anvil2"
384
+ profile={profileEmpty}
385
+ sideTop={undefined}
386
+ navigationMainItems={[navItems.projects]}
387
+ extraLinks={
388
+ <TitanLayout.Link
389
+ id="search"
390
+ to="/search"
391
+ title="Search"
392
+ icon={SvgSearch}
393
+ iconActive={SvgSearch}
394
+ extra={{ flashing: true }}
395
+ side={{ counter: true }}
396
+ />
397
+ }
398
+ {...useDefaultLayoutProps()}
399
+ >
402
400
  <Anvil2Page>
403
401
  <Anvil2Page.Content>
404
402
  <Content {...args} />
@@ -407,8 +405,26 @@ export const TitanLayoutAnvil2TopNav = (args: LayoutContentArgs) => (
407
405
  </TitanLayout>
408
406
  );
409
407
 
410
- export const TitanLayoutAnvil2Top = (args: LayoutContentArgs) => (
411
- <TitanLayout {...useLayoutProps(args)} appearance="anvil2" navVariant="top" top={undefined}>
408
+ export const ExtraWithTitleFlashing = (args: LayoutContentArgs) => (
409
+ <TitanLayout
410
+ {...useLayoutProps(args)}
411
+ appearance="anvil2"
412
+ profile={profileEmpty}
413
+ sideTop={undefined}
414
+ navigationMainItems={[navItems.projects]}
415
+ extraLinks={
416
+ <TitanLayout.Link
417
+ id="search"
418
+ to="/search"
419
+ title="Search"
420
+ icon={SvgSearch}
421
+ iconActive={SvgSearch}
422
+ extra={{ showTitle: true, flashing: true }}
423
+ side={{ counter: true }}
424
+ />
425
+ }
426
+ {...useDefaultLayoutProps()}
427
+ >
412
428
  <Anvil2Page>
413
429
  <Anvil2Page.Content>
414
430
  <Content {...args} />
@@ -0,0 +1,24 @@
1
+ import { withAnvil, withDefaultRedirects, withMemoryRouter } from '../../test/data';
2
+ import { getDefaultArgs, withDefaultLayoutProps } from '../../test/titan-layout';
3
+
4
+ export default {
5
+ title: 'Navigation/TitanLayout/Legacy',
6
+ decorators: [
7
+ withDefaultLayoutProps({ navVariant: 'top', top: undefined }),
8
+ withDefaultRedirects,
9
+ withMemoryRouter,
10
+ withAnvil,
11
+ ],
12
+ parameters: {},
13
+ argTypes: {},
14
+ args: getDefaultArgs(),
15
+ };
16
+
17
+ export {
18
+ ContentLegacy,
19
+ ContentAnvil1,
20
+ ContentAnvil2,
21
+ ExtraWithTitle,
22
+ ExtraWithFlashing,
23
+ ExtraWithTitleFlashing,
24
+ } from './titan-layout-default.stories';
@@ -0,0 +1,30 @@
1
+ import { TextField } from '@servicetitan/anvil2';
2
+
3
+ import { withAnvil, withDefaultRedirects, withMemoryRouter } from '../../test/data';
4
+ import { getDefaultArgs, withDefaultLayoutProps } from '../../test/titan-layout';
5
+
6
+ const SearchBar = () => (
7
+ <TextField size="small" placeholder="Search" className="w-100-i m-x-half-i" />
8
+ );
9
+
10
+ export default {
11
+ title: 'Navigation/TitanLayout/Stacked',
12
+ decorators: [
13
+ withDefaultLayoutProps({ navVariant: 'top', top: <SearchBar /> }),
14
+ withDefaultRedirects,
15
+ withMemoryRouter,
16
+ withAnvil,
17
+ ],
18
+ parameters: {},
19
+ argTypes: {},
20
+ args: getDefaultArgs(),
21
+ };
22
+
23
+ export {
24
+ ContentLegacy,
25
+ ContentAnvil1,
26
+ ContentAnvil2,
27
+ ExtraWithTitle,
28
+ ExtraWithFlashing,
29
+ ExtraWithTitleFlashing,
30
+ } from './titan-layout-default.stories';
@@ -93,7 +93,7 @@ const useAppearance = (appearance: TitanLayoutProps['appearance']) =>
93
93
  };
94
94
  }, [appearance]);
95
95
 
96
- const TitanLayoutComponent: FC<TitanLayoutProps> = ({
96
+ function TitanLayoutComponent({
97
97
  appearance = 'anvil2',
98
98
  navVariant = 'left',
99
99
  id,
@@ -113,7 +113,7 @@ const TitanLayoutComponent: FC<TitanLayoutProps> = ({
113
113
  extraText,
114
114
  minContentWidth,
115
115
  sideTop,
116
- }) => {
116
+ }: TitanLayoutProps) {
117
117
  const breakpoint = useTitanBreakpoint();
118
118
  const context: TitanLayoutContextType = useMemo(
119
119
  () => ({
@@ -149,10 +149,18 @@ const TitanLayoutComponent: FC<TitanLayoutProps> = ({
149
149
  }
150
150
  }, [view.isAnvil1]);
151
151
 
152
- const onBurgerClick = useCallback((e: MouseEvent<never>) => {
153
- setMobileDrawerOpened(true);
154
- e.stopPropagation();
155
- }, []);
152
+ const onBurgerClick = useCallback(
153
+ (e: MouseEvent<never>) => {
154
+ if (isMobile) {
155
+ setMobileDrawerOpened(true);
156
+ } else {
157
+ onStateChange?.({ navCollapsed: !state?.navCollapsed });
158
+ }
159
+
160
+ e.stopPropagation();
161
+ },
162
+ [isMobile, state?.navCollapsed, onStateChange]
163
+ );
156
164
 
157
165
  const onBarExpandChange = useCallback(
158
166
  (expanded: boolean) => {
@@ -168,7 +176,10 @@ const TitanLayoutComponent: FC<TitanLayoutProps> = ({
168
176
  (id: string, expanded: boolean) => {
169
177
  onStateChange?.({
170
178
  navCollapsed: state?.navCollapsed ?? false,
171
- submenuExpanded: expanded ? id : undefined,
179
+ submenusExpanded: [
180
+ ...(state?.submenusExpanded ?? []).filter(i => i !== id),
181
+ ...(expanded ? [id] : []),
182
+ ],
172
183
  });
173
184
  },
174
185
  [state, onStateChange]
@@ -272,7 +283,17 @@ const TitanLayoutComponent: FC<TitanLayoutProps> = ({
272
283
  </Fragment>
273
284
  }
274
285
  isMobile={isMobile}
275
- hasNotifications={hasNotifications || hasMenuNotifications}
286
+ hasNotifications={
287
+ isMobile && (hasNotifications || hasMenuNotifications)
288
+ }
289
+ hasBurger={hasSideBar}
290
+ burgerTooltip={
291
+ isMobile
292
+ ? undefined
293
+ : state?.navCollapsed
294
+ ? 'Expand'
295
+ : 'Collapse'
296
+ }
276
297
  onBurgerClick={onBurgerClick}
277
298
  />
278
299
  ) : (
@@ -291,6 +312,7 @@ const TitanLayoutComponent: FC<TitanLayoutProps> = ({
291
312
  isMobile={isMobile}
292
313
  hasNotifications={hasNotifications || hasMenuNotifications}
293
314
  onBurgerClick={onBurgerClick}
315
+ hasBurger={isMobile}
294
316
  navigationMainItems={navigationMainItems}
295
317
  navigationOverflowItems={navigationOverflowItems}
296
318
  />
@@ -303,7 +325,7 @@ const TitanLayoutComponent: FC<TitanLayoutProps> = ({
303
325
  mobile={breakpoint.isMobile}
304
326
  barExpanded={!state?.navCollapsed}
305
327
  onBarExpandChange={onBarExpandChange}
306
- submenuExpanded={state?.submenuExpanded}
328
+ submenusExpanded={state?.submenusExpanded}
307
329
  onSubmenuExpandChange={onSubmenuExpandChange}
308
330
  drawerOpened={mobileDrawerOpened}
309
331
  onDrawerOpenChange={setMobileDrawerOpened}
@@ -319,10 +341,11 @@ const TitanLayoutComponent: FC<TitanLayoutProps> = ({
319
341
  <InternalSideNavigationTrigger
320
342
  id="--extra-text"
321
343
  title={extraText}
322
- submenuExpanded={undefined}
323
- tag={undefined}
344
+ isActive={undefined}
324
345
  icon={undefined}
325
346
  iconActive={undefined}
347
+ tag={undefined}
348
+ className={undefined}
326
349
  />
327
350
  )}
328
351
  </Fragment>
@@ -352,7 +375,7 @@ const TitanLayoutComponent: FC<TitanLayoutProps> = ({
352
375
  </LayoutPlacementContext.Provider>
353
376
  </LayoutContext.Provider>
354
377
  );
355
- };
378
+ }
356
379
 
357
380
  const TitanLayoutHeaderObserved: FC<{
358
381
  children: ReactNode;
package/src/index.ts CHANGED
@@ -5,5 +5,4 @@ export * from './components/counter-tag';
5
5
  export * from './components/titan-layout';
6
6
  export type * from './utils/navigation';
7
7
  export type { NavLinkComponentProps } from './utils/navigation-context';
8
- export type * from './utils/navigation-legacy';
9
8
  export * from './utils/use-breakpoint';