@marigold/components 0.0.3 → 0.3.1

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 +174 -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 +15 -3
  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 +5 -0
  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 +10 -6
  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 +17 -10
  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 +1075 -562
  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 +1012 -542
  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 +21 -2
  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 +81 -52
  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 +13 -5
  115. package/src/Divider/Divider.tsx +12 -0
  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 +51 -21
  134. package/src/Link/Link.tsx +39 -13
  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 +27 -32
  164. package/src/Text/Text.stories.tsx +61 -0
  165. package/src/Text/Text.test.tsx +41 -36
  166. package/src/Text/Text.tsx +56 -31
  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 -45
  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 -152
  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 -119
  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,57 @@
1
+ import React from 'react';
2
+ import type { Meta, ComponentStory } from '@storybook/react';
3
+ import { Stack } from './Stack';
4
+ import { Text } from '../Text';
5
+
6
+ export default {
7
+ title: 'Components/Stack',
8
+ argTypes: {
9
+ space: {
10
+ control: {
11
+ type: 'select',
12
+ },
13
+ options: [
14
+ 'none',
15
+ 'xxsmall',
16
+ 'xsmall',
17
+ 'small',
18
+ 'medium',
19
+ 'large',
20
+ 'xlarge',
21
+ 'xxlarge',
22
+ ],
23
+ description: 'Responsive Style Value',
24
+ table: {
25
+ defaultValue: {
26
+ summary: 'none',
27
+ },
28
+ },
29
+ },
30
+ align: {
31
+ control: {
32
+ type: 'select',
33
+ },
34
+ options: ['left', 'right', 'center'],
35
+ description: 'HTML element style',
36
+ table: {
37
+ defaultValue: {
38
+ summary: 'left',
39
+ },
40
+ },
41
+ },
42
+ },
43
+ } as Meta;
44
+
45
+ export const Basic: ComponentStory<typeof Stack> = args => (
46
+ <Stack {...args}>
47
+ <Text as="h2" variant="headline2">
48
+ Heading
49
+ </Text>
50
+ <Text>
51
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse
52
+ dignissim dapibus elit, vel egestas felis pharetra non. Cras malesuada,
53
+ massa nec ultricies efficitur, lectus ante consequat magna, a porttitor
54
+ massa ex ut quam.
55
+ </Text>
56
+ </Stack>
57
+ );
@@ -1,110 +1,138 @@
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 { Stack } from './Stack';
4
6
  import { Text } from '../Text';
5
7
 
6
- test('supports default space prop', () => {
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 getTopPadding = (element: HTMLElement) =>
20
+ getComputedStyle(element).getPropertyValue('padding-top');
21
+
22
+ test('default space is "none"', () => {
7
23
  render(
8
- <Stack title="stack">
9
- <Text>stack</Text>
10
- </Stack>
24
+ <ThemeProvider theme={theme}>
25
+ <Stack>
26
+ <Text>first</Text>
27
+ <Text>second</Text>
28
+ <Text>third</Text>
29
+ </Stack>
30
+ </ThemeProvider>
11
31
  );
12
- const stack = screen.getByTitle(/stack/);
32
+ const first = screen.getByText(/first/).parentElement!;
33
+ const second = screen.getByText(/second/).parentElement!;
34
+ const third = screen.getByText(/third/).parentElement!;
13
35
 
14
- expect(stack).toHaveStyle(`padding: 0px`);
36
+ expect(getTopPadding(first)).toEqual('');
37
+ expect(second).toHaveStyle(`padding-top: 0px`);
38
+ expect(third).toHaveStyle(`padding-top: 0px`);
15
39
  });
16
40
 
17
- test('supports custom space prop', () => {
41
+ test('accepts and uses spacing from theme', () => {
18
42
  render(
19
- <Stack space={2} title="stack">
20
- <Text>stack</Text>
21
- </Stack>
43
+ <ThemeProvider theme={theme}>
44
+ <Stack space="small">
45
+ <Text>first</Text>
46
+ <Text>second</Text>
47
+ <Text>third</Text>
48
+ </Stack>
49
+ </ThemeProvider>
22
50
  );
23
- const stack = screen.getByTitle(/stack/);
24
-
25
- expect(stack).toHaveStyle(`padding: 8px`);
26
- });
27
-
28
- test('supports default prop align: left', () => {
29
- render(<Stack title="stack">stack</Stack>);
30
- const stack = screen.getByText(/stack/);
51
+ const first = screen.getByText(/first/);
52
+ const second = screen.getByText(/second/);
53
+ const third = screen.getByText(/third/);
31
54
 
32
- expect(stack).toHaveStyle(`align-items: flex-start`);
55
+ expect(getTopPadding(first)).toEqual('');
56
+ expect(second.parentElement).toHaveStyle(`padding-top: 2px`);
57
+ expect(third.parentElement).toHaveStyle(`padding-top: 2px`);
33
58
  });
34
59
 
35
- test('supports custom prop align: center', () => {
60
+ test('aligns children left by default', () => {
36
61
  render(
37
- <Stack align="center" title="stack">
38
- stack
62
+ <Stack data-testid="stack">
63
+ <Text>first</Text>
39
64
  </Stack>
40
65
  );
41
- const stack = screen.getByText(/stack/);
66
+ const stack = screen.getByTestId('stack');
42
67
 
43
- expect(stack).toHaveStyle(`align-items: center`);
68
+ expect(stack).toHaveStyle(`align-items: flex-start`);
44
69
  });
45
70
 
46
- test('supports custom prop align: right', () => {
71
+ test('allows to aligns children to the center', () => {
47
72
  render(
48
- <Stack align="right" title="stack">
49
- stack
73
+ <Stack align="center" data-testid="stack">
74
+ <Text>first</Text>
50
75
  </Stack>
51
76
  );
52
- const stack = screen.getByText(/stack/);
77
+ const stack = screen.getByTestId('stack');
53
78
 
54
- expect(stack).toHaveStyle(`align-items: flex-end`);
79
+ expect(stack).toHaveStyle(`align-items: center`);
55
80
  });
56
81
 
57
- test('supports two children', () => {
82
+ test('allows to aligns children to the right', () => {
58
83
  render(
59
- <Stack title="stack">
60
- <Text>stackText</Text>
61
- <Text>secondStackText</Text>
84
+ <Stack align="right" data-testid="stack">
85
+ <Text>first</Text>
62
86
  </Stack>
63
87
  );
64
- const stack = screen.getByTitle(/stack/);
65
- const stackText = screen.getByText(/stackText/);
66
- const secondStackText = screen.getByText(/secondStackText/);
88
+ const stack = screen.getByTestId('stack');
67
89
 
68
- expect(stack).toBeDefined();
69
- expect(stackText).toBeDefined();
70
- expect(secondStackText).toBeDefined();
90
+ expect(stack).toHaveStyle(`align-items: flex-end`);
71
91
  });
72
92
 
73
- test('supports nested children', () => {
93
+ test('supports nesting', () => {
74
94
  render(
75
- <Stack title="stack">
76
- <Stack title="nested">
77
- <Text>text</Text>
95
+ <ThemeProvider theme={theme}>
96
+ <Stack space="large">
97
+ <Stack space="small" data-testid="upperStack">
98
+ <Text>first</Text>
99
+ <Text>second</Text>
100
+ </Stack>
101
+ <Stack space="small" data-testid="lowerStack">
102
+ <Text>third</Text>
103
+ <Text>fourth</Text>
104
+ </Stack>
78
105
  </Stack>
79
- </Stack>
106
+ </ThemeProvider>
80
107
  );
81
- const stack = screen.getByTitle(/stack/);
82
- const nested = screen.getByTitle(/nested/);
83
- const text = screen.getByText(/text/);
108
+ const first = screen.getByText(/first/);
109
+ const second = screen.getByText(/second/);
110
+ const upperStack = screen.getByTestId('upperStack');
84
111
 
85
- expect(stack).toBeDefined();
86
- expect(nested).toBeDefined();
87
- expect(text).toBeDefined();
88
- });
112
+ const third = screen.getByText(/third/);
113
+ const fourth = screen.getByText(/fourth/);
114
+ const lowerStack = screen.getByTestId('lowerStack');
89
115
 
90
- test('renders correct HTML element', () => {
91
- render(
92
- <Stack title="stack">
93
- <Text>sdf</Text>
94
- </Stack>
95
- );
96
- const stack = screen.getByTitle(/stack/);
116
+ expect(getTopPadding(upperStack.parentElement!)).toEqual('');
117
+ expect(lowerStack.parentElement).toHaveStyle(`padding-top: 8px`);
97
118
 
98
- expect(stack instanceof HTMLDivElement).toBeTruthy();
119
+ expect(getTopPadding(first.parentElement!)).toEqual('');
120
+ expect(second.parentElement).toHaveStyle(`padding-top: 2px`);
121
+
122
+ expect(getTopPadding(third.parentElement!)).toEqual('');
123
+ expect(fourth.parentElement).toHaveStyle(`padding-top: 2px`);
99
124
  });
100
125
 
101
- test('accepts custom styles prop className', () => {
126
+ test('renders as div per default', () => {
102
127
  render(
103
- <Stack className="custom-class-name" title="stack">
104
- <Text>text</Text>
105
- </Stack>
128
+ <ThemeProvider theme={theme}>
129
+ <Stack data-testid="stack">
130
+ <Text>first</Text>
131
+ <Text>second</Text>
132
+ </Stack>
133
+ </ThemeProvider>
106
134
  );
107
- const stack = screen.getByTitle(/stack/);
108
135
 
109
- expect(stack.className).toMatch('custom-class-name');
136
+ const stack = screen.getByTestId('stack');
137
+ expect(stack instanceof HTMLDivElement).toBeTruthy();
110
138
  });
@@ -1,44 +1,39 @@
1
1
  import React, { Children } from 'react';
2
+ import flattenChildren from 'react-keyed-flatten-children';
3
+
2
4
  import { ResponsiveStyleValue } from '@marigold/system';
5
+
3
6
  import { Box } from '../Box';
4
- import flattenChildren from 'react-keyed-flatten-children';
5
7
 
6
8
  export type StackProps = {
7
- className?: string;
8
- space?: ResponsiveStyleValue<number | string>;
9
+ space?: ResponsiveStyleValue<string>;
9
10
  align?: 'left' | 'right' | 'center';
10
- title?: string; // For Testing
11
+ };
12
+
13
+ const ALIGNMENT = {
14
+ left: 'flex-start',
15
+ center: 'center',
16
+ right: 'flex-end',
11
17
  };
12
18
 
13
19
  export const Stack: React.FC<StackProps> = ({
14
- space = 0,
20
+ space = 'none',
15
21
  align = 'left',
16
22
  children,
17
23
  ...props
18
- }) => {
19
- let stackItems = flattenChildren(children);
20
- let display = 'flex';
21
- let flexDirection = 'column';
22
- let alignItems = align === 'right' ? 'flex-end' : 'center';
23
- if (align === 'left') {
24
- display = 'block';
25
- flexDirection = 'row';
26
- alignItems = 'flex-start';
27
- }
28
-
29
- return (
30
- <Box p={space} display={display} flexDirection={flexDirection} {...props}>
31
- {Children.map(stackItems, (child, index) => (
32
- <Box
33
- display={display}
34
- flexDirection={flexDirection}
35
- alignItems={alignItems}
36
- pt={space}
37
- mt={index === 0 ? -space! : 0}
38
- >
39
- {child}
40
- </Box>
41
- ))}
42
- </Box>
43
- );
44
- };
24
+ }) => (
25
+ <Box
26
+ {...props}
27
+ display="flex"
28
+ flexDirection="column"
29
+ alignItems={ALIGNMENT[align]}
30
+ css={{ '> * + *': { pt: space } }}
31
+ >
32
+ {Children.map(
33
+ flattenChildren(children) as unknown as React.ReactElement,
34
+ (child: React.ReactElement) => (
35
+ <Box>{React.cloneElement(child, {}, child.props.children)}</Box>
36
+ )
37
+ )}
38
+ </Box>
39
+ );
@@ -0,0 +1,61 @@
1
+ import React from 'react';
2
+ import type { Meta, ComponentStory } from '@storybook/react';
3
+ import { Text } from './Text';
4
+
5
+ export default {
6
+ title: 'Components/Text',
7
+ argTypes: {
8
+ as: {
9
+ control: {
10
+ type: 'select',
11
+ },
12
+ options: ['span', 'p', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6'],
13
+ description: 'Set HTML element',
14
+ table: {
15
+ defaultValue: {
16
+ summary: 'span',
17
+ },
18
+ },
19
+ },
20
+ variant: {
21
+ control: {
22
+ type: 'select',
23
+ },
24
+ options: [
25
+ 'body',
26
+ 'headline1',
27
+ 'headline2',
28
+ 'headline3',
29
+ 'headline4',
30
+ 'headline5',
31
+ 'headline6',
32
+ ],
33
+ description: 'CHoose between body and different headlines',
34
+ table: {
35
+ defaultValue: {
36
+ summary: 'body',
37
+ },
38
+ },
39
+ },
40
+ color: {
41
+ control: {
42
+ type: 'text',
43
+ },
44
+ description: 'Text color',
45
+ table: {
46
+ defaultValue: {
47
+ summary: 'inherit',
48
+ },
49
+ },
50
+ },
51
+ },
52
+ } as Meta;
53
+
54
+ export const Basic: ComponentStory<typeof Text> = args => (
55
+ <Text {...args}>
56
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse
57
+ dignissim dapibus elit, vel egestas felis pharetra non. Cras malesuada,
58
+ massa nec ultricies efficitur, lectus ante consequat magna, a porttitor
59
+ massa ex ut quam.
60
+ </Text>
61
+ );
@@ -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({ css: { 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,35 +1,60 @@
1
- import React from 'react';
2
- import { useStyles } from '@marigold/system';
3
- import { ComponentPropsWithRef } from '@marigold/types';
4
- import { Box, BoxProps } from '../Box';
1
+ import React, { forwardRef } from 'react';
2
+ import { ResponsiveStyleValue } from '@marigold/system';
3
+ import {
4
+ PolymorphicComponentWithRef,
5
+ PolymorphicPropsWithRef,
6
+ } from '@marigold/types';
5
7
 
6
- export type TextProps = {
7
- className?: string;
8
- as?: 'p' | 'span' | 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6';
9
- variant?: string;
10
- textColor?: string;
11
- } & ComponentPropsWithRef<'span'> &
12
- BoxProps;
8
+ import { Box, BoxOwnProps } from '../Box';
13
9
 
14
- export const Text: React.FC<TextProps> = ({
15
- as = 'span',
16
- variant = 'body',
17
- textColor = 'inherit',
18
- className,
19
- children,
20
- ...props
21
- }) => {
22
- const classNames = useStyles({
23
- variant: `text.${variant}`,
24
- css: {
25
- color: textColor,
26
- },
27
- className,
28
- });
10
+ // Theme Extension
11
+ // ---------------
12
+ export interface TextThemeExtension<Value> {
13
+ text?: {
14
+ [key: string]: Value;
15
+ };
16
+ }
29
17
 
30
- return (
31
- <Box as={as} className={classNames} {...props}>
32
- {children}
33
- </Box>
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
+ (
35
+ {
36
+ as = 'span',
37
+ variant = 'body',
38
+ children,
39
+ className,
40
+ align,
41
+ color,
42
+ cursor,
43
+ outline,
44
+ userSelect,
45
+ ...props
46
+ },
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
+ >
57
+ {children}
58
+ </Box>
59
+ )
34
60
  );
35
- };
@@ -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
+ );