@servicetitan/navigation 3.0.0 → 3.2.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 (43) hide show
  1. package/dist/components/header-navigation/header-navigation-tiny.stories.d.ts +3 -2
  2. package/dist/components/header-navigation/header-navigation-tiny.stories.d.ts.map +1 -1
  3. package/dist/components/header-navigation/header-navigation-tiny.stories.js +8 -5
  4. package/dist/components/header-navigation/header-navigation-tiny.stories.js.map +1 -1
  5. package/dist/components/header-navigation/header-navigation.module.less +71 -51
  6. package/dist/components/layout.stories.d.ts +8 -0
  7. package/dist/components/layout.stories.d.ts.map +1 -0
  8. package/dist/components/layout.stories.js +14 -0
  9. package/dist/components/layout.stories.js.map +1 -0
  10. package/dist/components/logo/logo-company-title.js +1 -1
  11. package/dist/components/logo/logo-company-title.js.map +1 -1
  12. package/dist/components/profile-dropdown/profile-dropdown.d.ts +0 -1
  13. package/dist/components/profile-dropdown/profile-dropdown.d.ts.map +1 -1
  14. package/dist/components/profile-dropdown/profile-dropdown.js +2 -2
  15. package/dist/components/profile-dropdown/profile-dropdown.js.map +1 -1
  16. package/dist/components/profile-dropdown/profile-icon.d.ts +1 -3
  17. package/dist/components/profile-dropdown/profile-icon.d.ts.map +1 -1
  18. package/dist/components/profile-dropdown/profile-icon.js +3 -1
  19. package/dist/components/profile-dropdown/profile-icon.js.map +1 -1
  20. package/dist/components/side-navigation/icons.d.ts +4 -1
  21. package/dist/components/side-navigation/icons.d.ts.map +1 -1
  22. package/dist/components/side-navigation/icons.js +1 -1
  23. package/dist/components/side-navigation/icons.js.map +1 -1
  24. package/dist/components/side-navigation/side-navigation.d.ts +10 -3
  25. package/dist/components/side-navigation/side-navigation.d.ts.map +1 -1
  26. package/dist/components/side-navigation/side-navigation.js +8 -7
  27. package/dist/components/side-navigation/side-navigation.js.map +1 -1
  28. package/dist/components/side-navigation/side-navigation.module.less +38 -23
  29. package/dist/components/side-navigation/side-navigation.stories.d.ts.map +1 -1
  30. package/dist/components/side-navigation/side-navigation.stories.js +2 -1
  31. package/dist/components/side-navigation/side-navigation.stories.js.map +1 -1
  32. package/package.json +2 -2
  33. package/src/components/header-navigation/header-navigation-tiny.stories.tsx +75 -17
  34. package/src/components/header-navigation/header-navigation.module.less +71 -51
  35. package/src/components/layout.stories.tsx +34 -0
  36. package/src/components/logo/logo-company-title.tsx +1 -1
  37. package/src/components/profile-dropdown/profile-dropdown.tsx +2 -4
  38. package/src/components/profile-dropdown/profile-icon.tsx +5 -5
  39. package/src/components/side-navigation/icons.tsx +17 -16
  40. package/src/components/side-navigation/side-navigation.module.less +38 -23
  41. package/src/components/side-navigation/side-navigation.module.less.d.ts +2 -1
  42. package/src/components/side-navigation/side-navigation.stories.tsx +2 -0
  43. package/src/components/side-navigation/side-navigation.tsx +33 -14
@@ -1,27 +1,28 @@
1
- export const IconSideOptions = () => (
1
+ import { FC } from 'react';
2
+
3
+ export const IconSideOptions: FC<{ expanded?: boolean }> = ({ expanded }) => (
2
4
  <svg
3
5
  width="1em"
4
6
  height="1em"
5
- viewBox="0 0 18 18"
7
+ viewBox="0 0 24 24"
6
8
  fill="none"
7
9
  xmlns="http://www.w3.org/2000/svg"
8
10
  >
9
11
  <path
10
- d="M1 3C1 1.89543 1.89543 1 3 1H7V17H3C1.89543 17 1 16.1046 1 15V3Z"
11
- stroke="currentColor"
12
- strokeWidth="2"
13
- strokeOpacity="1"
14
- />
15
- <rect
16
- x="1"
17
- y="1"
18
- width="16"
19
- height="16"
20
- rx="2"
21
- stroke="currentColor"
22
- strokeWidth="2"
23
- strokeOpacity="1"
12
+ d="M5 21C4.45 21 3.98 20.8 3.59 20.41C3.2 20.02 3 19.55 3 19V5C3 4.45 3.2 3.98 3.59 3.59C3.98 3.2 4.45 3 5 3H19C19.55 3 20.02 3.2 20.41 3.59C20.8 3.98 21 4.45 21 5V19C21 19.55 20.8 20.02 20.41 20.41C20.02 20.8 19.55 21 19 21H5ZM8 19V5H5V19H8ZM10 19H19V5H10V19Z"
13
+ fill="currentColor"
24
14
  />
15
+ {expanded ? (
16
+ <path
17
+ d="M16.54 14.19C16.71 14.38 16.71 14.66 16.54 14.85L16 15.46C15.9 15.56 15.77 15.62 15.62 15.62C15.48 15.62 15.35 15.56 15.25 15.46L12.46 12.33C12.29 12.14 12.29 11.86 12.46 11.67L15.25 8.54001C15.44 8.33001 15.81 8.33001 16 8.54001L16.54 9.15001C16.71 9.34001 16.71 9.62001 16.54 9.81001L14.58 12L16.54 14.19Z"
18
+ fill="currentColor"
19
+ />
20
+ ) : (
21
+ <path
22
+ d="M16.54 12.33L13.75 15.46C13.65 15.56 13.52 15.62 13.38 15.62C13.23 15.62 13.1 15.56 13 15.46L12.46 14.85C12.29 14.66 12.29 14.38 12.46 14.19L14.41 12L12.46 9.81001C12.29 9.62001 12.29 9.34001 12.46 9.15001L13 8.54001C13.19 8.33001 13.56 8.33001 13.75 8.54001L16.54 11.67C16.71 11.86 16.71 12.14 16.54 12.33Z"
23
+ fill="currentColor"
24
+ />
25
+ )}
25
26
  </svg>
26
27
  );
27
28
 
@@ -1,8 +1,11 @@
1
1
  /* stylelint-disable no-descending-specificity */
2
2
  @import (reference) '@servicetitan/tokens/core/tokens.less';
3
3
 
4
- @text-color: #383838;
5
- @border-color: #c5c5cb;
4
+ @text-color: var(--colorsTextInverted, @color-white);
5
+ @text-color-active: var(--colorsTextPrimarySubdued, @color-blue-300);
6
+ @border-color: var(--colorsTextOnGrey, @color-neutral-200);
7
+ @bg-color: var(--colorsSurfaceInvertedStrong, @color-neutral-400);
8
+ @bg-color-hover: rgba(255, 255, 255, 0.12);
6
9
 
7
10
  .side-nav {
8
11
  display: flex;
@@ -14,20 +17,16 @@
14
17
  -o-transition: width 100ms ease-in-out;
15
18
  transition: width 100ms ease-in-out;
16
19
 
17
- background-color: #ebebeb;
18
- border-right: 1px solid @border-color;
20
+ background-color: @bg-color;
19
21
 
20
22
  .side-nav-bottom {
21
- padding-left: 12px;
22
- padding-right: 12px;
23
+ padding-left: @spacing-1;
24
+ padding-right: @spacing-1;
25
+ border-top: 1px solid @border-color;
23
26
 
24
27
  display: flex;
25
28
  flex-direction: column;
26
29
  justify-content: center;
27
-
28
- .sideNavBottomDivider {
29
- border-top: 1px solid @border-color;
30
- }
31
30
  }
32
31
 
33
32
  &.side-nav-slim {
@@ -42,7 +41,7 @@
42
41
  }
43
42
 
44
43
  &.side-nav-expanded {
45
- width: 240px;
44
+ width: 204px;
46
45
  }
47
46
 
48
47
  .side-nav-content {
@@ -50,16 +49,24 @@
50
49
  flex-direction: column;
51
50
  align-items: stretch;
52
51
  overflow-y: auto;
53
- margin-top: @spacing-1;
54
- margin-bottom: @spacing-1;
52
+ padding-top: @spacing-1;
53
+ padding-bottom: @spacing-1;
55
54
  flex-grow: 1;
56
55
  flex-basis: 0;
57
56
  }
57
+
58
+ .side-nav-top {
59
+ display: flex;
60
+ flex-direction: column;
61
+ align-items: stretch;
62
+ padding-top: @spacing-1;
63
+ padding-bottom: @spacing-1;
64
+ }
58
65
  }
59
66
 
60
67
  .navigation-item {
61
68
  font-family: @base-font-family;
62
- color: #383838;
69
+ color: @text-color;
63
70
  position: relative;
64
71
  display: flex;
65
72
  justify-content: flex-start;
@@ -73,11 +80,12 @@
73
80
  border-radius: 12px;
74
81
 
75
82
  &.navigation-item-active {
76
- background-color: @color-white;
83
+ background-color: rgba(2, 101, 220, 0.3);
84
+ color: @text-color-active;
77
85
  }
78
86
 
79
87
  &:hover:not(.navigation-item-active) {
80
- opacity: 0.7;
88
+ background-color: @bg-color-hover;
81
89
  }
82
90
 
83
91
  .navigation-item-counter {
@@ -109,27 +117,28 @@
109
117
  flex-wrap: nowrap;
110
118
  text-wrap: nowrap;
111
119
  cursor: pointer;
112
- height: 32px;
120
+ height: 40px;
113
121
 
114
122
  margin-top: @spacing-1;
115
123
  margin-bottom: @spacing-1;
116
124
  border-radius: 8px;
117
125
 
118
126
  &:hover {
119
- background-color: @color-white;
127
+ background-color: @bg-color-hover;
120
128
  }
121
129
 
122
130
  .options-icon {
123
- height: 18px;
124
- width: 18px;
125
- font-size: 18px;
126
- padding-left: 7px;
131
+ height: 24px;
132
+ width: 24px;
133
+ font-size: 24px;
134
+ padding-left: @spacing-1;
135
+ padding-right: @spacing-1;
127
136
  }
128
137
 
129
138
  .options-item-text {
130
139
  font-family: @base-font-family;
131
140
  font-size: @typescale-3;
132
- padding-left: @spacing-2;
141
+ padding-left: @spacing-1;
133
142
  flex: 1;
134
143
  }
135
144
  }
@@ -151,3 +160,9 @@
151
160
  .options-popover-item-active {
152
161
  border-radius: @border-radius-1;
153
162
  }
163
+
164
+ .divider {
165
+ border-top: 1px solid @border-color;
166
+ margin-left: 12px;
167
+ margin-right: 12px;
168
+ }
@@ -1,4 +1,5 @@
1
1
  export const __esModule: true;
2
+ export const divider: string;
2
3
  export const navigationIcon: string;
3
4
  export const navigationItem: string;
4
5
  export const navigationItemActive: string;
@@ -12,8 +13,8 @@ export const optionsPopoverItemClickable: string;
12
13
  export const optionsPopoverItemInactive: string;
13
14
  export const sideNav: string;
14
15
  export const sideNavBottom: string;
15
- export const sideNavBottomDivider: string;
16
16
  export const sideNavContent: string;
17
17
  export const sideNavExpanded: string;
18
18
  export const sideNavSlim: string;
19
+ export const sideNavTop: string;
19
20
 
@@ -50,6 +50,7 @@ const items = {
50
50
  pointOfSale: getItem('pointOfSale', { iconName: 'cash-register' }),
51
51
  projects: getItem('projects', { iconName: 'folder_special' }),
52
52
  reports: getItem('reports', { iconName: 'poll' }),
53
+ tasks: getItem('tasks', { iconName: 'format_list_bulleted' }),
53
54
  };
54
55
 
55
56
  const NavLinkMock: FC<NavLinkComponentProps> = props => (
@@ -88,6 +89,7 @@ export const DefaultSideNavigation = () => {
88
89
  items.pointOfSale,
89
90
  items.reports,
90
91
  ]}
92
+ itemsTop={[items.tasks]}
91
93
  />
92
94
  );
93
95
  };
@@ -1,6 +1,6 @@
1
1
  import { BodyText, Divider, Eyebrow, Icon, Popover, Stack } from '@servicetitan/design-system';
2
2
  import classNames from 'classnames';
3
- import { FC, useState } from 'react';
3
+ import { FC, Fragment, PropsWithChildren, useState } from 'react';
4
4
  import { HeaderNavigationItemData, NavLinkComponentProps } from '../../utils/navigation';
5
5
  import {
6
6
  DefaultNavLinkComponent,
@@ -19,6 +19,8 @@ export interface SideNavigationProps {
19
19
  id?: string;
20
20
  /** main navigation items */
21
21
  items?: HeaderNavigationItemData[];
22
+ /** top navigation items */
23
+ itemsTop?: HeaderNavigationItemData[];
22
24
  /** is menu expanded */
23
25
  expanded?: boolean;
24
26
  /** navigation component used for routing */
@@ -32,6 +34,7 @@ export const SideNavigation: FC<SideNavigationProps> = ({
32
34
  expanded,
33
35
  id,
34
36
  items,
37
+ itemsTop,
35
38
  navigationComponent = DefaultNavLinkComponent,
36
39
  onExpandedChange,
37
40
  }) => {
@@ -46,14 +49,23 @@ export const SideNavigation: FC<SideNavigationProps> = ({
46
49
  id={id}
47
50
  data-cy="side-navigation"
48
51
  >
52
+ {!!itemsTop?.length && (
53
+ <Fragment>
54
+ <div className={Styles.sideNavTop} data-cy="navigation-items-top">
55
+ {itemsTop.map(item => (
56
+ <SideNavigationItem key={item.id} expanded={expanded} {...item} />
57
+ ))}
58
+ </div>
59
+ <div className={Styles.divider} />
60
+ </Fragment>
61
+ )}
49
62
  <div className={Styles.sideNavContent} data-cy="navigation-items">
50
63
  {items?.map(item => (
51
64
  <SideNavigationItem key={item.id} expanded={expanded} {...item} />
52
65
  ))}
53
66
  </div>
54
67
  <div className={Styles.sideNavBottom}>
55
- <div className={Styles.sideNavBottomDivider} />
56
- <SideNavigationOptions
68
+ <SideNavigationOptionsToggle
57
69
  expanded={expanded}
58
70
  onExpandedChange={onExpandedChange}
59
71
  />
@@ -115,30 +127,37 @@ export const SideNavigationItem: FC<SideNavigationItemProps> = ({
115
127
  );
116
128
  };
117
129
 
118
- /** Side Navigation options item */
119
- export const SideNavigationOptions: FC<{
130
+ /** Side Navigation options toggle */
131
+ export const SideNavigationOptionsToggle: FC<{
120
132
  expanded?: boolean;
121
133
  onExpandedChange(expanded: boolean): void;
122
- }> = ({ expanded, onExpandedChange }) => {
123
- const [open, setOpen] = useState(false);
124
-
125
- const trigger = withTooltip(
134
+ }> = ({ expanded, onExpandedChange }) =>
135
+ withTooltip(
126
136
  <div
127
137
  data-cy="navigation-left-options"
128
138
  data-pendo="navigation-left-options"
129
139
  className={classNames(Styles.optionsItem)}
130
- onClick={() => setOpen(!open)}
140
+ onClick={() => onExpandedChange(!expanded)}
131
141
  >
132
142
  <div className={Styles.optionsIcon}>
133
- <IconSideOptions />
143
+ <IconSideOptions expanded={expanded} />
134
144
  </div>
135
145
 
136
- {!!expanded && <span className={Styles.optionsItemText}>Menu Options</span>}
146
+ {!!expanded && <span className={Styles.optionsItemText}>Collapse Menu</span>}
137
147
  </div>,
138
- open || expanded ? undefined : 'Menu Options',
148
+ expanded ? undefined : 'Expand Menu',
139
149
  'r'
140
150
  );
141
151
 
152
+ /** Side Navigation options popover */
153
+ export const SideNavigationOptionsPopover: FC<
154
+ PropsWithChildren<{
155
+ expanded?: boolean;
156
+ onExpandedChange(expanded: boolean): void;
157
+ }>
158
+ > = ({ children, expanded, onExpandedChange }) => {
159
+ const [open, setOpen] = useState(false);
160
+
142
161
  const onExpand = () => {
143
162
  setOpen(false);
144
163
  onExpandedChange(true);
@@ -151,7 +170,7 @@ export const SideNavigationOptions: FC<{
151
170
  return (
152
171
  <Popover
153
172
  className="bg-neutral-30"
154
- trigger={trigger}
173
+ trigger={children}
155
174
  direction="tr"
156
175
  onClickOutside={() => setOpen(false)}
157
176
  open={open}