@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,110 @@
1
+ import React from 'react';
2
+ import type { Meta, ComponentStory } from '@storybook/react';
3
+ import { Field } from './Field';
4
+
5
+ export default {
6
+ title: 'Components/Field',
7
+ argTypes: {
8
+ variant: {
9
+ control: {
10
+ type: 'text',
11
+ },
12
+ description: 'Field variant',
13
+ table: {
14
+ defaultValue: {
15
+ summary: '__default',
16
+ },
17
+ },
18
+ },
19
+ labelVariant: {
20
+ control: {
21
+ type: 'text',
22
+ },
23
+ description: 'Field label variant',
24
+ table: {
25
+ defaultValue: {
26
+ summary: 'above',
27
+ },
28
+ },
29
+ },
30
+ htmlFor: {
31
+ control: {
32
+ type: 'text',
33
+ },
34
+ defaultValue: 'id',
35
+ },
36
+ label: {
37
+ control: {
38
+ type: 'text',
39
+ },
40
+ defaultValue: 'Label',
41
+ },
42
+ error: {
43
+ control: {
44
+ type: 'boolean',
45
+ },
46
+ description: 'Error',
47
+ table: {
48
+ defaultValue: {
49
+ summary: false,
50
+ },
51
+ },
52
+ },
53
+ errorMessage: {
54
+ control: {
55
+ type: 'text',
56
+ },
57
+ description: 'Error Message',
58
+ },
59
+ required: {
60
+ control: {
61
+ type: 'boolean',
62
+ },
63
+ options: [true, false],
64
+ table: {
65
+ defaultValue: {
66
+ summary: false,
67
+ },
68
+ },
69
+ },
70
+ disabled: {
71
+ control: {
72
+ type: 'boolean',
73
+ },
74
+ options: [true, false],
75
+ table: {
76
+ defaultValue: {
77
+ summary: false,
78
+ },
79
+ },
80
+ },
81
+ type: {
82
+ control: {
83
+ type: 'select',
84
+ },
85
+ options: [
86
+ 'date',
87
+ 'datetime-local',
88
+ 'email',
89
+ 'month',
90
+ 'number',
91
+ 'password',
92
+ 'search',
93
+ 'tel',
94
+ 'text',
95
+ 'time',
96
+ 'time',
97
+ 'url',
98
+ 'week',
99
+ ],
100
+ defaultValue: 'text',
101
+ table: {
102
+ defaultValue: {
103
+ summary: 'text',
104
+ },
105
+ },
106
+ },
107
+ },
108
+ } as Meta;
109
+
110
+ export const Basic: ComponentStory<typeof Field> = args => <Field {...args} />;
@@ -1,21 +1,30 @@
1
1
  import React from 'react';
2
2
  import { render, screen } from '@testing-library/react';
3
3
  import { ThemeProvider } from '@marigold/system';
4
- import { Field } from '@marigold/components';
5
- import { useStyles } from '@marigold/system';
4
+ import { Field } from './Field';
6
5
 
7
6
  const theme = {
8
- form: {
9
- field: {
10
- padding: '4px',
7
+ space: {
8
+ none: 0,
9
+ small: 4,
10
+ medium: 8,
11
+ },
12
+ label: {
13
+ above: {
14
+ fontSize: '14px',
15
+ },
16
+ },
17
+ input: {
18
+ __default: {
19
+ padding: 'small',
11
20
  },
12
- inputField: {
13
- padding: '8px',
21
+ error: {
22
+ padding: 'medium',
14
23
  },
15
24
  },
16
25
  };
17
26
 
18
- test('supports default variant and themeSection', () => {
27
+ test('renders correct HTML element', () => {
19
28
  render(
20
29
  <ThemeProvider theme={theme}>
21
30
  <Field htmlFor="myId" label="label" />
@@ -23,29 +32,47 @@ test('supports default variant and themeSection', () => {
23
32
  );
24
33
  const field = screen.getByText(/label/);
25
34
 
26
- expect(field).toHaveStyle(`padding: 4px`);
35
+ expect(field instanceof HTMLLabelElement).toBeTruthy();
27
36
  });
28
37
 
29
- test('accepts other variant than default', () => {
38
+ test('supports default variant', () => {
30
39
  render(
31
40
  <ThemeProvider theme={theme}>
32
- <Field htmlFor="myId" label="inputField" variant="inputField" />
41
+ <Field htmlFor="myId" label="Name" data-testid="field" />
33
42
  </ThemeProvider>
34
43
  );
35
- const inputField = screen.getByText(/inputField/);
44
+ const field = screen.getByTestId(/field/);
45
+ expect(field).toHaveStyle(`padding: 4px`);
46
+ });
36
47
 
37
- expect(inputField).toHaveStyle(`padding: 8px`);
48
+ test('supports other variant than default', () => {
49
+ render(
50
+ <ThemeProvider theme={theme}>
51
+ <Field htmlFor="myId" label="Name" variant="error" data-testid="field" />
52
+ </ThemeProvider>
53
+ );
54
+ const field = screen.getByTestId(/field/);
55
+ expect(field).toHaveStyle(`padding: 8px`);
38
56
  });
39
57
 
40
- test('renders correct HTML element', () => {
58
+ test('supports default variantLabel', () => {
41
59
  render(
42
60
  <ThemeProvider theme={theme}>
43
- <Field htmlFor="myId" label="label" />
61
+ <Field htmlFor="myId" label="Name" />
44
62
  </ThemeProvider>
45
63
  );
46
- const field = screen.getByText(/label/);
64
+ const label = screen.getByText(/Name/);
65
+ expect(label).toHaveStyle(`font-size: 14px`);
66
+ });
47
67
 
48
- expect(field instanceof HTMLLabelElement).toBeTruthy();
68
+ test('supports other variantLabel than default', () => {
69
+ render(
70
+ <ThemeProvider theme={theme}>
71
+ <Field htmlFor="myId" label="Name" />
72
+ </ThemeProvider>
73
+ );
74
+ const label = screen.getByText(/Name/);
75
+ expect(label).toHaveStyle(`font-size: 14px`);
49
76
  });
50
77
 
51
78
  test('supports label prop', () => {
@@ -56,34 +83,48 @@ test('supports label prop', () => {
56
83
  });
57
84
 
58
85
  test('supports htmlFor prop', () => {
59
- render(<Field htmlFor="myId" label="Name" error="Validation error" />);
86
+ render(<Field htmlFor="myId" label="Name" />);
60
87
  const field = screen.getByText(/Name/);
61
88
 
62
89
  expect(field).toHaveAttribute('for');
63
90
  });
64
91
 
65
- test('supports error prop', () => {
66
- render(<Field htmlFor="myId" label="label" error="Validation error" />);
67
- const field = screen.getByText(/Validation/);
92
+ test('supports required prop', () => {
93
+ render(<Field htmlFor="myId" label="label" required />);
94
+ const fieldLabel = screen.getByText(/label/);
68
95
 
69
- expect(field).toBeDefined();
96
+ expect(fieldLabel.nextSibling).toBeDefined();
97
+ expect(fieldLabel.nextSibling instanceof SVGElement).toBeTruthy();
98
+ });
99
+
100
+ test('supports error and errorMessage prop', () => {
101
+ render(
102
+ <Field htmlFor="myId" label="label" error errorMessage="Validation error" />
103
+ );
104
+
105
+ const errorMessage = screen.getByText(/Validation/);
106
+ expect(errorMessage).toBeDefined();
107
+ });
108
+
109
+ test('supports disabled prop', () => {
110
+ render(<Field htmlFor="myId" label="label" disabled />);
111
+ const fieldLabel = screen.getByText(/label/);
112
+ expect(fieldLabel.nextSibling).toHaveAttribute('disabled');
70
113
  });
71
114
 
72
115
  test('accepts custom styles prop className', () => {
73
- const TestComponent: React.FC = ({ children, ...props }) => {
74
- const classNames = useStyles({ fontSize: '8px' });
75
- return (
76
- <Field htmlFor="myId" label="label" className={classNames} {...props} />
77
- );
78
- };
79
-
80
- const { getByText } = render(
116
+ render(
81
117
  <ThemeProvider theme={theme}>
82
- <TestComponent />
118
+ <Field
119
+ htmlFor="myId"
120
+ label="label"
121
+ className="custom-class-name"
122
+ title="field"
123
+ data-testid="field"
124
+ />
83
125
  </ThemeProvider>
84
126
  );
85
- const testelem = getByText('label');
86
- const field = getComputedStyle(testelem);
127
+ const field = screen.getByTestId(/field/);
87
128
 
88
- expect(field.fontSize).toEqual('8px');
129
+ expect(field.className).toMatch('custom-class-name');
89
130
  });
@@ -1,49 +1,56 @@
1
1
  import React from 'react';
2
- import { Input, Label, ValidationMessage } from '@marigold/components';
3
- import { useStyles, system } from '@marigold/system';
4
- import { Exclamation, Required } from '@marigold/icons';
5
- import b2bTheme from '@marigold/theme-b2b';
2
+ import { Exclamation } from '@marigold/icons';
3
+ import { ComponentProps } from '@marigold/types';
6
4
 
7
- type FieldProps = {
5
+ import { Input } from '../Input';
6
+ import { Label } from '../Label';
7
+ import { ValidationMessage } from '../ValidationMessage';
8
+
9
+ // Props
10
+ // ---------------
11
+ export type FieldProps = {
8
12
  variant?: string;
13
+ labelVariant?: string;
9
14
  htmlFor: string;
10
15
  label: string;
11
- error?: string;
12
- };
16
+ required?: boolean;
17
+ error?: boolean;
18
+ errorMessage?: string;
19
+ disabled?: boolean;
20
+ } & ComponentProps<'input'>;
13
21
 
14
- export const Field = system<FieldProps, 'input'>(
15
- ({
16
- variant = 'field',
17
- type = 'text',
18
- htmlFor,
19
- label,
20
- error,
21
- className = '',
22
- ...props
23
- }) => {
24
- const classNames = useStyles(
25
- {
26
- variant: `form.${variant}`,
27
- },
28
- className
29
- );
30
-
31
- return (
32
- <div>
33
- <Label htmlFor={htmlFor} className={classNames} {...props}>
34
- {label}
35
- {error ? <Required size={16} fill={b2bTheme.colors.red60} /> : ''}
36
- </Label>
37
- <Input type={type} id={htmlFor} />
38
- {error ? (
39
- <ValidationMessage>
40
- <Exclamation size={16} />
41
- {error}
42
- </ValidationMessage>
43
- ) : (
44
- ''
45
- )}
46
- </div>
47
- );
48
- }
49
- );
22
+ // Component
23
+ // ---------------
24
+ export const Field: React.FC<FieldProps> = ({
25
+ type = 'text',
26
+ variant = '',
27
+ labelVariant = 'above',
28
+ htmlFor,
29
+ label,
30
+ required,
31
+ error,
32
+ errorMessage,
33
+ disabled,
34
+ ...props
35
+ }) => {
36
+ return (
37
+ <>
38
+ <Label variant={labelVariant} htmlFor={htmlFor} required={required}>
39
+ {label}
40
+ </Label>
41
+ <Input
42
+ {...props}
43
+ type={type}
44
+ id={htmlFor}
45
+ disabled={disabled}
46
+ variant={variant}
47
+ />
48
+ {error && errorMessage && (
49
+ <ValidationMessage>
50
+ <Exclamation size={16} />
51
+ {errorMessage}
52
+ </ValidationMessage>
53
+ )}
54
+ </>
55
+ );
56
+ };
@@ -0,0 +1,34 @@
1
+ import React from 'react';
2
+ import type { Meta, ComponentStory } from '@storybook/react';
3
+ import { Image } from './Image';
4
+
5
+ export default {
6
+ title: 'Components/Image',
7
+ argTypes: {
8
+ variant: {
9
+ control: {
10
+ type: 'text',
11
+ },
12
+ description: 'there is only one variant',
13
+ table: {
14
+ defaultValue: {
15
+ summary: 'fullWidth',
16
+ },
17
+ },
18
+ },
19
+ alt: {
20
+ control: {
21
+ type: 'text',
22
+ },
23
+ description: 'Description text for screenreaders',
24
+ },
25
+ },
26
+ } as Meta;
27
+
28
+ export const Basic: ComponentStory<typeof Image> = args => (
29
+ <Image
30
+ src="https://www.reservix.net/_Resources/Persistent/0e8f5885125940fdb2bc2d54840f497782f56584/Reservix_Logo_dtp_web_rgb_font_black_180704.png"
31
+ alt="marigold_logo"
32
+ {...args}
33
+ />
34
+ );
@@ -1,11 +1,14 @@
1
1
  import React from 'react';
2
2
  import { render, screen } from '@testing-library/react';
3
3
  import { ThemeProvider } from '@marigold/system';
4
- import { Image } from '@marigold/components';
4
+ import { Image } from './Image';
5
5
 
6
6
  const theme = {
7
- content: {
8
- images: {
7
+ colors: {
8
+ primary: 'hotpink',
9
+ },
10
+ image: {
11
+ fullWidth: {
9
12
  alignItems: 'center',
10
13
  },
11
14
  logos: {
@@ -1,19 +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 ImageProps = {
5
+ // Theme Extension
6
+ // ---------------
7
+ export interface ImageThemeExtension<Value> {
8
+ image?: {
9
+ [key: string]: Value;
10
+ };
11
+ }
12
+
13
+ // Props
14
+ // ---------------
15
+ export type ImageProps = {
5
16
  variant?: string;
6
- alt?: string;
7
- };
17
+ children?: never;
18
+ } & ComponentProps<'img'>;
8
19
 
9
- export const Image = system<ImageProps, 'img'>(
10
- ({ variant = 'images', alt = '', className, ...props }) => {
11
- const classNames = useStyles(
12
- {
13
- variant: `content.${variant}`,
14
- },
15
- className
16
- );
17
- return <img className={classNames} alt={alt} {...props} />;
18
- }
19
- );
20
+ // Component
21
+ // ---------------
22
+ export const Image: React.FC<ImageProps> = ({
23
+ variant = 'fullWidth',
24
+ ...props
25
+ }) => <Box {...props} as="img" variant={`image.${variant}`} />;
@@ -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';