@marigold/components 0.1.0 → 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 (112) hide show
  1. package/dist/ActionGroup/ActionGroup.d.ts +9 -0
  2. package/dist/ActionGroup/index.d.ts +1 -0
  3. package/dist/Alert/Alert.d.ts +16 -1
  4. package/dist/Box/Box.d.ts +2 -1
  5. package/dist/Button/Button.d.ts +4 -6
  6. package/dist/Card/Card.d.ts +9 -0
  7. package/dist/Card/index.d.ts +1 -0
  8. package/dist/Checkbox/Checkbox.d.ts +3 -0
  9. package/dist/Checkbox/CheckboxIcons.d.ts +9 -0
  10. package/dist/Column/Column.d.ts +3 -1
  11. package/dist/Dialog/Dialog.d.ts +8 -1
  12. package/dist/Dialog/ModalDialog.d.ts +5 -0
  13. package/dist/Field/Field.d.ts +4 -2
  14. package/dist/Label/Label.d.ts +2 -1
  15. package/dist/Provider/MarigoldProvider.d.ts +3 -0
  16. package/dist/Provider/index.d.ts +3 -0
  17. package/dist/Radio/Radio.d.ts +3 -0
  18. package/dist/Radio/RadioIcons.d.ts +9 -0
  19. package/dist/Select/ListBox.d.ts +8 -0
  20. package/dist/Select/ListBoxSection.d.ts +8 -0
  21. package/dist/Select/Option.d.ts +8 -0
  22. package/dist/Select/Popover.d.ts +9 -0
  23. package/dist/Select/Select.d.ts +11 -4
  24. package/dist/Stack/Stack.d.ts +1 -3
  25. package/dist/Textarea/Textarea.d.ts +2 -1
  26. package/dist/components.cjs.development.js +868 -357
  27. package/dist/components.cjs.development.js.map +1 -1
  28. package/dist/components.cjs.production.min.js +1 -1
  29. package/dist/components.cjs.production.min.js.map +1 -1
  30. package/dist/components.esm.js +837 -359
  31. package/dist/components.esm.js.map +1 -1
  32. package/dist/index.d.ts +4 -0
  33. package/package.json +18 -3
  34. package/src/ActionGroup/ActionGroup.stories.mdx +62 -0
  35. package/src/ActionGroup/ActionGroup.test.tsx +83 -0
  36. package/src/ActionGroup/ActionGroup.tsx +43 -0
  37. package/src/ActionGroup/index.ts +1 -0
  38. package/src/Alert/Alert.stories.mdx +28 -38
  39. package/src/Alert/Alert.test.tsx +1 -1
  40. package/src/Alert/Alert.tsx +11 -33
  41. package/src/Badge/Badge.stories.mdx +48 -34
  42. package/src/Badge/Badge.test.tsx +7 -15
  43. package/src/Badge/Badge.tsx +1 -2
  44. package/src/Box/Box.stories.mdx +322 -26
  45. package/src/Box/Box.tsx +58 -50
  46. package/src/Button/Button.stories.mdx +54 -166
  47. package/src/Button/Button.test.tsx +48 -8
  48. package/src/Button/Button.tsx +47 -18
  49. package/src/Card/Card.stories.mdx +49 -0
  50. package/src/Card/Card.test.tsx +66 -0
  51. package/src/Card/Card.tsx +36 -0
  52. package/src/Card/index.ts +1 -0
  53. package/src/Checkbox/Checkbox.stories.mdx +76 -71
  54. package/src/Checkbox/Checkbox.test.tsx +70 -24
  55. package/src/Checkbox/Checkbox.tsx +68 -49
  56. package/src/Checkbox/CheckboxIcons.tsx +49 -0
  57. package/src/Column/Column.stories.mdx +39 -64
  58. package/src/Column/Column.test.tsx +8 -0
  59. package/src/Column/Column.tsx +12 -2
  60. package/src/Columns/Columns.stories.mdx +58 -240
  61. package/src/Container/Container.stories.mdx +8 -25
  62. package/src/Dialog/Dialog.stories.mdx +65 -56
  63. package/src/Dialog/Dialog.test.tsx +64 -24
  64. package/src/Dialog/Dialog.tsx +64 -12
  65. package/src/Dialog/ModalDialog.tsx +47 -0
  66. package/src/Divider/Divider.stories.mdx +28 -34
  67. package/src/Field/Field.stories.mdx +88 -48
  68. package/src/Field/Field.test.tsx +31 -40
  69. package/src/Field/Field.tsx +26 -21
  70. package/src/Heading/Heading.stories.mdx +30 -82
  71. package/src/Hidden/Hidden.stories.mdx +29 -54
  72. package/src/Image/Image.stories.mdx +26 -30
  73. package/src/Input/Input.stories.mdx +52 -36
  74. package/src/Label/Label.stories.mdx +47 -29
  75. package/src/Label/Label.test.tsx +15 -1
  76. package/src/Label/Label.tsx +20 -7
  77. package/src/Link/Link.stories.mdx +36 -29
  78. package/src/Menu/Menu.stories.mdx +71 -39
  79. package/src/Menu/Menu.test.tsx +4 -4
  80. package/src/Menu/Menu.tsx +12 -14
  81. package/src/MenuItem/MenuItem.stories.mdx +32 -27
  82. package/src/MenuItem/MenuItem.test.tsx +15 -11
  83. package/src/MenuItem/MenuItem.tsx +7 -10
  84. package/src/Message/Message.stories.mdx +35 -35
  85. package/src/Message/Message.tsx +2 -10
  86. package/src/Provider/MarigoldProvider.test.tsx +126 -0
  87. package/src/Provider/MarigoldProvider.tsx +29 -0
  88. package/src/Provider/index.ts +3 -0
  89. package/src/Radio/Radio.stories.mdx +78 -92
  90. package/src/Radio/Radio.test.tsx +57 -15
  91. package/src/Radio/Radio.tsx +71 -51
  92. package/src/Radio/RadioIcons.tsx +39 -0
  93. package/src/Select/ListBox.tsx +39 -0
  94. package/src/Select/ListBoxSection.tsx +40 -0
  95. package/src/Select/Option.tsx +48 -0
  96. package/src/Select/Popover.tsx +50 -0
  97. package/src/Select/Select.stories.mdx +70 -36
  98. package/src/Select/Select.test.tsx +279 -35
  99. package/src/Select/Select.tsx +151 -18
  100. package/src/Slider/Slider.stories.mdx +22 -49
  101. package/src/Stack/Stack.stories.mdx +40 -94
  102. package/src/Stack/Stack.test.tsx +84 -65
  103. package/src/Stack/Stack.tsx +25 -41
  104. package/src/Text/Text.stories.mdx +52 -52
  105. package/src/Text/Text.tsx +13 -14
  106. package/src/Textarea/Textarea.stories.mdx +65 -56
  107. package/src/Textarea/Textarea.test.tsx +4 -5
  108. package/src/Textarea/Textarea.tsx +28 -37
  109. package/src/ValidationMessage/ValidationMessage.stories.mdx +26 -26
  110. package/src/ValidationMessage/ValidationMessage.test.tsx +4 -4
  111. package/src/ValidationMessage/ValidationMessage.tsx +11 -12
  112. package/src/index.ts +5 -0
@@ -1,247 +1,65 @@
1
- import { Meta, Story, Canvas } from '@storybook/addon-docs/blocks';
2
- import { Column, Columns, Divider, Text } from '@marigold/components';
3
- import { useStyles } from '@marigold/system';
4
-
5
- <Meta title="Components/Columns" />
1
+ import { ArgsTable, Canvas, Meta, Story } from '@storybook/addon-docs';
2
+ import { Column, Columns, Text } from '@marigold/components';
3
+
4
+ <Meta
5
+ title="Components/Columns"
6
+ argTypes={{
7
+ space: {
8
+ control: {
9
+ type: 'range',
10
+ min: 0,
11
+ max: 96,
12
+ step: 2,
13
+ },
14
+ description: 'Absolute space value',
15
+ table: {
16
+ defaultValue: {
17
+ summary: 0,
18
+ },
19
+ },
20
+ },
21
+ horizontalAlign: {
22
+ control: {
23
+ type: 'select',
24
+ },
25
+ options: ['left', 'right', 'center'],
26
+ description: 'where to place',
27
+ table: {
28
+ defaultValue: {
29
+ summary: 'left',
30
+ },
31
+ },
32
+ },
33
+ verticalAlign: {
34
+ control: {
35
+ type: 'select',
36
+ },
37
+ options: ['top', 'bottom', 'center'],
38
+ description: 'where to place',
39
+ table: {
40
+ defaultValue: {
41
+ summary: 'top',
42
+ },
43
+ },
44
+ },
45
+ }}
46
+ />
6
47
 
7
48
  # Columns
8
49
 
9
- ## Description
10
-
11
- With the Columns component you can add a bundle of column components by adding props to create a layout.
12
-
13
- ## Properties
14
-
15
- | Property | Type | Default |
16
- | :--------------------------- | :-------------------- | :------ |
17
- | `space` (optional) | `number` | `0` |
18
- | `horizontalAlign` (optional) | `left, right, center` | `left` |
19
- | `verticalAlign` (optional) | `top, bottom, center` | `top` |
20
-
21
- ## Import
22
-
23
- ```tsx
24
- import { Columns } from '@marigold/components';
25
- ```
26
-
27
- ## Usage
28
-
29
- ### Spacing
50
+ export const Template = args => (
51
+ <Columns {...args}>
52
+ <Column width={6}>
53
+ <Text>First column</Text>
54
+ </Column>
55
+ <Column width={6}>
56
+ <Text>Second column</Text>
57
+ </Column>
58
+ </Columns>
59
+ );
30
60
 
31
61
  <Canvas>
32
- <Story name="Spacing">
33
- <Columns space={24} className={useStyles({ bg: '#f3f3f3' })}>
34
- <Column width={4}>
35
- <Text>
36
- Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse
37
- dignissim dapibus elit, vel egestas felis pharetra non. Cras
38
- malesuada, massa nec ultricies efficitur, lectus ante consequat magna,
39
- a porttitor massa ex ut quam.
40
- </Text>
41
- </Column>
42
- <Column width={4}>
43
- <Text>
44
- Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse
45
- dignissim dapibus elit, vel egestas felis pharetra non. Cras
46
- malesuada, massa nec ultricies efficitur, lectus ante consequat magna,
47
- a porttitor massa ex ut quam.
48
- </Text>
49
- </Column>
50
- <Column width={4}>
51
- <Text>
52
- Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse
53
- dignissim dapibus elit, vel egestas felis pharetra non. Cras
54
- malesuada, massa nec ultricies efficitur, lectus ante consequat magna,
55
- a porttitor massa ex ut quam.
56
- </Text>
57
- </Column>
58
- </Columns>
59
- </Story>
62
+ <Story name="Default">{Template.bind({})}</Story>
60
63
  </Canvas>
61
64
 
62
- ### Width
63
-
64
- <Canvas>
65
- <Story name="Width">
66
- <Columns space={24} className={useStyles({ bg: '#f3f3f3' })}>
67
- <Column
68
- width={12}
69
- className={useStyles({
70
- border: '1px solid',
71
- borderRadius: '4px',
72
- padding: '4px',
73
- })}
74
- >
75
- <Text>width=12</Text>
76
- </Column>
77
- <Column
78
- width={6}
79
- className={useStyles({
80
- border: '1px solid',
81
- borderRadius: '4px',
82
- padding: '4px',
83
- })}
84
- >
85
- <Text>width=6</Text>
86
- </Column>
87
- <Column
88
- width={6}
89
- className={useStyles({
90
- border: '1px solid',
91
- borderRadius: '4px',
92
- padding: '4px',
93
- })}
94
- >
95
- <Text>width=6</Text>
96
- </Column>
97
- <Column
98
- width={4}
99
- className={useStyles({
100
- border: '1px solid',
101
- borderRadius: '4px',
102
- padding: '4px',
103
- })}
104
- >
105
- <Text>width=4</Text>
106
- </Column>
107
- <Column
108
- width={4}
109
- className={useStyles({
110
- border: '1px solid',
111
- borderRadius: '4px',
112
- padding: '4px',
113
- })}
114
- >
115
- <Text>width=4</Text>
116
- </Column>
117
- <Column
118
- width={4}
119
- className={useStyles({
120
- border: '1px solid',
121
- borderRadius: '4px',
122
- padding: '4px',
123
- })}
124
- >
125
- <Text>width=4</Text>
126
- </Column>
127
- <Column
128
- width={3}
129
- className={useStyles({
130
- border: '1px solid',
131
- borderRadius: '4px',
132
- padding: '4px',
133
- })}
134
- >
135
- <Text>width=3</Text>
136
- </Column>
137
- <Column
138
- width={3}
139
- className={useStyles({
140
- border: '1px solid',
141
- borderRadius: '4px',
142
- padding: '4px',
143
- })}
144
- >
145
- <Text>width=3</Text>
146
- </Column>
147
- <Column
148
- width={3}
149
- className={useStyles({
150
- border: '1px solid',
151
- borderRadius: '4px',
152
- padding: '4px',
153
- })}
154
- >
155
- <Text>width=3</Text>
156
- </Column>
157
- <Column
158
- width={3}
159
- className={useStyles({
160
- border: '1px solid',
161
- borderRadius: '4px',
162
- padding: '4px',
163
- })}
164
- >
165
- <Text>width=3</Text>
166
- </Column>
167
- </Columns>
168
- </Story>
169
- </Canvas>
170
-
171
- ### Horizontal Alignment
172
-
173
- <Canvas>
174
- <Story name="horizantalAlign">
175
- <Columns
176
- space={24}
177
- horizontalAlign="left"
178
- className={useStyles({ bg: '#f3f3f3' })}
179
- >
180
- <Column width={1}>
181
- <Text>left</Text>
182
- </Column>
183
- </Columns>
184
- <Divider />
185
- <Columns
186
- space={24}
187
- horizontalAlign="center"
188
- className={useStyles({ bg: '#f3f3f3' })}
189
- >
190
- <Column width={1}>
191
- <Text>center</Text>
192
- </Column>
193
- </Columns>
194
- <Divider />
195
- <Columns
196
- space={24}
197
- horizontalAlign="right"
198
- className={useStyles({ bg: '#f3f3f3' })}
199
- >
200
- <Column width={1}>
201
- <Text>right</Text>
202
- </Column>
203
- </Columns>
204
- </Story>
205
- </Canvas>
206
-
207
- ### Vertical Alignment
208
-
209
- <Canvas>
210
- <Story name="verticalAlign">
211
- <Columns
212
- verticalAlign="top"
213
- className={useStyles({
214
- bg: '#f3f3f3',
215
- height: '80px',
216
- })}
217
- >
218
- <Column width={1}>
219
- <Text>top</Text>
220
- </Column>
221
- </Columns>
222
- <Divider />
223
- <Columns
224
- verticalAlign="center"
225
- className={useStyles({
226
- bg: '#f3f3f3',
227
- height: '80px',
228
- })}
229
- >
230
- <Column width={1}>
231
- <Text>center</Text>
232
- </Column>
233
- </Columns>
234
- <Divider />
235
- <Columns
236
- verticalAlign="bottom"
237
- className={useStyles({
238
- bg: '#f3f3f3',
239
- height: '80px',
240
- })}
241
- >
242
- <Column width={1}>
243
- <Text>bottom</Text>
244
- </Column>
245
- </Columns>
246
- </Story>
247
- </Canvas>
65
+ <ArgsTable story="Default" />
@@ -1,36 +1,19 @@
1
- import { Meta, Story, Canvas } from '@storybook/addon-docs/blocks';
1
+ import { ArgsTable, Canvas, Meta, Story } from '@storybook/addon-docs';
2
2
  import { Container } from './Container';
3
3
  import { Text } from '../Text';
4
- import { useStyles } from '@marigold/system';
5
4
 
6
5
  <Meta title="Components/Container" />
7
6
 
8
7
  # Container
9
8
 
10
- ## Description
11
-
12
- Primitive layout component to embed other elements.
13
-
14
- ## Import
15
-
16
- ```tsx
17
- import { Container } from '@marigold/components';
18
- ```
19
-
20
- ## Usage
9
+ export const Template = args => (
10
+ <Container {...args}>
11
+ <Text>Container with width=100%</Text>
12
+ </Container>
13
+ );
21
14
 
22
15
  <Canvas>
23
- <Story name="Example 1">
24
- <Container className={useStyles({ bg: 'gray' })}>
25
- <Text>Example #1</Text>
26
- </Container>
27
- </Story>
16
+ <Story name="Default">{Template.bind({})}</Story>
28
17
  </Canvas>
29
18
 
30
- <Canvas>
31
- <Story name="Example 2">
32
- <Container className={useStyles({ bg: 'green', padding: 4, margin: 1 })}>
33
- <Text>Example #2</Text>
34
- </Container>
35
- </Story>
36
- </Canvas>
19
+ <ArgsTable story="Default" />
@@ -1,64 +1,73 @@
1
- import { Meta, Story, Canvas } from '@storybook/addon-docs/blocks';
2
- import { useStyles } from '@marigold/system';
3
- import { Dialog } from './Dialog';
4
- import { Heading } from '../Heading/';
5
- import { Text } from '../Text/';
6
- import { Button } from '../Button/';
1
+ import { ArgsTable, Canvas, Meta, Story } from '@storybook/addon-docs';
2
+ import { Dialog, useDialogButtonProps } from './Dialog';
3
+ import { Button } from '../Button';
4
+ import { Text } from '../Text';
7
5
 
8
- <Meta title="Components/Dialog" />
6
+ <Meta
7
+ title="Components/Dialog"
8
+ parameters={{
9
+ actions: {
10
+ handles: ['click'],
11
+ },
12
+ }}
13
+ argTypes={{
14
+ isOpen: {
15
+ control: {
16
+ type: 'boolean',
17
+ },
18
+ description: 'handled by state from useDialogButtonProps',
19
+ options: [true, false],
20
+ table: {
21
+ defaultValue: {
22
+ summary: false,
23
+ },
24
+ },
25
+ },
26
+ title: {
27
+ control: {
28
+ type: 'text',
29
+ },
30
+ description: 'set dialog title',
31
+ },
32
+ close: {
33
+ control: {
34
+ type: 'text',
35
+ },
36
+ description: 'handled by state from useDialogButtonProps',
37
+ },
38
+ }}
39
+ />
9
40
 
10
41
  # Dialog
11
42
 
12
- ## Description
13
-
14
- Element to display a Dialog as a reaction to an event. The user style or fill the body of the dialog with content.
15
-
16
- ## Properties
17
-
18
- | Property | Type | Default |
19
- | :-------- | :--------- | :------ |
20
- | `onClick` | `function` | |
21
-
22
- ## Import
23
-
24
- ```tsx
25
- import { Dialog } from '@marigold/components';
26
- ```
27
-
28
- ## Usage
43
+ export const Template = ({ ...args }) => {
44
+ const { state, openButtonProps, openButtonRef } = useDialogButtonProps();
45
+ return (
46
+ <>
47
+ <Button
48
+ variant="secondary"
49
+ size="small"
50
+ {...openButtonProps}
51
+ ref={openButtonRef}
52
+ >
53
+ Open Dialog
54
+ </Button>
55
+ {state.isOpen && (
56
+ <Dialog
57
+ title="Dialog Title"
58
+ isOpen={state.isOpen}
59
+ close={state.close}
60
+ {...args}
61
+ >
62
+ <Text>Dialog content</Text>
63
+ </Dialog>
64
+ )}
65
+ </>
66
+ );
67
+ };
29
68
 
30
69
  <Canvas>
31
- <Story name="basic">
32
- <Dialog
33
- title="Title"
34
- className={useStyles({
35
- background: '#f3f3f3',
36
- })}
37
- >
38
- <Heading as="h4" variant="h4">
39
- Dialog Title
40
- </Heading>
41
- <Text>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</Text>
42
- <Text>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</Text>
43
- <Text>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</Text>
44
- </Dialog>
45
- </Story>
70
+ <Story name="Default">{Template.bind({})}</Story>
46
71
  </Canvas>
47
72
 
48
- <Canvas>
49
- <Story name="button">
50
- <Dialog
51
- title="Title"
52
- className={useStyles({
53
- border: '1px solid',
54
- })}
55
- >
56
- <Heading as="h4" variant="h4">
57
- Marigold
58
- </Heading>
59
- <Text>Do you love the marigold design system?</Text>
60
- <br />
61
- <Button variant="secondary.small">Agree</Button>
62
- </Dialog>
63
- </Story>
64
- </Canvas>
73
+ <ArgsTable story="Default" />
@@ -1,47 +1,87 @@
1
1
  import React from 'react';
2
- import { render, screen } from '@testing-library/react';
2
+ import { fireEvent, render, screen } from '@testing-library/react';
3
+ import userEvent from '@testing-library/user-event';
3
4
  import { ThemeProvider } from '@marigold/system';
4
- import { Dialog } from './Dialog';
5
+ import { Dialog, useDialogButtonProps } from './Dialog';
6
+ import { Button } from '../Button';
5
7
 
6
8
  const theme = {
7
9
  dialog: {
8
10
  wrapper: {
9
- alignItems: 'center',
11
+ p: '8px',
12
+ },
13
+ body: {
14
+ p: '4px',
15
+ },
16
+ onClose: {
17
+ p: '0px',
10
18
  },
11
19
  },
12
20
  };
13
21
 
14
- test('supports default variant', () => {
15
- render(
16
- <ThemeProvider theme={theme}>
17
- <Dialog title="default">Default</Dialog>
18
- </ThemeProvider>
22
+ const DialogComponent: React.FC = props => {
23
+ const { state, openButtonProps, openButtonRef } = useDialogButtonProps();
24
+ return (
25
+ <>
26
+ <Button {...openButtonProps} ref={openButtonRef}>
27
+ Open
28
+ </Button>
29
+ {state.isOpen && (
30
+ <Dialog
31
+ title="Title"
32
+ isOpen={state.isOpen}
33
+ close={state.close}
34
+ {...props}
35
+ >
36
+ Content
37
+ </Dialog>
38
+ )}
39
+ </>
19
40
  );
20
- const dialog = screen.getByTitle(/default/);
41
+ };
21
42
 
22
- expect(dialog).toHaveStyle(`align-items: center`);
43
+ test('dialog can be opened by button', () => {
44
+ render(<DialogComponent />);
45
+ const button = screen.getByText(/Open/);
46
+ fireEvent.click(button);
47
+ const dialog = screen.getByText(/Content/);
48
+ expect(dialog).toBeDefined();
23
49
  });
24
50
 
25
- test('renders correct HTML element', () => {
51
+ test('supports theme variants', () => {
26
52
  render(
27
53
  <ThemeProvider theme={theme}>
28
- <Dialog title="default">Default</Dialog>
54
+ <DialogComponent data-testid="Dialog" />
29
55
  </ThemeProvider>
30
56
  );
31
- const dialog = screen.getByTitle(/default/);
57
+ const button = screen.getByText(/Open/);
58
+ fireEvent.click(button);
32
59
 
33
- expect(dialog instanceof HTMLDivElement).toBeTruthy();
60
+ const dialogBody = screen.getByTestId(/Dialog/);
61
+ expect(dialogBody).toHaveStyle(`padding: 8px`);
62
+ const dialogTitle = screen.getByText(/Title/);
63
+ expect(dialogTitle.parentElement).toHaveStyle(`padding: 4px`);
34
64
  });
35
65
 
36
- test('accepts custom styles prop className', () => {
37
- render(
38
- <ThemeProvider theme={theme}>
39
- <Dialog className="custom-class-name" title="dialog">
40
- Dialog
41
- </Dialog>
42
- </ThemeProvider>
43
- );
44
- const dialog = screen.getByTitle(/dialog/);
66
+ test('close Dialog by escape key', () => {
67
+ render(<DialogComponent />);
68
+ const button = screen.getByText(/Open/);
69
+ fireEvent.click(button);
70
+
71
+ const dialog = screen.getByText(/Content/);
72
+ userEvent.type(dialog, '{esc}');
73
+ expect(dialog).not.toBeVisible();
74
+ });
75
+
76
+ test('close Dialog by close button', () => {
77
+ render(<DialogComponent data-testid="Dialog" />);
78
+ const button = screen.getByText(/Open/);
79
+ fireEvent.click(button);
45
80
 
46
- expect(dialog.className).toMatch('custom-class-name');
81
+ const dialog = screen.getByTestId(/Dialog/);
82
+ expect(dialog).toBeVisible();
83
+ const buttonDiv = dialog.lastChild;
84
+ const onClose = buttonDiv && buttonDiv.firstChild;
85
+ onClose && fireEvent.click(onClose);
86
+ expect(dialog).not.toBeVisible();
47
87
  });
@@ -1,32 +1,84 @@
1
- import React from 'react';
1
+ import React, { RefObject } from 'react';
2
2
  import { ComponentProps } from '@marigold/types';
3
-
3
+ import { useOverlayTriggerState } from '@react-stately/overlays';
4
+ import { OverlayContainer } from '@react-aria/overlays';
5
+ import { useButton } from '@react-aria/button';
4
6
  import { Close } from '@marigold/icons';
5
- import { Button } from '../Button';
7
+
6
8
  import { Box } from '../Box';
9
+ import { Button } from '../Button';
10
+ import { Heading } from '../Heading';
11
+
12
+ import { ModalDialog } from './ModalDialog';
7
13
 
8
14
  export type DialogProps = {
9
- onClose?: ComponentProps<typeof Button>['onClick'];
15
+ isOpen: boolean;
16
+ close: ComponentProps<typeof Button>['onClick'];
17
+ title?: string;
10
18
  } & ComponentProps<'div'>;
11
19
 
12
20
  export const Dialog: React.FC<DialogProps> = ({
13
- onClose,
14
21
  children,
22
+ title,
15
23
  className,
24
+ isOpen,
25
+ close,
16
26
  ...props
17
27
  }) => {
28
+ const closeButtonRef = React.useRef<HTMLElement>() as RefObject<HTMLElement>;
29
+
30
+ // useButton ensures that focus management is handled correctly,
31
+ // across all browsers. Focus is restored to the button once the
32
+ // dialog closes.
33
+ const { buttonProps: closeButtonProps } = useButton(
34
+ {
35
+ onPress: () => close(),
36
+ },
37
+ closeButtonRef
38
+ );
39
+
18
40
  return (
19
- <Box display="flex" width="100%">
20
- <Box {...props} variant="dialog.wrapper" className={className}>
21
- <Box display="flex">
22
- <Box variant="dialog.body">{children}</Box>
41
+ <OverlayContainer>
42
+ <ModalDialog isOpen={isOpen} onClose={close} isDismissable>
43
+ <Box variant="dialog.wrapper" className={className} {...props}>
44
+ <Box variant="dialog.body">
45
+ {title && (
46
+ <Heading as="h4" variant="h4">
47
+ {title}
48
+ </Heading>
49
+ )}
50
+ {children}
51
+ </Box>
23
52
  <Box variant="dialog.onClose">
24
- <Button variant="text.root" onClick={onClose}>
53
+ <Button
54
+ variant="close"
55
+ size="xsmall"
56
+ {...closeButtonProps}
57
+ ref={closeButtonRef}
58
+ >
25
59
  <Close size={16} />
26
60
  </Button>
27
61
  </Box>
28
62
  </Box>
29
- </Box>
30
- </Box>
63
+ </ModalDialog>
64
+ </OverlayContainer>
65
+ );
66
+ };
67
+
68
+ // use this hook to get the overlayTriggerState and openButton props for using the dialog component
69
+ export const useDialogButtonProps = () => {
70
+ const state = useOverlayTriggerState({});
71
+ const openButtonRef = React.useRef<HTMLElement>() as RefObject<HTMLElement>;
72
+ const { buttonProps: openButtonProps } = useButton(
73
+ {
74
+ onPress: () => state.open(),
75
+ },
76
+ openButtonRef
31
77
  );
78
+
79
+ return {
80
+ state,
81
+ openButtonProps,
82
+ openButtonRef,
83
+ };
32
84
  };