@marigold/components 0.0.2 → 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.
Files changed (224) hide show
  1. package/CHANGELOG.md +294 -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 +16 -3
  6. package/dist/Alert/Alert.stories.d.ts +5 -0
  7. package/dist/Badge/Badge.d.ts +11 -5
  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 -5
  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 +17 -5
  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 +6 -4
  19. package/dist/Column/Column.stories.d.ts +5 -0
  20. package/dist/Columns/Columns.d.ts +10 -0
  21. package/dist/Columns/Columns.stories.d.ts +5 -0
  22. package/dist/Columns/index.d.ts +1 -0
  23. package/dist/Container/Container.d.ts +5 -4
  24. package/dist/Container/Container.stories.d.ts +5 -0
  25. package/dist/Dialog/Dialog.d.ts +17 -0
  26. package/dist/Dialog/Dialog.stories.d.ts +5 -0
  27. package/dist/Dialog/ModalDialog.d.ts +8 -0
  28. package/dist/Dialog/index.d.ts +1 -0
  29. package/dist/Divider/Divider.d.ts +10 -3
  30. package/dist/Divider/Divider.stories.d.ts +5 -0
  31. package/dist/Field/Field.d.ts +10 -5
  32. package/dist/Field/Field.stories.d.ts +5 -0
  33. package/dist/Image/Image.d.ts +11 -5
  34. package/dist/Image/Image.stories.d.ts +5 -0
  35. package/dist/Inline/Inline.d.ts +7 -0
  36. package/dist/Inline/Inline.stories.d.ts +5 -0
  37. package/dist/Inline/index.d.ts +1 -0
  38. package/dist/Input/Input.d.ts +10 -4
  39. package/dist/Input/Input.stories.d.ts +5 -0
  40. package/dist/Label/Label.d.ts +18 -5
  41. package/dist/Label/Label.stories.d.ts +5 -0
  42. package/dist/Link/Link.d.ts +10 -5
  43. package/dist/Link/Link.stories.d.ts +5 -0
  44. package/dist/Menu/Menu.d.ts +11 -4
  45. package/dist/Menu/Menu.stories.d.ts +5 -0
  46. package/dist/MenuItem/MenuItem.d.ts +11 -4
  47. package/dist/MenuItem/MenuItem.stories.d.ts +5 -0
  48. package/dist/Message/Message.d.ts +10 -4
  49. package/dist/Message/Message.stories.d.ts +5 -0
  50. package/dist/Provider/MarigoldProvider.d.ts +11 -0
  51. package/dist/Provider/index.d.ts +3 -0
  52. package/dist/Radio/Radio.d.ts +17 -4
  53. package/dist/Radio/RadioIcons.d.ts +10 -0
  54. package/dist/Select/ListBox.d.ts +9 -0
  55. package/dist/Select/ListBoxSection.d.ts +9 -0
  56. package/dist/Select/Option.d.ts +9 -0
  57. package/dist/Select/Popover.d.ts +9 -0
  58. package/dist/Select/Select.d.ts +27 -3
  59. package/dist/Select/Select.stories.d.ts +5 -0
  60. package/dist/Slider/Slider.d.ts +10 -4
  61. package/dist/Slider/Slider.stories.d.ts +5 -0
  62. package/dist/Stack/Stack.d.ts +7 -0
  63. package/dist/Stack/Stack.stories.d.ts +5 -0
  64. package/dist/Stack/index.d.ts +1 -0
  65. package/dist/Text/Text.d.ts +17 -7
  66. package/dist/Text/Text.stories.d.ts +5 -0
  67. package/dist/Textarea/Textarea.d.ts +15 -4
  68. package/dist/Textarea/Textarea.stories.d.ts +5 -0
  69. package/dist/ValidationMessage/ValidationMessage.d.ts +10 -4
  70. package/dist/ValidationMessage/ValidationMessage.stories.d.ts +5 -0
  71. package/dist/VisuallyHidden/VisuallyHidden.d.ts +1 -0
  72. package/dist/VisuallyHidden/VisuallyHidden.stories.d.ts +5 -0
  73. package/dist/VisuallyHidden/index.d.ts +1 -0
  74. package/dist/components.cjs.development.js +1276 -461
  75. package/dist/components.cjs.development.js.map +1 -1
  76. package/dist/components.cjs.production.min.js +1 -1
  77. package/dist/components.cjs.production.min.js.map +1 -1
  78. package/dist/components.esm.js +1229 -461
  79. package/dist/components.esm.js.map +1 -1
  80. package/dist/index.d.ts +10 -3
  81. package/dist/theme.d.ts +23 -28
  82. package/package.json +27 -4
  83. package/src/ActionGroup/ActionGroup.stories.tsx +47 -0
  84. package/src/ActionGroup/ActionGroup.test.tsx +83 -0
  85. package/src/ActionGroup/ActionGroup.tsx +32 -0
  86. package/src/ActionGroup/index.ts +1 -0
  87. package/src/Alert/Alert.stories.tsx +32 -0
  88. package/src/Alert/Alert.test.tsx +34 -23
  89. package/src/Alert/Alert.tsx +48 -24
  90. package/src/Badge/Badge.stories.tsx +38 -0
  91. package/src/Badge/Badge.test.tsx +14 -40
  92. package/src/Badge/Badge.tsx +31 -28
  93. package/src/Box.ts +2 -0
  94. package/src/Button/Button.stories.tsx +57 -0
  95. package/src/Button/Button.test.tsx +76 -13
  96. package/src/Button/Button.tsx +58 -23
  97. package/src/Card/Card.stories.tsx +41 -0
  98. package/src/Card/Card.test.tsx +71 -0
  99. package/src/Card/Card.tsx +48 -0
  100. package/src/Card/index.ts +1 -0
  101. package/src/Checkbox/Checkbox.stories.mdx +90 -112
  102. package/src/Checkbox/Checkbox.stories.tsx +78 -0
  103. package/src/Checkbox/Checkbox.test.tsx +139 -24
  104. package/src/Checkbox/Checkbox.tsx +95 -58
  105. package/src/Checkbox/CheckboxIcons.tsx +59 -0
  106. package/src/Column/Column.stories.tsx +33 -0
  107. package/src/Column/Column.test.tsx +15 -59
  108. package/src/Column/Column.tsx +21 -19
  109. package/src/Columns/Columns.stories.tsx +75 -0
  110. package/src/Columns/Columns.test.tsx +113 -0
  111. package/src/Columns/Columns.tsx +69 -0
  112. package/src/Columns/index.ts +1 -0
  113. package/src/Container/Container.stories.tsx +14 -0
  114. package/src/Container/Container.test.tsx +8 -49
  115. package/src/Container/Container.tsx +8 -19
  116. package/src/Dialog/Dialog.stories.tsx +88 -0
  117. package/src/Dialog/Dialog.test.tsx +158 -0
  118. package/src/Dialog/Dialog.tsx +130 -0
  119. package/src/Dialog/ModalDialog.tsx +76 -0
  120. package/src/Dialog/index.ts +1 -0
  121. package/src/Divider/Divider.stories.tsx +30 -0
  122. package/src/Divider/Divider.test.tsx +14 -6
  123. package/src/Divider/Divider.tsx +20 -13
  124. package/src/Field/Field.stories.tsx +110 -0
  125. package/src/Field/Field.test.tsx +75 -34
  126. package/src/Field/Field.tsx +50 -43
  127. package/src/Image/Image.stories.tsx +34 -0
  128. package/src/Image/Image.test.tsx +6 -3
  129. package/src/Image/Image.tsx +21 -15
  130. package/src/Inline/Inline.stories.tsx +39 -0
  131. package/src/Inline/Inline.test.tsx +99 -0
  132. package/src/Inline/Inline.tsx +38 -0
  133. package/src/Inline/index.ts +1 -0
  134. package/src/Input/Input.stories.tsx +54 -0
  135. package/src/Input/Input.test.tsx +9 -5
  136. package/src/Input/Input.tsx +21 -16
  137. package/src/Label/Label.stories.tsx +41 -0
  138. package/src/Label/Label.test.tsx +41 -6
  139. package/src/Label/Label.tsx +59 -18
  140. package/src/Link/Link.stories.tsx +35 -0
  141. package/src/Link/Link.test.tsx +52 -22
  142. package/src/Link/Link.tsx +40 -20
  143. package/src/Menu/Menu.stories.tsx +62 -0
  144. package/src/Menu/Menu.test.tsx +13 -7
  145. package/src/Menu/Menu.tsx +44 -38
  146. package/src/MenuItem/MenuItem.stories.tsx +30 -0
  147. package/src/MenuItem/MenuItem.test.tsx +23 -14
  148. package/src/MenuItem/MenuItem.tsx +29 -18
  149. package/src/Message/Message.stories.tsx +30 -0
  150. package/src/Message/Message.test.tsx +5 -2
  151. package/src/Message/Message.tsx +48 -40
  152. package/src/Provider/MarigoldProvider.test.tsx +136 -0
  153. package/src/Provider/MarigoldProvider.tsx +47 -0
  154. package/src/Provider/index.ts +4 -0
  155. package/src/Radio/Radio.stories.mdx +91 -94
  156. package/src/Radio/Radio.test.tsx +92 -16
  157. package/src/Radio/Radio.tsx +114 -50
  158. package/src/Radio/RadioIcons.tsx +39 -0
  159. package/src/Select/ListBox.tsx +40 -0
  160. package/src/Select/ListBoxSection.tsx +40 -0
  161. package/src/Select/Option.tsx +48 -0
  162. package/src/Select/Popover.tsx +50 -0
  163. package/src/Select/Select.stories.tsx +81 -0
  164. package/src/Select/Select.test.tsx +311 -43
  165. package/src/Select/Select.tsx +174 -28
  166. package/src/Slider/Slider.stories.tsx +24 -0
  167. package/src/Slider/Slider.test.tsx +11 -7
  168. package/src/Slider/Slider.tsx +30 -15
  169. package/src/Stack/Stack.stories.tsx +57 -0
  170. package/src/Stack/Stack.test.tsx +138 -0
  171. package/src/Stack/Stack.tsx +39 -0
  172. package/src/Stack/index.ts +1 -0
  173. package/src/Text/Text.stories.tsx +61 -0
  174. package/src/Text/Text.test.tsx +41 -36
  175. package/src/Text/Text.tsx +55 -29
  176. package/src/Textarea/Textarea.stories.tsx +64 -0
  177. package/src/Textarea/Textarea.test.tsx +41 -5
  178. package/src/Textarea/Textarea.tsx +57 -17
  179. package/src/ValidationMessage/ValidationMessage.stories.tsx +27 -0
  180. package/src/ValidationMessage/ValidationMessage.test.tsx +19 -14
  181. package/src/ValidationMessage/ValidationMessage.tsx +36 -21
  182. package/src/VisuallyHidden/VisuallyHidden.stories.tsx +19 -0
  183. package/src/VisuallyHidden/VisuallyHidden.test.tsx +10 -0
  184. package/src/VisuallyHidden/VisuallyHidden.tsx +1 -0
  185. package/src/VisuallyHidden/index.ts +1 -0
  186. package/src/index.ts +11 -3
  187. package/src/theme.ts +49 -28
  188. package/dist/Heading/Heading.d.ts +0 -5
  189. package/dist/Heading/index.d.ts +0 -1
  190. package/dist/Hidden/Hidden.d.ts +0 -6
  191. package/dist/Hidden/index.d.ts +0 -1
  192. package/dist/Svg/Svg.d.ts +0 -6
  193. package/dist/Svg/index.d.ts +0 -1
  194. package/src/Alert/Alert.stories.mdx +0 -49
  195. package/src/Badge/Badge.stories.mdx +0 -41
  196. package/src/Button/Button.stories.mdx +0 -155
  197. package/src/Column/Column.stories.mdx +0 -76
  198. package/src/Container/Container.stories.mdx +0 -42
  199. package/src/Divider/Divider.stories.mdx +0 -42
  200. package/src/Field/Field.stories.mdx +0 -57
  201. package/src/Heading/Heading.stories.mdx +0 -79
  202. package/src/Heading/Heading.test.tsx +0 -63
  203. package/src/Heading/Heading.tsx +0 -22
  204. package/src/Heading/index.ts +0 -1
  205. package/src/Hidden/Hidden.stories.mdx +0 -64
  206. package/src/Hidden/Hidden.test.tsx +0 -87
  207. package/src/Hidden/Hidden.tsx +0 -25
  208. package/src/Hidden/index.ts +0 -1
  209. package/src/Image/Image.stories.mdx +0 -40
  210. package/src/Input/Input.stories.mdx +0 -44
  211. package/src/Label/Label.stories.mdx +0 -34
  212. package/src/Link/Link.stories.mdx +0 -37
  213. package/src/Menu/Menu.stories.mdx +0 -47
  214. package/src/MenuItem/MenuItem.stories.mdx +0 -32
  215. package/src/Message/Message.stories.mdx +0 -43
  216. package/src/Select/Select.stories.mdx +0 -43
  217. package/src/Slider/Slider.stories.mdx +0 -57
  218. package/src/Svg/Svg.stories.mdx +0 -47
  219. package/src/Svg/Svg.test.tsx +0 -76
  220. package/src/Svg/Svg.tsx +0 -31
  221. package/src/Svg/index.ts +0 -1
  222. package/src/Text/Text.stories.mdx +0 -60
  223. package/src/Textarea/Textarea.stories.mdx +0 -34
  224. package/src/ValidationMessage/ValidationMessage.stories.mdx +0 -36
@@ -1,16 +1,22 @@
1
1
  import React from 'react';
2
2
  import { render, screen } from '@testing-library/react';
3
- import { useStyles, ThemeProvider } from '@marigold/system';
4
- import { Alert } from '@marigold/components';
3
+ import { ThemeProvider } from '@marigold/system';
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
- danger: {
14
+ error: {
12
15
  alignItems: 'right',
13
16
  },
17
+ warning: {
18
+ alignItems: 'left',
19
+ },
14
20
  },
15
21
  };
16
22
 
@@ -25,19 +31,32 @@ test('supports default variant and themeSection', () => {
25
31
  expect(alert).toHaveStyle(`align-items: center`);
26
32
  });
27
33
 
28
- test('accepts other variant than default', () => {
34
+ test('accepts error variant', () => {
29
35
  render(
30
36
  <ThemeProvider theme={theme}>
31
- <Alert title="danger" variant="danger">
32
- Danger
37
+ <Alert title="error" variant="error">
38
+ Error
33
39
  </Alert>
34
40
  </ThemeProvider>
35
41
  );
36
- const alert = screen.getByTitle(/danger/);
42
+ const alert = screen.getByTitle(/error/);
37
43
 
38
44
  expect(alert).toHaveStyle(`align-items: right`);
39
45
  });
40
46
 
47
+ test('accepts warning variant', () => {
48
+ render(
49
+ <ThemeProvider theme={theme}>
50
+ <Alert title="warning" variant="warning">
51
+ warning
52
+ </Alert>
53
+ </ThemeProvider>
54
+ );
55
+ const alert = screen.getByTitle(/warning/);
56
+
57
+ expect(alert).toHaveStyle(`align-items: left`);
58
+ });
59
+
41
60
  test('renders correct HTML element', () => {
42
61
  render(
43
62
  <ThemeProvider theme={theme}>
@@ -50,22 +69,14 @@ test('renders correct HTML element', () => {
50
69
  });
51
70
 
52
71
  test('accepts custom styles prop className', () => {
53
- const TestComponent: React.FC = ({ children, ...props }) => {
54
- const classNames = useStyles({ fontSize: '8px' });
55
- return (
56
- <Alert className={classNames} {...props}>
57
- {children}
58
- </Alert>
59
- );
60
- };
61
-
62
- const { getByText } = render(
72
+ render(
63
73
  <ThemeProvider theme={theme}>
64
- <TestComponent>text</TestComponent>
74
+ <Alert className="custom-class-name" title="alert">
75
+ alert
76
+ </Alert>
65
77
  </ThemeProvider>
66
78
  );
67
- const testelem = getByText('text');
68
- const text = getComputedStyle(testelem);
79
+ const alert = screen.getByTitle(/alert/);
69
80
 
70
- expect(text.fontSize).toEqual('8px');
81
+ expect(alert.className).toMatch('custom-class-name');
71
82
  });
@@ -1,28 +1,52 @@
1
1
  import React from 'react';
2
- import { useStyles, system } from '@marigold/system';
2
+ import { Exclamation, Check, Notification } from '@marigold/icons';
3
+ import { type ComponentProps } from '@marigold/types';
3
4
 
4
- type AlertProps = {
5
- variant?: string;
6
- };
5
+ import { Box } from '../Box';
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;
7
14
 
8
- export const Alert = system<AlertProps, 'div'>(
9
- ({ variant = 'info', className, children, ...props }) => {
10
- const classNames = useStyles(
11
- {
12
- variant: `alerts.${variant}`,
13
- display: 'flex',
14
- alignItems: 'center',
15
- px: 3,
16
- py: 2,
17
- borderRadius: 4,
18
- },
19
- className
20
- );
15
+ // Theme Extension
16
+ // ---------------
17
+ export interface AlertThemeExtension<Value> {
18
+ alert?: {
19
+ [key in AlertVariants]?: Value;
20
+ };
21
+ }
21
22
 
22
- return (
23
- <div className={classNames} {...props}>
24
- {children}
25
- </div>
26
- );
27
- }
28
- );
23
+ // Props
24
+ // ---------------
25
+ export type AlertProps = {
26
+ variant?: AlertVariants;
27
+ } & ComponentProps<'div'>;
28
+
29
+ // Component
30
+ // ---------------
31
+ export const Alert: React.FC<AlertProps> = ({
32
+ variant = 'success',
33
+ children,
34
+ ...props
35
+ }) => {
36
+ const Icon = ICON_MAP[variant];
37
+
38
+ return (
39
+ <Box {...props} display="flex" variant={`alert.${variant}`}>
40
+ <Box
41
+ display="inline-block"
42
+ alignItems="center"
43
+ width="32px"
44
+ height="32px"
45
+ bg={variant}
46
+ >
47
+ <Box as={Icon} size={12} color="#fff" bg={variant} m={10} />
48
+ </Box>
49
+ <Box mx="16px">{children}</Box>
50
+ </Box>
51
+ );
52
+ };
@@ -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';
4
- import { Badge } from '@marigold/components';
3
+ import { ThemeProvider } from '@marigold/system';
4
+ import { Badge } from './Badge';
5
5
 
6
6
  const theme = {
7
- content: {
8
- badge: {
7
+ radii: {
8
+ none: 0,
9
+ larger: 8,
10
+ },
11
+ badge: {
12
+ __default: {
9
13
  borderRadius: '8px',
10
14
  },
11
15
  fatBadge: {
@@ -36,28 +40,6 @@ test('renders correct HTML element', () => {
36
40
  expect(badge instanceof HTMLDivElement).toBeTruthy();
37
41
  });
38
42
 
39
- test('supports custom borderColor prop', () => {
40
- render(
41
- <ThemeProvider theme={theme}>
42
- <Badge title="badge" borderColor="#000" />
43
- </ThemeProvider>
44
- );
45
- const badge = screen.getByTitle(/badge/);
46
-
47
- expect(badge).toHaveStyle(`border: 1px solid #000`);
48
- });
49
-
50
- test('supports custom backgroundColor prop', () => {
51
- render(
52
- <ThemeProvider theme={theme}>
53
- <Badge title="badge" backgroundColor="#1ee" />
54
- </ThemeProvider>
55
- );
56
- const badge = screen.getByTitle(/badge/);
57
-
58
- expect(badge).toHaveStyle(`background: #1ee`);
59
- });
60
-
61
43
  test('supports other variant than default', () => {
62
44
  render(
63
45
  <ThemeProvider theme={theme}>
@@ -70,22 +52,14 @@ test('supports other variant than default', () => {
70
52
  });
71
53
 
72
54
  test('accepts custom styles prop className', () => {
73
- const TestComponent: React.FC = ({ children, ...props }) => {
74
- const classNames = useStyles({ fontSize: '8px' });
75
- return (
76
- <Badge className={classNames} {...props}>
77
- {children}
78
- </Badge>
79
- );
80
- };
81
-
82
- const { getByText } = render(
55
+ render(
83
56
  <ThemeProvider theme={theme}>
84
- <TestComponent>text</TestComponent>
57
+ <Badge className="custom-class-name" title="badge">
58
+ badge
59
+ </Badge>
85
60
  </ThemeProvider>
86
61
  );
87
- const testelem = getByText('text');
88
- const text = getComputedStyle(testelem);
62
+ const badge = screen.getByTitle(/badge/);
89
63
 
90
- expect(text.fontSize).toEqual('8px');
64
+ expect(badge.className).toMatch('custom-class-name');
91
65
  });
@@ -1,34 +1,37 @@
1
1
  import React from 'react';
2
- import { useStyles, system } from '@marigold/system';
2
+ import { ComponentProps } from '@marigold/types';
3
+ import { Box } from '../Box';
3
4
 
4
- type BadgeProps = {
5
+ // Theme Extension
6
+ // ---------------
7
+ export interface BadgeThemeExtension<Value> {
8
+ badge?: {
9
+ [key: string]: Value;
10
+ };
11
+ }
12
+
13
+ // Props
14
+ // ---------------
15
+ export type BadgeProps = {
5
16
  variant?: string;
17
+ bgColor?: string;
6
18
  borderColor?: string;
7
- backgroundColor?: string;
8
- };
9
-
10
- export const Badge = system<BadgeProps, 'div'>(
11
- ({
12
- variant = 'badge',
13
- borderColor = 'inherit',
14
- backgroundColor = 'inherit',
15
- className,
16
- children,
17
- ...props
18
- }) => {
19
- const classNames = useStyles(
20
- {
21
- variant: `content.${variant}`,
22
- border: '1px solid ' + borderColor,
23
- bg: backgroundColor,
24
- },
25
- className
26
- );
19
+ } & ComponentProps<'div'>;
27
20
 
28
- return (
29
- <div className={classNames} {...props}>
30
- {children}
31
- </div>
32
- );
33
- }
21
+ // Component
22
+ // ---------------
23
+ export const Badge: React.FC<BadgeProps> = ({
24
+ variant = '',
25
+ bgColor = 'transparent',
26
+ borderColor = 'transparent',
27
+ children,
28
+ ...props
29
+ }) => (
30
+ <Box
31
+ css={{ bg: bgColor, borderColor: borderColor }}
32
+ variant={`badge.${variant}`}
33
+ {...props}
34
+ >
35
+ {children}
36
+ </Box>
34
37
  );
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,29 +1,64 @@
1
- import React from 'react';
2
- import { useStyles, system } from '@marigold/system';
1
+ import React, { forwardRef, RefObject } from 'react';
2
+ import { useButton } from '@react-aria/button';
3
+ import {
4
+ PolymorphicComponentWithRef,
5
+ PolymorphicPropsWithRef,
6
+ } from '@marigold/types';
3
7
 
4
- type ButtonProps = {
5
- variant?: string;
6
- };
8
+ import { Box, BoxOwnProps } from '../Box';
7
9
 
8
- export const Button = system<ButtonProps, 'button'>(
9
- ({ variant = 'primary.large', className, children, ...props }) => {
10
- const classNames = useStyles(
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
+ (
11
27
  {
12
- variant: `button.${variant}`,
28
+ as = 'button',
29
+ variant = 'primary',
30
+ size = 'large',
31
+ space = 'none',
32
+ disabled,
33
+ children,
34
+ className,
35
+ ...props
13
36
  },
14
- className
15
- );
16
- return (
17
- <button className={classNames} {...props}>
18
- <span
19
- className={useStyles({
20
- display: 'inline-flex',
21
- alignItems: 'center',
22
- })}
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 }}
23
59
  >
24
60
  {children}
25
- </span>
26
- </button>
27
- );
28
- }
29
- );
61
+ </Box>
62
+ );
63
+ }
64
+ );
@@ -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
+ );