@marigold/components 0.1.0 → 0.3.2

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 +180 -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 +12 -4
  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 +7 -3
  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 +3 -0
  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 +5 -0
  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 +1068 -601
  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 +1003 -579
  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 +22 -3
  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 +67 -68
  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 +32 -23
  115. package/src/Divider/Divider.tsx +27 -7
  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 +6 -2
  134. package/src/Link/Link.tsx +12 -1
  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 +25 -41
  164. package/src/Text/Text.stories.tsx +61 -0
  165. package/src/Text/Text.test.tsx +2 -2
  166. package/src/Text/Text.tsx +25 -14
  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 -46
  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 -157
  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 -81
  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
package/src/Menu/Menu.tsx CHANGED
@@ -1,10 +1,17 @@
1
1
  import React from 'react';
2
- import { useStyles } from '@marigold/system';
3
2
  import { ComponentProps } from '@marigold/types';
4
3
 
5
4
  import { Button } from '../Button';
6
5
  import { Box } from '../Box';
7
6
 
7
+ // Theme Extension
8
+ // ---------------
9
+ export interface MenuThemeExtension<Value> {
10
+ menu?: Value;
11
+ }
12
+
13
+ // Props
14
+ // ---------------
8
15
  export type MenuProps = {
9
16
  variant?: string;
10
17
  label?: string;
@@ -14,30 +21,31 @@ export type MenuProps = {
14
21
  title?: string; // For testing
15
22
  };
16
23
 
24
+ // Component
25
+ // ---------------
17
26
  export const Menu: React.FC<MenuProps> = ({
18
- variant = 'menu',
27
+ variant = 'default',
19
28
  label = 'Menu',
20
29
  onClick,
21
30
  show = false,
22
31
  children,
23
32
  ...props
24
33
  }) => {
25
- const itemStyles = useStyles({
26
- css: {
27
- position: 'absolute',
28
- minWidth: '120px',
29
- display: 'block',
30
- textAlign: 'left',
31
- borderRadius: '2px',
32
- },
33
- });
34
-
35
34
  return (
36
- <Box variant={`content.${variant}`} {...props}>
35
+ <Box variant={`menu.${variant}`} {...props}>
37
36
  <Button onClick={onClick} variant="menu">
38
37
  {label}
39
38
  </Button>
40
- {show ? <div className={itemStyles}>{children}</div> : null}
39
+ {show ? (
40
+ <Box
41
+ display="block"
42
+ position="absolute"
43
+ minWidth="120px"
44
+ borderRadius="2px"
45
+ >
46
+ {children}
47
+ </Box>
48
+ ) : null}
41
49
  </Box>
42
50
  );
43
51
  };
@@ -0,0 +1,30 @@
1
+ import React from 'react';
2
+ import type { Meta, ComponentStory } from '@storybook/react';
3
+ import { MenuItem } from './MenuItem';
4
+
5
+ export default {
6
+ title: 'Components/MenuItem',
7
+ parameters: {
8
+ actions: {
9
+ handles: ['click'],
10
+ },
11
+ },
12
+ argTypes: {
13
+ variant: {
14
+ control: {
15
+ type: 'text',
16
+ },
17
+ table: {
18
+ defaultValue: {
19
+ summary: 'default',
20
+ },
21
+ },
22
+ },
23
+ },
24
+ } as Meta;
25
+
26
+ export const Basic: ComponentStory<typeof MenuItem> = args => (
27
+ <MenuItem href="#" {...args}>
28
+ Home
29
+ </MenuItem>
30
+ );
@@ -4,42 +4,49 @@ import { ThemeProvider } from '@marigold/system';
4
4
  import { MenuItem } from './MenuItem';
5
5
 
6
6
  const theme = {
7
- menu: {
8
- menuItem: {
9
- padding: '4px',
7
+ space: {
8
+ none: 0,
9
+ small: 4,
10
+ medium: 8,
11
+ },
12
+ menuItem: {
13
+ default: {
14
+ padding: 'small',
10
15
  },
11
16
  item: {
12
- padding: '8px',
17
+ padding: 'medium',
13
18
  },
14
19
  },
15
20
  };
16
21
 
17
- test('supports default variant and themeSection', () => {
22
+ test('supports default variant', () => {
18
23
  render(
19
24
  <ThemeProvider theme={theme}>
20
- <MenuItem title="menuItem" />
25
+ <MenuItem title="menuItem">Item</MenuItem>
21
26
  </ThemeProvider>
22
27
  );
23
28
  const menuItem = screen.getByTitle(/menuItem/);
24
29
 
25
- expect(menuItem).toHaveStyle(`padding: 4px`);
30
+ expect(menuItem.parentElement).toHaveStyle(`padding: 4px`);
26
31
  });
27
32
 
28
33
  test('accepts other variant than default', () => {
29
34
  render(
30
35
  <ThemeProvider theme={theme}>
31
- <MenuItem title="menuItem" variant="item" />
36
+ <MenuItem title="menuItem" variant="item">
37
+ Item
38
+ </MenuItem>
32
39
  </ThemeProvider>
33
40
  );
34
41
  const menuItem = screen.getByTitle(/menuItem/);
35
42
 
36
- expect(menuItem).toHaveStyle(`padding: 8px`);
43
+ expect(menuItem.parentElement).toHaveStyle(`padding: 8px`);
37
44
  });
38
45
 
39
46
  test('renders correct HTML element', () => {
40
47
  render(
41
48
  <ThemeProvider theme={theme}>
42
- <MenuItem title="menuItem" />
49
+ <MenuItem title="menuItem">Item</MenuItem>
43
50
  </ThemeProvider>
44
51
  );
45
52
  const menuItem = screen.getByTitle(/menuItem/);
@@ -50,10 +57,12 @@ test('renders correct HTML element', () => {
50
57
  test('accepts custom styles prop className', () => {
51
58
  render(
52
59
  <ThemeProvider theme={theme}>
53
- <MenuItem className="custom-class-name" title="menuItem" />
60
+ <MenuItem title="menuItem" className="custom-class-name">
61
+ Item
62
+ </MenuItem>
54
63
  </ThemeProvider>
55
64
  );
56
- const menuItem = screen.getByTitle(/menuItem/);
65
+ const menuItem = screen.getByText(/Item/).parentElement;
57
66
 
58
- expect(menuItem.className).toMatch('custom-class-name');
67
+ expect(menuItem).toHaveClass('custom-class-name');
59
68
  });
@@ -1,26 +1,35 @@
1
1
  import React from 'react';
2
- import { useStyles } from '@marigold/system';
3
2
  import { ComponentProps } from '@marigold/types';
4
3
  import { Link } from '../Link';
4
+ import { Box } from '../Box';
5
5
 
6
+ // Theme Extension
7
+ // ---------------
8
+ export interface MenuItemThemeExtension<Value> {
9
+ menuItem?: {
10
+ [key: string]: Value;
11
+ };
12
+ }
13
+
14
+ // Props
15
+ // ---------------
6
16
  export type MenuItemProps = {
7
17
  variant?: string;
8
18
  } & ComponentProps<typeof Link>;
9
19
 
20
+ // Component
21
+ // ---------------
10
22
  export const MenuItem: React.FC<MenuItemProps> = ({
11
- variant = 'menuItem',
23
+ variant = 'default',
12
24
  className,
13
25
  children,
14
26
  ...props
15
27
  }) => {
16
- const classNames = useStyles({
17
- variant: `menu.${variant}`,
18
- className,
19
- });
20
-
21
28
  return (
22
- <Link {...props} variant="menu" className={classNames}>
23
- {children}
24
- </Link>
29
+ <Box variant={`menuItem.${variant}`} className={className}>
30
+ <Link variant="menuItemLink" {...props}>
31
+ {children}
32
+ </Link>
33
+ </Box>
25
34
  );
26
35
  };
@@ -0,0 +1,30 @@
1
+ import React from 'react';
2
+ import type { Meta, ComponentStory } from '@storybook/react';
3
+ import { Message } from './Message';
4
+ import { Text } from '../Text';
5
+
6
+ export default {
7
+ title: 'Components/Message',
8
+ argTypes: {
9
+ variant: {
10
+ control: {
11
+ type: 'select',
12
+ },
13
+ options: ['warning', 'error', 'info'],
14
+ description: 'Messaging in different colors and icons',
15
+ },
16
+ messageTitle: {
17
+ control: {
18
+ type: 'text',
19
+ },
20
+ description: 'Content',
21
+ defaultValue: 'Danger Zone!',
22
+ },
23
+ },
24
+ } as Meta;
25
+
26
+ export const Basic: ComponentStory<typeof Message> = args => (
27
+ <Message {...args}>
28
+ <Text>Hello, I am a simple message.</Text>
29
+ </Message>
30
+ );
@@ -4,7 +4,10 @@ import { ThemeProvider } from '@marigold/system';
4
4
  import { Message } from './Message';
5
5
 
6
6
  const theme = {
7
- messages: {
7
+ colors: {
8
+ primary: 'hotpink',
9
+ },
10
+ message: {
8
11
  info: {
9
12
  alignItems: 'center',
10
13
  },
@@ -1,15 +1,26 @@
1
1
  import React from 'react';
2
2
  import { Exclamation, Info, Notification } from '@marigold/icons';
3
- import { useStyles } from '@marigold/system';
4
3
  import { ComponentProps } from '@marigold/types';
5
4
  import { Box } from '../Box';
6
- import { Heading } from '../Heading';
5
+ import { Text } from '../Text';
7
6
 
7
+ // Theme Extension
8
+ // ---------------
9
+ export interface MessageThemeExtension<Value> {
10
+ message?: {
11
+ [key: string]: Value;
12
+ };
13
+ }
14
+
15
+ // Props
16
+ // ---------------
8
17
  export type MessageProps = {
9
18
  messageTitle: string;
10
19
  variant?: string;
11
20
  } & ComponentProps<'div'>;
12
21
 
22
+ // Component
23
+ // ---------------
13
24
  export const Message: React.FC<MessageProps> = ({
14
25
  messageTitle,
15
26
  variant = 'info',
@@ -28,24 +39,17 @@ export const Message: React.FC<MessageProps> = ({
28
39
  return (
29
40
  <Box
30
41
  display="inline-block"
31
- variant={`messages.${variant}`}
42
+ variant={`message.${variant}`}
32
43
  className={className}
33
44
  {...props}
34
45
  >
35
- <Box display="flex" alignItems="center" variant="messages.title">
46
+ <Box display="flex" alignItems="center" variant="message.title">
36
47
  {icon}
37
- <Heading
38
- variant="h4"
39
- className={useStyles({
40
- css: {
41
- display: 'inline',
42
- },
43
- })}
44
- >
48
+ <Text as="h4" variant="headline4">
45
49
  {messageTitle}
46
- </Heading>
50
+ </Text>
47
51
  </Box>
48
- <Box className={useStyles({ css: { color: 'black' } })}>{children}</Box>
52
+ <Box css={{ color: 'black' }}>{children}</Box>
49
53
  </Box>
50
54
  );
51
55
  };
@@ -0,0 +1,136 @@
1
+ import React from 'react';
2
+ import { useTheme } from '@marigold/system';
3
+ import { render, screen } from '@testing-library/react';
4
+
5
+ import { MarigoldProvider } from './MarigoldProvider';
6
+
7
+ // Setup
8
+ // ---------------
9
+ const theme = {
10
+ colors: {
11
+ black: '#000',
12
+ },
13
+ fontSizes: {
14
+ body: 16,
15
+ heading: 32,
16
+ },
17
+ text: {
18
+ body: {
19
+ fontSize: 'body',
20
+ color: 'black',
21
+ },
22
+ },
23
+ };
24
+
25
+ test('themes can be cascaded', () => {
26
+ const outerTheme = {
27
+ colors: {
28
+ primary: 'coral',
29
+ },
30
+ };
31
+
32
+ const innerTheme = {
33
+ colors: {
34
+ primary: 'gainsboro',
35
+ },
36
+ };
37
+
38
+ const Theme = ({ testId }: { testId: string }) => {
39
+ const { theme } = useTheme();
40
+ return <div data-testid={testId}>{JSON.stringify(theme, null, 2)}</div>;
41
+ };
42
+
43
+ render(
44
+ <MarigoldProvider theme={outerTheme}>
45
+ <>
46
+ <Theme testId="outer" />
47
+ <MarigoldProvider theme={innerTheme}>
48
+ <Theme testId="inner" />
49
+ </MarigoldProvider>
50
+ </>
51
+ </MarigoldProvider>
52
+ );
53
+
54
+ const outer = screen.getByTestId('outer');
55
+ const inner = screen.getByTestId('inner');
56
+
57
+ expect(outer.innerHTML).toMatchInlineSnapshot(`
58
+ "{
59
+ \\"colors\\": {
60
+ \\"primary\\": \\"coral\\"
61
+ }
62
+ }"
63
+ `);
64
+ expect(inner.innerHTML).toMatchInlineSnapshot(`
65
+ "{
66
+ \\"colors\\": {
67
+ \\"primary\\": \\"gainsboro\\"
68
+ }
69
+ }"
70
+ `);
71
+ });
72
+
73
+ test('OverlayProvider is added', () => {
74
+ const { container } = render(
75
+ <MarigoldProvider theme={theme}>Test</MarigoldProvider>
76
+ );
77
+
78
+ expect(
79
+ container.querySelector(`div[data-overlay-container="true"]`)
80
+ ).toBeDefined();
81
+ });
82
+
83
+ test('OverlayProvider is added only once', () => {
84
+ const innerTheme = { colors: { primary: 'red' } };
85
+ const { container } = render(
86
+ <MarigoldProvider theme={theme}>
87
+ <MarigoldProvider theme={innerTheme}>Test</MarigoldProvider>
88
+ </MarigoldProvider>
89
+ );
90
+
91
+ expect(
92
+ container.querySelectorAll(`div[data-overlay-container="true"]`).length
93
+ ).toEqual(1);
94
+ });
95
+
96
+ test('applies global styles for body and html based on `theme.root`', () => {
97
+ const theme = {
98
+ fonts: {
99
+ body: 'Inter',
100
+ html: 'Roboto',
101
+ },
102
+ lineHeights: {
103
+ body: 2.5,
104
+ },
105
+ fontWeights: {
106
+ body: 500,
107
+ html: 700,
108
+ },
109
+ root: {
110
+ body: {
111
+ fontFamily: 'body',
112
+ lineHeight: 'body',
113
+ fontWeight: 'body',
114
+ },
115
+ html: {
116
+ fontFamily: 'html',
117
+ fontWeight: 'html',
118
+ },
119
+ },
120
+ };
121
+
122
+ const root = render(
123
+ <MarigoldProvider theme={theme}>
124
+ <h1>Hello</h1>
125
+ </MarigoldProvider>
126
+ );
127
+
128
+ const html = root.baseElement.parentElement;
129
+ expect(html).toHaveStyle(`font-family: ${theme.fonts.html}`);
130
+ expect(html).toHaveStyle(`font-weight: ${theme.fontWeights.html}`);
131
+
132
+ const body = root.baseElement;
133
+ expect(body).toHaveStyle(`font-family: ${theme.fonts.body}`);
134
+ expect(body).toHaveStyle(`font-weight: ${theme.fontWeights.body}`);
135
+ expect(body).toHaveStyle(`line-height: ${theme.lineHeights.body}`);
136
+ });
@@ -0,0 +1,47 @@
1
+ import React from 'react';
2
+ import { OverlayProvider } from '@react-aria/overlays';
3
+ import {
4
+ Theme,
5
+ Global,
6
+ ThemeProvider,
7
+ ThemeProviderProps,
8
+ useTheme,
9
+ __defaultTheme,
10
+ } from '@marigold/system';
11
+
12
+ // Theme Extension
13
+ // ---------------
14
+ export interface RootThemeExtension<Value> {
15
+ root?: {
16
+ body?: Value;
17
+ html?: Value;
18
+ };
19
+ }
20
+
21
+ // Props
22
+ // ---------------
23
+ export interface MarigoldProviderProps<T extends Theme>
24
+ extends ThemeProviderProps<T> {}
25
+
26
+ // Provider
27
+ // ---------------
28
+ export function MarigoldProvider<T extends Theme>({
29
+ theme,
30
+ children,
31
+ }: MarigoldProviderProps<T>) {
32
+ const outer = useTheme();
33
+ const isTopLevel = outer.theme === __defaultTheme;
34
+
35
+ return (
36
+ <ThemeProvider theme={theme}>
37
+ {isTopLevel ? (
38
+ <>
39
+ <Global />
40
+ <OverlayProvider>{children}</OverlayProvider>
41
+ </>
42
+ ) : (
43
+ children
44
+ )}
45
+ </ThemeProvider>
46
+ );
47
+ }
@@ -0,0 +1,4 @@
1
+ export { useTheme, ThemeProvider } from '@marigold/system';
2
+ export { SSRProvider } from '@react-aria/ssr';
3
+
4
+ export * from './MarigoldProvider';
@@ -0,0 +1,78 @@
1
+ import React, { useState } from 'react';
2
+ import type { Meta, ComponentStory } from '@storybook/react';
3
+
4
+ import { Radio } from './Radio';
5
+
6
+ export default {
7
+ title: 'Components/Radio',
8
+ parameters: {
9
+ actions: {
10
+ handles: ['click'],
11
+ },
12
+ },
13
+ argTypes: {
14
+ variant: {
15
+ control: {
16
+ type: 'text',
17
+ },
18
+ description: 'Radio variant',
19
+ defaultValue: '__default',
20
+ },
21
+ labelVariant: {
22
+ control: {
23
+ type: 'text',
24
+ },
25
+ description: 'Radio label variant',
26
+ defaultValue: 'inline',
27
+ },
28
+ label: {
29
+ control: {
30
+ type: 'text',
31
+ },
32
+ description: 'Label',
33
+ defaultValue: 'Radio Label',
34
+ },
35
+ required: {
36
+ control: {
37
+ type: 'boolean',
38
+ },
39
+ description: 'Required',
40
+ defaultValue: false,
41
+ },
42
+ disabled: {
43
+ control: {
44
+ type: 'boolean',
45
+ },
46
+ description: 'Disabled',
47
+ defaultValue: false,
48
+ },
49
+ error: {
50
+ control: {
51
+ type: 'boolean',
52
+ },
53
+ description: 'Error',
54
+ defaultValue: false,
55
+ },
56
+ errorMessage: {
57
+ control: {
58
+ type: 'text',
59
+ },
60
+ description: 'Error Message',
61
+ },
62
+ },
63
+ } as Meta;
64
+
65
+ export const Basic: ComponentStory<typeof Radio> = ({
66
+ onChange,
67
+ checked,
68
+ ...args
69
+ }) => {
70
+ const [isChecked, setChecked] = useState(false);
71
+ return (
72
+ <Radio
73
+ onChange={() => setChecked(!isChecked)}
74
+ checked={isChecked}
75
+ {...args}
76
+ />
77
+ );
78
+ };