@marigold/components 0.0.3 → 0.3.1

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 (220) hide show
  1. package/CHANGELOG.md +174 -0
  2. package/dist/ActionGroup/ActionGroup.d.ts +8 -0
  3. package/dist/ActionGroup/ActionGroup.stories.d.ts +5 -0
  4. package/dist/ActionGroup/index.d.ts +1 -0
  5. package/dist/Alert/Alert.d.ts +22 -1
  6. package/dist/Alert/Alert.stories.d.ts +5 -0
  7. package/dist/Badge/Badge.d.ts +5 -0
  8. package/dist/Badge/Badge.stories.d.ts +5 -0
  9. package/dist/Box.d.ts +2 -0
  10. package/dist/Button/Button.d.ts +9 -6
  11. package/dist/Button/Button.stories.d.ts +5 -0
  12. package/dist/Card/Card.d.ts +14 -0
  13. package/dist/Card/Card.stories.d.ts +5 -0
  14. package/dist/Card/index.d.ts +1 -0
  15. package/dist/Checkbox/Checkbox.d.ts +15 -3
  16. package/dist/Checkbox/Checkbox.stories.d.ts +5 -0
  17. package/dist/Checkbox/CheckboxIcons.d.ts +9 -0
  18. package/dist/Column/Column.d.ts +3 -1
  19. package/dist/Column/Column.stories.d.ts +5 -0
  20. package/dist/Columns/Columns.d.ts +2 -2
  21. package/dist/Columns/Columns.stories.d.ts +5 -0
  22. package/dist/Container/Container.stories.d.ts +5 -0
  23. package/dist/Dialog/Dialog.d.ts +12 -2
  24. package/dist/Dialog/Dialog.stories.d.ts +5 -0
  25. package/dist/Dialog/ModalDialog.d.ts +8 -0
  26. package/dist/Divider/Divider.d.ts +5 -0
  27. package/dist/Divider/Divider.stories.d.ts +5 -0
  28. package/dist/Field/Field.d.ts +5 -1
  29. package/dist/Field/Field.stories.d.ts +5 -0
  30. package/dist/Image/Image.d.ts +5 -0
  31. package/dist/Image/Image.stories.d.ts +5 -0
  32. package/dist/Inline/Inline.d.ts +7 -0
  33. package/dist/Inline/Inline.stories.d.ts +5 -0
  34. package/dist/Inline/index.d.ts +1 -0
  35. package/dist/Input/Input.d.ts +5 -0
  36. package/dist/Input/Input.stories.d.ts +5 -0
  37. package/dist/Label/Label.d.ts +14 -2
  38. package/dist/Label/Label.stories.d.ts +5 -0
  39. package/dist/Link/Link.d.ts +10 -6
  40. package/dist/Link/Link.stories.d.ts +5 -0
  41. package/dist/Menu/Menu.d.ts +3 -0
  42. package/dist/Menu/Menu.stories.d.ts +5 -0
  43. package/dist/MenuItem/MenuItem.d.ts +5 -0
  44. package/dist/MenuItem/MenuItem.stories.d.ts +5 -0
  45. package/dist/Message/Message.d.ts +5 -0
  46. package/dist/Message/Message.stories.d.ts +5 -0
  47. package/dist/Provider/MarigoldProvider.d.ts +11 -0
  48. package/dist/Provider/index.d.ts +3 -0
  49. package/dist/Radio/Radio.d.ts +11 -4
  50. package/dist/Radio/Radio.stories.d.ts +5 -0
  51. package/dist/Radio/RadioIcon.d.ts +9 -0
  52. package/dist/Select/ListBox.d.ts +9 -0
  53. package/dist/Select/ListBoxSection.d.ts +9 -0
  54. package/dist/Select/Option.d.ts +9 -0
  55. package/dist/Select/Popover.d.ts +9 -0
  56. package/dist/Select/Select.d.ts +25 -4
  57. package/dist/Select/Select.stories.d.ts +5 -0
  58. package/dist/Slider/Slider.d.ts +5 -0
  59. package/dist/Slider/Slider.stories.d.ts +5 -0
  60. package/dist/Stack/Stack.d.ts +1 -3
  61. package/dist/Stack/Stack.stories.d.ts +5 -0
  62. package/dist/Text/Text.d.ts +17 -10
  63. package/dist/Text/Text.stories.d.ts +5 -0
  64. package/dist/Textarea/Textarea.d.ts +7 -1
  65. package/dist/Textarea/Textarea.stories.d.ts +5 -0
  66. package/dist/ValidationMessage/ValidationMessage.d.ts +5 -0
  67. package/dist/ValidationMessage/ValidationMessage.stories.d.ts +5 -0
  68. package/dist/VisuallyHidden/VisuallyHidden.d.ts +1 -0
  69. package/dist/VisuallyHidden/VisuallyHidden.stories.d.ts +5 -0
  70. package/dist/VisuallyHidden/index.d.ts +1 -0
  71. package/dist/components.cjs.development.js +1075 -562
  72. package/dist/components.cjs.development.js.map +1 -1
  73. package/dist/components.cjs.production.min.js +1 -1
  74. package/dist/components.cjs.production.min.js.map +1 -1
  75. package/dist/components.esm.js +1012 -542
  76. package/dist/components.esm.js.map +1 -1
  77. package/dist/index.d.ts +6 -2
  78. package/dist/theme.d.ts +23 -48
  79. package/package.json +21 -2
  80. package/src/ActionGroup/ActionGroup.stories.tsx +47 -0
  81. package/src/ActionGroup/ActionGroup.test.tsx +83 -0
  82. package/src/ActionGroup/ActionGroup.tsx +32 -0
  83. package/src/ActionGroup/index.ts +1 -0
  84. package/src/Alert/Alert.stories.tsx +32 -0
  85. package/src/Alert/Alert.test.tsx +5 -2
  86. package/src/Alert/Alert.tsx +27 -34
  87. package/src/Badge/Badge.stories.tsx +38 -0
  88. package/src/Badge/Badge.test.tsx +12 -16
  89. package/src/Badge/Badge.tsx +14 -3
  90. package/src/Box.ts +2 -0
  91. package/src/Button/Button.stories.tsx +57 -0
  92. package/src/Button/Button.test.tsx +76 -13
  93. package/src/Button/Button.tsx +61 -18
  94. package/src/Card/Card.stories.tsx +41 -0
  95. package/src/Card/Card.test.tsx +71 -0
  96. package/src/Card/Card.tsx +48 -0
  97. package/src/Card/index.ts +1 -0
  98. package/src/Checkbox/Checkbox.stories.tsx +78 -0
  99. package/src/Checkbox/Checkbox.test.tsx +138 -23
  100. package/src/Checkbox/Checkbox.tsx +81 -52
  101. package/src/Checkbox/CheckboxIcons.tsx +59 -0
  102. package/src/Column/Column.stories.tsx +33 -0
  103. package/src/Column/Column.test.tsx +8 -0
  104. package/src/Column/Column.tsx +12 -2
  105. package/src/Columns/Columns.stories.tsx +75 -0
  106. package/src/Columns/Columns.test.tsx +34 -23
  107. package/src/Columns/Columns.tsx +30 -30
  108. package/src/Container/Container.stories.tsx +14 -0
  109. package/src/Dialog/Dialog.stories.tsx +88 -0
  110. package/src/Dialog/Dialog.test.tsx +129 -18
  111. package/src/Dialog/Dialog.tsx +113 -15
  112. package/src/Dialog/ModalDialog.tsx +76 -0
  113. package/src/Divider/Divider.stories.tsx +30 -0
  114. package/src/Divider/Divider.test.tsx +13 -5
  115. package/src/Divider/Divider.tsx +12 -0
  116. package/src/Field/Field.stories.tsx +110 -0
  117. package/src/Field/Field.test.tsx +74 -33
  118. package/src/Field/Field.tsx +27 -20
  119. package/src/Image/Image.stories.tsx +34 -0
  120. package/src/Image/Image.test.tsx +4 -1
  121. package/src/Image/Image.tsx +13 -1
  122. package/src/Inline/Inline.stories.tsx +39 -0
  123. package/src/Inline/Inline.test.tsx +99 -0
  124. package/src/Inline/Inline.tsx +38 -0
  125. package/src/Inline/index.ts +1 -0
  126. package/src/Input/Input.stories.tsx +54 -0
  127. package/src/Input/Input.test.tsx +7 -3
  128. package/src/Input/Input.tsx +13 -1
  129. package/src/Label/Label.stories.tsx +41 -0
  130. package/src/Label/Label.test.tsx +40 -5
  131. package/src/Label/Label.tsx +54 -8
  132. package/src/Link/Link.stories.tsx +35 -0
  133. package/src/Link/Link.test.tsx +51 -21
  134. package/src/Link/Link.tsx +39 -13
  135. package/src/Menu/Menu.stories.tsx +62 -0
  136. package/src/Menu/Menu.test.tsx +11 -6
  137. package/src/Menu/Menu.tsx +22 -14
  138. package/src/MenuItem/MenuItem.stories.tsx +30 -0
  139. package/src/MenuItem/MenuItem.test.tsx +22 -13
  140. package/src/MenuItem/MenuItem.tsx +19 -10
  141. package/src/Message/Message.stories.tsx +30 -0
  142. package/src/Message/Message.test.tsx +4 -1
  143. package/src/Message/Message.tsx +18 -14
  144. package/src/Provider/MarigoldProvider.test.tsx +136 -0
  145. package/src/Provider/MarigoldProvider.tsx +47 -0
  146. package/src/Provider/index.ts +4 -0
  147. package/src/Radio/Radio.stories.tsx +78 -0
  148. package/src/Radio/Radio.test.tsx +129 -18
  149. package/src/Radio/Radio.tsx +62 -71
  150. package/src/Radio/RadioIcon.tsx +49 -0
  151. package/src/Select/ListBox.tsx +40 -0
  152. package/src/Select/ListBoxSection.tsx +40 -0
  153. package/src/Select/Option.tsx +48 -0
  154. package/src/Select/Popover.tsx +50 -0
  155. package/src/Select/Select.stories.tsx +81 -0
  156. package/src/Select/Select.test.tsx +317 -35
  157. package/src/Select/Select.tsx +162 -18
  158. package/src/Slider/Slider.stories.tsx +24 -0
  159. package/src/Slider/Slider.test.tsx +10 -6
  160. package/src/Slider/Slider.tsx +25 -13
  161. package/src/Stack/Stack.stories.tsx +57 -0
  162. package/src/Stack/Stack.test.tsx +93 -65
  163. package/src/Stack/Stack.tsx +27 -32
  164. package/src/Text/Text.stories.tsx +61 -0
  165. package/src/Text/Text.test.tsx +41 -36
  166. package/src/Text/Text.tsx +56 -31
  167. package/src/Textarea/Textarea.stories.tsx +64 -0
  168. package/src/Textarea/Textarea.test.tsx +11 -8
  169. package/src/Textarea/Textarea.tsx +41 -38
  170. package/src/ValidationMessage/ValidationMessage.stories.tsx +27 -0
  171. package/src/ValidationMessage/ValidationMessage.test.tsx +9 -4
  172. package/src/ValidationMessage/ValidationMessage.tsx +23 -12
  173. package/src/VisuallyHidden/VisuallyHidden.stories.tsx +19 -0
  174. package/src/VisuallyHidden/VisuallyHidden.test.tsx +10 -0
  175. package/src/VisuallyHidden/VisuallyHidden.tsx +1 -0
  176. package/src/VisuallyHidden/index.ts +1 -0
  177. package/src/index.ts +7 -2
  178. package/src/theme.ts +49 -48
  179. package/dist/Box/Box.d.ts +0 -45
  180. package/dist/Box/index.d.ts +0 -1
  181. package/dist/Heading/Heading.d.ts +0 -7
  182. package/dist/Heading/index.d.ts +0 -1
  183. package/dist/Hidden/Hidden.d.ts +0 -5
  184. package/dist/Hidden/index.d.ts +0 -1
  185. package/src/Alert/Alert.stories.mdx +0 -45
  186. package/src/Badge/Badge.stories.mdx +0 -43
  187. package/src/Box/Box.stories.mdx +0 -38
  188. package/src/Box/Box.test.tsx +0 -133
  189. package/src/Box/Box.tsx +0 -152
  190. package/src/Box/index.ts +0 -1
  191. package/src/Button/Button.stories.mdx +0 -176
  192. package/src/Checkbox/Checkbox.stories.mdx +0 -119
  193. package/src/Column/Column.stories.mdx +0 -74
  194. package/src/Columns/Columns.stories.mdx +0 -247
  195. package/src/Container/Container.stories.mdx +0 -36
  196. package/src/Dialog/Dialog.stories.mdx +0 -64
  197. package/src/Divider/Divider.stories.mdx +0 -43
  198. package/src/Field/Field.stories.mdx +0 -57
  199. package/src/Heading/Heading.stories.mdx +0 -91
  200. package/src/Heading/Heading.test.tsx +0 -77
  201. package/src/Heading/Heading.tsx +0 -19
  202. package/src/Heading/index.ts +0 -1
  203. package/src/Hidden/Hidden.stories.mdx +0 -64
  204. package/src/Hidden/Hidden.test.tsx +0 -24
  205. package/src/Hidden/Hidden.tsx +0 -16
  206. package/src/Hidden/index.ts +0 -1
  207. package/src/Image/Image.stories.mdx +0 -40
  208. package/src/Input/Input.stories.mdx +0 -45
  209. package/src/Label/Label.stories.mdx +0 -34
  210. package/src/Link/Link.stories.mdx +0 -38
  211. package/src/Menu/Menu.stories.mdx +0 -49
  212. package/src/MenuItem/MenuItem.stories.mdx +0 -32
  213. package/src/Message/Message.stories.mdx +0 -44
  214. package/src/Radio/Radio.stories.mdx +0 -100
  215. package/src/Select/Select.stories.mdx +0 -44
  216. package/src/Slider/Slider.stories.mdx +0 -58
  217. package/src/Stack/Stack.stories.mdx +0 -105
  218. package/src/Text/Text.stories.mdx +0 -60
  219. package/src/Textarea/Textarea.stories.mdx +0 -65
  220. package/src/ValidationMessage/ValidationMessage.stories.mdx +0 -36
@@ -0,0 +1,32 @@
1
+ import React from 'react';
2
+
3
+ import { ResponsiveStyleValue } from '@marigold/system';
4
+ import { ComponentProps } from '@marigold/types';
5
+
6
+ import { Inline } from '../Inline';
7
+ import { Stack } from '../Stack';
8
+
9
+ // Props
10
+ // ---------------
11
+ export type ActionGroupProps = {
12
+ space?: ResponsiveStyleValue<string>;
13
+ verticalAlignment?: boolean;
14
+ } & ComponentProps<'div'>;
15
+
16
+ // Component
17
+ // ---------------
18
+ export const ActionGroup: React.FC<ActionGroupProps> = ({
19
+ space = 'none',
20
+ verticalAlignment = false,
21
+ children,
22
+ ...props
23
+ }) =>
24
+ verticalAlignment ? (
25
+ <Stack space={space} {...props}>
26
+ {children}
27
+ </Stack>
28
+ ) : (
29
+ <Inline space={space} {...props}>
30
+ {children}
31
+ </Inline>
32
+ );
@@ -0,0 +1 @@
1
+ export * from './ActionGroup';
@@ -0,0 +1,32 @@
1
+ import React from 'react';
2
+ import type { Meta, ComponentStory } from '@storybook/react';
3
+
4
+ import { Alert } from './Alert';
5
+ import { Text } from '../Text';
6
+
7
+ export default {
8
+ title: 'Components/Alert',
9
+ argTypes: {
10
+ variant: {
11
+ description: 'usage types',
12
+ control: {
13
+ type: 'select',
14
+ },
15
+ options: ['success', 'warning', 'error'],
16
+ defaultValue: 'success',
17
+ },
18
+ children: {
19
+ description: 'text to display',
20
+ control: {
21
+ type: 'text',
22
+ },
23
+ defaultValue: 'Put some text here!',
24
+ },
25
+ },
26
+ } as Meta;
27
+
28
+ export const Basic: ComponentStory<typeof Alert> = ({ children, ...args }) => (
29
+ <Alert {...args}>
30
+ <Text>{children}</Text>
31
+ </Alert>
32
+ );
@@ -4,8 +4,11 @@ import { ThemeProvider } from '@marigold/system';
4
4
  import { Alert } from './Alert';
5
5
 
6
6
  const theme = {
7
- alerts: {
8
- info: {
7
+ colors: {
8
+ primary: '#000',
9
+ },
10
+ alert: {
11
+ success: {
9
12
  alignItems: 'center',
10
13
  },
11
14
  error: {
@@ -1,57 +1,50 @@
1
1
  import React from 'react';
2
- import { ComponentProps } from '@marigold/types';
3
2
  import { Exclamation, Check, Notification } from '@marigold/icons';
4
- import { useStyles } from '@marigold/system';
3
+ import { type ComponentProps } from '@marigold/types';
4
+
5
5
  import { Box } from '../Box';
6
6
 
7
+ const ICON_MAP = {
8
+ success: Check,
9
+ warning: Notification,
10
+ error: Exclamation,
11
+ } as const;
12
+
13
+ export type AlertVariants = keyof typeof ICON_MAP;
14
+
15
+ // Theme Extension
16
+ // ---------------
17
+ export interface AlertThemeExtension<Value> {
18
+ alert?: {
19
+ [key in AlertVariants]?: Value;
20
+ };
21
+ }
22
+
23
+ // Props
24
+ // ---------------
7
25
  export type AlertProps = {
8
- variant?: string;
26
+ variant?: AlertVariants;
9
27
  } & ComponentProps<'div'>;
10
28
 
29
+ // Component
30
+ // ---------------
11
31
  export const Alert: React.FC<AlertProps> = ({
12
32
  variant = 'success',
13
33
  children,
14
- className,
15
34
  ...props
16
35
  }) => {
17
- const classNames = useStyles({
18
- css: {
19
- display: 'flex',
20
- alignItems: 'center',
21
- },
22
- variant: `alerts.${variant}`,
23
- className,
24
- });
25
-
26
- var bgColor = 'success';
27
- if (variant === 'warning') {
28
- bgColor = 'warning';
29
- } else if (variant === 'error') {
30
- bgColor = 'error';
31
- }
32
- const iconClassName = useStyles({ css: { bg: bgColor, m: '10px' } });
33
-
34
- var icon = <Check size={12} color="#ffffff" className={iconClassName} />;
35
- if (variant === 'warning') {
36
- icon = <Notification size={12} color="#ffffff" className={iconClassName} />;
37
- } else if (variant === 'error') {
38
- icon = <Exclamation size={12} color="#ffffff" className={iconClassName} />;
39
- }
36
+ const Icon = ICON_MAP[variant];
40
37
 
41
38
  return (
42
- <Box {...props} className={classNames}>
39
+ <Box {...props} display="flex" variant={`alert.${variant}`}>
43
40
  <Box
44
41
  display="inline-block"
45
42
  alignItems="center"
46
43
  width="32px"
47
44
  height="32px"
48
- className={useStyles({
49
- css: {
50
- bg: bgColor,
51
- },
52
- })}
45
+ bg={variant}
53
46
  >
54
- {icon}
47
+ <Box as={Icon} size={12} color="#fff" bg={variant} m={10} />
55
48
  </Box>
56
49
  <Box mx="16px">{children}</Box>
57
50
  </Box>
@@ -0,0 +1,38 @@
1
+ import React from 'react';
2
+ import type { Meta, ComponentStory } from '@storybook/react';
3
+
4
+ import { Badge } from './Badge';
5
+ import { Check } from '@marigold/icons';
6
+
7
+ export default {
8
+ title: 'Components/Badge',
9
+ argTypes: {
10
+ variant: {
11
+ description: 'badge variant',
12
+ control: {
13
+ type: 'text',
14
+ },
15
+ defaultValue: '',
16
+ },
17
+ bgColor: {
18
+ description: 'background color',
19
+ control: {
20
+ type: 'text',
21
+ },
22
+ defaultValue: 'primary',
23
+ },
24
+ borderColor: {
25
+ description: 'outline color',
26
+ control: {
27
+ type: 'text',
28
+ },
29
+ defaultValue: 'transparent',
30
+ },
31
+ },
32
+ } as Meta;
33
+
34
+ export const Basic: ComponentStory<typeof Badge> = args => (
35
+ <Badge {...args}>
36
+ <Check /> Check
37
+ </Badge>
38
+ );
@@ -1,11 +1,15 @@
1
1
  import React from 'react';
2
2
  import { render, screen } from '@testing-library/react';
3
- import { useStyles, ThemeProvider } from '@marigold/system';
3
+ import { ThemeProvider } from '@marigold/system';
4
4
  import { Badge } from './Badge';
5
5
 
6
6
  const theme = {
7
+ radii: {
8
+ none: 0,
9
+ larger: 8,
10
+ },
7
11
  badge: {
8
- default: {
12
+ __default: {
9
13
  borderRadius: '8px',
10
14
  },
11
15
  fatBadge: {
@@ -48,22 +52,14 @@ test('supports other variant than default', () => {
48
52
  });
49
53
 
50
54
  test('accepts custom styles prop className', () => {
51
- const TestComponent: React.FC = ({ children, ...props }) => {
52
- const classNames = useStyles({ css: { fontSize: '8px' } });
53
- return (
54
- <Badge className={classNames} {...props}>
55
- {children}
56
- </Badge>
57
- );
58
- };
59
-
60
- const { getByText } = render(
55
+ render(
61
56
  <ThemeProvider theme={theme}>
62
- <TestComponent>text</TestComponent>
57
+ <Badge className="custom-class-name" title="badge">
58
+ badge
59
+ </Badge>
63
60
  </ThemeProvider>
64
61
  );
65
- const testelem = getByText('text');
66
- const text = getComputedStyle(testelem);
62
+ const badge = screen.getByTitle(/badge/);
67
63
 
68
- expect(text.fontSize).toEqual('8px');
64
+ expect(badge.className).toMatch('custom-class-name');
69
65
  });
@@ -1,23 +1,34 @@
1
1
  import React from 'react';
2
2
  import { ComponentProps } from '@marigold/types';
3
3
  import { Box } from '../Box';
4
- import { useStyles } from '@marigold/system';
5
4
 
5
+ // Theme Extension
6
+ // ---------------
7
+ export interface BadgeThemeExtension<Value> {
8
+ badge?: {
9
+ [key: string]: Value;
10
+ };
11
+ }
12
+
13
+ // Props
14
+ // ---------------
6
15
  export type BadgeProps = {
7
16
  variant?: string;
8
17
  bgColor?: string;
9
18
  borderColor?: string;
10
19
  } & ComponentProps<'div'>;
11
20
 
21
+ // Component
22
+ // ---------------
12
23
  export const Badge: React.FC<BadgeProps> = ({
13
- variant = 'default',
24
+ variant = '',
14
25
  bgColor = 'transparent',
15
26
  borderColor = 'transparent',
16
27
  children,
17
28
  ...props
18
29
  }) => (
19
30
  <Box
20
- className={useStyles({ css: { bg: bgColor, borderColor: borderColor } })}
31
+ css={{ bg: bgColor, borderColor: borderColor }}
21
32
  variant={`badge.${variant}`}
22
33
  {...props}
23
34
  >
package/src/Box.ts ADDED
@@ -0,0 +1,2 @@
1
+ export { Box } from '@marigold/system';
2
+ export type { BoxProps, BoxOwnProps, StyleProps } from '@marigold/system';
@@ -0,0 +1,57 @@
1
+ import React from 'react';
2
+ import type { Meta, ComponentStory } from '@storybook/react';
3
+ import { Facebook } from '@marigold/icons';
4
+ import { Button } from './Button';
5
+
6
+ export default {
7
+ title: 'Components/Button',
8
+ parameters: {
9
+ actions: {
10
+ handles: ['click'],
11
+ },
12
+ },
13
+ argTypes: {
14
+ variant: {
15
+ control: {
16
+ type: 'select',
17
+ },
18
+ options: ['primary', 'secondary', 'ghost', 'text', 'menu', 'select'],
19
+ description: 'What the button looks like',
20
+ table: {
21
+ defaultValue: {
22
+ summary: 'primary',
23
+ },
24
+ },
25
+ },
26
+ size: {
27
+ control: {
28
+ type: 'select',
29
+ },
30
+ options: ['large', 'small'],
31
+ description: 'How big the button is rendered',
32
+ table: {
33
+ defaultValue: {
34
+ summary: 'large',
35
+ },
36
+ },
37
+ },
38
+ disabled: {
39
+ control: {
40
+ type: 'boolean',
41
+ },
42
+ options: [true, false],
43
+ description: 'Disable the button',
44
+ table: {
45
+ defaultValue: {
46
+ summary: 'false',
47
+ },
48
+ },
49
+ },
50
+ },
51
+ } as Meta;
52
+
53
+ export const Basic: ComponentStory<typeof Button> = args => (
54
+ <Button {...args}>
55
+ <Facebook /> Like me
56
+ </Button>
57
+ );
@@ -5,21 +5,43 @@ import { Button } from './Button';
5
5
  import { Facebook } from '@marigold/icons';
6
6
 
7
7
  const theme = {
8
+ fonts: {
9
+ body: 'Arial',
10
+ fancy: 'Inter',
11
+ },
12
+ space: {
13
+ none: 0,
14
+ small: 2,
15
+ large: 16,
16
+ },
8
17
  button: {
18
+ large: {
19
+ p: 'large',
20
+ },
21
+ small: {
22
+ p: 'large',
23
+ },
9
24
  primary: {
10
- large: {
11
- fontFamily: 'Inter',
12
- },
25
+ fontFamily: 'fancy',
13
26
  },
14
27
  secondary: {
15
- large: {
16
- fontFamily: 'Arial',
17
- },
28
+ fontFamily: 'body',
18
29
  },
19
30
  },
20
31
  };
21
32
 
22
- test('supports default variant and themeSection', () => {
33
+ test('supports default variant', () => {
34
+ render(
35
+ <ThemeProvider theme={theme}>
36
+ <Button>button</Button>
37
+ </ThemeProvider>
38
+ );
39
+ const button = screen.getByText(/button/);
40
+
41
+ expect(button).toHaveStyle(`font-family: Inter`);
42
+ });
43
+
44
+ test('supports default size', () => {
23
45
  render(
24
46
  <ThemeProvider theme={theme}>
25
47
  <Button>button</Button>
@@ -27,18 +49,29 @@ test('supports default variant and themeSection', () => {
27
49
  );
28
50
  const button = screen.getByText(/button/);
29
51
 
30
- expect(button.parentElement).toHaveStyle(`font-family: Inter`);
52
+ expect(button).toHaveStyle(`padding: 16px`);
31
53
  });
32
54
 
33
55
  test('accepts other variant than default', () => {
34
56
  render(
35
57
  <ThemeProvider theme={theme}>
36
- <Button variant="secondary.large">button</Button>
58
+ <Button variant="secondary">button</Button>
37
59
  </ThemeProvider>
38
60
  );
39
61
  const button = screen.getByText(/button/);
40
62
 
41
- expect(button.parentElement).toHaveStyle(`font-family: Arial`);
63
+ expect(button).toHaveStyle(`font-family: Arial`);
64
+ });
65
+
66
+ test('accepts other size than default', () => {
67
+ render(
68
+ <ThemeProvider theme={theme}>
69
+ <Button size="small">button</Button>
70
+ </ThemeProvider>
71
+ );
72
+ const button = screen.getByText(/button/);
73
+
74
+ expect(button).toHaveStyle(`padding: 16px`);
42
75
  });
43
76
 
44
77
  test('renders <button> element', () => {
@@ -49,8 +82,23 @@ test('renders <button> element', () => {
49
82
  );
50
83
  const button = screen.getByText(/button/);
51
84
 
52
- expect(button.parentElement instanceof HTMLButtonElement).toBeTruthy();
53
- expect(button instanceof HTMLSpanElement).toBeTruthy();
85
+ expect(button instanceof HTMLButtonElement).toBeTruthy();
86
+ });
87
+
88
+ test('accepts other button components', () => {
89
+ const CustomButton = React.forwardRef<
90
+ HTMLSpanElement,
91
+ { children?: React.ReactNode }
92
+ >(() => <span>I am a Button!</span>);
93
+
94
+ render(
95
+ <ThemeProvider theme={theme}>
96
+ <Button as={CustomButton}>Button</Button>
97
+ </ThemeProvider>
98
+ );
99
+
100
+ const button = screen.getByText('I am a Button!');
101
+ expect(button).toBeTruthy();
54
102
  });
55
103
 
56
104
  test('add icon in button works as expected', () => {
@@ -65,13 +113,28 @@ test('add icon in button works as expected', () => {
65
113
  const button = screen.getByText(/iconbutton/);
66
114
  const icon = screen.getByTitle(/facebook/);
67
115
 
68
- expect(button instanceof HTMLSpanElement).toBeTruthy();
116
+ expect(button instanceof HTMLButtonElement).toBeTruthy();
69
117
  expect(button).toHaveStyle('display: inline-flex');
70
118
  expect(button.firstChild instanceof SVGElement).toBeTruthy();
71
119
  expect(icon.getAttribute('fill')).toEqual('red');
72
120
  expect(icon.getAttribute('width')).toEqual('30');
73
121
  });
74
122
 
123
+ test('add space to button works as expected', () => {
124
+ render(
125
+ <ThemeProvider theme={theme}>
126
+ <Button title="iconbutton" space="small">
127
+ <Facebook fill="red" size={30} title="facebook" />
128
+ iconbutton
129
+ </Button>
130
+ </ThemeProvider>
131
+ );
132
+ const button = screen.getByTitle(/iconbutton/);
133
+
134
+ const style = window.getComputedStyle(button);
135
+ expect(style.columnGap).toBe(`2px`);
136
+ });
137
+
75
138
  test('accepts custom styles prop className', () => {
76
139
  render(
77
140
  <ThemeProvider theme={theme}>
@@ -1,21 +1,64 @@
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
+ // Theme Extension
11
+ // ---------------
12
+ export interface ButtonThemeExtension<Value> {
13
+ button?: {
14
+ [key: string]: Value;
15
+ };
16
+ }
17
+
18
+ // Props
19
+ // ---------------
20
+ export type ButtonProps = PolymorphicPropsWithRef<BoxOwnProps, 'button'>;
21
+
22
+ // Component
23
+ // ---------------
24
+ export const Button: PolymorphicComponentWithRef<BoxOwnProps, 'button'> =
25
+ forwardRef(
26
+ (
27
+ {
28
+ as = 'button',
29
+ variant = 'primary',
30
+ size = 'large',
31
+ space = 'none',
32
+ disabled,
33
+ children,
34
+ className,
35
+ ...props
36
+ },
37
+ ref
38
+ ) => {
39
+ const { buttonProps } = useButton(
40
+ {
41
+ ...props,
42
+ elementType: typeof as === 'string' ? as : 'span',
43
+ isDisabled: disabled,
44
+ },
45
+ ref as RefObject<HTMLSpanElement>
46
+ );
47
+
48
+ return (
49
+ <Box
50
+ {...buttonProps}
51
+ {...props}
52
+ as={as}
53
+ display="inline-flex"
54
+ alignItems="center"
55
+ variant={[`button.${variant}`, `button.${size}`]}
56
+ className={className}
57
+ ref={ref}
58
+ css={{ columnGap: space }}
59
+ >
60
+ {children}
61
+ </Box>
62
+ );
63
+ }
20
64
  );
21
- };
@@ -0,0 +1,41 @@
1
+ import React from 'react';
2
+ import type { Meta, ComponentStory } from '@storybook/react';
3
+ import { Card } from './Card';
4
+ import { Text } from '../Text';
5
+
6
+ export default {
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
+ } as Meta;
33
+
34
+ export const Basic: ComponentStory<typeof Card> = args => (
35
+ <Card title="Card" {...args}>
36
+ <Text>
37
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse
38
+ dignissim dapibus elit.
39
+ </Text>
40
+ </Card>
41
+ );
@@ -0,0 +1,71 @@
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
+ space: {
9
+ none: 0,
10
+ small: 4,
11
+ medium: 8,
12
+ },
13
+ card: {
14
+ __default: {
15
+ p: 'medium',
16
+ },
17
+ custom: {
18
+ p: 'small',
19
+ },
20
+ },
21
+ };
22
+
23
+ test('supports default variant', () => {
24
+ render(
25
+ <ThemeProvider theme={theme}>
26
+ <Card>card</Card>
27
+ </ThemeProvider>
28
+ );
29
+ const card = screen.getByText(/card/);
30
+ expect(card).toHaveStyle(`padding: 8px`);
31
+ });
32
+
33
+ test('supports other variant than default', () => {
34
+ render(
35
+ <ThemeProvider theme={theme}>
36
+ <Card variant="custom">card</Card>
37
+ </ThemeProvider>
38
+ );
39
+ const card = screen.getByText(/card/);
40
+ expect(card).toHaveStyle(`padding: 4px`);
41
+ });
42
+
43
+ test('accepts title prop', () => {
44
+ render(
45
+ <ThemeProvider theme={theme}>
46
+ <Card title="title">content</Card>
47
+ </ThemeProvider>
48
+ );
49
+ const title = screen.getByText(/title/);
50
+ expect(title).toBeDefined();
51
+ });
52
+
53
+ test('accepts width prop', () => {
54
+ render(
55
+ <ThemeProvider theme={theme}>
56
+ <Card width="320px">content</Card>
57
+ </ThemeProvider>
58
+ );
59
+ const card = screen.getByText(/content/);
60
+ expect(card).toHaveStyle(`maxWidth: 320px`);
61
+ });
62
+
63
+ test('renders correct HTMl element', () => {
64
+ render(
65
+ <ThemeProvider theme={theme}>
66
+ <Card>card</Card>
67
+ </ThemeProvider>
68
+ );
69
+ const card = screen.getByText(/card/);
70
+ expect(card instanceof HTMLDivElement).toBeTruthy();
71
+ });