@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
package/src/Box/Box.tsx CHANGED
@@ -1,5 +1,5 @@
1
- import { createElement, forwardRef } from 'react';
2
- import { ResponsiveStyleValue, useStyles } from '@marigold/system';
1
+ import React, { forwardRef } from 'react';
2
+ import { CSSObject, Element, ResponsiveStyleValue } from '@marigold/system';
3
3
  import {
4
4
  PolymorphicPropsWithRef,
5
5
  PolymorphicComponentWithRef,
@@ -8,6 +8,7 @@ import {
8
8
  export type BoxOwnProps = {
9
9
  className?: string;
10
10
  variant?: string | string[];
11
+ css?: CSSObject;
11
12
 
12
13
  display?: ResponsiveStyleValue<string>;
13
14
 
@@ -63,6 +64,7 @@ export const Box: PolymorphicComponentWithRef<BoxOwnProps, 'div'> = forwardRef(
63
64
  {
64
65
  variant,
65
66
  as = 'div',
67
+ css,
66
68
  children,
67
69
  className,
68
70
  display,
@@ -106,52 +108,58 @@ export const Box: PolymorphicComponentWithRef<BoxOwnProps, 'div'> = forwardRef(
106
108
  ...props
107
109
  },
108
110
  ref
109
- ) => {
110
- const cn = useStyles({
111
- element: as,
112
- variant,
113
- className,
114
- css: {
115
- display,
116
- height,
117
- width,
118
- minWidth,
119
- maxWidth,
120
- position,
121
- top,
122
- bottom,
123
- right,
124
- left,
125
- zIndex,
126
- p,
127
- px,
128
- py,
129
- pt,
130
- pb,
131
- pl,
132
- pr,
133
- m,
134
- mx,
135
- my,
136
- mt,
137
- mb,
138
- ml,
139
- mr,
140
- flexDirection,
141
- flexWrap,
142
- flexShrink,
143
- flexGrow,
144
- alignItems,
145
- justifyContent,
146
- bg,
147
- border,
148
- borderRadius,
149
- boxShadow,
150
- opacity,
151
- overflow,
152
- transition,
153
- },
154
- });
155
- return createElement(as, { ...props, ref, className: cn }, children);
156
- }
111
+ ) => (
112
+ <Element
113
+ as={as}
114
+ ref={ref}
115
+ variant={variant}
116
+ css={{
117
+ ...{
118
+ display,
119
+ height,
120
+ width,
121
+ minWidth,
122
+ maxWidth,
123
+ position,
124
+ top,
125
+ bottom,
126
+ right,
127
+ left,
128
+ zIndex,
129
+ p,
130
+ px,
131
+ py,
132
+ pt,
133
+ pb,
134
+ pl,
135
+ pr,
136
+ m,
137
+ mx,
138
+ my,
139
+ mt,
140
+ mb,
141
+ ml,
142
+ mr,
143
+ flexDirection,
144
+ flexWrap,
145
+ flexShrink,
146
+ flexGrow,
147
+ alignItems,
148
+ justifyContent,
149
+ bg,
150
+ border,
151
+ borderRadius,
152
+ boxShadow,
153
+ opacity,
154
+ overflow,
155
+ transition,
156
+ },
157
+ ...css,
158
+ }}
159
+ className={className}
160
+ {...props}
161
+ >
162
+ {children}
163
+ </Element>
164
+ )
157
165
  );
@@ -1,176 +1,64 @@
1
- import { Meta, Story, Canvas } from '@storybook/addon-docs/blocks';
1
+ import { ArgsTable, Canvas, Meta, Story } from '@storybook/addon-docs';
2
2
  import { Facebook } from '@marigold/icons';
3
3
  import { Button } from './Button';
4
- import { useStyles } from '@marigold/system';
5
4
 
6
- <Meta title="Components/Button" />
5
+ <Meta
6
+ title="Components/Button"
7
+ parameters={{
8
+ actions: {
9
+ handles: ['click'],
10
+ },
11
+ }}
12
+ argTypes={{
13
+ variant: {
14
+ control: {
15
+ type: 'select',
16
+ },
17
+ options: ['primary', 'secondary', 'ghost', 'text', 'menu', 'select'],
18
+ description: 'What the button looks like',
19
+ table: {
20
+ defaultValue: {
21
+ summary: 'primary',
22
+ },
23
+ },
24
+ },
25
+ size: {
26
+ control: {
27
+ type: 'select',
28
+ },
29
+ options: ['large', 'small'],
30
+ description: 'How big the button is rendered',
31
+ table: {
32
+ defaultValue: {
33
+ summary: 'large',
34
+ },
35
+ },
36
+ },
37
+ disabled: {
38
+ control: {
39
+ type: 'boolean',
40
+ },
41
+ options: [true, false],
42
+ description: 'Disable the button',
43
+ table: {
44
+ defaultValue: {
45
+ summary: 'false',
46
+ },
47
+ },
48
+ },
49
+ }}
50
+ />
7
51
 
8
52
  # Button
9
53
 
10
- ## Description
11
-
12
- With the Button component you can render a `button` element.
13
- The style variant and size of the button can be added with the variant prop and is composed like `variant.size`.
14
-
15
- ## Properties
16
-
17
- | Property | Type | Default |
18
- | :------------------- | :--------------------------------------------------------------------------------------------------- | :-------------- |
19
- | `variant` (optional) | `primary.small`, `primary.large`, `secondary.small`, `secondary.large`, `ghost.small`, `ghost.large` | `primary.large` |
20
-
21
- ## Import
22
-
23
- ```tsx
24
- import { Button } from '@marigold/components';
25
- ```
26
-
27
- ## Usage
28
-
29
- ### Large
30
-
31
- <Canvas>
32
- <Story name="primary.large">
33
- <Button variant="primary.large">Primary</Button>
34
- </Story>
35
- <Story name="secondary.large">
36
- <Button variant="secondary.large">Secondary</Button>
37
- </Story>
38
- <Story name="ghost.large">
39
- <Button variant="ghost.large">Ghost</Button>
40
- </Story>
41
- <Story name="text.large">
42
- <Button variant="text.large">Text Only</Button>
43
- </Story>
44
- </Canvas>
45
-
46
- ### Small
47
-
48
- <Canvas>
49
- <Story name="primary.small">
50
- <Button variant="primary.small">Primary</Button>
51
- </Story>
52
- <Story name="secondary.small">
53
- <Button variant="secondary.small">Secondary</Button>
54
- </Story>
55
- <Story name="ghost.small">
56
- <Button variant="ghost.small">Ghost</Button>
57
- </Story>
58
- <Story name="text.small">
59
- <Button variant="text.small">Text Only</Button>
60
- </Story>
61
- </Canvas>
62
-
63
- ### Disabled
64
-
65
- <Canvas>
66
- <Story name="primary.large.disabled">
67
- <Button variant="primary.large" disabled>
68
- Primary Large Disabled
69
- </Button>
70
- </Story>
71
- <Story name="secondary.large.disabled">
72
- <Button variant="secondary.large" disabled>
73
- Secondary Large Disabled
74
- </Button>
75
- </Story>
76
- <Story name="ghost.large.disabled">
77
- <Button variant="ghost.large" disabled>
78
- Ghost Large Disabled
79
- </Button>
80
- </Story>
81
- <Story name="text.large.disabled">
82
- <Button variant="text.large" disabled>
83
- Text Only Large Disabled
84
- </Button>
85
- </Story>
86
- </Canvas>
87
-
88
- ### Default with icon
54
+ export const Template = args => (
55
+ <Button {...args}>
56
+ <Facebook /> Like me
57
+ </Button>
58
+ );
89
59
 
90
60
  <Canvas>
91
- <Story name="primary.large with default icon">
92
- <Button variant="primary.large">
93
- <Facebook /> Like me!
94
- </Button>
95
- </Story>
96
- <Story name="primary.small with default icon">
97
- <Button variant="primary.small">
98
- <Facebook /> Like me!
99
- </Button>
100
- </Story>
101
- <Story name="secondary.large with default icon">
102
- <Button variant="secondary.large">
103
- <Facebook /> Like me!
104
- </Button>
105
- </Story>
106
- <Story name="secondary.small with default icon">
107
- <Button variant="secondary.small">
108
- <Facebook /> Like me!
109
- </Button>
110
- </Story>
111
- <Story name="ghost.large with default icon">
112
- <Button variant="ghost.large">
113
- <Facebook /> Like me!
114
- </Button>
115
- </Story>
116
- <Story name="ghost.small with default icon">
117
- <Button variant="ghost.small">
118
- <Facebook /> Like me!
119
- </Button>
120
- </Story>
121
- <Story name="text.large with default icon">
122
- <Button variant="text.large">
123
- <Facebook /> Like me!
124
- </Button>
125
- </Story>
126
- <Story name="text.small with default icon">
127
- <Button variant="text.small">
128
- <Facebook /> Like me!
129
- </Button>
130
- </Story>
61
+ <Story name="Default">{Template.bind({})}</Story>
131
62
  </Canvas>
132
63
 
133
- ### Large with large icon
134
-
135
- <Canvas>
136
- <Story name="primary.large with large icon">
137
- <Button variant="primary.large">
138
- <Facebook size={48} /> Like me!
139
- </Button>
140
- </Story>
141
- </Canvas>
142
-
143
- ### Small with small icon
144
-
145
- <Canvas>
146
- <Story name="primary.small with small icon">
147
- <Button variant="primary.small">
148
- <Facebook size={20} /> Like me!
149
- </Button>
150
- </Story>
151
- </Canvas>
152
-
153
- ### With color
154
-
155
- <Canvas>
156
- <Story name="with color">
157
- <Button variant="primary.small">
158
- <Facebook fill="black" /> Like me!
159
- </Button>
160
- </Story>
161
- </Canvas>
162
-
163
- ### Custom styled
164
-
165
- <Canvas>
166
- <Story name="custom">
167
- <Button
168
- variant="primary.small"
169
- className={useStyles({
170
- bg: '#3b5998',
171
- })}
172
- >
173
- <Facebook /> Like me!
174
- </Button>
175
- </Story>
176
- </Canvas>
64
+ <ArgsTable story="Default" />
@@ -6,20 +6,22 @@ import { Facebook } from '@marigold/icons';
6
6
 
7
7
  const theme = {
8
8
  button: {
9
+ large: {
10
+ p: '16px',
11
+ },
12
+ small: {
13
+ p: '16px',
14
+ },
9
15
  primary: {
10
- large: {
11
- fontFamily: 'Inter',
12
- },
16
+ fontFamily: 'Inter',
13
17
  },
14
18
  secondary: {
15
- large: {
16
- fontFamily: 'Arial',
17
- },
19
+ fontFamily: 'Arial',
18
20
  },
19
21
  },
20
22
  };
21
23
 
22
- test('supports default variant and themeSection', () => {
24
+ test('supports default variant', () => {
23
25
  render(
24
26
  <ThemeProvider theme={theme}>
25
27
  <Button>button</Button>
@@ -30,10 +32,21 @@ test('supports default variant and themeSection', () => {
30
32
  expect(button.parentElement).toHaveStyle(`font-family: Inter`);
31
33
  });
32
34
 
35
+ test('supports default size', () => {
36
+ render(
37
+ <ThemeProvider theme={theme}>
38
+ <Button>button</Button>
39
+ </ThemeProvider>
40
+ );
41
+ const button = screen.getByText(/button/);
42
+
43
+ expect(button.parentElement).toHaveStyle(`padding: 16px`);
44
+ });
45
+
33
46
  test('accepts other variant than default', () => {
34
47
  render(
35
48
  <ThemeProvider theme={theme}>
36
- <Button variant="secondary.large">button</Button>
49
+ <Button variant="secondary">button</Button>
37
50
  </ThemeProvider>
38
51
  );
39
52
  const button = screen.getByText(/button/);
@@ -41,6 +54,17 @@ test('accepts other variant than default', () => {
41
54
  expect(button.parentElement).toHaveStyle(`font-family: Arial`);
42
55
  });
43
56
 
57
+ test('accepts other size than default', () => {
58
+ render(
59
+ <ThemeProvider theme={theme}>
60
+ <Button size="small">button</Button>
61
+ </ThemeProvider>
62
+ );
63
+ const button = screen.getByText(/button/);
64
+
65
+ expect(button.parentElement).toHaveStyle(`padding: 16px`);
66
+ });
67
+
44
68
  test('renders <button> element', () => {
45
69
  render(
46
70
  <ThemeProvider theme={theme}>
@@ -53,6 +77,22 @@ test('renders <button> element', () => {
53
77
  expect(button instanceof HTMLSpanElement).toBeTruthy();
54
78
  });
55
79
 
80
+ test('accepts other button components', () => {
81
+ const CustomButton = React.forwardRef<
82
+ HTMLSpanElement,
83
+ { children?: React.ReactNode }
84
+ >(() => <span>I am a Button!</span>);
85
+
86
+ render(
87
+ <ThemeProvider theme={theme}>
88
+ <Button as={CustomButton}>Button</Button>
89
+ </ThemeProvider>
90
+ );
91
+
92
+ const button = screen.getByText('I am a Button!');
93
+ expect(button).toBeTruthy();
94
+ });
95
+
56
96
  test('add icon in button works as expected', () => {
57
97
  render(
58
98
  <ThemeProvider theme={theme}>
@@ -1,21 +1,50 @@
1
- import React from 'react';
2
- import { ComponentPropsWithRef } from '@marigold/types';
3
- import { Box } from '../Box';
1
+ import React, { forwardRef, RefObject } from 'react';
2
+ import { useButton } from '@react-aria/button';
3
+ import {
4
+ PolymorphicComponentWithRef,
5
+ PolymorphicPropsWithRef,
6
+ } from '@marigold/types';
4
7
 
5
- export type ButtonProps = {
6
- variant?: string;
7
- } & ComponentPropsWithRef<'button'>;
8
+ import { Box, BoxOwnProps } from '../Box';
8
9
 
9
- export const Button: React.FC<ButtonProps> = ({
10
- variant = 'primary.large',
11
- children,
12
- ...props
13
- }) => {
14
- return (
15
- <Box as="button" {...props} variant={`button.${variant}`}>
16
- <Box as="span" display="inline-flex" alignItems="center">
17
- {children}
18
- </Box>
19
- </Box>
10
+ export type ButtonProps = PolymorphicPropsWithRef<BoxOwnProps, 'button'>;
11
+
12
+ export const Button: PolymorphicComponentWithRef<BoxOwnProps, 'button'> =
13
+ forwardRef(
14
+ (
15
+ {
16
+ as = 'button',
17
+ variant = 'primary',
18
+ size = 'large',
19
+ disabled,
20
+ children,
21
+ className,
22
+ ...props
23
+ },
24
+ ref
25
+ ) => {
26
+ const { buttonProps } = useButton(
27
+ {
28
+ ...props,
29
+ elementType: typeof as === 'string' ? as : 'span',
30
+ isDisabled: disabled,
31
+ },
32
+ ref as RefObject<HTMLSpanElement>
33
+ );
34
+
35
+ return (
36
+ <Box
37
+ {...buttonProps}
38
+ {...props}
39
+ as={as}
40
+ variant={[`button.${variant}`, `button.${size}`]}
41
+ className={className}
42
+ ref={ref}
43
+ >
44
+ <Box as="span" display="inline-flex" alignItems="center">
45
+ {children}
46
+ </Box>
47
+ </Box>
48
+ );
49
+ }
20
50
  );
21
- };
@@ -0,0 +1,49 @@
1
+ import { ArgsTable, Canvas, Meta, Story } from '@storybook/addon-docs';
2
+ import { Heading } from '../Heading';
3
+ import { Card } from './Card';
4
+ import { Text } from '../Text';
5
+
6
+ <Meta
7
+ title="Components/Card"
8
+ argTypes={{
9
+ variant: {
10
+ control: {
11
+ type: 'text',
12
+ },
13
+ table: {
14
+ defaultValue: {
15
+ summary: 'default',
16
+ },
17
+ },
18
+ },
19
+ title: {
20
+ control: {
21
+ type: 'text',
22
+ },
23
+ description: 'card title',
24
+ },
25
+ width: {
26
+ control: {
27
+ type: 'text',
28
+ },
29
+ description: 'max width of the card',
30
+ },
31
+ }}
32
+ />
33
+
34
+ # Card
35
+
36
+ export const Template = args => (
37
+ <Card title="Card" {...args}>
38
+ <Text>
39
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse
40
+ dignissim dapibus elit.
41
+ </Text>
42
+ </Card>
43
+ );
44
+
45
+ <Canvas>
46
+ <Story name="Default">{Template.bind({})}</Story>
47
+ </Canvas>
48
+
49
+ <ArgsTable story="Default" />
@@ -0,0 +1,66 @@
1
+ import React from 'react';
2
+ import { render, screen } from '@testing-library/react';
3
+ import { ThemeProvider } from '@marigold/system';
4
+
5
+ import { Card } from './Card';
6
+
7
+ const theme = {
8
+ card: {
9
+ default: {
10
+ p: '8px',
11
+ },
12
+ custom: {
13
+ p: '4px',
14
+ },
15
+ },
16
+ };
17
+
18
+ test('supports default variant', () => {
19
+ render(
20
+ <ThemeProvider theme={theme}>
21
+ <Card>card</Card>
22
+ </ThemeProvider>
23
+ );
24
+ const card = screen.getByText(/card/);
25
+ expect(card).toHaveStyle(`padding: 8px`);
26
+ });
27
+
28
+ test('supports other variant than default', () => {
29
+ render(
30
+ <ThemeProvider theme={theme}>
31
+ <Card variant="custom">card</Card>
32
+ </ThemeProvider>
33
+ );
34
+ const card = screen.getByText(/card/);
35
+ expect(card).toHaveStyle(`padding: 4px`);
36
+ });
37
+
38
+ test('accepts title prop', () => {
39
+ render(
40
+ <ThemeProvider theme={theme}>
41
+ <Card title="title">content</Card>
42
+ </ThemeProvider>
43
+ );
44
+ const title = screen.getByText(/title/);
45
+ expect(title).toBeDefined();
46
+ });
47
+
48
+ test('accepts width prop', () => {
49
+ render(
50
+ <ThemeProvider theme={theme}>
51
+ <Card width="320px">content</Card>
52
+ </ThemeProvider>
53
+ );
54
+ const card = screen.getByText(/content/);
55
+ expect(card).toHaveStyle(`maxWidth: 320px`);
56
+ });
57
+
58
+ test('renders correct HTMl element', () => {
59
+ render(
60
+ <ThemeProvider theme={theme}>
61
+ <Card>card</Card>
62
+ </ThemeProvider>
63
+ );
64
+ const card = screen.getByText(/card/);
65
+ expect(card instanceof HTMLDivElement).toBeTruthy();
66
+ });
@@ -0,0 +1,36 @@
1
+ import React from 'react';
2
+ import { ResponsiveStyleValue } from '@marigold/system';
3
+ import { ComponentProps } from '@marigold/types';
4
+
5
+ import { Box } from '../Box';
6
+
7
+ export type CardProps = {
8
+ title?: string;
9
+ width?: ResponsiveStyleValue<string>;
10
+ variant?: string;
11
+ } & ComponentProps<'div'>;
12
+
13
+ export const Card: React.FC<CardProps> = ({
14
+ variant = 'default',
15
+ title,
16
+ width,
17
+ className,
18
+ children,
19
+ ...props
20
+ }) => {
21
+ return (
22
+ <Box
23
+ {...props}
24
+ variant={`card.${variant}`}
25
+ maxWidth={width}
26
+ className={className}
27
+ >
28
+ {title && (
29
+ <Box as="h2" variant="text.h2" pb="small">
30
+ {title}
31
+ </Box>
32
+ )}
33
+ {children}
34
+ </Box>
35
+ );
36
+ };
@@ -0,0 +1 @@
1
+ export * from './Card';