@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,50 @@
1
+ import React, { forwardRef, RefObject } from 'react';
2
+ import { FocusScope } from '@react-aria/focus';
3
+ import {
4
+ DismissButton,
5
+ OverlayContainer,
6
+ useModal,
7
+ useOverlay,
8
+ } from '@react-aria/overlays';
9
+ import { mergeProps } from '@react-aria/utils';
10
+
11
+ import { Box } from '../Box';
12
+
13
+ interface PopoverProps {
14
+ isOpen?: boolean;
15
+ onClose?: () => void;
16
+ ref?: React.Ref<HTMLDivElement>;
17
+ className?: string;
18
+ }
19
+
20
+ export const Popover: React.FC<PopoverProps> = forwardRef(
21
+ ({ children, className, isOpen, onClose, ...otherProps }, ref) => {
22
+ // Handle events that should cause the popup to close,
23
+ const { overlayProps } = useOverlay(
24
+ {
25
+ isOpen,
26
+ onClose,
27
+ shouldCloseOnBlur: true,
28
+ isDismissable: true,
29
+ },
30
+ ref as RefObject<HTMLElement>
31
+ );
32
+ // Hide content outside the modal from screen readers.
33
+ const { modalProps } = useModal();
34
+
35
+ return (
36
+ <OverlayContainer>
37
+ <FocusScope restoreFocus>
38
+ <Box
39
+ {...mergeProps(overlayProps, otherProps, modalProps)}
40
+ className={className}
41
+ ref={ref}
42
+ >
43
+ {children}
44
+ <DismissButton onDismiss={onClose} />
45
+ </Box>
46
+ </FocusScope>
47
+ </OverlayContainer>
48
+ );
49
+ }
50
+ );
@@ -0,0 +1,81 @@
1
+ import React from 'react';
2
+ import type { Meta, ComponentStory } from '@storybook/react';
3
+ import { Select } from './Select';
4
+ import { Item } from '@marigold/components';
5
+
6
+ export default {
7
+ title: 'Components/Select',
8
+ argTypes: {
9
+ label: {
10
+ control: {
11
+ type: 'text',
12
+ },
13
+ table: {
14
+ defaultValue: {
15
+ summary: 'Select label',
16
+ },
17
+ },
18
+ defaultValue: 'Favorite Color',
19
+ },
20
+ placeholder: {
21
+ control: {
22
+ type: 'text',
23
+ },
24
+ table: {
25
+ defaultValue: {
26
+ summary: 'Select an option',
27
+ },
28
+ },
29
+ },
30
+ disabled: {
31
+ control: {
32
+ type: 'boolean',
33
+ },
34
+ options: [true, false],
35
+ table: {
36
+ defaultValue: {
37
+ summary: false,
38
+ },
39
+ },
40
+ },
41
+ required: {
42
+ control: {
43
+ type: 'boolean',
44
+ },
45
+ options: [true, false],
46
+ table: {
47
+ defaultValue: {
48
+ summary: false,
49
+ },
50
+ },
51
+ },
52
+ error: {
53
+ control: {
54
+ type: 'boolean',
55
+ },
56
+ description: 'Error',
57
+ table: {
58
+ defaultValue: {
59
+ summary: false,
60
+ },
61
+ },
62
+ },
63
+ errorMessage: {
64
+ control: {
65
+ type: 'text',
66
+ },
67
+ description: 'Error Message',
68
+ },
69
+ width: {
70
+ control: 'number',
71
+ },
72
+ },
73
+ } as Meta;
74
+
75
+ export const Basic: ComponentStory<typeof Select> = args => (
76
+ <Select {...args}>
77
+ <Item>Red</Item>
78
+ <Item>Orange</Item>
79
+ <Item>Yellow</Item>
80
+ </Select>
81
+ );
@@ -1,81 +1,349 @@
1
1
  import React from 'react';
2
- import { render, screen } from '@testing-library/react';
3
- import { ThemeProvider } from '@marigold/system';
4
- import { Select } from '@marigold/components';
2
+ import { fireEvent, render, screen } from '@testing-library/react';
3
+ import userEvent from '@testing-library/user-event';
4
+
5
+ import { Item, MarigoldProvider, Section } from '..';
6
+ import { Select } from './Select';
5
7
 
6
8
  const theme = {
7
- form: {
9
+ colors: {
10
+ red: 'red',
11
+ },
12
+ fonts: {
13
+ body: 'Inter',
14
+ },
15
+ button: {
8
16
  select: {
9
- fontFamily: 'Inter',
17
+ fontFamily: 'body',
18
+ errorOpened: {
19
+ color: 'red',
20
+ },
10
21
  },
11
- other: {
12
- fontFamily: 'Oswald',
22
+ },
23
+ label: {
24
+ above: {
25
+ fontSize: '8px',
26
+ },
27
+ inline: {
28
+ fontSize: '14px',
13
29
  },
14
30
  },
15
31
  };
16
32
 
17
- test('supports default variant and themeSection', () => {
33
+ test('supports button select variant', () => {
18
34
  render(
19
- <ThemeProvider theme={theme}>
20
- <Select title="select">
21
- <option>1</option>
35
+ <MarigoldProvider theme={theme}>
36
+ <Select label="MyLabel" data-testid="selectId">
37
+ <Item>1</Item>
22
38
  </Select>
23
- </ThemeProvider>
39
+ </MarigoldProvider>
24
40
  );
25
- const select = screen.getByTitle(/select/);
26
-
41
+ const select = screen.getByTestId('selectId');
42
+ expect(select).toBeDefined();
27
43
  expect(select).toHaveStyle(`font-family: Inter`);
28
44
  });
29
45
 
30
- test('accepts other variant than default', () => {
46
+ test('supports default labelVariant', () => {
31
47
  render(
32
- <ThemeProvider theme={theme}>
33
- <Select title="select" variant="other">
34
- <option>1</option>
48
+ <MarigoldProvider theme={theme}>
49
+ <Select label="MyLabel" data-testid="selectId">
50
+ <Item>1</Item>
35
51
  </Select>
36
- </ThemeProvider>
52
+ </MarigoldProvider>
37
53
  );
38
- const select = screen.getByTitle(/select/);
54
+ const label = screen.getAllByText('MyLabel');
55
+ expect(label[0]).toHaveStyle(`font-size: 8px`);
56
+ });
39
57
 
40
- expect(select).toHaveStyle(`font-family: Oswald`);
58
+ test('supports other labelVariant than default', () => {
59
+ render(
60
+ <MarigoldProvider theme={theme}>
61
+ <Select label="MyLabel" data-testid="selectId" labelVariant="inline">
62
+ <Item>1</Item>
63
+ </Select>
64
+ </MarigoldProvider>
65
+ );
66
+ const label = screen.getAllByText('MyLabel');
67
+ expect(label[0]).toHaveStyle(`font-size: 14px`);
41
68
  });
42
69
 
43
- test('renders correct HTML element', () => {
70
+ test('accepts custom styles prop className', () => {
44
71
  render(
45
- <ThemeProvider theme={theme}>
46
- <Select title="select">
47
- <option>1</option>
72
+ <MarigoldProvider theme={theme}>
73
+ <Select
74
+ label="MyLabel"
75
+ className="custom-class-name"
76
+ data-testid="selectId"
77
+ >
78
+ <Item>1</Item>
48
79
  </Select>
49
- </ThemeProvider>
80
+ </MarigoldProvider>
50
81
  );
51
- const select = screen.getByTitle(/select/);
82
+ const select = screen.getByTestId('selectId');
83
+ expect(select.className).toMatch('custom-class-name');
84
+ });
52
85
 
53
- expect(select instanceof HTMLSelectElement).toBeTruthy();
86
+ test('supports label with htmlFor prop', () => {
87
+ render(
88
+ <MarigoldProvider theme={theme}>
89
+ <Select label="MyLabel">
90
+ <Item>1</Item>
91
+ </Select>
92
+ </MarigoldProvider>
93
+ );
94
+ const selectLabel = screen.getAllByText(/MyLabel/);
95
+ expect(selectLabel[0]).toHaveAttribute('for');
54
96
  });
55
97
 
56
- test('variant styles cannot be overridden with CSS prop', () => {
98
+ test('supports disabled prop', () => {
57
99
  render(
58
- <ThemeProvider theme={theme}>
59
- <Select title="select" css={{ fontFamily: 'Oswald Regular' }}>
60
- <option>1</option>
100
+ <MarigoldProvider theme={theme}>
101
+ <Select label="MyLabel" data-testid="selectId" disabled>
102
+ <Item>1</Item>
61
103
  </Select>
62
- </ThemeProvider>
104
+ </MarigoldProvider>
63
105
  );
64
- const select = screen.getByTitle(/select/);
106
+ const select = screen.getByTestId('selectId');
107
+ expect(select).toHaveAttribute('disabled');
108
+ fireEvent.click(select);
109
+ expect(select).toHaveAttribute('aria-expanded', 'false');
110
+ });
65
111
 
66
- expect(select).not.toHaveStyle(`font-family: Oswald Regular`);
67
- expect(select).toHaveStyle(`font-family: Inter`);
112
+ test('supports placeholder prop', () => {
113
+ render(
114
+ <MarigoldProvider theme={theme}>
115
+ <Select label="MyLabel" placeholder="placeholder" data-testid="selectId">
116
+ <Item>1</Item>
117
+ </Select>
118
+ </MarigoldProvider>
119
+ );
120
+ const button = screen.getByTestId('selectId');
121
+ expect(button).toHaveTextContent(/placeholder/);
68
122
  });
69
123
 
70
- test('accepts custom styles prop className', () => {
124
+ test('supports required prop', () => {
71
125
  render(
72
- <ThemeProvider theme={theme}>
73
- <Select className="custom-class-name" title="select">
74
- <option>1</option>
126
+ <MarigoldProvider theme={theme}>
127
+ <Select label="MyLabel" required data-testid="selectId">
128
+ <Item>1</Item>
75
129
  </Select>
76
- </ThemeProvider>
130
+ </MarigoldProvider>
77
131
  );
78
- const select = screen.getByTitle(/select/);
132
+ const selectLabel = screen.getAllByText(/MyLabel/);
133
+ expect(selectLabel[0]).toContainHTML('path d="M10.8 3.84003');
134
+ });
79
135
 
80
- expect(select.className).toMatch('custom-class-name');
136
+ test('supports error and errorMessage prop', () => {
137
+ render(
138
+ <MarigoldProvider theme={theme}>
139
+ <Select label="MyLabel" error errorMessage="error" data-testid="selectId">
140
+ <Item>1</Item>
141
+ </Select>
142
+ </MarigoldProvider>
143
+ );
144
+ const validationMessage = screen.getAllByText(/error/);
145
+ expect(validationMessage).toBeDefined();
146
+ });
147
+
148
+ test('supports width prop', () => {
149
+ render(
150
+ <MarigoldProvider theme={theme}>
151
+ <Select label="MyLabel" width="120px" data-testid="selectId">
152
+ <Item>1</Item>
153
+ </Select>
154
+ </MarigoldProvider>
155
+ );
156
+ const select = screen.getByTestId('selectId');
157
+
158
+ expect(select.parentElement).toHaveStyle(`width: 120px`);
159
+ });
160
+
161
+ test('option list opens when element is clicked', () => {
162
+ render(
163
+ <MarigoldProvider theme={theme}>
164
+ <Select label="MyLabel" data-testid="selectId">
165
+ <Item>Red</Item>
166
+ </Select>
167
+ </MarigoldProvider>
168
+ );
169
+ const button = screen.getByTestId('selectId');
170
+ expect(button).toHaveAttribute('aria-expanded', 'false');
171
+
172
+ fireEvent.click(button);
173
+
174
+ // more than one item found because of the HiddenSelect component
175
+ const items = screen.getByRole('listbox');
176
+ expect(items).toBeVisible();
177
+ expect(button).toHaveAttribute('aria-expanded', 'true');
178
+ });
179
+
180
+ test('option list opens when element is clicked and theres an error', () => {
181
+ render(
182
+ <MarigoldProvider theme={theme}>
183
+ <Select label="MyLabel" error errorMessage="error" data-testid="selectId">
184
+ <Item>Red</Item>
185
+ </Select>
186
+ </MarigoldProvider>
187
+ );
188
+ const button = screen.getByTestId('selectId');
189
+ expect(button).toHaveAttribute('aria-expanded', 'false');
190
+
191
+ fireEvent.click(button);
192
+
193
+ const items = screen.getByRole('listbox');
194
+ expect(items).toBeVisible();
195
+ expect(button).toHaveAttribute('aria-expanded', 'true');
196
+ expect(button).toHaveStyle(`color: red`);
197
+ });
198
+
199
+ test('supports click and select an option', () => {
200
+ render(
201
+ <MarigoldProvider theme={theme}>
202
+ <Select label="MyLabel" data-testid="selectId">
203
+ <Item>Red</Item>
204
+ </Select>
205
+ </MarigoldProvider>
206
+ );
207
+ const button = screen.getByTestId('selectId');
208
+ expect(button).toHaveAttribute('aria-expanded', 'false');
209
+
210
+ fireEvent.click(button);
211
+ expect(button).toHaveAttribute('aria-expanded', 'true');
212
+ const items = screen.getAllByText(/Red/);
213
+ expect(items[1]).toBeVisible();
214
+ expect(items[1]).toHaveAttribute('aria-selected', 'false');
215
+
216
+ fireEvent.click(items[1]);
217
+ expect(button).toHaveTextContent('Red');
218
+
219
+ fireEvent.click(button);
220
+
221
+ // after selecting one item there are three elements with item text
222
+ const newItems = screen.getAllByText(/Red/);
223
+ expect(newItems[2]).toHaveAttribute('aria-selected', 'true');
224
+ });
225
+
226
+ test('popup closes after an option is selected', () => {
227
+ render(
228
+ <MarigoldProvider theme={theme}>
229
+ <Select label="MyLabel" data-testid="selectId">
230
+ <Item>Red</Item>
231
+ </Select>
232
+ </MarigoldProvider>
233
+ );
234
+ const button = screen.getByTestId('selectId');
235
+ expect(button).toHaveAttribute('aria-expanded', 'false');
236
+
237
+ fireEvent.click(button);
238
+ expect(button).toHaveAttribute('aria-expanded', 'true');
239
+ const items = screen.getAllByText(/Red/);
240
+ expect(items[1]).toBeVisible();
241
+
242
+ fireEvent.click(items[1]);
243
+ expect(button).toHaveTextContent('Red');
244
+ expect(items[1]).not.toBeVisible();
245
+ });
246
+
247
+ test('dismiss popup by clicking escape', () => {
248
+ render(
249
+ <MarigoldProvider theme={theme}>
250
+ <Select label="MyLabel" data-testid="selectId">
251
+ <Item>Red</Item>
252
+ </Select>
253
+ </MarigoldProvider>
254
+ );
255
+ const selectButton = screen.getByTestId('selectId');
256
+ fireEvent.click(selectButton);
257
+ expect(selectButton).toHaveAttribute('aria-expanded', 'true');
258
+ userEvent.type(selectButton, '{esc}');
259
+ expect(selectButton).toHaveAttribute('aria-expanded', 'false');
260
+ });
261
+
262
+ test('allow users to dismiss the popup with hidden dismiss button', () => {
263
+ render(
264
+ <MarigoldProvider theme={theme}>
265
+ <Select label="MyLabel" data-testid="selectId">
266
+ <Item>Red</Item>
267
+ </Select>
268
+ </MarigoldProvider>
269
+ );
270
+ const selectButton = screen.getByTestId('selectId');
271
+ fireEvent.click(selectButton);
272
+
273
+ const dismissButton = screen.getByLabelText(/Dismiss/);
274
+ expect(dismissButton).toBeDefined();
275
+
276
+ fireEvent.click(dismissButton);
277
+ expect(selectButton).toHaveAttribute('aria-expanded', 'false');
278
+ });
279
+
280
+ test('supports default selectedKey prop', () => {
281
+ render(
282
+ <MarigoldProvider theme={theme}>
283
+ <Select label="MyLabel" data-testid="selectId" defaultSelectedKey="Red">
284
+ <Item key="Red">Red</Item>
285
+ <Item key="Orange">Orange</Item>
286
+ </Select>
287
+ </MarigoldProvider>
288
+ );
289
+ const button = screen.getByTestId('selectId');
290
+ expect(button).toHaveTextContent('Red');
291
+ });
292
+
293
+ test('supports change default selectedKey', () => {
294
+ render(
295
+ <MarigoldProvider theme={theme}>
296
+ <Select label="MyLabel" data-testid="selectId" defaultSelectedKey="Red">
297
+ <Item key="Red">Red</Item>
298
+ <Item key="Orange">Orange</Item>
299
+ </Select>
300
+ </MarigoldProvider>
301
+ );
302
+ const button = screen.getByTestId('selectId');
303
+ expect(button).toHaveTextContent('Red');
304
+
305
+ fireEvent.click(button);
306
+ const items = screen.getAllByText(/Red/);
307
+ fireEvent.click(items[1]);
308
+
309
+ expect(button).toHaveTextContent('Red');
310
+ });
311
+
312
+ test('supports disabled item prop', () => {
313
+ render(
314
+ <MarigoldProvider theme={theme}>
315
+ <Select label="MyLabel" data-testid="selectId" disabledKeys={['Red']}>
316
+ <Item key="Red">Red</Item>
317
+ <Item key="Orange">Orange</Item>
318
+ </Select>
319
+ </MarigoldProvider>
320
+ );
321
+ const button = screen.getByTestId('selectId');
322
+ fireEvent.click(button);
323
+ const redItem = screen.getAllByText(/Red/);
324
+ fireEvent.click(redItem[1]);
325
+ expect(button).toHaveTextContent('Select an option');
326
+
327
+ const orangeItem = screen.getAllByText(/Orange/);
328
+ fireEvent.click(orangeItem[1]);
329
+ expect(button).toHaveTextContent('Orange');
330
+ });
331
+
332
+ test('supports section with items', () => {
333
+ render(
334
+ <MarigoldProvider theme={theme}>
335
+ <Select label="Section" data-testid="selectId">
336
+ <Section title="Color">
337
+ <Item>Red</Item>
338
+ </Section>
339
+ </Select>
340
+ </MarigoldProvider>
341
+ );
342
+ const button = screen.getByTestId('selectId');
343
+ fireEvent.click(button);
344
+
345
+ const items = screen.getAllByText(/Red/);
346
+ expect(items[1]).toBeVisible();
347
+ const sections = screen.getAllByText(/Color/);
348
+ expect(sections[0]).toBeVisible();
81
349
  });