@servicetitan/navigation 11.0.0-canary.237.6ce8e81.0 → 11.0.0-canary.237.7d5e2c9.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 (81) hide show
  1. package/dist/components/badge-tag.d.ts +1 -1
  2. package/dist/components/badge-tag.d.ts.map +1 -1
  3. package/dist/components/logo/logo-titan-text.d.ts +1 -1
  4. package/dist/components/logo/logo-titan-text.d.ts.map +1 -1
  5. package/dist/components/profile-dropdown/profile-dropdown.d.ts +1 -0
  6. package/dist/components/profile-dropdown/profile-dropdown.d.ts.map +1 -1
  7. package/dist/components/profile-dropdown/profile-dropdown.js +2 -2
  8. package/dist/components/profile-dropdown/profile-dropdown.js.map +1 -1
  9. package/dist/components/profile-dropdown/profile-dropdown.module.less +2 -0
  10. package/dist/components/titan-layout/layout-context.js +1 -1
  11. package/dist/components/titan-layout/layout-context.js.map +1 -1
  12. package/dist/components/titan-layout/layout-header.d.ts +2 -0
  13. package/dist/components/titan-layout/layout-header.d.ts.map +1 -1
  14. package/dist/components/titan-layout/layout-header.js +3 -4
  15. package/dist/components/titan-layout/layout-header.js.map +1 -1
  16. package/dist/components/titan-layout/layout-header.module.less +55 -36
  17. package/dist/components/titan-layout/layout-logo.d.ts.map +1 -1
  18. package/dist/components/titan-layout/layout-logo.js +2 -1
  19. package/dist/components/titan-layout/layout-logo.js.map +1 -1
  20. package/dist/components/titan-layout/layout-profile.d.ts.map +1 -1
  21. package/dist/components/titan-layout/layout-profile.js +20 -5
  22. package/dist/components/titan-layout/layout-profile.js.map +1 -1
  23. package/dist/components/titan-layout/layout-profile.stories.js +1 -1
  24. package/dist/components/titan-layout/layout-profile.stories.js.map +1 -1
  25. package/dist/components/titan-layout/layout-sidebar-links-internal.d.ts +2 -2
  26. package/dist/components/titan-layout/layout-sidebar-links-internal.d.ts.map +1 -1
  27. package/dist/components/titan-layout/layout-sidebar-links-internal.js +4 -4
  28. package/dist/components/titan-layout/layout-sidebar-links-internal.js.map +1 -1
  29. package/dist/components/titan-layout/layout-sidebar-links.d.ts.map +1 -1
  30. package/dist/components/titan-layout/layout-sidebar-links.js +9 -2
  31. package/dist/components/titan-layout/layout-sidebar-links.js.map +1 -1
  32. package/dist/components/titan-layout/layout-sidebar.d.ts +2 -0
  33. package/dist/components/titan-layout/layout-sidebar.d.ts.map +1 -1
  34. package/dist/components/titan-layout/layout-sidebar.js +6 -4
  35. package/dist/components/titan-layout/layout-sidebar.js.map +1 -1
  36. package/dist/components/titan-layout/layout-sidebar.module.less +25 -5
  37. package/dist/components/titan-layout/notifications-context.d.ts +13 -0
  38. package/dist/components/titan-layout/notifications-context.d.ts.map +1 -0
  39. package/dist/components/titan-layout/notifications-context.js +23 -0
  40. package/dist/components/titan-layout/notifications-context.js.map +1 -0
  41. package/dist/components/titan-layout/titan-layout.d.ts +6 -3
  42. package/dist/components/titan-layout/titan-layout.d.ts.map +1 -1
  43. package/dist/components/titan-layout/titan-layout.js +77 -22
  44. package/dist/components/titan-layout/titan-layout.js.map +1 -1
  45. package/dist/components/titan-layout/titan-layout.module.less +29 -7
  46. package/dist/components/titan-layout/titan-layout.stories.d.ts +2 -0
  47. package/dist/components/titan-layout/titan-layout.stories.d.ts.map +1 -1
  48. package/dist/components/titan-layout/titan-layout.stories.js +8 -5
  49. package/dist/components/titan-layout/titan-layout.stories.js.map +1 -1
  50. package/dist/test/data.d.ts +4 -1
  51. package/dist/test/data.d.ts.map +1 -1
  52. package/dist/test/data.js +2 -3
  53. package/dist/test/data.js.map +1 -1
  54. package/dist/utils/use-breakpoint.d.ts +1 -0
  55. package/dist/utils/use-breakpoint.d.ts.map +1 -1
  56. package/dist/utils/use-breakpoint.js +3 -2
  57. package/dist/utils/use-breakpoint.js.map +1 -1
  58. package/package.json +2 -2
  59. package/src/components/badge-tag.tsx +1 -1
  60. package/src/components/logo/logo-titan-text.tsx +1 -1
  61. package/src/components/profile-dropdown/profile-dropdown.module.less +2 -0
  62. package/src/components/profile-dropdown/profile-dropdown.tsx +5 -1
  63. package/src/components/titan-layout/layout-context.tsx +1 -1
  64. package/src/components/titan-layout/layout-header.module.less +55 -36
  65. package/src/components/titan-layout/layout-header.module.less.d.ts +2 -0
  66. package/src/components/titan-layout/layout-header.tsx +12 -5
  67. package/src/components/titan-layout/layout-logo.tsx +13 -6
  68. package/src/components/titan-layout/layout-profile.stories.tsx +1 -1
  69. package/src/components/titan-layout/layout-profile.tsx +42 -19
  70. package/src/components/titan-layout/layout-sidebar-links-internal.tsx +18 -5
  71. package/src/components/titan-layout/layout-sidebar-links.tsx +11 -2
  72. package/src/components/titan-layout/layout-sidebar.module.less +25 -5
  73. package/src/components/titan-layout/layout-sidebar.module.less.d.ts +1 -0
  74. package/src/components/titan-layout/layout-sidebar.tsx +14 -5
  75. package/src/components/titan-layout/notifications-context.tsx +44 -0
  76. package/src/components/titan-layout/titan-layout.module.less +29 -7
  77. package/src/components/titan-layout/titan-layout.module.less.d.ts +2 -1
  78. package/src/components/titan-layout/titan-layout.stories.tsx +13 -4
  79. package/src/components/titan-layout/titan-layout.tsx +212 -93
  80. package/src/test/data.tsx +2 -3
  81. package/src/utils/use-breakpoint.ts +3 -1
@@ -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={getCounterTag(props.counter, props.tag)}
36
+ tag={tag}
32
37
  />
33
38
  );
34
39
 
@@ -45,13 +50,17 @@ 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={getCounterTag(props.counter, props.tag)}
63
+ tag={tag}
55
64
  onClick={isMobile && !!onMobileClick ? onMobileClick : onClick}
56
65
  />
57
66
  );
@@ -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
- bottom: 0;
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;
@@ -33,9 +33,11 @@ export interface LayoutSidebarProps {
33
33
  mainItems?: NavigationItemData[];
34
34
  barExpanded: boolean;
35
35
  submenuExpanded: string | undefined;
36
+ drawerOpened: boolean;
36
37
  mobile: boolean;
37
38
  navigationComponent: FC<NavLinkComponentProps>;
38
39
  onBarExpandChange(expanded: boolean): void;
40
+ onDrawerOpenChange(expanded: boolean): void;
39
41
  onSubmenuExpandChange(id: string, expanded: boolean): void;
40
42
  }
41
43
 
@@ -44,29 +46,36 @@ export const LayoutSidebar: FC<LayoutSidebarProps> = ({
44
46
  mobile,
45
47
  barExpanded,
46
48
  submenuExpanded,
49
+ drawerOpened,
47
50
  onBarExpandChange,
48
51
  onSubmenuExpandChange,
52
+ onDrawerOpenChange,
49
53
  mainItems,
50
54
  top,
51
55
  bottom,
52
56
  navigationComponent,
53
57
  }) => {
54
- const handleClick = (e: MouseEvent<never>) => {
55
- e.stopPropagation();
58
+ const closeDrawer = () => {
59
+ if (mobile) {
60
+ onDrawerOpenChange?.(false);
61
+ }
56
62
  };
57
63
 
58
64
  return (
59
65
  <LayoutPlacementContext.Provider value="side">
66
+ {mobile && drawerOpened && (
67
+ <div className={Styles.navDrawerBackdrop} onClick={closeDrawer} />
68
+ )}
60
69
  <div
61
70
  className={classNames(
62
71
  Styles.nav,
63
72
  mobile && Styles.navDrawer,
64
- mobile && barExpanded && Styles.navDrawerOpened,
73
+ mobile && drawerOpened && Styles.navDrawerOpened,
65
74
  !mobile && (barExpanded ? Styles.navWide : Styles.navSlim),
66
75
  className
67
76
  )}
68
77
  data-cy="side-navigation"
69
- onClick={handleClick}
78
+ onClick={closeDrawer}
70
79
  >
71
80
  <ThemeProvider mode="dark" className={Styles.navMain}>
72
81
  {mobile && (
@@ -86,7 +95,7 @@ export const LayoutSidebar: FC<LayoutSidebarProps> = ({
86
95
  item.submenu ? (
87
96
  <SideNavigationGroupItem
88
97
  key={item.id}
89
- barExpanded={barExpanded}
98
+ barExpanded={mobile ? drawerOpened : barExpanded}
90
99
  submenuExpanded={!!item.id && submenuExpanded === item.id}
91
100
  onSubmenuExpand={onSubmenuExpandChange}
92
101
  navigationComponent={navigationComponent}
@@ -0,0 +1,44 @@
1
+ import {
2
+ FC,
3
+ PropsWithChildren,
4
+ createContext,
5
+ useCallback,
6
+ useContext,
7
+ useRef,
8
+ useState,
9
+ } from 'react';
10
+
11
+ interface NotificationsContextType {
12
+ onNotificationsUpdate: (id: string, hasNotifications: boolean) => void;
13
+ }
14
+
15
+ const NotificationsContext = createContext<NotificationsContextType>({
16
+ onNotificationsUpdate: () => {},
17
+ });
18
+
19
+ export const useNotificationsContext = () => useContext(NotificationsContext);
20
+
21
+ export const useNotificationsState = () => {
22
+ const [hasNotifications, setHasNotifications] = useState(false);
23
+ const items = useRef(new Set<string>());
24
+ const onNotificationsUpdate = useCallback((id: string, hasNotifications: boolean) => {
25
+ if (hasNotifications && !items.current.has(id)) {
26
+ items.current.add(id);
27
+ setHasNotifications(!!items.current.size);
28
+ } else if (!hasNotifications && items.current.has(id)) {
29
+ items.current.delete(id);
30
+ setHasNotifications(!!items.current.size);
31
+ }
32
+ }, []);
33
+
34
+ const NotificationsContextProvider: FC<PropsWithChildren> = useCallback(
35
+ ({ children }) => (
36
+ <NotificationsContext.Provider value={{ onNotificationsUpdate }}>
37
+ {children}
38
+ </NotificationsContext.Provider>
39
+ ),
40
+ [onNotificationsUpdate]
41
+ );
42
+
43
+ return { NotificationsContextProvider, hasNotifications };
44
+ };
@@ -13,7 +13,7 @@
13
13
  margin-top: var(--nav-offset-top);
14
14
 
15
15
  display: flex;
16
- flex-direction: row;
16
+ flex-direction: column;
17
17
 
18
18
  .side {
19
19
  flex-basis: var(--nav-offset-left);
@@ -31,7 +31,7 @@
31
31
  }
32
32
 
33
33
  .layout-anvil2 {
34
- .header {
34
+ .content-header {
35
35
  position: sticky;
36
36
  top: var(--nav-offset-top);
37
37
  z-index: 989;
@@ -59,11 +59,15 @@
59
59
  }
60
60
 
61
61
  .layout {
62
- --nav-offset-top: 49px;
62
+ --nav-offset-top: 0px;
63
+ --nav-offset-left: 0px;
63
64
 
64
- &.layout-mobile {
65
- --nav-offset-top: 61px;
66
- --nav-offset-left: 0;
65
+ &.layout-desktop.layout-top {
66
+ --nav-offset-top: 48px;
67
+ }
68
+
69
+ &.layout-mobile.layout-top {
70
+ --nav-offset-top: 72px;
67
71
  }
68
72
 
69
73
  &.layout-desktop.layout-nav-slim {
@@ -76,9 +80,27 @@
76
80
 
77
81
  .top {
78
82
  position: fixed;
83
+ width: 100vw;
79
84
  top: 0;
80
85
  left: 0;
81
- right: 0;
82
86
  z-index: 991;
83
87
  }
88
+
89
+ .content-header {
90
+ position: sticky;
91
+ left: 0;
92
+ right: 0;
93
+ }
94
+ }
95
+
96
+ @media print {
97
+ .layout {
98
+ --nav-offset-left: 0px !important;
99
+ --nav-offset-right: 0px !important;
100
+
101
+ .side,
102
+ .top {
103
+ display: none !important;
104
+ }
105
+ }
84
106
  }
@@ -1,6 +1,6 @@
1
1
  export const __esModule: true;
2
2
  export const content: string;
3
- export const header: string;
3
+ export const contentHeader: string;
4
4
  export const layout: string;
5
5
  export const layoutAnvil1: string;
6
6
  export const layoutAnvil2: string;
@@ -9,6 +9,7 @@ export const layoutLegacy: string;
9
9
  export const layoutMobile: string;
10
10
  export const layoutNavSlim: string;
11
11
  export const layoutNavWide: string;
12
+ export const layoutTop: string;
12
13
  export const side: string;
13
14
  export const top: string;
14
15
  export const topPlaceholder: string;
@@ -27,6 +27,8 @@ interface LayoutContentArgs {
27
27
  search: boolean;
28
28
  longContent: boolean;
29
29
  wideContent: boolean;
30
+ minWidth: boolean;
31
+ emptyNav: boolean;
30
32
  }
31
33
 
32
34
  export default {
@@ -41,6 +43,8 @@ export default {
41
43
  search: true,
42
44
  longContent: true,
43
45
  wideContent: false,
46
+ minWidth: false,
47
+ emptyNav: false,
44
48
  } as LayoutContentArgs,
45
49
  };
46
50
 
@@ -68,6 +72,7 @@ const profile = (
68
72
  to="https://google.com"
69
73
  tooltip="Google it"
70
74
  target="_blank"
75
+ tag={{ value: true }}
71
76
  >
72
77
  first link
73
78
  </ProfileDropdown.Link>
@@ -180,7 +185,9 @@ const ContentHeader = () => {
180
185
  </Fragment>
181
186
  );
182
187
  };
183
- const SearchBar = () => <TextField size="small" placeholder="Search" className="w-100-i" />;
188
+ const SearchBar = () => (
189
+ <TextField size="small" placeholder="Search" className="w-100-i m-x-half-i" />
190
+ );
184
191
 
185
192
  const useLayoutProps = (args: LayoutContentArgs): TitanLayoutProps => {
186
193
  const [state, setState] = useState<TitanLayoutState | undefined>(undefined);
@@ -190,7 +197,7 @@ const useLayoutProps = (args: LayoutContentArgs): TitanLayoutProps => {
190
197
  onStateChange: setState,
191
198
 
192
199
  navigationComponent: NavLinkMock,
193
- navigationMainItems: mainNavItems,
200
+ navigationMainItems: args.emptyNav ? [] : mainNavItems,
194
201
 
195
202
  profile,
196
203
  top: args.search ? <SearchBar /> : undefined,
@@ -200,14 +207,16 @@ const useLayoutProps = (args: LayoutContentArgs): TitanLayoutProps => {
200
207
  extraLinksTop,
201
208
  extraText: args.extraText ? 'EST (-8 hrs)' : undefined,
202
209
 
203
- sideTop: args.sideTop ? sidebarTop() : undefined,
210
+ sideTop: args.sideTop && !args.emptyNav ? sidebarTop() : undefined,
211
+
212
+ minContentWidth: args.minWidth ? 900 : undefined,
204
213
  };
205
214
  };
206
215
 
207
216
  const Content = (args: LayoutContentArgs) => {
208
217
  return (
209
218
  <Fragment>
210
- <LocationInfo />
219
+ <LocationInfo className="m-b-3" />
211
220
  {args.wideContent && (
212
221
  <div style={{ width: '1200px' }}>
213
222
  Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor