@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,20 +1,27 @@
1
1
  import React from 'react';
2
2
  import { render, screen } from '@testing-library/react';
3
+ import { ThemeProvider } from '@marigold/system';
4
+
3
5
  import { Text } from './Text';
4
- import { ThemeProvider, useStyles } from '@marigold/system';
5
6
 
6
7
  const theme = {
8
+ colors: {
9
+ primary: 'hotpink',
10
+ black: '#000',
11
+ white: '#FFF',
12
+ blue: '#2980b9',
13
+ },
7
14
  text: {
8
15
  body: {
9
16
  fontFamily: 'Oswald Regular',
10
17
  },
11
- heading: {
18
+ headline1: {
12
19
  fontFamily: 'Inter',
13
20
  },
14
21
  },
15
22
  };
16
23
 
17
- test('accepts default variant', () => {
24
+ test('uses `text.body` as default variant', () => {
18
25
  render(
19
26
  <ThemeProvider theme={theme}>
20
27
  <Text>text</Text>
@@ -25,70 +32,68 @@ test('accepts default variant', () => {
25
32
  expect(text).toHaveStyle(`font-family: Oswald Regular`);
26
33
  });
27
34
 
28
- test('accepts default <span>', () => {
35
+ test('allows to change variants via `variant` prop (with "text" prefix)', () => {
29
36
  render(
30
37
  <ThemeProvider theme={theme}>
31
- <Text>text</Text>
38
+ <Text variant="headline1">text</Text>
32
39
  </ThemeProvider>
33
40
  );
34
41
  const text = screen.getByText(/text/);
35
42
 
36
- expect(text instanceof HTMLSpanElement).toBeTruthy();
43
+ expect(text).toHaveStyle(`font-family: Inter`);
37
44
  });
38
45
 
39
- test('accepts as <p>', () => {
46
+ test('renders a <span> element by default', () => {
40
47
  render(
41
48
  <ThemeProvider theme={theme}>
42
- <Text as="p">text</Text>
49
+ <Text>text</Text>
43
50
  </ThemeProvider>
44
51
  );
45
52
  const text = screen.getByText(/text/);
46
53
 
47
- expect(text instanceof HTMLParagraphElement).toBeTruthy();
54
+ expect(text instanceof HTMLSpanElement).toBeTruthy();
48
55
  });
49
56
 
50
- test('variant works', () => {
57
+ test('allows to control the rendered element via the `as` prop', () => {
51
58
  render(
52
59
  <ThemeProvider theme={theme}>
53
- <Text variant="body">text</Text>
60
+ <Text as="p">text</Text>
54
61
  </ThemeProvider>
55
62
  );
56
63
  const text = screen.getByText(/text/);
57
64
 
58
- expect(text).toHaveStyle(`font-family: Oswald Regular`);
65
+ expect(text instanceof HTMLParagraphElement).toBeTruthy();
59
66
  });
60
67
 
61
- test('accepts other variant than default', () => {
68
+ test.each([
69
+ [{ color: 'primary' }, 'color: hotpink'],
70
+ [{ color: 'blue' }, 'color: #2980b9'],
71
+ [{ align: 'center' }, 'text-align: center'],
72
+ [{ cursor: 'pointer' }, 'cursor: pointer'],
73
+ [{ outline: 'dashed red' }, 'outline: dashed red'],
74
+ [{ userSelect: 'none' }, 'user-select: none'],
75
+ ])('test style prop %o', (...args) => {
76
+ const props = args.shift();
77
+
62
78
  render(
63
79
  <ThemeProvider theme={theme}>
64
- <Text variant="heading" textColor="#000">
65
- text
66
- </Text>
80
+ <Text {...props}>This is the Text!</Text>
67
81
  </ThemeProvider>
68
82
  );
69
- const text = screen.getByText(/text/);
70
83
 
71
- expect(text).toHaveStyle(`color: rgb(0,0,0)`);
72
- expect(text).toHaveStyle(`font-family: Inter`);
84
+ const box = screen.getByText('This is the Text!');
85
+ args.forEach((style: any) => {
86
+ expect(box).toHaveStyle(style);
87
+ });
73
88
  });
74
89
 
75
- test('accepts custom styles prop className', () => {
76
- const TestTextComponent: React.FC = ({ children, ...props }) => {
77
- const classNames = useStyles({ fontSize: '8px' });
78
- return (
79
- <Text className={classNames} {...props}>
80
- {children}
81
- </Text>
82
- );
83
- };
84
-
85
- const { getByText } = render(
86
- <ThemeProvider theme={theme}>
87
- <TestTextComponent>text</TestTextComponent>
88
- </ThemeProvider>
90
+ test('forwards ref', () => {
91
+ const ref = React.createRef<HTMLButtonElement>();
92
+ render(
93
+ <Text as="button" ref={ref}>
94
+ button
95
+ </Text>
89
96
  );
90
- const testelem = getByText('text');
91
- const text = getComputedStyle(testelem);
92
97
 
93
- expect(text.fontSize).toEqual('8px');
98
+ expect(ref.current instanceof HTMLButtonElement).toBeTruthy();
94
99
  });
package/src/Text/Text.tsx CHANGED
@@ -1,34 +1,60 @@
1
- import { useStyles, system } from '@marigold/system';
2
- import React from 'react';
1
+ import React, { forwardRef } from 'react';
2
+ import { ResponsiveStyleValue } from '@marigold/system';
3
+ import {
4
+ PolymorphicComponentWithRef,
5
+ PolymorphicPropsWithRef,
6
+ } from '@marigold/types';
3
7
 
4
- type TextProps = {
5
- as?: 'p' | 'span';
6
- variant?: 'body' | 'heading';
7
- textColor?: string;
8
- };
8
+ import { Box, BoxOwnProps } from '../Box';
9
9
 
10
- export const Text = system<TextProps, 'span'>(
11
- ({
12
- as = 'span',
13
- variant = 'body',
14
- textColor = 'inherit',
15
- className,
16
- children,
17
- ...props
18
- }) => {
19
- const classNames = useStyles(
10
+ // Theme Extension
11
+ // ---------------
12
+ export interface TextThemeExtension<Value> {
13
+ text?: {
14
+ [key: string]: Value;
15
+ };
16
+ }
17
+
18
+ // Props
19
+ // ---------------
20
+ export type TextOwnProps = {
21
+ align?: ResponsiveStyleValue<string>;
22
+ color?: ResponsiveStyleValue<string>;
23
+ cursor?: ResponsiveStyleValue<string>;
24
+ outline?: ResponsiveStyleValue<string>;
25
+ userSelect?: ResponsiveStyleValue<string>;
26
+ } & BoxOwnProps;
27
+
28
+ export type TextProps = PolymorphicPropsWithRef<TextOwnProps, 'span'>;
29
+
30
+ // Component
31
+ // ---------------
32
+ export const Text: PolymorphicComponentWithRef<TextOwnProps, 'span'> =
33
+ forwardRef(
34
+ (
20
35
  {
21
- variant: `text.${variant}`,
22
- color: textColor,
36
+ as = 'span',
37
+ variant = 'body',
38
+ children,
39
+ className,
40
+ align,
41
+ color,
42
+ cursor,
43
+ outline,
44
+ userSelect,
45
+ ...props
23
46
  },
24
- className
25
- );
26
- const Cmp = as;
27
-
28
- return (
29
- <Cmp className={classNames} {...props}>
47
+ ref
48
+ ) => (
49
+ <Box
50
+ {...props}
51
+ as={as}
52
+ variant={`text.${variant}`}
53
+ css={{ textAlign: align, color, cursor, outline, userSelect }}
54
+ className={className}
55
+ ref={ref}
56
+ >
30
57
  {children}
31
- </Cmp>
32
- );
33
- }
34
- );
58
+ </Box>
59
+ )
60
+ );
@@ -0,0 +1,64 @@
1
+ import React from 'react';
2
+ import type { Meta, ComponentStory } from '@storybook/react';
3
+ import { Textarea } from '.';
4
+
5
+ export default {
6
+ title: 'Components/Textarea',
7
+ argTypes: {
8
+ variant: {
9
+ control: {
10
+ type: 'text',
11
+ },
12
+ table: {
13
+ defaultValue: {
14
+ summary: '__default',
15
+ },
16
+ },
17
+ },
18
+ label: {
19
+ control: {
20
+ type: 'text',
21
+ },
22
+ description: 'Label text',
23
+ defaultValue: 'Textarea Label',
24
+ },
25
+ htmlFor: {
26
+ control: {
27
+ type: 'text',
28
+ },
29
+ description: 'Bind to label',
30
+ defaultValue: 'textareaId',
31
+ },
32
+ error: {
33
+ control: {
34
+ type: 'boolean',
35
+ },
36
+ description: 'Error',
37
+ table: {
38
+ defaultValue: {
39
+ summary: false,
40
+ },
41
+ },
42
+ },
43
+ errorMessage: {
44
+ control: {
45
+ type: 'text',
46
+ },
47
+ description: 'Error Message',
48
+ },
49
+ required: {
50
+ control: {
51
+ type: 'boolean',
52
+ },
53
+ table: {
54
+ defaultValue: {
55
+ summary: false,
56
+ },
57
+ },
58
+ },
59
+ },
60
+ } as Meta;
61
+
62
+ export const Basic: ComponentStory<typeof Textarea> = args => (
63
+ <Textarea placeholder="Placeholder..." {...args} />
64
+ );
@@ -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 { Textarea } from '@marigold/components';
4
+ import { Textarea } from '../Textarea';
5
5
 
6
6
  const theme = {
7
- form: {
8
- textarea: {
9
- fontFamily: 'Inter Regular',
7
+ fonts: {
8
+ body: 'Inter Regular',
9
+ fancy: 'Roboto',
10
+ },
11
+ textarea: {
12
+ __default: {
13
+ fontFamily: 'body',
10
14
  },
11
15
  textarea2: {
12
- fontFamily: 'Roboto',
16
+ fontFamily: 'fancy',
13
17
  },
14
18
  },
15
19
  };
@@ -47,6 +51,38 @@ test('renders correct HTML element', () => {
47
51
  expect(textarea instanceof HTMLTextAreaElement).toBeTruthy();
48
52
  });
49
53
 
54
+ test('supports label prop', () => {
55
+ render(
56
+ <ThemeProvider theme={theme}>
57
+ <Textarea label="test" htmlFor="myId" title="textarea" />
58
+ </ThemeProvider>
59
+ );
60
+ const textarea = screen.getByText(/test/);
61
+
62
+ expect(textarea instanceof HTMLLabelElement).toBeTruthy();
63
+ });
64
+
65
+ test('supports error and errorMessage prop', () => {
66
+ render(
67
+ <ThemeProvider theme={theme}>
68
+ <Textarea error errorMessage="error" label="label" title="textarea" />
69
+ </ThemeProvider>
70
+ );
71
+ const textarea = screen.getByText(/error/);
72
+ expect(textarea).toBeDefined();
73
+ });
74
+
75
+ test('supports required prop', () => {
76
+ render(
77
+ <ThemeProvider theme={theme}>
78
+ <Textarea label="test" htmlFor="myId" required title="textarea" />
79
+ </ThemeProvider>
80
+ );
81
+ const label = screen.getByText(/test/);
82
+
83
+ expect(label.nextSibling instanceof SVGElement).toBeTruthy();
84
+ });
85
+
50
86
  test('accepts custom styles prop className', () => {
51
87
  render(
52
88
  <ThemeProvider theme={theme}>
@@ -1,22 +1,62 @@
1
1
  import React from 'react';
2
- import { useStyles, system } from '@marigold/system';
2
+ import { Exclamation } from '@marigold/icons';
3
+ import { ComponentProps } from '@marigold/types';
3
4
 
4
- type TextareaProps = {
5
+ import { ValidationMessage } from '../ValidationMessage';
6
+ import { Label } from '../Label';
7
+ import { Box } from '../Box';
8
+
9
+ // Theme Extension
10
+ // ---------------
11
+ export interface TextareaThemeExtension<Value> {
12
+ textarea?: {
13
+ [key: string]: Value;
14
+ };
15
+ }
16
+
17
+ // Props
18
+ // ---------------
19
+ export type TextareaProps = {
5
20
  variant?: string;
6
- };
21
+ label?: string;
22
+ htmlFor?: string;
23
+ required?: boolean;
24
+ error?: boolean;
25
+ errorMessage?: string;
26
+ } & ComponentProps<'textarea'>;
7
27
 
8
- export const Textarea = system<TextareaProps, 'textarea'>(
9
- ({ variant = 'textarea', children, className, ...props }) => {
10
- const classNames = useStyles(
11
- {
12
- variant: `form.${variant}`,
13
- },
14
- className
15
- );
16
- return (
17
- <textarea className={classNames} {...props}>
18
- {children}
19
- </textarea>
20
- );
21
- }
28
+ // Component
29
+ // ---------------
30
+ export const Textarea: React.FC<TextareaProps> = ({
31
+ variant = '',
32
+ htmlFor = 'textarea',
33
+ label,
34
+ error,
35
+ errorMessage,
36
+ required,
37
+ className = '',
38
+ children,
39
+ ...props
40
+ }) => (
41
+ <Box>
42
+ {label && (
43
+ <Label htmlFor={htmlFor} required={required}>
44
+ {label}
45
+ </Label>
46
+ )}
47
+ <Box
48
+ as="textarea"
49
+ {...props}
50
+ display="block"
51
+ variant={`textarea.${variant}`}
52
+ css={{ outlineColor: error && 'error' }}
53
+ className={className}
54
+ />
55
+ {error && errorMessage && (
56
+ <ValidationMessage>
57
+ <Exclamation size={16} />
58
+ {errorMessage}
59
+ </ValidationMessage>
60
+ )}
61
+ </Box>
22
62
  );
@@ -0,0 +1,27 @@
1
+ import React from 'react';
2
+ import type { Meta, ComponentStory } from '@storybook/react';
3
+ import { ValidationMessage } from './ValidationMessage';
4
+ import { Exclamation } from '@marigold/icons';
5
+
6
+ export default {
7
+ title: 'Components/ValidationMessage',
8
+ argTypes: {
9
+ variant: {
10
+ control: {
11
+ type: 'text',
12
+ },
13
+ table: {
14
+ defaultValue: {
15
+ summary: 'error',
16
+ },
17
+ },
18
+ },
19
+ },
20
+ } as Meta;
21
+
22
+ export const Basic: ComponentStory<typeof ValidationMessage> = args => (
23
+ <ValidationMessage {...args}>
24
+ <Exclamation />
25
+ Validation message
26
+ </ValidationMessage>
27
+ );
@@ -1,15 +1,20 @@
1
1
  import React from 'react';
2
2
  import { render, screen } from '@testing-library/react';
3
3
  import { ThemeProvider } from '@marigold/system';
4
- import { ValidationMessage } from '@marigold/components';
4
+ import { ValidationMessage } from './ValidationMessage';
5
5
 
6
6
  const theme = {
7
+ space: {
8
+ none: 0,
9
+ small: 4,
10
+ medium: 8,
11
+ },
7
12
  validation: {
8
- negative: {
9
- alignItems: 'center',
13
+ error: {
14
+ p: 'medium',
10
15
  },
11
- danger: {
12
- alignItems: 'right',
16
+ warning: {
17
+ p: 'small',
13
18
  },
14
19
  },
15
20
  };
@@ -17,34 +22,34 @@ const theme = {
17
22
  test('supports default variant and themeSection', () => {
18
23
  render(
19
24
  <ThemeProvider theme={theme}>
20
- <ValidationMessage title="negative">negative</ValidationMessage>
25
+ <ValidationMessage title="error">error</ValidationMessage>
21
26
  </ThemeProvider>
22
27
  );
23
- const validation = screen.getByTitle(/negative/);
28
+ const validation = screen.getByTitle(/error/);
24
29
 
25
- expect(validation).toHaveStyle(`align-items: center`);
30
+ expect(validation).toHaveStyle(`padding: 8px`);
26
31
  });
27
32
 
28
33
  test('accepts other variant than default', () => {
29
34
  render(
30
35
  <ThemeProvider theme={theme}>
31
- <ValidationMessage title="danger" variant="danger">
32
- Danger
36
+ <ValidationMessage title="warning" variant="warning">
37
+ warning
33
38
  </ValidationMessage>
34
39
  </ThemeProvider>
35
40
  );
36
- const validation = screen.getByTitle(/danger/);
41
+ const validation = screen.getByTitle(/warning/);
37
42
 
38
- expect(validation).toHaveStyle(`align-items: right`);
43
+ expect(validation).toHaveStyle(`padding: 4px`);
39
44
  });
40
45
 
41
46
  test('renders correct HTML element', () => {
42
47
  render(
43
48
  <ThemeProvider theme={theme}>
44
- <ValidationMessage title="negative">negative</ValidationMessage>
49
+ <ValidationMessage title="error">error</ValidationMessage>
45
50
  </ThemeProvider>
46
51
  );
47
- const validation = screen.getByTitle(/negative/);
52
+ const validation = screen.getByTitle(/error/);
48
53
 
49
54
  expect(validation instanceof HTMLSpanElement).toBeTruthy();
50
55
  });
@@ -1,25 +1,40 @@
1
1
  import React from 'react';
2
- import { useStyles, system } from '@marigold/system';
2
+ import { ComponentProps } from '@marigold/types';
3
3
 
4
- type ValidationMessageProps = {
5
- variant?: string;
6
- };
4
+ import { Box } from '../Box';
7
5
 
8
- export const ValidationMessage = system<ValidationMessageProps, 'span'>(
9
- ({ variant = 'negative', children, className, ...props }) => {
10
- const classNames = useStyles(
11
- {
12
- variant: `validation.${variant}`,
13
- display: 'flex',
14
- alignItems: 'center',
15
- },
16
- className
17
- );
6
+ // Theme Extension
7
+ // ---------------
8
+ export interface ValidationMessageThemeExtension<Value> {
9
+ validation?: {
10
+ [key: string]: Value;
11
+ };
12
+ }
18
13
 
19
- return (
20
- <span className={classNames} {...props}>
21
- {children}
22
- </span>
23
- );
24
- }
25
- );
14
+ // Props
15
+ // ---------------
16
+ export type ValidationMessageProps = {
17
+ variant?: string;
18
+ } & ComponentProps<'span'>;
19
+
20
+ // Component
21
+ // ---------------
22
+ export const ValidationMessage: React.FC<ValidationMessageProps> = ({
23
+ variant = 'error',
24
+ children,
25
+ className,
26
+ ...props
27
+ }) => {
28
+ return (
29
+ <Box
30
+ as="span"
31
+ display="flex"
32
+ alignItems="center"
33
+ variant={`validation.${variant}`}
34
+ className={className}
35
+ {...props}
36
+ >
37
+ {children}
38
+ </Box>
39
+ );
40
+ };
@@ -0,0 +1,19 @@
1
+ import React from 'react';
2
+ import type { Meta, ComponentStory } from '@storybook/react';
3
+
4
+ import { VisuallyHidden } from './VisuallyHidden';
5
+ import { Text } from '../Text';
6
+
7
+ export default {
8
+ title: 'Components/Hidden',
9
+ } as Meta;
10
+
11
+ export const Basic: ComponentStory<typeof VisuallyHidden> = ({
12
+ children,
13
+ ...args
14
+ }) => (
15
+ <>
16
+ <Text>The Text below is visually hidden</Text>
17
+ <VisuallyHidden {...args}>Invisible!</VisuallyHidden>
18
+ </>
19
+ );
@@ -0,0 +1,10 @@
1
+ import React from 'react';
2
+ import { render, screen } from '@testing-library/react';
3
+ import { VisuallyHidden } from './VisuallyHidden';
4
+
5
+ test('is visually hidden', () => {
6
+ render(<VisuallyHidden>Default</VisuallyHidden>);
7
+ const hidden = screen.getByText('Default');
8
+
9
+ expect(hidden).toHaveStyle(`overflow: hidden`);
10
+ });
@@ -0,0 +1 @@
1
+ export { VisuallyHidden } from '@react-aria/visually-hidden';
@@ -0,0 +1 @@
1
+ export * from './VisuallyHidden';
package/src/index.ts CHANGED
@@ -1,26 +1,34 @@
1
1
  export * from './theme';
2
2
 
3
+ export * from './ActionGroup';
3
4
  export * from './Alert';
4
5
  export * from './Badge';
6
+ export * from './Box';
5
7
  export * from './Button';
8
+ export * from './Card';
6
9
  export * from './Checkbox';
7
10
  export * from './Column';
11
+ export * from './Columns';
12
+ export * from './Dialog';
8
13
  export * from './Divider';
9
14
  export * from './Field';
10
- export * from './Heading';
11
- export * from './Hidden';
15
+ export * from './VisuallyHidden';
12
16
  export * from './Image';
17
+ export * from './Inline';
13
18
  export * from './Label';
14
19
  export * from './Link';
15
20
  export * from './Menu';
16
21
  export * from './MenuItem';
17
22
  export * from './Message';
23
+ export * from './Provider';
18
24
  export * from './Radio';
19
25
  export * from './Slider';
20
26
  export * from './Select';
21
- export * from './Svg';
27
+ export * from './Stack';
22
28
  export * from './Text';
23
29
  export * from './Textarea';
24
30
  export * from './Input';
25
31
  export * from './Container';
26
32
  export * from './ValidationMessage';
33
+
34
+ export { Item, Section } from '@react-stately/collections';