@marigold/components 0.2.0 → 0.3.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.
- package/CHANGELOG.md +294 -0
- package/dist/ActionGroup/ActionGroup.d.ts +1 -2
- package/dist/ActionGroup/ActionGroup.stories.d.ts +5 -0
- package/dist/Alert/Alert.d.ts +10 -13
- package/dist/Alert/Alert.stories.d.ts +5 -0
- package/dist/Badge/Badge.d.ts +5 -0
- package/dist/Badge/Badge.stories.d.ts +5 -0
- package/dist/Box.d.ts +2 -0
- package/dist/Button/Button.d.ts +5 -0
- package/dist/Button/Button.stories.d.ts +5 -0
- package/dist/Card/Card.d.ts +5 -0
- package/dist/Card/Card.stories.d.ts +5 -0
- package/dist/Checkbox/Checkbox.d.ts +10 -5
- package/dist/Checkbox/Checkbox.stories.d.ts +5 -0
- package/dist/Checkbox/CheckboxIcons.d.ts +9 -9
- package/dist/Column/Column.stories.d.ts +5 -0
- package/dist/Columns/Columns.d.ts +2 -2
- package/dist/Columns/Columns.stories.d.ts +5 -0
- package/dist/Container/Container.stories.d.ts +5 -0
- package/dist/Dialog/Dialog.d.ts +5 -2
- package/dist/Dialog/Dialog.stories.d.ts +5 -0
- package/dist/Dialog/ModalDialog.d.ts +4 -1
- package/dist/Divider/Divider.d.ts +5 -0
- package/dist/Divider/Divider.stories.d.ts +5 -0
- package/dist/Field/Field.d.ts +2 -0
- package/dist/Field/Field.stories.d.ts +5 -0
- package/dist/Image/Image.d.ts +5 -0
- package/dist/Image/Image.stories.d.ts +5 -0
- package/dist/Inline/Inline.d.ts +7 -0
- package/dist/Inline/Inline.stories.d.ts +5 -0
- package/dist/Inline/index.d.ts +1 -0
- package/dist/Input/Input.d.ts +5 -0
- package/dist/Input/Input.stories.d.ts +5 -0
- package/dist/Label/Label.d.ts +12 -1
- package/dist/Label/Label.stories.d.ts +5 -0
- package/dist/Link/Link.d.ts +4 -1
- package/dist/Link/Link.stories.d.ts +5 -0
- package/dist/Menu/Menu.d.ts +3 -0
- package/dist/Menu/Menu.stories.d.ts +5 -0
- package/dist/MenuItem/MenuItem.d.ts +5 -0
- package/dist/MenuItem/MenuItem.stories.d.ts +5 -0
- package/dist/Message/Message.d.ts +5 -0
- package/dist/Message/Message.stories.d.ts +5 -0
- package/dist/Provider/MarigoldProvider.d.ts +11 -3
- package/dist/Provider/index.d.ts +1 -1
- package/dist/Radio/Radio.d.ts +6 -0
- package/dist/Radio/RadioIcons.d.ts +1 -0
- package/dist/Select/ListBox.d.ts +1 -0
- package/dist/Select/ListBoxSection.d.ts +1 -0
- package/dist/Select/Option.d.ts +1 -0
- package/dist/Select/Select.d.ts +15 -1
- package/dist/Select/Select.stories.d.ts +5 -0
- package/dist/Slider/Slider.d.ts +5 -0
- package/dist/Slider/Slider.stories.d.ts +5 -0
- package/dist/Stack/Stack.stories.d.ts +5 -0
- package/dist/Text/Text.d.ts +5 -0
- package/dist/Text/Text.stories.d.ts +5 -0
- package/dist/Textarea/Textarea.d.ts +5 -0
- package/dist/Textarea/Textarea.stories.d.ts +5 -0
- package/dist/ValidationMessage/ValidationMessage.d.ts +5 -0
- package/dist/ValidationMessage/ValidationMessage.stories.d.ts +5 -0
- package/dist/VisuallyHidden/VisuallyHidden.d.ts +1 -0
- package/dist/VisuallyHidden/VisuallyHidden.stories.d.ts +5 -0
- package/dist/VisuallyHidden/index.d.ts +1 -0
- package/dist/components.cjs.development.js +480 -496
- package/dist/components.cjs.development.js.map +1 -1
- package/dist/components.cjs.production.min.js +1 -1
- package/dist/components.cjs.production.min.js.map +1 -1
- package/dist/components.esm.js +415 -441
- package/dist/components.esm.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/theme.d.ts +23 -48
- package/package.json +4 -1
- package/src/ActionGroup/ActionGroup.stories.tsx +47 -0
- package/src/ActionGroup/ActionGroup.test.tsx +36 -36
- package/src/ActionGroup/ActionGroup.tsx +17 -28
- package/src/Alert/Alert.stories.tsx +32 -0
- package/src/Alert/Alert.test.tsx +4 -1
- package/src/Alert/Alert.tsx +18 -3
- package/src/Badge/Badge.stories.tsx +38 -0
- package/src/Badge/Badge.test.tsx +5 -1
- package/src/Badge/Badge.tsx +13 -1
- package/src/Box.ts +2 -0
- package/src/Button/{Button.stories.mdx → Button.stories.tsx} +10 -17
- package/src/Button/Button.test.tsx +34 -11
- package/src/Button/Button.tsx +17 -3
- package/src/Card/{Card.stories.mdx → Card.stories.tsx} +9 -17
- package/src/Card/Card.test.tsx +8 -3
- package/src/Card/Card.tsx +13 -1
- package/src/Checkbox/Checkbox.stories.mdx +11 -0
- package/src/Checkbox/Checkbox.stories.tsx +78 -0
- package/src/Checkbox/Checkbox.test.tsx +77 -8
- package/src/Checkbox/Checkbox.tsx +70 -90
- package/src/Checkbox/CheckboxIcons.tsx +51 -41
- package/src/Column/Column.stories.tsx +33 -0
- package/src/Columns/Columns.stories.tsx +75 -0
- package/src/Columns/Columns.test.tsx +34 -23
- package/src/Columns/Columns.tsx +30 -30
- package/src/Container/Container.stories.tsx +14 -0
- package/src/Dialog/{Dialog.stories.mdx → Dialog.stories.tsx} +33 -18
- package/src/Dialog/Dialog.test.tsx +91 -20
- package/src/Dialog/Dialog.tsx +63 -17
- package/src/Dialog/ModalDialog.tsx +33 -4
- package/src/Divider/{Divider.stories.mdx → Divider.stories.tsx} +10 -17
- package/src/Divider/Divider.test.tsx +13 -5
- package/src/Divider/Divider.tsx +12 -0
- package/src/Field/{Field.stories.mdx → Field.stories.tsx} +33 -20
- package/src/Field/Field.test.tsx +55 -5
- package/src/Field/Field.tsx +10 -8
- package/src/Image/Image.stories.tsx +34 -0
- package/src/Image/Image.test.tsx +4 -1
- package/src/Image/Image.tsx +13 -1
- package/src/Inline/Inline.stories.tsx +39 -0
- package/src/Inline/Inline.test.tsx +99 -0
- package/src/Inline/Inline.tsx +38 -0
- package/src/Inline/index.ts +1 -0
- package/src/Input/{Input.stories.mdx → Input.stories.tsx} +10 -17
- package/src/Input/Input.test.tsx +7 -3
- package/src/Input/Input.tsx +13 -1
- package/src/Label/{Label.stories.mdx → Label.stories.tsx} +10 -21
- package/src/Label/Label.test.tsx +25 -4
- package/src/Label/Label.tsx +42 -9
- package/src/Link/Link.stories.tsx +35 -0
- package/src/Link/Link.test.tsx +6 -2
- package/src/Link/Link.tsx +10 -0
- package/src/Menu/{Menu.stories.mdx → Menu.stories.tsx} +13 -32
- package/src/Menu/Menu.test.tsx +7 -2
- package/src/Menu/Menu.tsx +10 -0
- package/src/MenuItem/MenuItem.stories.tsx +30 -0
- package/src/MenuItem/MenuItem.test.tsx +7 -2
- package/src/MenuItem/MenuItem.tsx +12 -0
- package/src/Message/Message.stories.tsx +30 -0
- package/src/Message/Message.test.tsx +4 -1
- package/src/Message/Message.tsx +17 -5
- package/src/Provider/MarigoldProvider.test.tsx +65 -55
- package/src/Provider/MarigoldProvider.tsx +37 -19
- package/src/Provider/index.ts +2 -1
- package/src/Radio/Radio.stories.mdx +11 -0
- package/src/Radio/Radio.test.tsx +36 -2
- package/src/Radio/Radio.tsx +13 -2
- package/src/Radio/RadioIcons.tsx +1 -1
- package/src/Select/ListBox.tsx +1 -0
- package/src/Select/{Select.stories.mdx → Select.stories.tsx} +23 -20
- package/src/Select/Select.test.tsx +39 -1
- package/src/Select/Select.tsx +24 -13
- package/src/Slider/Slider.stories.tsx +24 -0
- package/src/Slider/Slider.test.tsx +10 -6
- package/src/Slider/Slider.tsx +25 -13
- package/src/Stack/Stack.stories.tsx +57 -0
- package/src/Stack/Stack.test.tsx +16 -7
- package/src/Text/{Text.stories.mdx → Text.stories.tsx} +20 -19
- package/src/Text/Text.test.tsx +2 -2
- package/src/Text/Text.tsx +12 -0
- package/src/Textarea/{Textarea.stories.mdx → Textarea.stories.tsx} +14 -24
- package/src/Textarea/Textarea.test.tsx +7 -3
- package/src/Textarea/Textarea.tsx +13 -1
- package/src/ValidationMessage/{ValidationMessage.stories.mdx → ValidationMessage.stories.tsx} +8 -17
- package/src/ValidationMessage/ValidationMessage.test.tsx +7 -2
- package/src/ValidationMessage/ValidationMessage.tsx +12 -0
- package/src/VisuallyHidden/VisuallyHidden.stories.tsx +19 -0
- package/src/VisuallyHidden/VisuallyHidden.test.tsx +10 -0
- package/src/VisuallyHidden/VisuallyHidden.tsx +1 -0
- package/src/VisuallyHidden/index.ts +1 -0
- package/src/index.ts +2 -2
- package/src/theme.ts +49 -48
- package/dist/Box/Box.d.ts +0 -47
- package/dist/Box/index.d.ts +0 -1
- package/dist/Heading/Heading.d.ts +0 -7
- package/dist/Heading/index.d.ts +0 -1
- package/dist/Hidden/Hidden.d.ts +0 -5
- package/dist/Hidden/index.d.ts +0 -1
- package/src/ActionGroup/ActionGroup.stories.mdx +0 -62
- package/src/Alert/Alert.stories.mdx +0 -35
- package/src/Badge/Badge.stories.mdx +0 -57
- package/src/Box/Box.stories.mdx +0 -334
- package/src/Box/Box.test.tsx +0 -133
- package/src/Box/Box.tsx +0 -165
- package/src/Box/index.ts +0 -1
- package/src/Column/Column.stories.mdx +0 -49
- package/src/Columns/Columns.stories.mdx +0 -65
- package/src/Container/Container.stories.mdx +0 -19
- package/src/Heading/Heading.stories.mdx +0 -39
- package/src/Heading/Heading.test.tsx +0 -77
- package/src/Heading/Heading.tsx +0 -19
- package/src/Heading/index.ts +0 -1
- package/src/Hidden/Hidden.stories.mdx +0 -39
- package/src/Hidden/Hidden.test.tsx +0 -24
- package/src/Hidden/Hidden.tsx +0 -16
- package/src/Hidden/index.ts +0 -1
- package/src/Image/Image.stories.mdx +0 -36
- package/src/Link/Link.stories.mdx +0 -45
- package/src/MenuItem/MenuItem.stories.mdx +0 -37
- package/src/Message/Message.stories.mdx +0 -44
- package/src/Slider/Slider.stories.mdx +0 -31
- package/src/Stack/Stack.stories.mdx +0 -51
|
@@ -1,102 +1,113 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { render, screen } from '@testing-library/react';
|
|
3
|
-
import { Column, Columns } from '@marigold/components';
|
|
3
|
+
import { Column, Columns, MarigoldProvider } from '@marigold/components';
|
|
4
|
+
|
|
5
|
+
const theme = {
|
|
6
|
+
space: {
|
|
7
|
+
none: 0,
|
|
8
|
+
large: 24,
|
|
9
|
+
},
|
|
10
|
+
};
|
|
4
11
|
|
|
5
12
|
test('supports default space prop', () => {
|
|
6
13
|
render(
|
|
7
|
-
<
|
|
8
|
-
<
|
|
9
|
-
|
|
14
|
+
<MarigoldProvider theme={theme}>
|
|
15
|
+
<Columns data-testid="column">
|
|
16
|
+
<Column>column</Column>
|
|
17
|
+
</Columns>
|
|
18
|
+
</MarigoldProvider>
|
|
10
19
|
);
|
|
11
|
-
const column = screen.
|
|
20
|
+
const column = screen.getByTestId(/column/);
|
|
12
21
|
|
|
13
22
|
expect(column).toHaveStyle(`margin: 0px`);
|
|
14
23
|
});
|
|
15
24
|
|
|
16
25
|
test('supports custom space prop', () => {
|
|
17
26
|
render(
|
|
18
|
-
<
|
|
19
|
-
<
|
|
20
|
-
|
|
27
|
+
<MarigoldProvider theme={theme}>
|
|
28
|
+
<Columns space="large" data-testid="column">
|
|
29
|
+
<Column>column</Column>
|
|
30
|
+
</Columns>
|
|
31
|
+
</MarigoldProvider>
|
|
21
32
|
);
|
|
22
|
-
const column = screen.
|
|
33
|
+
const column = screen.getByTestId(/column/);
|
|
23
34
|
|
|
24
35
|
expect(column).toHaveStyle(`margin: -12px`);
|
|
25
36
|
});
|
|
26
37
|
|
|
27
38
|
test('supports default horizontalAlign prop: left', () => {
|
|
28
39
|
render(
|
|
29
|
-
<Columns
|
|
40
|
+
<Columns data-testid="column">
|
|
30
41
|
<Column>column</Column>
|
|
31
42
|
</Columns>
|
|
32
43
|
);
|
|
33
|
-
const column = screen.
|
|
44
|
+
const column = screen.getByTestId(/column/);
|
|
34
45
|
|
|
35
46
|
expect(column).toHaveStyle(`justify-content: flex-start`);
|
|
36
47
|
});
|
|
37
48
|
|
|
38
49
|
test('supports custom horizontalAlign prop: center', () => {
|
|
39
50
|
render(
|
|
40
|
-
<Columns horizontalAlign="center"
|
|
51
|
+
<Columns horizontalAlign="center" data-testid="column">
|
|
41
52
|
<Column>column</Column>
|
|
42
53
|
</Columns>
|
|
43
54
|
);
|
|
44
|
-
const column = screen.
|
|
55
|
+
const column = screen.getByTestId(/column/);
|
|
45
56
|
|
|
46
57
|
expect(column).toHaveStyle(`justify-content: center`);
|
|
47
58
|
});
|
|
48
59
|
|
|
49
60
|
test('supports custom horizontalAlign prop: right', () => {
|
|
50
61
|
render(
|
|
51
|
-
<Columns horizontalAlign="right"
|
|
62
|
+
<Columns horizontalAlign="right" data-testid="column">
|
|
52
63
|
<Column>column</Column>
|
|
53
64
|
</Columns>
|
|
54
65
|
);
|
|
55
|
-
const column = screen.
|
|
66
|
+
const column = screen.getByTestId(/column/);
|
|
56
67
|
|
|
57
68
|
expect(column).toHaveStyle(`justify-content: flex-end`);
|
|
58
69
|
});
|
|
59
70
|
|
|
60
71
|
test('supports default verticalAlign prop: top', () => {
|
|
61
72
|
render(
|
|
62
|
-
<Columns
|
|
73
|
+
<Columns data-testid="column">
|
|
63
74
|
<Column>column</Column>
|
|
64
75
|
</Columns>
|
|
65
76
|
);
|
|
66
|
-
const column = screen.
|
|
77
|
+
const column = screen.getByTestId(/column/);
|
|
67
78
|
|
|
68
79
|
expect(column).toHaveStyle(`align-items: flex-start`);
|
|
69
80
|
});
|
|
70
81
|
|
|
71
82
|
test('supports custom verticalAlign prop: center', () => {
|
|
72
83
|
render(
|
|
73
|
-
<Columns verticalAlign="center"
|
|
84
|
+
<Columns verticalAlign="center" data-testid="column">
|
|
74
85
|
<Column>column</Column>
|
|
75
86
|
</Columns>
|
|
76
87
|
);
|
|
77
|
-
const column = screen.
|
|
88
|
+
const column = screen.getByTestId(/column/);
|
|
78
89
|
|
|
79
90
|
expect(column).toHaveStyle(`align-items: center`);
|
|
80
91
|
});
|
|
81
92
|
|
|
82
93
|
test('supports custom verticalAlign prop: bottom', () => {
|
|
83
94
|
render(
|
|
84
|
-
<Columns verticalAlign="bottom"
|
|
95
|
+
<Columns verticalAlign="bottom" data-testid="column">
|
|
85
96
|
<Column>column</Column>
|
|
86
97
|
</Columns>
|
|
87
98
|
);
|
|
88
|
-
const column = screen.
|
|
99
|
+
const column = screen.getByTestId(/column/);
|
|
89
100
|
|
|
90
101
|
expect(column).toHaveStyle(`align-items: flex-end`);
|
|
91
102
|
});
|
|
92
103
|
|
|
93
104
|
test('renders correct HTML element', () => {
|
|
94
105
|
render(
|
|
95
|
-
<Columns
|
|
106
|
+
<Columns data-testid="column">
|
|
96
107
|
<Column>column</Column>
|
|
97
108
|
</Columns>
|
|
98
109
|
);
|
|
99
|
-
const column = screen.
|
|
110
|
+
const column = screen.getByTestId(/column/);
|
|
100
111
|
|
|
101
112
|
expect(column instanceof HTMLDivElement).toBeTruthy();
|
|
102
113
|
});
|
package/src/Columns/Columns.tsx
CHANGED
|
@@ -1,63 +1,63 @@
|
|
|
1
1
|
import React, { Children } from 'react';
|
|
2
|
-
import { useStyles } from '@marigold/system';
|
|
3
2
|
import { Box } from '../Box';
|
|
4
3
|
import flattenChildren from 'react-keyed-flatten-children';
|
|
4
|
+
import { ResponsiveStyleValue, useTheme } from '@marigold/system';
|
|
5
5
|
|
|
6
6
|
type ColumnsProps = {
|
|
7
7
|
className?: string;
|
|
8
|
-
space?:
|
|
8
|
+
space?: ResponsiveStyleValue<string>;
|
|
9
9
|
horizontalAlign?: 'left' | 'right' | 'center';
|
|
10
10
|
verticalAlign?: 'top' | 'bottom' | 'center';
|
|
11
|
-
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
const useAlignment = (direction: string) => {
|
|
14
|
+
switch (direction) {
|
|
15
|
+
case 'right':
|
|
16
|
+
return 'flex-end';
|
|
17
|
+
case 'bottom':
|
|
18
|
+
return 'flex-end';
|
|
19
|
+
case 'center':
|
|
20
|
+
return 'center';
|
|
21
|
+
}
|
|
22
|
+
return 'flex-start';
|
|
12
23
|
};
|
|
13
24
|
|
|
14
25
|
export const Columns: React.FC<ColumnsProps> = ({
|
|
15
|
-
space =
|
|
26
|
+
space = 'none',
|
|
16
27
|
horizontalAlign = 'left',
|
|
17
28
|
verticalAlign = 'top',
|
|
18
29
|
className,
|
|
19
30
|
children,
|
|
20
31
|
...props
|
|
21
32
|
}) => {
|
|
22
|
-
|
|
23
|
-
|
|
33
|
+
const justifyContent = useAlignment(horizontalAlign);
|
|
34
|
+
const alignItems = useAlignment(verticalAlign);
|
|
24
35
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
// vertical Alignment
|
|
34
|
-
let alignItems = 'flex-start';
|
|
35
|
-
if (verticalAlign === 'bottom') {
|
|
36
|
-
alignItems = 'flex-end';
|
|
37
|
-
} else if (verticalAlign === 'center') {
|
|
38
|
-
alignItems = 'center';
|
|
39
|
-
}
|
|
36
|
+
/**
|
|
37
|
+
* transform space string to space value from theme
|
|
38
|
+
*/
|
|
39
|
+
const { css } = useTheme();
|
|
40
|
+
const spaceObject = css({ space }) as Object;
|
|
41
|
+
const spaceValue = Object.values(spaceObject)[0];
|
|
40
42
|
|
|
41
43
|
return (
|
|
42
|
-
<Box p={
|
|
44
|
+
<Box p={space} display="flex" className={className}>
|
|
43
45
|
<Box
|
|
44
|
-
width={`calc(100% + ${
|
|
45
|
-
m={`${-
|
|
46
|
+
width={`calc(100% + ${spaceValue}px)`}
|
|
47
|
+
m={`${-spaceValue / 2}px`}
|
|
46
48
|
display="flex"
|
|
47
49
|
flexWrap="wrap"
|
|
48
50
|
alignItems={alignItems}
|
|
49
|
-
justifyContent={
|
|
51
|
+
justifyContent={justifyContent}
|
|
50
52
|
{...props}
|
|
51
53
|
>
|
|
52
54
|
{Children.map(
|
|
53
|
-
|
|
55
|
+
flattenChildren(children) as unknown as React.ReactElement,
|
|
54
56
|
(child: React.ReactElement) => {
|
|
55
57
|
return React.cloneElement(
|
|
56
58
|
child,
|
|
57
|
-
{
|
|
58
|
-
|
|
59
|
-
},
|
|
60
|
-
<Box className={child && child.props.className}>
|
|
59
|
+
{},
|
|
60
|
+
<Box css={{ p: `${spaceValue / 2}px` }}>
|
|
61
61
|
{child.props.children}
|
|
62
62
|
</Box>
|
|
63
63
|
);
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { Meta, ComponentStory } from '@storybook/react';
|
|
3
|
+
import { Container } from './Container';
|
|
4
|
+
import { Text } from '../Text';
|
|
5
|
+
|
|
6
|
+
export default {
|
|
7
|
+
title: 'Components/Container',
|
|
8
|
+
} as Meta;
|
|
9
|
+
|
|
10
|
+
export const Basic: ComponentStory<typeof Container> = args => (
|
|
11
|
+
<Container {...args}>
|
|
12
|
+
<Text>Container with width=100%</Text>
|
|
13
|
+
</Container>
|
|
14
|
+
);
|
|
@@ -1,16 +1,17 @@
|
|
|
1
|
-
import
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { Meta, ComponentStory } from '@storybook/react';
|
|
2
3
|
import { Dialog, useDialogButtonProps } from './Dialog';
|
|
3
4
|
import { Button } from '../Button';
|
|
4
5
|
import { Text } from '../Text';
|
|
5
6
|
|
|
6
|
-
|
|
7
|
-
title
|
|
8
|
-
parameters
|
|
7
|
+
export default {
|
|
8
|
+
title: 'Components/Dialog',
|
|
9
|
+
parameters: {
|
|
9
10
|
actions: {
|
|
10
11
|
handles: ['click'],
|
|
11
12
|
},
|
|
12
|
-
}
|
|
13
|
-
argTypes
|
|
13
|
+
},
|
|
14
|
+
argTypes: {
|
|
14
15
|
isOpen: {
|
|
15
16
|
control: {
|
|
16
17
|
type: 'boolean',
|
|
@@ -35,12 +36,32 @@ import { Text } from '../Text';
|
|
|
35
36
|
},
|
|
36
37
|
description: 'handled by state from useDialogButtonProps',
|
|
37
38
|
},
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
39
|
+
variant: {
|
|
40
|
+
control: {
|
|
41
|
+
type: 'text',
|
|
42
|
+
},
|
|
43
|
+
description: 'Dialog variant',
|
|
44
|
+
table: {
|
|
45
|
+
defaultValue: {
|
|
46
|
+
summary: '__default',
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
backdropVariant: {
|
|
51
|
+
control: {
|
|
52
|
+
type: 'text',
|
|
53
|
+
},
|
|
54
|
+
description: 'Dialog backdrop variant',
|
|
55
|
+
table: {
|
|
56
|
+
defaultValue: {
|
|
57
|
+
summary: 'backdrop',
|
|
58
|
+
},
|
|
59
|
+
},
|
|
60
|
+
},
|
|
61
|
+
},
|
|
62
|
+
} as Meta;
|
|
42
63
|
|
|
43
|
-
export const
|
|
64
|
+
export const Basic: ComponentStory<typeof Dialog> = args => {
|
|
44
65
|
const { state, openButtonProps, openButtonRef } = useDialogButtonProps();
|
|
45
66
|
return (
|
|
46
67
|
<>
|
|
@@ -55,9 +76,9 @@ export const Template = ({ ...args }) => {
|
|
|
55
76
|
{state.isOpen && (
|
|
56
77
|
<Dialog
|
|
57
78
|
title="Dialog Title"
|
|
79
|
+
{...args}
|
|
58
80
|
isOpen={state.isOpen}
|
|
59
81
|
close={state.close}
|
|
60
|
-
{...args}
|
|
61
82
|
>
|
|
62
83
|
<Text>Dialog content</Text>
|
|
63
84
|
</Dialog>
|
|
@@ -65,9 +86,3 @@ export const Template = ({ ...args }) => {
|
|
|
65
86
|
</>
|
|
66
87
|
);
|
|
67
88
|
};
|
|
68
|
-
|
|
69
|
-
<Canvas>
|
|
70
|
-
<Story name="Default">{Template.bind({})}</Story>
|
|
71
|
-
</Canvas>
|
|
72
|
-
|
|
73
|
-
<ArgsTable story="Default" />
|
|
@@ -1,25 +1,44 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { fireEvent, render, screen } from '@testing-library/react';
|
|
3
3
|
import userEvent from '@testing-library/user-event';
|
|
4
|
+
|
|
4
5
|
import { ThemeProvider } from '@marigold/system';
|
|
6
|
+
|
|
5
7
|
import { Dialog, useDialogButtonProps } from './Dialog';
|
|
6
8
|
import { Button } from '../Button';
|
|
7
9
|
|
|
8
10
|
const theme = {
|
|
11
|
+
space: {
|
|
12
|
+
none: 0,
|
|
13
|
+
xxsmall: 1,
|
|
14
|
+
xsmall: 2,
|
|
15
|
+
small: 4,
|
|
16
|
+
medium: 8,
|
|
17
|
+
large: 16,
|
|
18
|
+
},
|
|
9
19
|
dialog: {
|
|
10
|
-
|
|
11
|
-
p: '
|
|
20
|
+
__default: {
|
|
21
|
+
p: 'small',
|
|
12
22
|
},
|
|
13
|
-
|
|
14
|
-
p: '
|
|
23
|
+
default: {
|
|
24
|
+
p: 'medium',
|
|
15
25
|
},
|
|
16
|
-
|
|
17
|
-
p: '
|
|
26
|
+
backdrop: {
|
|
27
|
+
p: 'none',
|
|
18
28
|
},
|
|
19
29
|
},
|
|
20
30
|
};
|
|
21
31
|
|
|
22
|
-
|
|
32
|
+
type DialogComponentProps = {
|
|
33
|
+
title?: string;
|
|
34
|
+
variant?: string;
|
|
35
|
+
backdropVariant?: string;
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
const DialogComponent: React.FC<DialogComponentProps> = ({
|
|
39
|
+
variant,
|
|
40
|
+
backdropVariant,
|
|
41
|
+
}) => {
|
|
23
42
|
const { state, openButtonProps, openButtonRef } = useDialogButtonProps();
|
|
24
43
|
return (
|
|
25
44
|
<>
|
|
@@ -28,10 +47,11 @@ const DialogComponent: React.FC = props => {
|
|
|
28
47
|
</Button>
|
|
29
48
|
{state.isOpen && (
|
|
30
49
|
<Dialog
|
|
50
|
+
variant={variant}
|
|
51
|
+
backdropVariant={backdropVariant}
|
|
31
52
|
title="Title"
|
|
32
53
|
isOpen={state.isOpen}
|
|
33
54
|
close={state.close}
|
|
34
|
-
{...props}
|
|
35
55
|
>
|
|
36
56
|
Content
|
|
37
57
|
</Dialog>
|
|
@@ -48,19 +68,67 @@ test('dialog can be opened by button', () => {
|
|
|
48
68
|
expect(dialog).toBeDefined();
|
|
49
69
|
});
|
|
50
70
|
|
|
51
|
-
test('supports
|
|
71
|
+
test('supports default variants', () => {
|
|
52
72
|
render(
|
|
53
73
|
<ThemeProvider theme={theme}>
|
|
54
|
-
<DialogComponent
|
|
74
|
+
<DialogComponent />
|
|
55
75
|
</ThemeProvider>
|
|
56
76
|
);
|
|
57
77
|
const button = screen.getByText(/Open/);
|
|
58
78
|
fireEvent.click(button);
|
|
59
79
|
|
|
60
|
-
const
|
|
61
|
-
expect(
|
|
62
|
-
|
|
63
|
-
|
|
80
|
+
const dialog = screen.getByRole(/dialog/);
|
|
81
|
+
expect(dialog).toHaveStyle(`padding: 4px`);
|
|
82
|
+
expect(dialog.parentElement).toHaveStyle(`padding: 0px`);
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
test('supports other variants than default', () => {
|
|
86
|
+
render(
|
|
87
|
+
<ThemeProvider theme={theme}>
|
|
88
|
+
<DialogComponent variant="default" backdropVariant="default" />
|
|
89
|
+
</ThemeProvider>
|
|
90
|
+
);
|
|
91
|
+
const button = screen.getByText(/Open/);
|
|
92
|
+
fireEvent.click(button);
|
|
93
|
+
|
|
94
|
+
const dialog = screen.getByRole(/dialog/);
|
|
95
|
+
expect(dialog).toHaveStyle(`padding: 8px`);
|
|
96
|
+
expect(dialog.parentElement).toHaveStyle(`padding: 8px`);
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
test('dialog has correct baseCSS styles', async () => {
|
|
100
|
+
render(
|
|
101
|
+
<ThemeProvider theme={theme}>
|
|
102
|
+
<DialogComponent variant="default" backdropVariant="default" />
|
|
103
|
+
</ThemeProvider>
|
|
104
|
+
);
|
|
105
|
+
const button = screen.getByText(/Open/);
|
|
106
|
+
fireEvent.click(button);
|
|
107
|
+
|
|
108
|
+
const dialog = screen.getByRole(/dialog/);
|
|
109
|
+
expect(dialog.firstChild).toHaveStyle(`display: flex`);
|
|
110
|
+
expect(dialog.firstChild?.lastChild).toHaveStyle(`alignItems: start`);
|
|
111
|
+
|
|
112
|
+
// ModalDialog baseCSS
|
|
113
|
+
expect(dialog.parentElement).toHaveStyle(`display: grid`);
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
test('dialog has correct baseCSS styles with theme index', async () => {
|
|
117
|
+
render(
|
|
118
|
+
<ThemeProvider theme={theme}>
|
|
119
|
+
<DialogComponent variant="default" backdropVariant="default" />
|
|
120
|
+
</ThemeProvider>
|
|
121
|
+
);
|
|
122
|
+
const button = screen.getByText(/Open/);
|
|
123
|
+
fireEvent.click(button);
|
|
124
|
+
|
|
125
|
+
const dialog = screen.getByRole(/dialog/);
|
|
126
|
+
expect(dialog.firstChild).toHaveStyle(`paddingLeft: 16`);
|
|
127
|
+
expect(dialog.firstChild?.lastChild).toHaveStyle(`paddingTop: 2`);
|
|
128
|
+
|
|
129
|
+
// find all buttons to get the close and not the open button
|
|
130
|
+
const onCloseButton = await screen.findAllByRole('button');
|
|
131
|
+
expect(onCloseButton[1]).toHaveStyle(`paddingLeft: 1`);
|
|
64
132
|
});
|
|
65
133
|
|
|
66
134
|
test('close Dialog by escape key', () => {
|
|
@@ -73,15 +141,18 @@ test('close Dialog by escape key', () => {
|
|
|
73
141
|
expect(dialog).not.toBeVisible();
|
|
74
142
|
});
|
|
75
143
|
|
|
76
|
-
test('close Dialog by close button', () => {
|
|
77
|
-
render(<DialogComponent
|
|
144
|
+
test('close Dialog by close button', async () => {
|
|
145
|
+
render(<DialogComponent />);
|
|
78
146
|
const button = screen.getByText(/Open/);
|
|
79
147
|
fireEvent.click(button);
|
|
80
148
|
|
|
81
|
-
const dialog = screen.
|
|
149
|
+
const dialog = screen.getByRole(/dialog/);
|
|
82
150
|
expect(dialog).toBeVisible();
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
151
|
+
|
|
152
|
+
// find all buttons to get the close and not the open button
|
|
153
|
+
const onCloseButton = await screen.findAllByRole('button');
|
|
154
|
+
expect(onCloseButton[1]).toBeVisible();
|
|
155
|
+
fireEvent.click(onCloseButton[1]);
|
|
156
|
+
|
|
86
157
|
expect(dialog).not.toBeVisible();
|
|
87
158
|
});
|
package/src/Dialog/Dialog.tsx
CHANGED
|
@@ -7,22 +7,31 @@ import { Close } from '@marigold/icons';
|
|
|
7
7
|
|
|
8
8
|
import { Box } from '../Box';
|
|
9
9
|
import { Button } from '../Button';
|
|
10
|
-
import {
|
|
10
|
+
import { Text } from '../Text';
|
|
11
11
|
|
|
12
|
-
import { ModalDialog } from './ModalDialog';
|
|
12
|
+
import { ModalDialog, ModalDialogProps } from './ModalDialog';
|
|
13
13
|
|
|
14
|
+
// Props
|
|
15
|
+
// ---------------
|
|
14
16
|
export type DialogProps = {
|
|
15
|
-
|
|
17
|
+
backdropVariant?: string;
|
|
16
18
|
close: ComponentProps<typeof Button>['onClick'];
|
|
19
|
+
isOpen: boolean;
|
|
17
20
|
title?: string;
|
|
18
|
-
|
|
21
|
+
variant?: string;
|
|
22
|
+
} & ModalDialogProps &
|
|
23
|
+
ComponentProps<'div'>;
|
|
19
24
|
|
|
25
|
+
// Component
|
|
26
|
+
// ---------------
|
|
20
27
|
export const Dialog: React.FC<DialogProps> = ({
|
|
28
|
+
backdropVariant,
|
|
21
29
|
children,
|
|
22
|
-
title,
|
|
23
30
|
className,
|
|
24
|
-
isOpen,
|
|
25
31
|
close,
|
|
32
|
+
isOpen,
|
|
33
|
+
title,
|
|
34
|
+
variant,
|
|
26
35
|
...props
|
|
27
36
|
}) => {
|
|
28
37
|
const closeButtonRef = React.useRef<HTMLElement>() as RefObject<HTMLElement>;
|
|
@@ -39,25 +48,62 @@ export const Dialog: React.FC<DialogProps> = ({
|
|
|
39
48
|
|
|
40
49
|
return (
|
|
41
50
|
<OverlayContainer>
|
|
42
|
-
<ModalDialog
|
|
43
|
-
|
|
44
|
-
|
|
51
|
+
<ModalDialog
|
|
52
|
+
variant={variant}
|
|
53
|
+
backdropVariant={backdropVariant}
|
|
54
|
+
isOpen={isOpen}
|
|
55
|
+
onClose={close}
|
|
56
|
+
isDismissable
|
|
57
|
+
{...props}
|
|
58
|
+
>
|
|
59
|
+
<Box
|
|
60
|
+
__baseCSS={{
|
|
61
|
+
display: 'flex',
|
|
62
|
+
justifyContent: 'space-between',
|
|
63
|
+
borderRadius: 'small',
|
|
64
|
+
pl: 'large',
|
|
65
|
+
pb: 'large',
|
|
66
|
+
}}
|
|
67
|
+
className={className}
|
|
68
|
+
>
|
|
69
|
+
<Box pt="medium">
|
|
45
70
|
{title && (
|
|
46
|
-
<
|
|
71
|
+
<Text as="h4" variant="headline4">
|
|
47
72
|
{title}
|
|
48
|
-
</
|
|
73
|
+
</Text>
|
|
49
74
|
)}
|
|
50
75
|
{children}
|
|
51
76
|
</Box>
|
|
52
|
-
<Box
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
77
|
+
<Box
|
|
78
|
+
__baseCSS={{
|
|
79
|
+
display: 'flex',
|
|
80
|
+
justifyContent: 'flex-end',
|
|
81
|
+
alignItems: 'start',
|
|
82
|
+
paddingTop: 'xsmall',
|
|
83
|
+
paddingX: 'xsmall',
|
|
84
|
+
}}
|
|
85
|
+
>
|
|
86
|
+
<Box
|
|
87
|
+
as={Button}
|
|
88
|
+
__baseCSS={{
|
|
89
|
+
color: 'text',
|
|
90
|
+
bg: 'transparent',
|
|
91
|
+
lineHeight: 'xsmall',
|
|
92
|
+
px: 'xxsmall',
|
|
93
|
+
':hover': {
|
|
94
|
+
color: 'text',
|
|
95
|
+
bg: 'transparent',
|
|
96
|
+
cursor: 'pointer',
|
|
97
|
+
},
|
|
98
|
+
':focus': {
|
|
99
|
+
outline: 0,
|
|
100
|
+
},
|
|
101
|
+
}}
|
|
56
102
|
{...closeButtonProps}
|
|
57
103
|
ref={closeButtonRef}
|
|
58
104
|
>
|
|
59
105
|
<Close size={16} />
|
|
60
|
-
</
|
|
106
|
+
</Box>
|
|
61
107
|
</Box>
|
|
62
108
|
</Box>
|
|
63
109
|
</ModalDialog>
|
|
@@ -65,7 +111,7 @@ export const Dialog: React.FC<DialogProps> = ({
|
|
|
65
111
|
);
|
|
66
112
|
};
|
|
67
113
|
|
|
68
|
-
//
|
|
114
|
+
// get the overlayTriggerState and openButton props for using the dialog component
|
|
69
115
|
export const useDialogButtonProps = () => {
|
|
70
116
|
const state = useOverlayTriggerState({});
|
|
71
117
|
const openButtonRef = React.useRef<HTMLElement>() as RefObject<HTMLElement>;
|
|
@@ -11,16 +11,31 @@ import { AriaDialogProps } from '@react-types/dialog';
|
|
|
11
11
|
|
|
12
12
|
import { Box } from '../Box';
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
// Props
|
|
15
|
+
// ---------------
|
|
16
|
+
export type ModalDialogProps = {
|
|
17
|
+
variant?: string;
|
|
18
|
+
backdropVariant?: string;
|
|
19
|
+
} & OverlayProps &
|
|
20
|
+
AriaDialogProps;
|
|
15
21
|
|
|
22
|
+
// Component
|
|
23
|
+
// ---------------
|
|
16
24
|
export const ModalDialog: React.FC<ModalDialogProps> = ({
|
|
25
|
+
variant,
|
|
26
|
+
backdropVariant = 'backdrop',
|
|
17
27
|
children,
|
|
18
28
|
...props
|
|
19
29
|
}) => {
|
|
30
|
+
const { isDismissable, isOpen, onClose, ...restProps } = props;
|
|
31
|
+
|
|
20
32
|
// Handle interacting outside the dialog and pressing
|
|
21
33
|
// the Escape key to close the modal.
|
|
22
34
|
const ref = React.useRef<HTMLElement>() as RefObject<HTMLElement>;
|
|
23
|
-
const { overlayProps, underlayProps } = useOverlay(
|
|
35
|
+
const { overlayProps, underlayProps } = useOverlay(
|
|
36
|
+
{ isDismissable, isOpen, onClose },
|
|
37
|
+
ref
|
|
38
|
+
);
|
|
24
39
|
|
|
25
40
|
// Prevent scrolling while the modal is open, and hide content
|
|
26
41
|
// outside the modal from screen readers.
|
|
@@ -30,14 +45,28 @@ export const ModalDialog: React.FC<ModalDialogProps> = ({
|
|
|
30
45
|
const { dialogProps } = useDialog(props, ref);
|
|
31
46
|
|
|
32
47
|
return (
|
|
33
|
-
<Box
|
|
48
|
+
<Box
|
|
49
|
+
__baseCSS={{
|
|
50
|
+
display: 'grid',
|
|
51
|
+
placeItems: 'center',
|
|
52
|
+
position: 'fixed',
|
|
53
|
+
zIndex: 100,
|
|
54
|
+
top: 0,
|
|
55
|
+
left: 0,
|
|
56
|
+
bottom: 0,
|
|
57
|
+
right: 0,
|
|
58
|
+
}}
|
|
59
|
+
variant={`dialog.${backdropVariant}`}
|
|
60
|
+
{...underlayProps}
|
|
61
|
+
>
|
|
34
62
|
<FocusScope contain restoreFocus autoFocus>
|
|
35
63
|
<Box
|
|
36
64
|
{...overlayProps}
|
|
37
65
|
{...dialogProps}
|
|
38
66
|
{...modalProps}
|
|
39
67
|
ref={ref}
|
|
40
|
-
variant=
|
|
68
|
+
variant={variant ? `dialog.${variant}` : `dialog`}
|
|
69
|
+
{...restProps}
|
|
41
70
|
>
|
|
42
71
|
{children}
|
|
43
72
|
</Box>
|