@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
@@ -0,0 +1,39 @@
1
+ import React from 'react';
2
+ import type { Meta, ComponentStory } from '@storybook/react';
3
+ import { Text } from '../Text';
4
+ import { Inline } from './Inline';
5
+ import { Check } from '@marigold/icons';
6
+
7
+ export default {
8
+ title: 'Components/Inline',
9
+ argTypes: {
10
+ space: {
11
+ control: {
12
+ type: 'select',
13
+ },
14
+ options: [
15
+ 'none',
16
+ 'xxsmall',
17
+ 'xsmall',
18
+ 'small',
19
+ 'medium',
20
+ 'large',
21
+ 'xlarge',
22
+ 'xxlarge',
23
+ ],
24
+ description: 'Responsive Style Value',
25
+ table: {
26
+ defaultValue: {
27
+ summary: 'none',
28
+ },
29
+ },
30
+ },
31
+ },
32
+ } as Meta;
33
+
34
+ export const Basic: ComponentStory<typeof Inline> = args => (
35
+ <Inline {...args}>
36
+ <Check />
37
+ <Text>Check</Text>
38
+ </Inline>
39
+ );
@@ -0,0 +1,99 @@
1
+ import React from 'react';
2
+ import { render, screen } from '@testing-library/react';
3
+ import { ThemeProvider } from '@marigold/system';
4
+
5
+ import { Inline } from './Inline';
6
+ import { Text } from '../Text';
7
+
8
+ // Setup
9
+ // ---------------
10
+ const theme = {
11
+ space: {
12
+ none: 0,
13
+ small: 2,
14
+ medium: 4,
15
+ large: 8,
16
+ },
17
+ };
18
+
19
+ const getLeftPadding = (element: HTMLElement) =>
20
+ getComputedStyle(element).getPropertyValue('padding-left');
21
+
22
+ test('default space is "none"', () => {
23
+ render(
24
+ <ThemeProvider theme={theme}>
25
+ <Inline>
26
+ <Text>first</Text>
27
+ <Text>second</Text>
28
+ </Inline>
29
+ </ThemeProvider>
30
+ );
31
+ const first = screen.getByText(/first/).parentElement!;
32
+ const second = screen.getByText(/second/).parentElement!;
33
+
34
+ expect(getLeftPadding(first)).toEqual('');
35
+ expect(second).toHaveStyle(`padding-left: 0px`);
36
+ });
37
+
38
+ test('accepts and uses spacing from theme', () => {
39
+ render(
40
+ <ThemeProvider theme={theme}>
41
+ <Inline space="small">
42
+ <Text>first</Text>
43
+ <Text>second</Text>
44
+ </Inline>
45
+ </ThemeProvider>
46
+ );
47
+ const first = screen.getByText(/first/);
48
+ const second = screen.getByText(/second/);
49
+
50
+ expect(getLeftPadding(first)).toEqual('');
51
+ expect(second.parentElement).toHaveStyle(`padding-left: 2px`);
52
+ });
53
+
54
+ test('supports nesting', () => {
55
+ render(
56
+ <ThemeProvider theme={theme}>
57
+ <Inline space="large">
58
+ <Inline space="small" data-testid="leftInline">
59
+ <Text>first</Text>
60
+ <Text>second</Text>
61
+ </Inline>
62
+ <Inline space="small" data-testid="rightInline">
63
+ <Text>third</Text>
64
+ <Text>fourth</Text>
65
+ </Inline>
66
+ </Inline>
67
+ </ThemeProvider>
68
+ );
69
+ const first = screen.getByText(/first/);
70
+ const second = screen.getByText(/second/);
71
+ const leftInline = screen.getByTestId('leftInline');
72
+
73
+ const third = screen.getByText(/third/);
74
+ const fourth = screen.getByText(/fourth/);
75
+ const rightInline = screen.getByTestId('rightInline');
76
+
77
+ expect(getLeftPadding(leftInline.parentElement!)).toEqual('');
78
+ expect(rightInline.parentElement).toHaveStyle(`padding-left: 8px`);
79
+
80
+ expect(getLeftPadding(first.parentElement!)).toEqual('');
81
+ expect(second.parentElement).toHaveStyle(`padding-left: 2px`);
82
+
83
+ expect(getLeftPadding(third.parentElement!)).toEqual('');
84
+ expect(fourth.parentElement).toHaveStyle(`padding-left: 2px`);
85
+ });
86
+
87
+ test('renders div per default', () => {
88
+ render(
89
+ <ThemeProvider theme={theme}>
90
+ <Inline data-testid="inline">
91
+ <Text>first</Text>
92
+ <Text>second</Text>
93
+ </Inline>
94
+ </ThemeProvider>
95
+ );
96
+
97
+ const inline = screen.getByTestId('inline');
98
+ expect(inline instanceof HTMLDivElement).toBeTruthy();
99
+ });
@@ -0,0 +1,38 @@
1
+ import React, { Children } from 'react';
2
+ import flattenChildren from 'react-keyed-flatten-children';
3
+
4
+ import { ResponsiveStyleValue } from '@marigold/system';
5
+
6
+ import { Box } from '../Box';
7
+
8
+ export type InlineProps = {
9
+ space?: ResponsiveStyleValue<string>;
10
+ align?: 'top' | 'center' | 'bottom';
11
+ };
12
+
13
+ const ALIGNMENT = {
14
+ top: 'flex-start',
15
+ center: 'center',
16
+ bottom: 'flex-end',
17
+ };
18
+
19
+ export const Inline: React.FC<InlineProps> = ({
20
+ space = 'none',
21
+ align = 'center',
22
+ children,
23
+ ...props
24
+ }) => (
25
+ <Box
26
+ display="inline-flex"
27
+ css={{ '> * + *': { pl: space } }}
28
+ alignItems={ALIGNMENT[align]}
29
+ {...props}
30
+ >
31
+ {Children.map(
32
+ flattenChildren(children) as unknown as React.ReactElement,
33
+ (child: React.ReactElement) => (
34
+ <Box>{React.cloneElement(child, {}, child.props.children)}</Box>
35
+ )
36
+ )}
37
+ </Box>
38
+ );
@@ -0,0 +1 @@
1
+ export * from './Inline';
@@ -0,0 +1,54 @@
1
+ import React from 'react';
2
+ import type { Meta, ComponentStory } from '@storybook/react';
3
+ import { Input } from './Input';
4
+ import { Label } from '../Label';
5
+
6
+ export default {
7
+ title: 'Components/Input',
8
+ argTypes: {
9
+ variant: {
10
+ control: {
11
+ type: 'text',
12
+ },
13
+ description: '?',
14
+ table: {
15
+ defaultValue: {
16
+ summary: '__default',
17
+ },
18
+ },
19
+ },
20
+ type: {
21
+ control: {
22
+ type: 'select',
23
+ },
24
+ options: [
25
+ 'date',
26
+ 'datetime-local',
27
+ 'email',
28
+ 'month',
29
+ 'number',
30
+ 'password',
31
+ 'search',
32
+ 'tel',
33
+ 'text',
34
+ 'time',
35
+ 'time',
36
+ 'url',
37
+ 'week',
38
+ ],
39
+ defaultValue: 'text',
40
+ table: {
41
+ defaultValue: {
42
+ summary: 'text',
43
+ },
44
+ },
45
+ },
46
+ },
47
+ } as Meta;
48
+
49
+ export const Basic: ComponentStory<typeof Input> = args => (
50
+ <Label htmlFor="input">
51
+ Label
52
+ <Input id="input" placeholder="Placeholder..." {...args} />
53
+ </Label>
54
+ );
@@ -4,12 +4,16 @@ import { ThemeProvider } from '@marigold/system';
4
4
  import { Input } from './Input';
5
5
 
6
6
  const theme = {
7
+ fonts: {
8
+ body: 'Inter',
9
+ forms: 'Roboto',
10
+ },
7
11
  input: {
8
- default: {
9
- fontFamily: 'Inter',
12
+ __default: {
13
+ fontFamily: 'body',
10
14
  },
11
15
  input2: {
12
- fontFamily: 'Roboto',
16
+ fontFamily: 'forms',
13
17
  },
14
18
  },
15
19
  };
@@ -2,12 +2,24 @@ import React from 'react';
2
2
  import { ComponentProps } from '@marigold/types';
3
3
  import { Box } from '../Box';
4
4
 
5
+ // Theme Extension
6
+ // ---------------
7
+ export interface InputThemeExtension<Value> {
8
+ input?: {
9
+ [key: string]: Value;
10
+ };
11
+ }
12
+
13
+ // Props
14
+ // ---------------
5
15
  export type InputProps = {
6
16
  variant?: string;
7
17
  } & ComponentProps<'input'>;
8
18
 
19
+ // Component
20
+ // ---------------
9
21
  export const Input: React.FC<InputProps> = ({
10
- variant = 'default',
22
+ variant = '',
11
23
  type = 'text',
12
24
  ...props
13
25
  }) => <Box {...props} as="input" type={type} variant={`input.${variant}`} />;
@@ -0,0 +1,41 @@
1
+ import React from 'react';
2
+ import type { Meta, ComponentStory } from '@storybook/react';
3
+ import { Label } from './Label';
4
+
5
+ export default {
6
+ title: 'Components/Label',
7
+ argTypes: {
8
+ variant: {
9
+ control: {
10
+ type: 'text',
11
+ },
12
+ description: '?',
13
+ table: {
14
+ defaultValue: {
15
+ summary: 'above',
16
+ },
17
+ },
18
+ },
19
+ htmlFor: {
20
+ control: {
21
+ type: 'text',
22
+ },
23
+ defaultValue: 'input',
24
+ },
25
+ required: {
26
+ control: {
27
+ type: 'boolean',
28
+ },
29
+ description: 'Adds required Icon to label',
30
+ table: {
31
+ defaultValue: {
32
+ summary: false,
33
+ },
34
+ },
35
+ },
36
+ },
37
+ } as Meta;
38
+
39
+ export const Basic: ComponentStory<typeof Label> = args => (
40
+ <Label {...args}>Label</Label>
41
+ );
@@ -4,17 +4,25 @@ import { ThemeProvider } from '@marigold/system';
4
4
  import { Label } from './Label';
5
5
 
6
6
  const theme = {
7
+ fonts: {
8
+ body: 'Inter Regular',
9
+ label: 'Oswald',
10
+ },
7
11
  label: {
8
- default: {
9
- fontFamily: 'Inter Regular',
12
+ above: {
13
+ fontFamily: 'body',
10
14
  },
11
15
  myLabel: {
12
- fontFamily: 'Oswald Regular',
16
+ fontFamily: 'label',
13
17
  },
14
18
  },
19
+ colors: {
20
+ text: 'black',
21
+ disabled: 'gray',
22
+ },
15
23
  };
16
24
 
17
- test('supports default variant and themeSection', () => {
25
+ test('supports default variant and styles', () => {
18
26
  render(
19
27
  <ThemeProvider theme={theme}>
20
28
  <Label htmlFor="labelId">label</Label>
@@ -23,6 +31,7 @@ test('supports default variant and themeSection', () => {
23
31
  const label = screen.getByText(/label/);
24
32
 
25
33
  expect(label).toHaveStyle(`font-family: Inter Regular`);
34
+ expect(label).toHaveStyle(`color: black`);
26
35
  });
27
36
 
28
37
  test('supports other variant than default', () => {
@@ -35,7 +44,7 @@ test('supports other variant than default', () => {
35
44
  );
36
45
  const label = screen.getByText(/label/);
37
46
 
38
- expect(label).toHaveStyle(`font-family: Oswald Regular`);
47
+ expect(label).toHaveStyle(`font-family: Oswald`);
39
48
  });
40
49
 
41
50
  test('supports htmlFor prop', () => {
@@ -49,6 +58,32 @@ test('supports htmlFor prop', () => {
49
58
  expect(label).toHaveAttribute('for');
50
59
  });
51
60
 
61
+ test('supports required prop', () => {
62
+ render(
63
+ <ThemeProvider theme={theme}>
64
+ <Label htmlFor="labelId" required>
65
+ label
66
+ </Label>
67
+ </ThemeProvider>
68
+ );
69
+ const label = screen.getByText(/label/);
70
+ const parent = label.parentElement;
71
+
72
+ expect(parent instanceof HTMLSpanElement).toBeTruthy();
73
+ });
74
+
75
+ test('supports color prop', () => {
76
+ render(
77
+ <ThemeProvider theme={theme}>
78
+ <Label htmlFor="labelId" color="disabled">
79
+ label
80
+ </Label>
81
+ </ThemeProvider>
82
+ );
83
+ const label = screen.getByText(/label/);
84
+ expect(label).toHaveStyle(`color: gray`);
85
+ });
86
+
52
87
  test('renders <label> element', () => {
53
88
  render(
54
89
  <ThemeProvider theme={theme}>
@@ -1,18 +1,64 @@
1
1
  import React from 'react';
2
+
2
3
  import { ComponentProps } from '@marigold/types';
4
+ import { Required } from '@marigold/icons';
5
+ import { ResponsiveStyleValue } from '@marigold/system';
6
+
3
7
  import { Box } from '../Box';
4
8
 
5
- export type LabelProps = {
6
- htmlFor: string;
9
+ // Theme Extension
10
+ // ---------------
11
+ export interface LabelThemeExtension<Value> {
12
+ label?: {
13
+ [key: string]: Value;
14
+ };
15
+ }
16
+
17
+ // LabelBase
18
+ // ---------------
19
+ export type LabelBaseProps = {
20
+ htmlFor?: string;
7
21
  variant?: string;
22
+ required?: boolean;
23
+ color?: ResponsiveStyleValue<string>;
8
24
  } & ComponentProps<'label'>;
9
25
 
26
+ export const LabelBase: React.FC<LabelProps> = ({
27
+ variant = 'above',
28
+ required,
29
+ color = 'text',
30
+ children,
31
+ ...props
32
+ }) => {
33
+ return (
34
+ <Box
35
+ {...props}
36
+ as="label"
37
+ __baseCSS={{ color: color }}
38
+ variant={`label.${variant}`}
39
+ >
40
+ {children}
41
+ </Box>
42
+ );
43
+ };
44
+
45
+ // Label
46
+ // ---------------
47
+ export type LabelProps = {
48
+ required?: boolean;
49
+ } & LabelBaseProps;
50
+
10
51
  export const Label: React.FC<LabelProps> = ({
11
- variant = 'default',
52
+ required,
12
53
  children,
13
54
  ...props
14
- }) => (
15
- <Box {...props} as="label" variant={`label.${variant}`}>
16
- {children}
17
- </Box>
18
- );
55
+ }) => {
56
+ return required ? (
57
+ <Box as="span" display="inline-flex" alignItems="center">
58
+ <LabelBase {...props}>{children}</LabelBase>
59
+ {required && <Box as={Required} size={16} css={{ color: 'error' }} />}
60
+ </Box>
61
+ ) : (
62
+ <LabelBase {...props}>{children}</LabelBase>
63
+ );
64
+ };
@@ -0,0 +1,35 @@
1
+ import React from 'react';
2
+ import type { Meta, ComponentStory } from '@storybook/react';
3
+ import { Link } from './Link';
4
+ import { Text } from '../Text';
5
+
6
+ export default {
7
+ title: 'Components/Link',
8
+ argTypes: {
9
+ variant: {
10
+ control: {
11
+ type: 'text',
12
+ },
13
+ description: '?',
14
+ table: {
15
+ defaultValue: {
16
+ summary: 'link',
17
+ },
18
+ },
19
+ },
20
+ href: {
21
+ control: {
22
+ type: 'text',
23
+ },
24
+ description: 'The URL to direct to',
25
+ },
26
+ },
27
+ } as Meta;
28
+
29
+ export const Basic: ComponentStory<typeof Link> = args => (
30
+ <Text>
31
+ <Link href="https://marigold-ui.io" target="_blank" {...args}>
32
+ Marigold Docs
33
+ </Link>
34
+ </Text>
35
+ );
@@ -4,12 +4,16 @@ import { ThemeProvider } from '@marigold/system';
4
4
  import { Link } from './Link';
5
5
 
6
6
  const theme = {
7
+ fonts: {
8
+ link: 'Inter',
9
+ body: 'Oswald',
10
+ },
7
11
  text: {
8
12
  link: {
9
- fontFamily: 'Inter',
13
+ fontFamily: 'link',
10
14
  },
11
15
  second: {
12
- fontFamily: 'Oswald',
16
+ fontFamily: 'body',
13
17
  },
14
18
  },
15
19
  };
package/src/Link/Link.tsx CHANGED
@@ -4,9 +4,19 @@ import { PolymorphicComponent, PolymorphicProps } from '@marigold/types';
4
4
 
5
5
  import { Text, TextOwnProps } from '../Text';
6
6
 
7
+ // Theme Extension
8
+ // ---------------
9
+ export interface LinkThemeExtension<Value> {
10
+ link?: Value;
11
+ }
12
+
13
+ // Props
14
+ // ---------------
7
15
  export type LinkOwnProps = { disabled?: boolean } & TextOwnProps;
8
16
  export type LinkProps = PolymorphicProps<LinkOwnProps, 'a'>;
9
17
 
18
+ // Component
19
+ // ---------------
10
20
  export const Link = (({
11
21
  as = 'a',
12
22
  variant = 'link',
@@ -17,7 +27,8 @@ export const Link = (({
17
27
  const ref = useRef<any>();
18
28
  const { linkProps } = useLink(
19
29
  {
20
- ...props,
30
+ // We typecast here because the element could very well be a `span`
31
+ ...(props as PolymorphicProps<LinkOwnProps, any>),
21
32
  elementType: typeof as === 'string' ? as : 'span',
22
33
  isDisabled: disabled,
23
34
  },
@@ -0,0 +1,62 @@
1
+ import React, { useState } from 'react';
2
+ import type { Meta, ComponentStory } from '@storybook/react';
3
+ import { Menu } from './Menu';
4
+ import { MenuItem } from '../MenuItem';
5
+
6
+ export default {
7
+ title: 'Components/Menu',
8
+ parameters: {
9
+ actions: {
10
+ handles: ['click'],
11
+ },
12
+ },
13
+ argTypes: {
14
+ variant: {
15
+ control: {
16
+ type: 'text',
17
+ },
18
+ description: '?',
19
+ table: {
20
+ defaultValue: {
21
+ summary: 'default',
22
+ },
23
+ },
24
+ },
25
+ label: {
26
+ control: {
27
+ type: 'text',
28
+ },
29
+ description: 'Menu label on hover',
30
+ defaultValue: 'Menu',
31
+ },
32
+ show: {
33
+ control: {
34
+ type: 'boolean',
35
+ },
36
+ options: [true, false],
37
+ description: 'Show what',
38
+ table: {
39
+ defaultValue: {
40
+ summary: false,
41
+ },
42
+ },
43
+ },
44
+ onClick: {
45
+ control: {
46
+ type: 'text',
47
+ },
48
+ description: 'Function to show menu or toggle something',
49
+ },
50
+ },
51
+ } as Meta;
52
+
53
+ export const Basic: ComponentStory<typeof Menu> = ({ onClick, ...args }) => {
54
+ const [showMenu, setShowMenu] = useState(false);
55
+ return (
56
+ <Menu onClick={() => setShowMenu(!showMenu)} show={showMenu} {...args}>
57
+ <MenuItem href="#">Home</MenuItem>
58
+ <MenuItem href="#">Tickets</MenuItem>
59
+ <MenuItem href="#">Logout</MenuItem>
60
+ </Menu>
61
+ );
62
+ };
@@ -5,12 +5,17 @@ import { Menu } from './Menu';
5
5
  import { MenuItem } from '../MenuItem';
6
6
 
7
7
  const theme = {
8
- content: {
9
- menu: {
10
- padding: '4px',
8
+ space: {
9
+ none: 0,
10
+ small: 4,
11
+ medium: 8,
12
+ },
13
+ menu: {
14
+ default: {
15
+ padding: 'small',
11
16
  },
12
- options: {
13
- padding: '8px',
17
+ custom: {
18
+ padding: 'medium',
14
19
  },
15
20
  },
16
21
  };
@@ -31,7 +36,7 @@ test('supports default variant and themeSection', () => {
31
36
  test('accepts other variant than default', () => {
32
37
  render(
33
38
  <ThemeProvider theme={theme}>
34
- <Menu variant="options" title="menu" onClick={() => {}}>
39
+ <Menu variant="custom" title="menu" onClick={() => {}}>
35
40
  <MenuItem href="#">Home</MenuItem>
36
41
  </Menu>
37
42
  </ThemeProvider>