@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
@@ -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
+ );
@@ -1,15 +1,19 @@
1
1
  import React from 'react';
2
2
  import { render, screen } from '@testing-library/react';
3
3
  import { ThemeProvider } from '@marigold/system';
4
- import { Input } from '@marigold/components';
4
+ import { Input } from './Input';
5
5
 
6
6
  const theme = {
7
- form: {
8
- input: {
9
- fontFamily: 'Inter',
7
+ fonts: {
8
+ body: 'Inter',
9
+ forms: 'Roboto',
10
+ },
11
+ input: {
12
+ __default: {
13
+ fontFamily: 'body',
10
14
  },
11
15
  input2: {
12
- fontFamily: 'Roboto',
16
+ fontFamily: 'forms',
13
17
  },
14
18
  },
15
19
  };
@@ -1,20 +1,25 @@
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 InputProps = {
5
- variant?: string;
6
- };
5
+ // Theme Extension
6
+ // ---------------
7
+ export interface InputThemeExtension<Value> {
8
+ input?: {
9
+ [key: string]: Value;
10
+ };
11
+ }
7
12
 
8
- export const Input = system<InputProps, 'input'>(
9
- ({ variant = 'input', type = 'text', className, ...props }) => {
10
- const classNames = useStyles(
11
- {
12
- variant: `form.${variant}`,
13
- border: 0,
14
- },
15
- className
16
- );
13
+ // Props
14
+ // ---------------
15
+ export type InputProps = {
16
+ variant?: string;
17
+ } & ComponentProps<'input'>;
17
18
 
18
- return <input type={type} className={classNames} {...props} />;
19
- }
20
- );
19
+ // Component
20
+ // ---------------
21
+ export const Input: React.FC<InputProps> = ({
22
+ variant = '',
23
+ type = 'text',
24
+ ...props
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
- form: {
8
- label: {
9
- fontFamily: 'Inter Regular',
7
+ fonts: {
8
+ body: 'Inter Regular',
9
+ label: 'Oswald',
10
+ },
11
+ label: {
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,23 +1,64 @@
1
1
  import React from 'react';
2
- import { system, useStyles } from '@marigold/system';
3
2
 
4
- type TextProps = {
5
- htmlFor: string;
3
+ import { ComponentProps } from '@marigold/types';
4
+ import { Required } from '@marigold/icons';
5
+ import { ResponsiveStyleValue } from '@marigold/system';
6
+
7
+ import { Box } from '../Box';
8
+
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;
6
21
  variant?: string;
22
+ required?: boolean;
23
+ color?: ResponsiveStyleValue<string>;
24
+ } & ComponentProps<'label'>;
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
+ );
7
43
  };
8
44
 
9
- export const Label = system<TextProps, 'label'>(
10
- ({ variant = 'label', htmlFor, children, className, ...props }) => {
11
- const classNames = useStyles(
12
- {
13
- variant: `form.${variant}`,
14
- },
15
- className
16
- );
17
- return (
18
- <label htmlFor={htmlFor} className={classNames} {...props}>
19
- {children}
20
- </label>
21
- );
22
- }
23
- );
45
+ // Label
46
+ // ---------------
47
+ export type LabelProps = {
48
+ required?: boolean;
49
+ } & LabelBaseProps;
50
+
51
+ export const Label: React.FC<LabelProps> = ({
52
+ required,
53
+ children,
54
+ ...props
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
+ );
@@ -1,67 +1,97 @@
1
1
  import React from 'react';
2
2
  import { render, screen } from '@testing-library/react';
3
3
  import { ThemeProvider } from '@marigold/system';
4
- import { Link } from '@marigold/components';
4
+ import { Link } from './Link';
5
5
 
6
6
  const theme = {
7
- link: {
8
- normal: {
9
- fontFamily: 'Inter',
7
+ fonts: {
8
+ link: 'Inter',
9
+ body: 'Oswald',
10
+ },
11
+ text: {
12
+ link: {
13
+ fontFamily: 'link',
10
14
  },
11
15
  second: {
12
- fontFamily: 'Oswald',
16
+ fontFamily: 'body',
13
17
  },
14
18
  },
15
19
  };
16
20
 
17
- test('supports default variant and themeSection', () => {
21
+ test('uses `text.link` as default variant', () => {
18
22
  render(
19
23
  <ThemeProvider theme={theme}>
20
- <Link href="#!" title="link">
21
- Link
22
- </Link>
24
+ <Link href="#!">Link</Link>
23
25
  </ThemeProvider>
24
26
  );
25
- const link = screen.getByTitle(/link/);
27
+ const link = screen.getByText(/Link/);
26
28
 
27
29
  expect(link).toHaveStyle(`font-family: Inter`);
28
30
  });
29
31
 
30
- test('accepts other variant than default', () => {
32
+ test('allows to change variants via `variant` prop (with "text" prefix)', () => {
31
33
  render(
32
34
  <ThemeProvider theme={theme}>
33
- <Link href="#!" title="link" variant="second">
35
+ <Link href="#!" variant="second">
34
36
  Link
35
37
  </Link>
36
38
  </ThemeProvider>
37
39
  );
38
- const link = screen.getByTitle(/link/);
40
+ const link = screen.getByText(/Link/);
39
41
 
40
42
  expect(link).toHaveStyle(`font-family: Oswald`);
41
43
  });
42
44
 
43
- test('renders correct HTML element', () => {
45
+ test('renders a <a> element by default', () => {
44
46
  render(
45
47
  <ThemeProvider theme={theme}>
46
- <Link href="#!" title="link">
47
- Link
48
- </Link>
48
+ <Link href="#!">Link</Link>
49
49
  </ThemeProvider>
50
50
  );
51
- const link = screen.getByTitle(/link/);
51
+ const link = screen.getByText(/Link/);
52
52
 
53
53
  expect(link instanceof HTMLAnchorElement).toBeTruthy();
54
54
  });
55
55
 
56
- test('accepts custom styles prop className', () => {
56
+ test('accepts custom className', () => {
57
57
  render(
58
58
  <ThemeProvider theme={theme}>
59
- <Link href="#!" className="custom-class-name" title="link">
60
- link
59
+ <Link href="#!" className="custom-class-name">
60
+ Link
61
61
  </Link>
62
62
  </ThemeProvider>
63
63
  );
64
- const link = screen.getByTitle(/link/);
64
+ const link = screen.getByText(/Link/);
65
65
 
66
66
  expect(link.className).toMatch('custom-class-name');
67
67
  });
68
+
69
+ test('accepts other routing components', () => {
70
+ const RouterLink = React.forwardRef<
71
+ HTMLSpanElement,
72
+ { to: string; children?: React.ReactNode }
73
+ >(() => <span>I am a Router Link!</span>);
74
+
75
+ render(
76
+ <ThemeProvider theme={theme}>
77
+ <Link as={RouterLink} to="/Home">
78
+ Link
79
+ </Link>
80
+ </ThemeProvider>
81
+ );
82
+
83
+ const link = screen.getByText('I am a Router Link!');
84
+ expect(link).toBeTruthy();
85
+ });
86
+
87
+ test('a link can be disabled via aria attributes', () => {
88
+ render(
89
+ <ThemeProvider theme={theme}>
90
+ <Link href="#!" disabled={true}>
91
+ Link
92
+ </Link>
93
+ </ThemeProvider>
94
+ );
95
+ const link = screen.getByText(/Link/);
96
+ expect(link.getAttribute('aria-disabled')).toEqual('true');
97
+ });
package/src/Link/Link.tsx CHANGED
@@ -1,22 +1,42 @@
1
- import React from 'react';
2
- import { useStyles, system } from '@marigold/system';
1
+ import React, { useRef } from 'react';
2
+ import { useLink } from '@react-aria/link';
3
+ import { PolymorphicComponent, PolymorphicProps } from '@marigold/types';
3
4
 
4
- type LinkProps = {
5
- variant?: string;
6
- };
5
+ import { Text, TextOwnProps } from '../Text';
7
6
 
8
- export const Link = system<LinkProps, 'a'>(
9
- ({ variant = 'normal', children, className, ...props }) => {
10
- const classNames = useStyles(
11
- {
12
- variant: `link.${variant}`,
13
- },
14
- className
15
- );
16
- return (
17
- <a className={classNames} {...props}>
18
- {children}
19
- </a>
20
- );
21
- }
22
- );
7
+ // Theme Extension
8
+ // ---------------
9
+ export interface LinkThemeExtension<Value> {
10
+ link?: Value;
11
+ }
12
+
13
+ // Props
14
+ // ---------------
15
+ export type LinkOwnProps = { disabled?: boolean } & TextOwnProps;
16
+ export type LinkProps = PolymorphicProps<LinkOwnProps, 'a'>;
17
+
18
+ // Component
19
+ // ---------------
20
+ export const Link = (({
21
+ as = 'a',
22
+ variant = 'link',
23
+ children,
24
+ disabled,
25
+ ...props
26
+ }: LinkProps) => {
27
+ const ref = useRef<any>();
28
+ const { linkProps } = useLink(
29
+ {
30
+ ...props,
31
+ elementType: typeof as === 'string' ? as : 'span',
32
+ isDisabled: disabled,
33
+ },
34
+ ref
35
+ );
36
+
37
+ return (
38
+ <Text {...props} {...linkProps} as={as} variant={variant} ref={ref}>
39
+ {children}
40
+ </Text>
41
+ );
42
+ }) as PolymorphicComponent<LinkOwnProps, 'a'>;
@@ -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
+ };
@@ -1,15 +1,21 @@
1
1
  import React from 'react';
2
2
  import { render, screen } from '@testing-library/react';
3
3
  import { ThemeProvider } from '@marigold/system';
4
- import { Menu, MenuItem } from '@marigold/components';
4
+ import { Menu } from './Menu';
5
+ import { MenuItem } from '../MenuItem';
5
6
 
6
7
  const theme = {
7
- content: {
8
- menu: {
9
- padding: '4px',
8
+ space: {
9
+ none: 0,
10
+ small: 4,
11
+ medium: 8,
12
+ },
13
+ menu: {
14
+ default: {
15
+ padding: 'small',
10
16
  },
11
- options: {
12
- padding: '8px',
17
+ custom: {
18
+ padding: 'medium',
13
19
  },
14
20
  },
15
21
  };
@@ -30,7 +36,7 @@ test('supports default variant and themeSection', () => {
30
36
  test('accepts other variant than default', () => {
31
37
  render(
32
38
  <ThemeProvider theme={theme}>
33
- <Menu variant="options" title="menu" onClick={() => {}}>
39
+ <Menu variant="custom" title="menu" onClick={() => {}}>
34
40
  <MenuItem href="#">Home</MenuItem>
35
41
  </Menu>
36
42
  </ThemeProvider>