@nuskin/foundation-ui-components 1.1.1 → 1.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 (44) hide show
  1. package/package.json +5 -5
  2. package/src/common/auth-dropdown/NsAuthDropdown.tsx +16 -7
  3. package/src/common/autocomplete/NsAutocomplete.spec.tsx +3 -3
  4. package/src/common/autocomplete/mock/MockData.ts +1 -0
  5. package/src/common/button/NsButton.stories.tsx +0 -1
  6. package/src/common/card/styled/NsFfgStyled.tsx +0 -1
  7. package/src/common/carousal/NsCarousal.tsx +9 -3
  8. package/src/common/cart-icon/NsCartIcon.spec.tsx +5 -4
  9. package/src/common/cart-icon/NsCartIcon.stories.tsx +1 -1
  10. package/src/common/cart-icon/NsCartIcon.tsx +1 -1
  11. package/src/common/cart-icon/types.d.ts +2 -2
  12. package/src/common/checkbox/types.d.ts +1 -1
  13. package/src/common/dropdown/NsDropdown.tsx +17 -8
  14. package/src/common/hooks/useOnClickOutside.tsx +28 -0
  15. package/src/common/icon/NsIcon.spec.tsx +11 -5
  16. package/src/common/icon/NsIconVariants.ts +3 -1
  17. package/src/common/icon/icons/AlertErrorIcon.tsx +2 -1
  18. package/src/common/icon/icons/ArrowLeft.tsx +2 -2
  19. package/src/common/icon/icons/ArrowRight.tsx +2 -2
  20. package/src/common/icon/icons/CartBadge.tsx +2 -2
  21. package/src/common/icon/icons/Check.tsx +25 -0
  22. package/src/common/icon/icons/CloseIcon.tsx +1 -1
  23. package/src/common/icon/icons/ErrorIcon.tsx +3 -2
  24. package/src/common/icon/icons/SearchIcon.tsx +3 -2
  25. package/src/common/icon/icons/SuccessIcon.tsx +7 -1
  26. package/src/common/icon/icons/TrashIcon.tsx +2 -1
  27. package/src/common/icon/icons/UserOutline.tsx +4 -1
  28. package/src/common/icon/icons/WarningIcon.tsx +3 -2
  29. package/src/common/index.ts +8 -4
  30. package/src/common/label/NsLabel.stories.tsx +0 -3
  31. package/src/common/label/NsLabel.tsx +1 -1
  32. package/src/common/progress/NsProgress.spec.tsx +47 -0
  33. package/src/common/progress/NsProgress.stories.tsx +37 -0
  34. package/src/common/progress/NsProgress.styled.tsx +39 -0
  35. package/src/common/progress/NsProgress.tsx +27 -0
  36. package/src/common/progress/index.ts +2 -0
  37. package/src/common/progress/types.d.ts +21 -0
  38. package/src/common/radiogroup/NsRadioGroup.styled.tsx +4 -3
  39. package/src/common/select/NsSelect.spec.tsx +98 -17
  40. package/src/common/select/NsSelect.styled.tsx +52 -22
  41. package/src/common/select/NsSelect.tsx +109 -44
  42. package/src/common/select/NsSelectOption.tsx +0 -1
  43. package/src/common/select/stories/NsSelect.stories.tsx +23 -14
  44. package/src/common/select/types.d.ts +3 -1
@@ -16,7 +16,6 @@ export const Default: Story = {
16
16
  args: {
17
17
  children: 'Label',
18
18
  required: false,
19
- size: 16,
20
19
  },
21
20
  };
22
21
 
@@ -24,7 +23,6 @@ export const Optional: Story = {
24
23
  args: {
25
24
  children: 'Label',
26
25
  showOptional: true,
27
- size: 16,
28
26
  },
29
27
  };
30
28
 
@@ -33,6 +31,5 @@ export const Required: Story = {
33
31
  children: 'Label',
34
32
  showOptional: true,
35
33
  required: true,
36
- size: 16,
37
34
  },
38
35
  };
@@ -27,7 +27,7 @@ const StyledLabel = styled(FormLabel)<{ fontSize?: number; style?: CSSProperties
27
27
  const NsLabel = (props: NsLabelProps) => {
28
28
  const { required, showOptional, children, size } = props;
29
29
  return (
30
- <StyledLabel {...props} fontSize={size} required={required}>
30
+ <StyledLabel fontSize={size} {...props} required={required}>
31
31
  {children}
32
32
  {!required && showOptional ? <span className="optional-label">{' (Optional)'}</span> : null}
33
33
  </StyledLabel>
@@ -0,0 +1,47 @@
1
+ import { render, screen } from '@testing-library/react';
2
+ import React from 'react';
3
+ import Progress from './NsProgress';
4
+
5
+ describe(' NsProgress Component', () => {
6
+ test('should render Progress bar', () => {
7
+ render(<Progress color="primary" value={10}></Progress>);
8
+
9
+ const pbar = screen.getByRole('progressbar');
10
+
11
+ expect(pbar).toBeInTheDocument();
12
+ });
13
+
14
+ it('matches the height of the progress bar to the width of the container', () => {
15
+ // Define the props
16
+ const value = 50;
17
+
18
+ // Render the StyledProgress component with the value prop
19
+ const { container } = render(<Progress color="primary" value={value} />);
20
+
21
+ // Get the progress bar element
22
+ const progressBar = container.querySelector('.MuiLinearProgress-bar');
23
+
24
+ // Check if the progress bar element exists
25
+ if (progressBar) {
26
+ // Retrieve the computed width of the container element
27
+ const containerWidth = container.clientWidth;
28
+
29
+ // Retrieve the computed styles of the progress bar
30
+ const progressBarStyle = getComputedStyle(progressBar);
31
+ const progressBarHeight = parseFloat(progressBarStyle.height);
32
+ const progressBarPadding =
33
+ parseFloat(progressBarStyle.paddingTop) + parseFloat(progressBarStyle.paddingBottom);
34
+ const progressBarBorder =
35
+ parseFloat(progressBarStyle.borderTopWidth) + parseFloat(progressBarStyle.borderBottomWidth);
36
+
37
+ // Calculate the expected height of the progress bar
38
+ const expectedHeight = containerWidth - progressBarPadding - progressBarBorder;
39
+
40
+ // Assert that the height of the progress bar matches the width of the container
41
+ expect(progressBarHeight).toBe(expectedHeight);
42
+ } else {
43
+ // Handle the case where the progress bar element is not found
44
+ throw new Error('Progress bar element not found');
45
+ }
46
+ });
47
+ });
@@ -0,0 +1,37 @@
1
+ import { withCenterDecorator } from '@/stories/decorators/withCenterDecorator';
2
+ import type { StoryObj, Meta } from '@storybook/react';
3
+ import NsProgress from './NsProgress';
4
+
5
+ type ComponentType = typeof NsProgress;
6
+ type Story = StoryObj<ComponentType>;
7
+ type MetaStory = Meta<ComponentType>;
8
+
9
+ export default {
10
+ component: NsProgress,
11
+ title: 'Input/NsProgress',
12
+ decorators: [withCenterDecorator],
13
+ argTypes: {
14
+ color: {
15
+ description: 'defines the color for the completed progress',
16
+ },
17
+ height: {
18
+ description: 'height of the bar',
19
+ },
20
+ value: {
21
+ description: 'value of the progress done',
22
+ },
23
+ backgroundColor: {
24
+ description: 'color of incomplete progress',
25
+ },
26
+ },
27
+ } as MetaStory;
28
+
29
+ export const ProgressBar: Story = {
30
+ args: {
31
+ color: 'primary',
32
+ backgroundColor: '#19dbdb',
33
+ value: undefined,
34
+ height: '10px',
35
+ body: <span>{'% Complete'}</span>,
36
+ },
37
+ };
@@ -0,0 +1,39 @@
1
+ import { styled, ColorUtils } from '@nuskin/foundation-theme';
2
+ import { LinearProgress } from '@mui/material';
3
+ import CheckCircleIcon from '@mui/icons-material/CheckCircle';
4
+ import { NsProgressProps } from './types';
5
+
6
+ const { color } = ColorUtils;
7
+ export const StyledCheckCircle = styled(CheckCircleIcon)`
8
+ color: ${color('neutral', '50')};
9
+ padding-top: 0.6em;
10
+ padding-right: 0.5em;
11
+ justify-self: flex-end;
12
+ `;
13
+
14
+ export const PercentDiv = styled('div')`
15
+ color: ${color('primary', '100')};
16
+ display: flex;
17
+ justify-content: flex-end;
18
+ font-family: Inter;
19
+ font-size: 12px;
20
+ font-style: normal;
21
+ font-weight: 700;
22
+ text-transform: uppercase;
23
+ `;
24
+
25
+ export const StyledLinearProgress = styled(LinearProgress)<Omit<NsProgressProps, 'value'>>(
26
+ ({ height, backgroundColor, color }) => ({
27
+ width: '334px',
28
+ height,
29
+ backgroundColor,
30
+ borderRadius: '3px',
31
+ display: 'inline-block',
32
+
33
+ '.MuiLinearProgress-bar': {
34
+ backgroundColor: color,
35
+ },
36
+ })
37
+ );
38
+
39
+ export default StyledLinearProgress;
@@ -0,0 +1,27 @@
1
+ import React from 'react';
2
+
3
+ import { NsProgressProps } from './types';
4
+ import StyledLinearProgress, { PercentDiv, StyledCheckCircle } from './NsProgress.styled';
5
+
6
+ const NsProgress = (props: NsProgressProps) => {
7
+ const { color, backgroundColor, height, value, body } = props;
8
+ return (
9
+ <>
10
+ <PercentDiv>
11
+ {value}
12
+ {body}
13
+ </PercentDiv>
14
+ <StyledLinearProgress
15
+ variant="determinate"
16
+ role="progressbar"
17
+ color={color}
18
+ value={value}
19
+ height={height}
20
+ backgroundColor={backgroundColor}
21
+ />
22
+ <StyledCheckCircle />
23
+ </>
24
+ );
25
+ };
26
+
27
+ export default NsProgress;
@@ -0,0 +1,2 @@
1
+ export { default as NsProgress } from './NsProgress';
2
+ export type { NsProgressProps } from './types.d';
@@ -0,0 +1,21 @@
1
+ import { FoundationTheme } from '@nuskin/foundation-theme';
2
+ import { ReactNode } from 'react';
3
+
4
+ declare module '@mui/material/LinearProgress' {
5
+ // eslint-disable-next-line no-unused-vars
6
+ interface LinearProgressPropsColorOverrides {
7
+ neutral: true;
8
+ accentColorA: true;
9
+ accentColorB: true;
10
+ accentColorC: true;
11
+ accentColorD: true;
12
+ }
13
+ }
14
+
15
+ export type NsProgressProps = {
16
+ color?: FoundationTheme.PaletteColors;
17
+ backgroundColor?: string;
18
+ height?: string;
19
+ value: number;
20
+ body?: ReactNode;
21
+ };
@@ -5,9 +5,10 @@ import { skipDarkModeEnabled } from '../util';
5
5
  const { paletteColor, isDarkMode, color } = ColorUtils;
6
6
 
7
7
  export const StyledHelperText = styled('div')`
8
- margin-top :10px;
9
- justify-self:flex-start;
10
- padding-left: 0.5em;
8
+ margin-top :10px;
9
+ padding-left: 0.5em;
10
+ text-align: left;
11
+ justify-self: flex-start;
11
12
  )`;
12
13
 
13
14
  export const StyledSpan = styled('span')`
@@ -8,7 +8,7 @@ function createSelectOptions(options: { value: string; label: string }[]) {
8
8
  }
9
9
 
10
10
  describe('NsSelectOption', () => {
11
- test('renders NsSelectOption component without errors', () => {
11
+ it('1. renders NsSelectOption component without errors', () => {
12
12
  const value = 'option1';
13
13
  const label = 'Option 1';
14
14
  const { getByTestId, getByText } = render(<NsSelectOption value={value} label={label} />);
@@ -21,7 +21,7 @@ describe('NsSelectOption', () => {
21
21
  const optionLabel = getByText(label);
22
22
  expect(optionLabel).toBeInTheDocument();
23
23
  });
24
- test('clicking on NsSelectOption selects the option', () => {
24
+ it('2. clicking on NsSelectOption selects the option', () => {
25
25
  const value = 'option1';
26
26
  const label = 'Option 1';
27
27
  const onSelect = jest.fn();
@@ -43,7 +43,7 @@ describe('NsSelect', () => {
43
43
  { value: 'Option3', label: 'Option 3' },
44
44
  ];
45
45
 
46
- it('renders the placeholder text when no value is selected', () => {
46
+ it('1. renders the placeholder text when no value is selected', () => {
47
47
  render(
48
48
  <NsSelect
49
49
  placeholder="Select an option"
@@ -58,9 +58,7 @@ describe('NsSelect', () => {
58
58
  expect(screen.getByText('Select an option')).toBeInTheDocument();
59
59
  });
60
60
 
61
- test('clicking outside the select container closes the dropdown', () => {
62
- // const value = 'option1';
63
- // const label = 'Option 1';
61
+ it('2. clicking outside the select container closes the dropdown', () => {
64
62
  const onSelect = jest.fn();
65
63
  const selectedLabel = 'Option 1';
66
64
  const { getByTestId, queryByTestId } = render(
@@ -74,7 +72,7 @@ describe('NsSelect', () => {
74
72
  expect(queryByTestId('option-Option1')).toBeNull();
75
73
  });
76
74
 
77
- it('renders the selected value label', () => {
75
+ it('3. renders the selected value label', () => {
78
76
  const selectedLabel = 'Option 1';
79
77
  render(
80
78
  <NsSelect selectedValue="Option1" selectedLabel={selectedLabel} onSelect={onSelect}>
@@ -85,7 +83,7 @@ describe('NsSelect', () => {
85
83
  expect(screen.getByText(selectedLabel)).toBeInTheDocument();
86
84
  });
87
85
 
88
- test('clicking on select button opens the dropdown', () => {
86
+ it('4. clicking on select button opens the dropdown', () => {
89
87
  const { getByTestId, getByText } = render(
90
88
  <NsSelect selectedValue="Option1" selectedLabel={selectedLabel} onSelect={onSelect}>
91
89
  {createSelectOptions(options)}
@@ -105,7 +103,7 @@ describe('NsSelect', () => {
105
103
  expect(option2).toBeInTheDocument();
106
104
  });
107
105
 
108
- test('disabling the select component prevents interaction', () => {
106
+ it('5. disabling the select component prevents interaction', () => {
109
107
  const onSelect = jest.fn();
110
108
  const { getByTestId, queryByTestId } = render(
111
109
  <NsSelect selectedValue="Option1" selectedLabel={selectedLabel} onSelect={onSelect} disabled>
@@ -124,7 +122,7 @@ describe('NsSelect', () => {
124
122
  expect(onSelect).not.toHaveBeenCalled();
125
123
  });
126
124
 
127
- it('select closes on mouse leave when closeOnMouseLeave is set to true', async () => {
125
+ it('6. select closes on mouse leave when closeOnMouseLeave is set to true', async () => {
128
126
  render(
129
127
  <NsSelect closeOnMouseLeave selectedValue={selectedValue} selectedLabel={selectedLabel} onSelect={onSelect}>
130
128
  {createSelectOptions(options)}
@@ -146,7 +144,7 @@ describe('NsSelect', () => {
146
144
  expect(option3).not.toBeInTheDocument();
147
145
  });
148
146
  });
149
- it('select does not open when disabled', () => {
147
+ it('7. select does not open when disabled', () => {
150
148
  render(
151
149
  <NsSelect selectedValue={selectedValue} selectedLabel={selectedLabel} onSelect={onSelect} disabled>
152
150
  {createSelectOptions(options)}
@@ -159,7 +157,7 @@ describe('NsSelect', () => {
159
157
  expect(screen.queryByTestId('select-list')).not.toBeInTheDocument();
160
158
  });
161
159
 
162
- it('opens the select on "ArrowDown" key press', () => {
160
+ it('8. opens the select on "ArrowDown" key press', () => {
163
161
  render(
164
162
  <NsSelect selectedValue={selectedValue} selectedLabel={selectedLabel} onSelect={onSelect}>
165
163
  {createSelectOptions(options)}
@@ -172,9 +170,77 @@ describe('NsSelect', () => {
172
170
  expect(selectHead).toBeInTheDocument();
173
171
  });
174
172
 
175
- test('renders SelectContainer with error styles when errorMessage is present', () => {
176
- const errorMessage = 'Invalid value';
173
+ it('9. closes the select when closeSelect is called', () => {
174
+ const { getByTestId } = render(
175
+ <NsSelect selectedValue={selectedValue} selectedLabel={selectedLabel} onSelect={onSelect} closeOnMouseLeave>
176
+ {createSelectOptions(options)}
177
+ </NsSelect>
178
+ );
179
+
180
+ const selectContainer = getByTestId('select-container');
181
+ fireEvent.mouseLeave(selectContainer);
182
+
183
+ expect(screen.queryByTestId('select-list')).not.toBeInTheDocument();
184
+ });
185
+
186
+ it('10. does not open the select when disabled', () => {
177
187
  render(
188
+ <NsSelect selectedValue={selectedValue} selectedLabel={selectedLabel} onSelect={onSelect} disabled>
189
+ {createSelectOptions(options)}
190
+ </NsSelect>
191
+ );
192
+
193
+ const selectHead = screen.getByTestId('select-head');
194
+ fireEvent.mouseDown(selectHead);
195
+
196
+ expect(screen.queryByTestId('select-list')).not.toBeInTheDocument();
197
+ });
198
+
199
+ it('11. selects the next option on arrow right click', () => {
200
+ // Render the NsSelect component with options and onSelect function
201
+ const onSelect = jest.fn();
202
+ const { getByTestId } = render(
203
+ <NsSelect selectedValue={selectedValue} selectedLabel={selectedLabel} onSelect={onSelect} hasArrows>
204
+ {createSelectOptions(options)}
205
+ </NsSelect>
206
+ );
207
+
208
+ // Simulate the arrow right click on the NsSelect component
209
+ const selectHead = getByTestId('select-head');
210
+ fireEvent.mouseDown(selectHead);
211
+
212
+ const rightArrow = document.getElementsByClassName('RightArrow')[0];
213
+ fireEvent.click(rightArrow);
214
+
215
+ // Verify that the next option is selected and the onSelect function is called
216
+ expect(onSelect).toHaveBeenCalledWith('Option1');
217
+ });
218
+
219
+ it('12. selects the previous option on arrow left click', () => {
220
+ const { getByTestId } = render(
221
+ <NsSelect
222
+ selectedValue={selectedValue}
223
+ selectedLabel={selectedLabel}
224
+ onSelect={onSelect}
225
+ hasArrows
226
+ reverseArrowControls
227
+ >
228
+ {createSelectOptions(options)}
229
+ </NsSelect>
230
+ );
231
+
232
+ const selectHead = getByTestId('select-head');
233
+ fireEvent.mouseDown(selectHead);
234
+
235
+ const leftArrow = document.getElementsByClassName('LeftArrow')[0];
236
+ fireEvent.click(leftArrow);
237
+
238
+ expect(onSelect).toHaveBeenCalledWith('Option1');
239
+ });
240
+
241
+ it('13. renders an error message with red styles', () => {
242
+ const errorMessage = 'Invalid value';
243
+ const { getByText } = render(
178
244
  <NsSelect
179
245
  selectedValue={selectedValue}
180
246
  selectedLabel={selectedLabel}
@@ -185,9 +251,24 @@ describe('NsSelect', () => {
185
251
  </NsSelect>
186
252
  );
187
253
 
188
- const selectContainer = screen.getByTestId('select-container');
254
+ // Check if the error message is rendered correctly with red styles
255
+ const errorText = getByText(errorMessage);
256
+ expect(errorText).toBeInTheDocument();
257
+ });
258
+ it('14. selecting an option calls the onSelect callback', () => {
259
+ const onSelect = jest.fn();
260
+ const { getByTestId } = render(
261
+ <NsSelect selectedValue={selectedValue} selectedLabel={selectedLabel} onSelect={onSelect}>
262
+ {createSelectOptions(options)}
263
+ </NsSelect>
264
+ );
265
+
266
+ const selectHead = getByTestId('select-head');
267
+ fireEvent.mouseDown(selectHead);
268
+
269
+ const option1 = getByTestId('option-Option1');
270
+ fireEvent.click(option1);
189
271
 
190
- expect(selectContainer).toHaveStyle('borderColor: red');
191
- expect(selectContainer).toHaveStyle('color: red');
272
+ expect(onSelect).toHaveBeenCalledWith('Option1');
192
273
  });
193
274
  });
@@ -1,12 +1,27 @@
1
+ import { HTMLAttributes } from 'react';
1
2
  import { styled, ColorUtils, FoundationTheme } from '@nuskin/foundation-theme';
2
3
  import { Themed } from '../common.types';
3
4
  import { getDropdownHeadBorder } from '../dropdown/NsDropdown.styled';
4
5
  const { color, paletteColor, isDarkMode } = ColorUtils;
5
6
 
6
- export const SelectContainer = styled.div<{ disabled: boolean }>`
7
+ interface SelectLabelProps extends HTMLAttributes<HTMLLabelElement> {
8
+ errorMessage?: string;
9
+ }
10
+
11
+ export const SelectContainer = styled.div<{ disabled: boolean; errorMessage?: string }>`
7
12
  position: relative;
8
13
  display: inline-block;
9
14
  opacity: ${({ disabled }) => (disabled ? '0.5' : '1')};
15
+ color: ${({ theme, errorMessage }) =>
16
+ errorMessage ? paletteColor('error')({ theme }) : paletteColor('primary')({ theme })};
17
+ `;
18
+ export const SelectMain = styled.div`
19
+ position: relative;
20
+ display: flex;
21
+ `;
22
+
23
+ export const ErrorContainer = styled.div`
24
+ color: ${paletteColor('error')};
10
25
  `;
11
26
 
12
27
  export const SelectHead = styled.div<{ type: string; disabled: boolean }>`
@@ -26,6 +41,18 @@ export const SelectButton = styled.div`
26
41
  padding-right: 10px;
27
42
  `;
28
43
 
44
+ export const LeftArrowContainer = styled.div`
45
+ display: flex;
46
+ align-items: center;
47
+ padding-top: 30px;
48
+ `;
49
+
50
+ export const RightArrowContainer = styled.div`
51
+ display: flex;
52
+ align-items: center;
53
+ padding-top: 30px;
54
+ `;
55
+
29
56
  export const SelectList = styled.div<{ borderColor: FoundationTheme.PaletteColors }>`
30
57
  position: absolute;
31
58
  z-index: 100;
@@ -33,18 +60,28 @@ export const SelectList = styled.div<{ borderColor: FoundationTheme.PaletteColor
33
60
  padding: 0;
34
61
  margin: 0;
35
62
  width: -webkit-fill-available;
36
- color: ${paletteColor('primary')};
63
+ color: ${paletteColor('primary', 'main')};
37
64
  background-color: ${paletteColor('primary', 'contrastText')};
65
+ max-height: 200px;
66
+ overflow-y: auto;
38
67
  `;
39
68
 
40
- const getDividerColor = (props: { theme: FoundationTheme.Theme }) => {
41
- return !isDarkMode(props) ? color('neutral', '30')(props) : color('neutral', '20')(props);
42
- };
43
-
44
- const getListBgColor = (props: { theme: FoundationTheme.Theme }) => {
69
+ const getDividerColor = ({ theme }: Themed) =>
70
+ isDarkMode({ theme }) ? color('neutral', '20')({ theme }) : color('neutral', '30')({ theme });
71
+ const getListBgColor = (props: Themed) => {
45
72
  return !isDarkMode(props) ? color('accentColorB', '10')(props) : color('accentColorB', '50')(props);
46
73
  };
47
74
  type ContainerParam = { borderBottom: string; bgColor: string; color: string; hoveredBg: string };
75
+
76
+ export const ListItemContainer = styled.div<{ showListDivider: boolean; isSelected: boolean }>`
77
+ ${({ showListDivider, isSelected, theme }) => {
78
+ const borderBottom = showListDivider ? getDividerColor({ theme }) : 'none';
79
+ const bgColor = isSelected ? paletteColor('primary')({ theme }) : 'white';
80
+ const color = isSelected ? 'white' : 'black';
81
+ const hoveredBg = getListBgColor({ theme });
82
+ return createListContainerStyle({ borderBottom, bgColor, color, hoveredBg });
83
+ }}
84
+ `;
48
85
  function createListContainerStyle({ borderBottom, bgColor, color, hoveredBg }: ContainerParam) {
49
86
  return `
50
87
  cursor: pointer;
@@ -62,15 +99,6 @@ function createListContainerStyle({ borderBottom, bgColor, color, hoveredBg }: C
62
99
  }
63
100
  `;
64
101
  }
65
- export const ListItemContainer = styled.div<{ showListDivider: boolean; isSelected: boolean }>`
66
- ${({ showListDivider, isSelected, theme }) => {
67
- const borderBottom = showListDivider ? getDividerColor({ theme }) : 'none';
68
- const bgColor = isSelected ? paletteColor('primary')({ theme }) : 'white';
69
- const color = isSelected ? 'white' : 'black';
70
- const hoveredBg = getListBgColor({ theme });
71
- return createListContainerStyle({ borderBottom, bgColor, color, hoveredBg });
72
- }}
73
- `;
74
102
  const getListItemBgColor = ({ isSelected, theme }: { isSelected: boolean } & Themed) => {
75
103
  if (isSelected) {
76
104
  return paletteColor('primary')({ theme });
@@ -86,6 +114,14 @@ const getListItemBorderLeftColor = ({ isSelected, theme }: { isSelected: boolean
86
114
  return 'none';
87
115
  };
88
116
 
117
+ export const SelectLabel = styled.label<SelectLabelProps>`
118
+ display: block;
119
+ margin-bottom: 5px;
120
+ color: ${({ theme, errorMessage }) =>
121
+ errorMessage ? paletteColor('error')({ theme }) : paletteColor('primary')({ theme })};
122
+ }
123
+ `;
124
+
89
125
  export const ListItem = styled.div<{ isSelected: boolean }>(({ isSelected, theme }) => ({
90
126
  padding: '5px 10px',
91
127
  borderLeft: getListItemBorderLeftColor({ isSelected, theme }),
@@ -96,9 +132,3 @@ export const ListItem = styled.div<{ isSelected: boolean }>(({ isSelected, theme
96
132
  fontWeight: 'bold',
97
133
  },
98
134
  }));
99
-
100
- export const SelectLabel = styled.label`
101
- display: block;
102
- margin-bottom: 5px;
103
- color: ${paletteColor('primary')} !important;
104
- `;