@pautena/react-design-system 0.1.2 → 0.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 (191) hide show
  1. package/README.md +4 -0
  2. package/dist/cjs/index.js +4 -259
  3. package/dist/cjs/index.js.map +1 -1
  4. package/dist/cjs/types/generators/model-router/screens/add-screen.d.ts +1 -1
  5. package/dist/cjs/types/generators/model-router/screens/list-screen.d.ts +1 -1
  6. package/dist/cjs/types/generators/model-router/screens/screens.types.d.ts +20 -0
  7. package/dist/cjs/types/generators/model-router/screens/update-screen.d.ts +1 -1
  8. package/dist/cjs/types/index.d.ts +1 -0
  9. package/dist/esm/index.js +4 -259
  10. package/dist/esm/index.js.map +1 -1
  11. package/dist/esm/types/generators/model-router/screens/add-screen.d.ts +1 -1
  12. package/dist/esm/types/generators/model-router/screens/list-screen.d.ts +1 -1
  13. package/dist/esm/types/generators/model-router/screens/screens.types.d.ts +20 -0
  14. package/dist/esm/types/generators/model-router/screens/update-screen.d.ts +1 -1
  15. package/dist/esm/types/index.d.ts +1 -0
  16. package/dist/index.d.ts +52 -3
  17. package/package.json +13 -2
  18. package/src/components/app-bar/app-bar.stories.tsx +54 -0
  19. package/src/components/app-bar/app-bar.test.tsx +142 -0
  20. package/src/components/app-bar/app-bar.tsx +150 -0
  21. package/src/components/app-bar/app-bar.types.ts +17 -0
  22. package/src/components/app-bar/index.ts +3 -0
  23. package/src/components/app-bar/mini-app-bar/index.ts +1 -0
  24. package/src/components/app-bar/mini-app-bar/mini-app-bar.tsx +31 -0
  25. package/src/components/bullet/bullet.stories.tsx +43 -0
  26. package/src/components/bullet/bullet.test.tsx +24 -0
  27. package/src/components/bullet/bullet.tsx +30 -0
  28. package/src/components/bullet/index.ts +1 -0
  29. package/src/components/center-container/center-container.stories.tsx +50 -0
  30. package/src/components/center-container/center-container.test.tsx +16 -0
  31. package/src/components/center-container/center-container.tsx +32 -0
  32. package/src/components/center-container/index.ts +1 -0
  33. package/src/components/content/content.stories.tsx +23 -0
  34. package/src/components/content/content.test.tsx +26 -0
  35. package/src/components/content/content.tsx +11 -0
  36. package/src/components/content/content.types.ts +5 -0
  37. package/src/components/content/index.ts +2 -0
  38. package/src/components/drawer/__snapshots__/drawer.test.tsx.snap +20 -0
  39. package/src/components/drawer/drawer.context.ts +20 -0
  40. package/src/components/drawer/drawer.mixins.ts +24 -0
  41. package/src/components/drawer/drawer.mock.tsx +100 -0
  42. package/src/components/drawer/drawer.provider.tsx +23 -0
  43. package/src/components/drawer/drawer.test.tsx +97 -0
  44. package/src/components/drawer/drawer.tsx +30 -0
  45. package/src/components/drawer/drawer.types.ts +53 -0
  46. package/src/components/drawer/index.ts +5 -0
  47. package/src/components/drawer/mini-drawer/index.ts +1 -0
  48. package/src/components/drawer/mini-drawer/mini-drawer.stories.tsx +34 -0
  49. package/src/components/drawer/mini-drawer/mini-drawer.tsx +67 -0
  50. package/src/components/drawer-content/drawer-content.stories.tsx +29 -0
  51. package/src/components/drawer-content/drawer-content.test.tsx +34 -0
  52. package/src/components/drawer-content/drawer-content.tsx +18 -0
  53. package/src/components/drawer-content/index.ts +1 -0
  54. package/src/components/drawer-item/drawer-item.stories.tsx +62 -0
  55. package/src/components/drawer-item/drawer-item.test.tsx +119 -0
  56. package/src/components/drawer-item/drawer-item.tsx +71 -0
  57. package/src/components/drawer-item/index.ts +1 -0
  58. package/src/components/drawer-section/drawer-section.mock.tsx +39 -0
  59. package/src/components/drawer-section/drawer-section.stories.tsx +28 -0
  60. package/src/components/drawer-section/drawer-section.test.tsx +44 -0
  61. package/src/components/drawer-section/drawer-section.tsx +40 -0
  62. package/src/components/drawer-section/index.ts +1 -0
  63. package/src/components/header/header.dummy.ts +55 -0
  64. package/src/components/header/header.stories.tsx +116 -0
  65. package/src/components/header/header.test.tsx +159 -0
  66. package/src/components/header/header.tsx +121 -0
  67. package/src/components/header/header.types.ts +61 -0
  68. package/src/components/header/index.ts +2 -0
  69. package/src/components/index.ts +18 -0
  70. package/src/components/label/index.ts +1 -0
  71. package/src/components/label/label.stories.tsx +49 -0
  72. package/src/components/label/label.test.tsx +30 -0
  73. package/src/components/label/label.tsx +60 -0
  74. package/src/components/link/index.ts +1 -0
  75. package/src/components/link/link.tsx +17 -0
  76. package/src/components/loading-area/index.ts +1 -0
  77. package/src/components/loading-area/loading-area.stories.tsx +17 -0
  78. package/src/components/loading-area/loading-area.test.tsx +11 -0
  79. package/src/components/loading-area/loading-area.tsx +13 -0
  80. package/src/components/placeholder/index.ts +1 -0
  81. package/src/components/placeholder/placeholder.mock.ts +15 -0
  82. package/src/components/placeholder/placeholder.stories.tsx +44 -0
  83. package/src/components/placeholder/placeholder.test.tsx +76 -0
  84. package/src/components/placeholder/placeholder.tsx +75 -0
  85. package/src/components/query-container/index.ts +1 -0
  86. package/src/components/query-container/query-container.stories.tsx +68 -0
  87. package/src/components/query-container/query-container.test.tsx +95 -0
  88. package/src/components/query-container/query-container.tsx +71 -0
  89. package/src/components/sign-in/index.ts +1 -0
  90. package/src/components/sign-in/sign-in.stories.tsx +36 -0
  91. package/src/components/sign-in/sign-in.test.tsx +95 -0
  92. package/src/components/sign-in/sign-in.tsx +97 -0
  93. package/src/components/tab/index.ts +2 -0
  94. package/src/components/tab/tab-card/index.ts +1 -0
  95. package/src/components/tab/tab-card/tab-card.dummy.tsx +30 -0
  96. package/src/components/tab/tab-card/tab-card.stories.tsx +22 -0
  97. package/src/components/tab/tab-card/tab-card.test.tsx +53 -0
  98. package/src/components/tab/tab-card/tab-card.tsx +27 -0
  99. package/src/components/tab/tab-panel/index.ts +1 -0
  100. package/src/components/tab/tab-panel/tab-panel.test.tsx +26 -0
  101. package/src/components/tab/tab-panel/tab-panel.tsx +27 -0
  102. package/src/components/table/enhanced-remote-table/enhanced-remote-table.mock.tsx +27 -0
  103. package/src/components/table/enhanced-remote-table/enhanced-remote-table.stories.tsx +24 -0
  104. package/src/components/table/enhanced-remote-table/enhanced-remote-table.test.tsx +77 -0
  105. package/src/components/table/enhanced-remote-table/enhanced-remote-table.tsx +74 -0
  106. package/src/components/table/enhanced-remote-table/index.ts +1 -0
  107. package/src/components/table/enhanced-table/enhanced-table-head.tsx +58 -0
  108. package/src/components/table/enhanced-table/enhanced-table.mock.tsx +93 -0
  109. package/src/components/table/enhanced-table/enhanced-table.stories.tsx +21 -0
  110. package/src/components/table/enhanced-table/enhanced-table.test.tsx +107 -0
  111. package/src/components/table/enhanced-table/enhanced-table.tsx +136 -0
  112. package/src/components/table/enhanced-table/index.ts +2 -0
  113. package/src/components/table/index.ts +2 -0
  114. package/src/components/table-list/index.ts +1 -0
  115. package/src/components/table-list/table-list.stories.tsx +75 -0
  116. package/src/components/table-list/table-list.test.tsx +291 -0
  117. package/src/components/table-list/table-list.tsx +127 -0
  118. package/src/components/value-displays/group-value-card/group-value-card.mock.tsx +35 -0
  119. package/src/components/value-displays/group-value-card/group-value-card.stories.tsx +26 -0
  120. package/src/components/value-displays/group-value-card/group-value-card.test.tsx +58 -0
  121. package/src/components/value-displays/group-value-card/group-value-card.tsx +63 -0
  122. package/src/components/value-displays/group-value-card/index.ts +1 -0
  123. package/src/components/value-displays/index.ts +4 -0
  124. package/src/components/value-displays/value-boolean/index.ts +1 -0
  125. package/src/components/value-displays/value-boolean/value-boolean.stories.tsx +25 -0
  126. package/src/components/value-displays/value-boolean/value-boolean.test.tsx +27 -0
  127. package/src/components/value-displays/value-boolean/value-boolean.tsx +33 -0
  128. package/src/components/value-displays/value-card/index.ts +1 -0
  129. package/src/components/value-displays/value-card/value-card.stories.tsx +22 -0
  130. package/src/components/value-displays/value-card/value-card.test.tsx +18 -0
  131. package/src/components/value-displays/value-card/value-card.tsx +12 -0
  132. package/src/components/value-displays/value-text/index.ts +1 -0
  133. package/src/components/value-displays/value-text/value-test.test.tsx +21 -0
  134. package/src/components/value-displays/value-text/value-text.stories.tsx +26 -0
  135. package/src/components/value-displays/value-text/value-text.tsx +32 -0
  136. package/src/generators/generators.mock.ts +238 -0
  137. package/src/generators/generators.model.ts +46 -0
  138. package/src/generators/index.ts +4 -0
  139. package/src/generators/model-form/index.ts +1 -0
  140. package/src/generators/model-form/model-form.stories.tsx +30 -0
  141. package/src/generators/model-form/model-form.test.tsx +100 -0
  142. package/src/generators/model-form/model-form.tsx +97 -0
  143. package/src/generators/model-router/index.ts +1 -0
  144. package/src/generators/model-router/model-router.test.tsx +831 -0
  145. package/src/generators/model-router/model-router.tsx +30 -0
  146. package/src/generators/model-router/model-router.types.ts +14 -0
  147. package/src/generators/model-router/screens/add-screen.tsx +70 -0
  148. package/src/generators/model-router/screens/details-screen.tsx +62 -0
  149. package/src/generators/model-router/screens/index.ts +4 -0
  150. package/src/generators/model-router/screens/list-screen.tsx +125 -0
  151. package/src/generators/model-router/screens/screens.types.ts +38 -0
  152. package/src/generators/model-router/screens/update-screen.tsx +97 -0
  153. package/src/generators/model-router/stories/details-screen.stories.tsx +38 -0
  154. package/src/generators/model-router/stories/list-screen.stories.tsx +96 -0
  155. package/src/generators/model-router/stories/model-router.stories.tsx +176 -0
  156. package/src/generators/model-router/stories/templates.tsx +39 -0
  157. package/src/generators/object-details/index.ts +1 -0
  158. package/src/generators/object-details/object-details.stories.tsx +20 -0
  159. package/src/generators/object-details/object-details.test.tsx +21 -0
  160. package/src/generators/object-details/object-details.tsx +76 -0
  161. package/src/index.ts +5 -0
  162. package/src/layouts/app-bar-with-drawer-layout/app-bar-with-drawer-layout.stories.tsx +28 -0
  163. package/src/layouts/app-bar-with-drawer-layout/app-bar-with-drawer-layout.test.tsx +30 -0
  164. package/src/layouts/app-bar-with-drawer-layout/app-bar-with-drawer-layout.tsx +37 -0
  165. package/src/layouts/app-bar-with-drawer-layout/index.ts +1 -0
  166. package/src/layouts/header-layout/header-layout.stories.tsx +204 -0
  167. package/src/layouts/header-layout/header-layout.test.tsx +37 -0
  168. package/src/layouts/header-layout/header-layout.tsx +23 -0
  169. package/src/layouts/header-layout/index.ts +1 -0
  170. package/src/layouts/index.ts +2 -0
  171. package/src/providers/index.ts +2 -0
  172. package/src/providers/notification-center/index.ts +2 -0
  173. package/src/providers/notification-center/notification-center.context.ts +37 -0
  174. package/src/providers/notification-center/notification-center.provider.tsx +51 -0
  175. package/src/providers/notification-center/notification-center.stories.tsx +52 -0
  176. package/src/providers/notification-center/notification-center.test.tsx +112 -0
  177. package/src/providers/tab-provider/index.ts +2 -0
  178. package/src/providers/tab-provider/tab-provider.context.ts +8 -0
  179. package/src/providers/tab-provider/tab-provider.provider.tsx +13 -0
  180. package/src/storybook.tsx +90 -0
  181. package/src/tests/assertions.ts +76 -0
  182. package/src/tests/components.tsx +60 -0
  183. package/src/tests/content-placeholder.stories.tsx +16 -0
  184. package/src/tests/index.ts +3 -0
  185. package/src/tests/skeleton-card.stories.tsx +18 -0
  186. package/src/tests/testing-library.tsx +65 -0
  187. package/src/utils/arrays.test.ts +9 -0
  188. package/src/utils/arrays.ts +7 -0
  189. package/src/utils/index.ts +2 -0
  190. package/src/utils/theme.ts +11 -0
  191. package/.prettierrc.js +0 -5
@@ -0,0 +1,29 @@
1
+ import React from "react";
2
+ import { ComponentMeta } from "@storybook/react";
3
+ import { createTemplate } from "../../storybook";
4
+ import { DrawerContent } from "./drawer-content";
5
+ import { mockNav } from "../drawer/drawer.mock";
6
+ import { Box } from "@mui/material";
7
+ import { withMemoryRouter } from "~/storybook";
8
+
9
+ export default {
10
+ title: "Drawers/DrawerContent",
11
+ component: DrawerContent,
12
+ decorators: [
13
+ withMemoryRouter(),
14
+ (Story) => {
15
+ return <Box maxWidth={300}>{<Story />}</Box>;
16
+ },
17
+ ],
18
+ parameters: {
19
+ layout: "fullscreen",
20
+ },
21
+ } as ComponentMeta<typeof DrawerContent>;
22
+
23
+ const Template = createTemplate(DrawerContent);
24
+
25
+ export const Default = Template.bind({});
26
+ Default.args = {
27
+ nav: mockNav,
28
+ open: true,
29
+ };
@@ -0,0 +1,34 @@
1
+ import React from "react";
2
+ import { render, screen } from "../../tests";
3
+ import { mockNav } from "../drawer/drawer.mock";
4
+ import { DrawerContent } from "./drawer-content";
5
+
6
+ describe("DrawerContent", () => {
7
+ const renderComponent = () => {
8
+ return render(<DrawerContent nav={mockNav} />);
9
+ };
10
+
11
+ it.each([[/section 2/i], [/section avatar/i]])(
12
+ "would render the title section %s",
13
+ (sectionTitle: RegExp) => {
14
+ renderComponent();
15
+
16
+ expect(screen.getByRole("heading", { name: sectionTitle })).toBeInTheDocument();
17
+ },
18
+ );
19
+
20
+ it.each([
21
+ [/item 1.1/i],
22
+ [/item 1.2/i],
23
+ [/item 1.3/i],
24
+ [/item 1.4/i],
25
+ [/item 2.1/i],
26
+ [/item 2.2/i],
27
+ [/avatar 1/i],
28
+ [/avatar 2/i],
29
+ ])("would render the item %s", (itemText: RegExp) => {
30
+ renderComponent();
31
+
32
+ expect(screen.getByRole("link", { name: itemText })).toBeInTheDocument();
33
+ });
34
+ });
@@ -0,0 +1,18 @@
1
+ import React from "react";
2
+ import { DrawerSection } from "../drawer-section";
3
+ import { DrawerContentComponent, DrawerContentProps } from "../drawer/drawer.types";
4
+
5
+ /**
6
+ * Content to be shown inside a navigation
7
+ */
8
+ export const DrawerContent: DrawerContentComponent = ({ nav }: DrawerContentProps) => {
9
+ const { items } = nav;
10
+
11
+ return (
12
+ <>
13
+ {items.map(({ title, items }, i) => (
14
+ <DrawerSection key={i} title={title} items={items} />
15
+ ))}
16
+ </>
17
+ );
18
+ };
@@ -0,0 +1 @@
1
+ export * from "./drawer-content";
@@ -0,0 +1,62 @@
1
+ import React from "react";
2
+ import { ComponentMeta } from "@storybook/react";
3
+ import { createTemplate } from "../../storybook";
4
+ import { DrawerItem } from "./drawer-item";
5
+ import DiamondIcon from "@mui/icons-material/Diamond";
6
+ import { withContainer } from "../../storybook";
7
+ import { withMemoryRouter } from "~/storybook";
8
+
9
+ export default {
10
+ title: "Drawers/DrawerItem",
11
+ component: DrawerItem,
12
+ decorators: [withMemoryRouter(), withContainer({ width: 250 })],
13
+ parameters: {
14
+ layout: "centered",
15
+ },
16
+ } as ComponentMeta<typeof DrawerItem>;
17
+
18
+ const Template = createTemplate(DrawerItem);
19
+
20
+ export const OnlyText = Template.bind({});
21
+ OnlyText.args = {
22
+ text: "Lorem ipsum",
23
+ href: "/items/1",
24
+ };
25
+
26
+ export const WithIcon = Template.bind({});
27
+ WithIcon.args = {
28
+ text: "Lorem ipsum",
29
+ href: "/items/1",
30
+ icon: <DiamondIcon />,
31
+ };
32
+
33
+ export const WithAvatar = Template.bind({});
34
+ WithAvatar.args = {
35
+ text: "Lorem ipsum",
36
+ href: "/items/1",
37
+ avatar: {
38
+ src: "https://c.pxhere.com/images/f6/e0/022ab77c391925931fe227c97ab4-1447675.jpg!d",
39
+ alt: "Avatar 1",
40
+ },
41
+ };
42
+
43
+ export const WithLabel = Template.bind({});
44
+ WithLabel.args = {
45
+ text: "Lorem ipsum",
46
+ href: "/items/1",
47
+ icon: <DiamondIcon />,
48
+ label: {
49
+ text: "new",
50
+ variant: "info",
51
+ },
52
+ };
53
+
54
+ export const WithBullet = Template.bind({});
55
+ WithBullet.args = {
56
+ text: "Lorem ipsum",
57
+ href: "/items/1",
58
+ icon: <DiamondIcon />,
59
+ bullet: {
60
+ variant: "error",
61
+ },
62
+ };
@@ -0,0 +1,119 @@
1
+ import React, { ReactElement } from "react";
2
+ import userEvent from "@testing-library/user-event";
3
+ import { DrawerItem } from "./drawer-item";
4
+ import DiamondIcon from "@mui/icons-material/Diamond";
5
+ import { render, screen } from "../../tests";
6
+ import { NavItemAvatar, NavItemBullet, NavItemLabel } from "../drawer/drawer.types";
7
+
8
+ describe("DrawerItem", () => {
9
+ const renderComponent = ({
10
+ icon,
11
+ avatar,
12
+ label,
13
+ bullet,
14
+ }: {
15
+ icon?: ReactElement;
16
+ avatar?: NavItemAvatar;
17
+ label?: NavItemLabel;
18
+ bullet?: NavItemBullet;
19
+ } = {}) => {
20
+ return render(
21
+ <DrawerItem
22
+ text="Lorem ipsum"
23
+ href="/items/1"
24
+ icon={icon}
25
+ bullet={bullet}
26
+ avatar={avatar}
27
+ label={label}
28
+ />,
29
+ );
30
+ };
31
+
32
+ it("would render the text", () => {
33
+ renderComponent();
34
+
35
+ expect(screen.getByRole("link", { name: /lorem ipsum/i })).toBeInTheDocument();
36
+ });
37
+
38
+ it("would navigate to the href when is clicked", () => {
39
+ const { history } = renderComponent();
40
+
41
+ userEvent.click(screen.getByRole("link", { name: /lorem ipsum/i }));
42
+
43
+ expect(history.location.pathname).toBe("/items/1");
44
+ });
45
+
46
+ describe("icon", () => {
47
+ it("would render an icon when is set", () => {
48
+ renderComponent({ icon: <DiamondIcon /> });
49
+
50
+ expect(screen.getByTestId("DiamondIcon")).toBeInTheDocument();
51
+ });
52
+
53
+ it("wouldn't render an icon if is not set", () => {
54
+ renderComponent({ icon: undefined });
55
+
56
+ expect(screen.queryByTestId("DiamondIcon")).not.toBeInTheDocument();
57
+ });
58
+ });
59
+
60
+ describe("avatar", () => {
61
+ it("would render an avatar when is set", () => {
62
+ renderComponent({
63
+ avatar: {
64
+ src: "https://c.pxhere.com/images/f6/e0/022ab77c391925931fe227c97ab4-1447675.jpg!d",
65
+ alt: "Avatar 1",
66
+ },
67
+ });
68
+
69
+ expect(screen.getByRole("img", { name: /avatar 1/i })).toBeInTheDocument();
70
+ });
71
+
72
+ it("wouldn't render an avatar if is not set", () => {
73
+ renderComponent();
74
+
75
+ expect(screen.queryByRole("img", { name: /avatar 1/i })).not.toBeInTheDocument();
76
+ });
77
+ });
78
+
79
+ describe("label", () => {
80
+ it("would render a label when is set", () => {
81
+ renderComponent({
82
+ label: {
83
+ text: "new",
84
+ variant: "info",
85
+ },
86
+ });
87
+
88
+ const label = screen.getByRole("label", { name: /new/i });
89
+ expect(label).toBeInTheDocument();
90
+ expect(label).toHaveAttribute("aria-describedby", "info");
91
+ });
92
+
93
+ it("wouldn't render a label if is not set", () => {
94
+ renderComponent();
95
+
96
+ expect(screen.queryByRole("label", { name: /new/i })).not.toBeInTheDocument();
97
+ });
98
+ });
99
+
100
+ describe("bullet", () => {
101
+ it("would render a bullet when is set", () => {
102
+ renderComponent({
103
+ bullet: {
104
+ variant: "info",
105
+ },
106
+ });
107
+
108
+ const bullet = screen.getByRole("bullet");
109
+ expect(bullet).toBeInTheDocument();
110
+ expect(bullet).toHaveAttribute("aria-describedby", "info");
111
+ });
112
+
113
+ it("wouldn't render a bullet if is not set", () => {
114
+ renderComponent();
115
+
116
+ expect(screen.queryByRole("bullet")).not.toBeInTheDocument();
117
+ });
118
+ });
119
+ });
@@ -0,0 +1,71 @@
1
+ import React, { ReactElement } from "react";
2
+ import {
3
+ Avatar,
4
+ ListItem,
5
+ ListItemAvatar,
6
+ ListItemButton,
7
+ ListItemIcon,
8
+ ListItemText,
9
+ styled,
10
+ } from "@mui/material";
11
+ import { Bullet } from "../bullet";
12
+ import { Label } from "../label";
13
+ import { NavItemAvatar, NavItemBullet, NavItemLabel } from "../drawer/drawer.types";
14
+ import { Link } from "../link";
15
+
16
+ export interface DrawerItemProps {
17
+ /**
18
+ * Text displayed inside the item
19
+ */
20
+ text: string;
21
+ /**
22
+ * Url where the user is going to be redirected
23
+ * if the item is clicked
24
+ */
25
+ href: string;
26
+ /**
27
+ * Icon displayed to the left
28
+ */
29
+ icon?: ReactElement;
30
+ /**
31
+ * Avatar displayed to the left
32
+ */
33
+ avatar?: NavItemAvatar;
34
+ /**
35
+ * Label with extra info displayed to the right
36
+ */
37
+ label?: NavItemLabel;
38
+ /**
39
+ * Bullet to attract the user attention displyed to the right
40
+ */
41
+ bullet?: NavItemBullet;
42
+ }
43
+
44
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
45
+ // @ts-ignore
46
+ const DrawerItemLink = styled(Link)(({ theme }) => {
47
+ return {
48
+ color: theme.palette.text.primary,
49
+ };
50
+ });
51
+
52
+ /**
53
+ * Clicable item inside a drawer
54
+ */
55
+ export const DrawerItem = ({ text, icon, avatar, label, bullet, href }: DrawerItemProps) => {
56
+ return (
57
+ <ListItem disablePadding sx={{ display: "block" }} component={DrawerItemLink} href={href}>
58
+ <ListItemButton>
59
+ {icon && <ListItemIcon>{icon}</ListItemIcon>}
60
+ {avatar && (
61
+ <ListItemAvatar>
62
+ <Avatar alt={avatar.alt} src={avatar.src} />
63
+ </ListItemAvatar>
64
+ )}
65
+ <ListItemText primary={text} />
66
+ {label && <Label text={label.text} variant={label.variant} />}
67
+ {bullet && <Bullet variant={bullet.variant} />}
68
+ </ListItemButton>
69
+ </ListItem>
70
+ );
71
+ };
@@ -0,0 +1 @@
1
+ export * from "./drawer-item";
@@ -0,0 +1,39 @@
1
+ import React from "react";
2
+ import DiamondIcon from "@mui/icons-material/Diamond";
3
+ import { NavItem } from "../drawer/drawer.types";
4
+
5
+ export const SectionItems: NavItem[] = [
6
+ {
7
+ id: "item1.1",
8
+ text: "Item 1",
9
+ icon: <DiamondIcon />,
10
+ href: "/items/1-1",
11
+ },
12
+ {
13
+ id: "item1.2",
14
+ text: "Item 2",
15
+ href: "/items/1-2",
16
+ avatar: {
17
+ src: "https://c.pxhere.com/images/f6/e0/022ab77c391925931fe227c97ab4-1447675.jpg!d",
18
+ alt: "Avatar 1",
19
+ },
20
+ },
21
+ {
22
+ id: "item1.3",
23
+ text: "Item 3",
24
+ href: "/items/1-3",
25
+ bullet: {
26
+ variant: "secondary",
27
+ },
28
+ },
29
+ {
30
+ id: "item1.4",
31
+ text: "Item 4",
32
+ href: "/items/1-4",
33
+ icon: <DiamondIcon />,
34
+ label: {
35
+ text: "new",
36
+ variant: "error",
37
+ },
38
+ },
39
+ ];
@@ -0,0 +1,28 @@
1
+ import { ComponentMeta } from "@storybook/react";
2
+ import { createTemplate } from "../../storybook";
3
+ import { DrawerSection } from "./drawer-section";
4
+ import { withContainer } from "../../storybook";
5
+ import { withMemoryRouter } from "~/storybook";
6
+ import { SectionItems } from "./drawer-section.mock";
7
+
8
+ export default {
9
+ title: "Drawers/DrawerSection",
10
+ component: DrawerSection,
11
+ decorators: [withMemoryRouter(), withContainer({ width: 250 })],
12
+ parameters: {
13
+ layout: "centered",
14
+ },
15
+ } as ComponentMeta<typeof DrawerSection>;
16
+
17
+ const Template = createTemplate(DrawerSection);
18
+
19
+ export const Default = Template.bind({});
20
+ Default.args = {
21
+ title: "Lorem ipsum",
22
+ items: SectionItems,
23
+ };
24
+
25
+ export const WihtoutTitle = Template.bind({});
26
+ WihtoutTitle.args = {
27
+ items: SectionItems,
28
+ };
@@ -0,0 +1,44 @@
1
+ import React from "react";
2
+ import { render, screen } from "../../tests";
3
+ import userEvent from "@testing-library/user-event";
4
+ import { DrawerSection } from "./drawer-section";
5
+ import { SectionItems } from "./drawer-section.mock";
6
+
7
+ describe("DrawerSection", () => {
8
+ const renderComponent = ({
9
+ title,
10
+ }: {
11
+ title?: string;
12
+ } = {}) => {
13
+ return render(<DrawerSection title={title} items={SectionItems} />);
14
+ };
15
+
16
+ describe("title", () => {
17
+ it("would render if is set", () => {
18
+ renderComponent({ title: "Lorem ipsum" });
19
+
20
+ expect(screen.getByRole("heading", { name: /lorem ipsum/i })).toBeInTheDocument();
21
+ });
22
+
23
+ it("wouldn't render if it's not set", () => {
24
+ renderComponent({ title: undefined });
25
+
26
+ expect(screen.queryByRole("heading", { name: /lorem ipsum/i })).not.toBeInTheDocument();
27
+ });
28
+ });
29
+
30
+ describe("click list item", () => {
31
+ it.each([
32
+ ["/items/1-1", /item 1/i],
33
+ ["/items/1-2", /item 2/i],
34
+ ["/items/1-3", /item 3/i],
35
+ ["/items/1-4", /item 4/i],
36
+ ])("would navigate to %s if %s is clicked", async (to: string, item: RegExp) => {
37
+ const { history } = renderComponent();
38
+
39
+ await userEvent.click(screen.getByRole("link", { name: item }));
40
+
41
+ expect(history.location.pathname).toBe(to);
42
+ });
43
+ });
44
+ });
@@ -0,0 +1,40 @@
1
+ import { List, ListSubheader } from "@mui/material";
2
+ import React from "react";
3
+ import { DrawerItem } from "../drawer-item";
4
+ import { NavItem } from "../drawer/drawer.types";
5
+
6
+ export interface DrawerSectionProps {
7
+ /**
8
+ * Section title
9
+ */
10
+ title?: string;
11
+ /**
12
+ * List of items of that section
13
+ */
14
+ items: NavItem[];
15
+ }
16
+
17
+ /**
18
+ * Render a group of items inside the drawer
19
+ * with an optional title
20
+ */
21
+ export const DrawerSection = ({ title, items }: DrawerSectionProps) => {
22
+ return (
23
+ <>
24
+ {title && <ListSubheader role="heading">{title}</ListSubheader>}
25
+ <List>
26
+ {items.map(({ id, text, icon, avatar, label, bullet, href }) => (
27
+ <DrawerItem
28
+ key={id}
29
+ text={text}
30
+ icon={icon}
31
+ avatar={avatar}
32
+ label={label}
33
+ bullet={bullet}
34
+ href={href}
35
+ />
36
+ ))}
37
+ </List>
38
+ </>
39
+ );
40
+ };
@@ -0,0 +1 @@
1
+ export * from "./drawer-section";
@@ -0,0 +1,55 @@
1
+ import { action } from "@storybook/addon-actions";
2
+ import { HeaderBreadcrumb, HeaderAction, HeaderTab } from "./header";
3
+
4
+ export const breadcrumbs: HeaderBreadcrumb[] = [
5
+ {
6
+ id: "list",
7
+ text: "Items",
8
+ link: "/items",
9
+ },
10
+ {
11
+ id: "item",
12
+ text: "Item 1",
13
+ link: "/items/1",
14
+ },
15
+ ];
16
+
17
+ export const actions: HeaderAction[] = [
18
+ {
19
+ id: "new",
20
+ text: "Add",
21
+ href: "/items/add",
22
+ },
23
+ {
24
+ id: "edit",
25
+ text: "Edit",
26
+ onClick: action("click action edit"),
27
+ },
28
+ {
29
+ id: "disabled",
30
+ text: "Disabled",
31
+ disabled: true,
32
+ onClick: action("click action disabled"),
33
+ },
34
+ {
35
+ id: "delete",
36
+ text: "Delete",
37
+ onClick: action("click action delete"),
38
+ },
39
+ ];
40
+
41
+ export const tabs: HeaderTab[] = [
42
+ {
43
+ id: "tab1",
44
+ label: "Tab 1",
45
+ },
46
+ {
47
+ id: "tab2",
48
+ label: "Tab 2",
49
+ disabled: true,
50
+ },
51
+ {
52
+ id: "tab3",
53
+ label: "Tab 3",
54
+ },
55
+ ];
@@ -0,0 +1,116 @@
1
+ import { ComponentMeta } from "@storybook/react";
2
+ import { createTemplate } from "../../storybook";
3
+ import { Header } from "./header";
4
+ import { withMemoryRouter } from "~/storybook";
5
+ import { breadcrumbs, tabs, actions } from "./header.dummy";
6
+
7
+ export default {
8
+ title: "Sections/Header",
9
+ component: Header,
10
+ decorators: [withMemoryRouter()],
11
+ parameters: {
12
+ layout: "fullscreen",
13
+ },
14
+ } as ComponentMeta<typeof Header>;
15
+
16
+ const Template = createTemplate(Header);
17
+
18
+ export const Default = Template.bind({});
19
+ Default.args = {
20
+ title: "Lorem ipsum",
21
+ subtitle: "Dolor sit amet",
22
+ preset: "inherit",
23
+ breadcrumbs,
24
+ actions,
25
+ };
26
+
27
+ export const OnlyTitle = Template.bind({});
28
+ OnlyTitle.args = {
29
+ title: "Lorem ipsum",
30
+ };
31
+
32
+ export const ColorInherit = Template.bind({});
33
+ ColorInherit.args = {
34
+ title: "Lorem ipsum",
35
+ subtitle: "Dolor sit amet",
36
+ preset: "inherit",
37
+ breadcrumbs,
38
+ tabs,
39
+ selectedTab: 2,
40
+ actions,
41
+ };
42
+
43
+ export const ColorPrimary = Template.bind({});
44
+ ColorPrimary.args = {
45
+ title: "Lorem ipsum",
46
+ subtitle: "Dolor sit amet",
47
+ preset: "primary",
48
+ breadcrumbs,
49
+ tabs,
50
+ selectedTab: 2,
51
+ actions,
52
+ };
53
+
54
+ export const ColorSecondary = Template.bind({});
55
+ ColorSecondary.args = {
56
+ title: "Lorem ipsum",
57
+ subtitle: "Dolor sit amet",
58
+ preset: "secondary",
59
+ breadcrumbs,
60
+ tabs,
61
+ selectedTab: 2,
62
+ actions,
63
+ };
64
+
65
+ export const ColorDefault = Template.bind({});
66
+ ColorDefault.args = {
67
+ title: "Lorem ipsum",
68
+ subtitle: "Dolor sit amet",
69
+ preset: "default",
70
+ breadcrumbs,
71
+ tabs,
72
+ selectedTab: 2,
73
+ actions,
74
+ };
75
+
76
+ export const ColorTransparent = Template.bind({});
77
+ ColorTransparent.args = {
78
+ title: "Lorem ipsum",
79
+ subtitle: "Dolor sit amet",
80
+ preset: "transparent",
81
+ breadcrumbs,
82
+ tabs,
83
+ selectedTab: 2,
84
+ actions,
85
+ };
86
+
87
+ export const WithSubheader = Template.bind({});
88
+ WithSubheader.args = {
89
+ title: "Lorem ipsum",
90
+ subtitle: "Dolor sit amet",
91
+ };
92
+
93
+ export const WithBreadcumbs = Template.bind({});
94
+ WithBreadcumbs.args = {
95
+ title: "Lorem ipsum",
96
+ breadcrumbs,
97
+ };
98
+
99
+ export const WithActions = Template.bind({});
100
+ WithActions.args = {
101
+ title: "Lorem ipsum",
102
+ subtitle: "Dolor sit amet",
103
+ preset: "default",
104
+ breadcrumbs,
105
+ actions,
106
+ };
107
+
108
+ export const WithTabs = Template.bind({});
109
+ WithTabs.args = {
110
+ title: "Lorem ipsum",
111
+ subtitle: "Dolor sit amet",
112
+ preset: "default",
113
+ breadcrumbs,
114
+ tabs,
115
+ selectedTab: 2,
116
+ };