Skip to content

Commit dae67ef

Browse files
author
Dave Ferris
authored
Merge pull request #49 from user-interviews/feature/UIDS-48-consistent-select-heights
UIDS-48 Make select heights consistent with other input controls
2 parents 95caffa + 06769dd commit dae67ef

File tree

10 files changed

+138
-48
lines changed

10 files changed

+138
-48
lines changed

.eslintrc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@
1111
},
1212
{
1313
"files": [
14-
"src/**/*.{js,jsx}"
14+
"src/**/*.{js,jsx}",
15+
"spec/**/*.{js,jsx}"
1516
],
1617
"env": {
1718
"browser": true

spec/Select/AsyncSelect.test.jsx

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import React from 'react';
2+
import Async from 'react-select/async';
3+
import { create } from 'react-test-renderer';
4+
5+
import { AsyncSelect, SELECT_SIZES } from 'src/Select';
6+
7+
const renderAsync = (props) => create(
8+
<AsyncSelect loadOptions={jest.fn()} {...props} />,
9+
);
10+
11+
const getContentStyles = ({ styles }) => styles.control({}, { isDisabled: false });
12+
13+
describe('AsyncSelect', () => {
14+
test('size prop set to small will set height of select', () => {
15+
const { root } = renderAsync({ size: SELECT_SIZES.small });
16+
const { props } = root.findByType(Async);
17+
const contentStyles = getContentStyles(props);
18+
19+
expect(contentStyles.height).toBe('2.25rem');
20+
expect(contentStyles.minHeight).toBe('2.25rem');
21+
});
22+
23+
test('size prop set to null will not set height of select', () => {
24+
const { root } = renderAsync({ size: null });
25+
const { props } = root.findByType(Async);
26+
const contentStyles = getContentStyles(props);
27+
28+
expect(contentStyles).not.toContain('height');
29+
expect(contentStyles).not.toContain('minHeight');
30+
});
31+
});

spec/Select/SingleSelect.test.jsx

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import React from 'react';
2+
import Select from 'react-select';
3+
import { create } from 'react-test-renderer';
4+
5+
import { SingleSelect, SELECT_SIZES } from 'src/Select';
6+
7+
const renderSelect = (props) => create(
8+
<SingleSelect options={[]} onChange={jest.fn()} {...props} />,
9+
);
10+
11+
const getContentStyles = ({ styles }) => styles.control({}, { isDisabled: false });
12+
13+
describe('SingleSelect', () => {
14+
test('size prop set to small will set height of select', () => {
15+
const { root } = renderSelect({ size: SELECT_SIZES.small });
16+
const { props } = root.findByType(Select);
17+
const contentStyles = getContentStyles(props);
18+
19+
expect(contentStyles.height).toBe('2.25rem');
20+
expect(contentStyles.minHeight).toBe('2.25rem');
21+
});
22+
23+
test('size prop set to null will not set height of select', () => {
24+
const { root } = renderSelect({ size: null });
25+
const { props } = root.findByType(Select);
26+
const contentStyles = getContentStyles(props);
27+
28+
expect(contentStyles).not.toContain('height');
29+
expect(contentStyles).not.toContain('minHeight');
30+
});
31+
});

spec/__snapshots__/Storyshots.test.js.snap

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -782,7 +782,7 @@ exports[`Storyshots Design System/Selects/Async Default 1`] = `
782782
onKeyDown={[Function]}
783783
>
784784
<div
785-
className=" css-ou4jig-control"
785+
className=" css-qv254q-control"
786786
onMouseDown={[Function]}
787787
onTouchEnd={[Function]}
788788
>
@@ -904,7 +904,7 @@ exports[`Storyshots Design System/Selects/Async Labeled 1`] = `
904904
onKeyDown={[Function]}
905905
>
906906
<div
907-
className=" css-ou4jig-control"
907+
className=" css-qv254q-control"
908908
onMouseDown={[Function]}
909909
onTouchEnd={[Function]}
910910
>
@@ -1019,7 +1019,7 @@ exports[`Storyshots Design System/Selects/Single Default 1`] = `
10191019
onKeyDown={[Function]}
10201020
>
10211021
<div
1022-
className=" css-ou4jig-control"
1022+
className=" css-qv254q-control"
10231023
onMouseDown={[Function]}
10241024
onTouchEnd={[Function]}
10251025
>
@@ -1096,7 +1096,7 @@ exports[`Storyshots Design System/Selects/Single Labeled 1`] = `
10961096
onKeyDown={[Function]}
10971097
>
10981098
<div
1099-
className=" css-ou4jig-control"
1099+
className=" css-qv254q-control"
11001100
onMouseDown={[Function]}
11011101
onTouchEnd={[Function]}
11021102
>
@@ -1166,7 +1166,7 @@ exports[`Storyshots Design System/Selects/Single Loading 1`] = `
11661166
onKeyDown={[Function]}
11671167
>
11681168
<div
1169-
className=" css-ekx51g-control"
1169+
className=" css-1wkj6wz-control"
11701170
onMouseDown={[Function]}
11711171
onTouchEnd={[Function]}
11721172
>
@@ -1236,7 +1236,7 @@ exports[`Storyshots Design System/Selects/Single Searchable 1`] = `
12361236
onKeyDown={[Function]}
12371237
>
12381238
<div
1239-
className=" css-ou4jig-control"
1239+
className=" css-qv254q-control"
12401240
onMouseDown={[Function]}
12411241
onTouchEnd={[Function]}
12421242
>

src/FormGroup/FormGroup.scss

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,8 @@
2222
@include ui-remove-list-styles();
2323
}
2424
}
25+
26+
.form-control {
27+
height: 2.25rem;
28+
}
2529
}

src/Select/AsyncSelect.jsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import Async from 'react-select/async';
44

55
import zStack from 'src/Styles/zStack';
66

7-
import { defaultStyles, defaultTheme } from './styles';
7+
import { defaultStyles, defaultTheme, SELECT_SIZES } from './styles';
88

99
const AsyncSelect = ({
1010
'aria-label': ariaLabel,
@@ -24,6 +24,7 @@ const AsyncSelect = ({
2424
name,
2525
noOptionsMessage,
2626
placeholder,
27+
size,
2728
value,
2829

2930
onChange,
@@ -50,7 +51,7 @@ const AsyncSelect = ({
5051
placeholder={placeholder}
5152
shouldShowValue
5253
styles={{
53-
...defaultStyles,
54+
...defaultStyles({ size }),
5455
menuPortal: (base) => (
5556
modal ?
5657
base :
@@ -84,6 +85,7 @@ AsyncSelect.propTypes = {
8485
name: propTypes.string,
8586
noOptionsMessage: propTypes.func,
8687
placeholder: propTypes.string,
88+
size: propTypes.oneOf(Object.values(SELECT_SIZES)),
8789
value: propTypes.object,
8890

8991
onChange: propTypes.func,
@@ -106,6 +108,7 @@ AsyncSelect.defaultProps = {
106108
name: undefined,
107109
noOptionsMessage: undefined,
108110
placeholder: undefined,
111+
size: SELECT_SIZES.SMALL,
109112
value: undefined,
110113

111114
onChange: undefined,

src/Select/SingleSelect.jsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import propTypes from 'prop-types';
44

55
import zStack from 'src/Styles/zStack';
66

7-
import { defaultTheme, defaultStyles } from './styles';
7+
import { defaultTheme, defaultStyles, SELECT_SIZES } from './styles';
88

99
const SingleSelect = ({
1010
'aria-label': ariaLabel,
@@ -22,6 +22,7 @@ const SingleSelect = ({
2222
name,
2323
options,
2424
placeholder,
25+
size,
2526
value,
2627

2728
onChange,
@@ -44,7 +45,7 @@ const SingleSelect = ({
4445
options={options}
4546
placeholder={placeholder}
4647
styles={{
47-
...defaultStyles,
48+
...defaultStyles({ size }),
4849
menuPortal: (base) => (
4950
modal ?
5051
base :
@@ -74,6 +75,7 @@ SingleSelect.propTypes = {
7475
name: propTypes.string,
7576
options: propTypes.arrayOf(propTypes.object).isRequired,
7677
placeholder: propTypes.string,
78+
size: propTypes.oneOf(Object.values(SELECT_SIZES)),
7779
value: propTypes.object,
7880

7981
onChange: propTypes.func.isRequired,
@@ -94,6 +96,7 @@ SingleSelect.defaultProps = {
9496
modal: false,
9597
name: undefined,
9698
placeholder: undefined,
99+
size: SELECT_SIZES.SMALL,
97100
value: undefined,
98101
};
99102

src/Select/index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
import AsyncSelect from './AsyncSelect';
22
import SingleSelect from './SingleSelect';
3+
import { SELECT_SIZES } from './styles';
34

45
export {
56
AsyncSelect,
7+
SELECT_SIZES,
68
SingleSelect,
79
};

src/Select/styles.js

Lines changed: 50 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,60 @@
11
import systemColors from 'src/Styles/colors';
22

3+
export const SELECT_SIZES = { SMALL: 'small' };
4+
5+
const getHeightProps = (size) => {
6+
if (size === SELECT_SIZES.SMALL) {
7+
return {
8+
height: '2.25rem',
9+
minHeight: '2.25rem',
10+
};
11+
}
12+
return null;
13+
};
14+
315
/*
416
To set styles for your item, make sure your option object has a child `colors` object
517
with a text and/or hover key defined to override the defaults
618
*/
7-
const defaultStyles = {
8-
control: (styles, { isDisabled }) => ({
9-
...styles,
10-
backgroundColor: isDisabled ? systemColors.inputDisabledBg : styles.backgroundColor,
11-
borderColor: systemColors.inputBorderColor,
12-
}),
13-
indicatorSeparator: (styles) => ({ ...styles, display: 'none' }),
14-
singleValue: (styles, { data }) => ({
15-
...styles,
16-
color: (data.colors ? data.colors.text : systemColors.uxGray600) || systemColors.uxGray600,
17-
}),
18-
option: (styles, {
19-
data,
20-
isDisabled,
21-
isFocused,
22-
isSelected,
23-
}) => {
24-
const colors = data.colors || {};
25-
26-
return {
19+
const defaultStyles = ({ size }) => ({
20+
control: (styles, { isDisabled }) => ({
2721
...styles,
28-
backgroundColor: isSelected || isFocused ? colors.hover : styles.backgroundColor,
29-
color: colors.text,
30-
cursor: 'pointer',
31-
32-
':active': {
33-
...styles[':active'],
34-
backgroundColor:
35-
!isDisabled && isSelected ? systemColors.uxGray200 : styles[':active'].backgroundColor,
36-
},
37-
38-
':hover': {
39-
...styles[':hover'],
40-
backgroundColor: colors.hover || systemColors.uxGray200,
41-
},
42-
};
43-
},
44-
};
22+
...getHeightProps(size),
23+
backgroundColor: isDisabled ? systemColors.inputDisabledBg : styles.backgroundColor,
24+
borderColor: systemColors.inputBorderColor,
25+
}),
26+
indicatorSeparator: (styles) => ({ ...styles, display: 'none' }),
27+
singleValue: (styles, { data }) => ({
28+
...styles,
29+
color: (data.colors ? data.colors.text : systemColors.uxGray600) || systemColors.uxGray600,
30+
}),
31+
option: (styles, {
32+
data,
33+
isDisabled,
34+
isFocused,
35+
isSelected,
36+
}) => {
37+
const colors = data.colors || {};
38+
39+
return {
40+
...styles,
41+
backgroundColor: isSelected || isFocused ? colors.hover : styles.backgroundColor,
42+
color: colors.text,
43+
cursor: 'pointer',
44+
45+
':active': {
46+
...styles[':active'],
47+
backgroundColor:
48+
!isDisabled && isSelected ? systemColors.uxGray200 : styles[':active'].backgroundColor,
49+
},
50+
51+
':hover': {
52+
...styles[':hover'],
53+
backgroundColor: colors.hover || systemColors.uxGray200,
54+
},
55+
};
56+
},
57+
});
4558

4659
const defaultTheme = (theme) => ({
4760
...theme,

src/index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import RadioButton from 'src/RadioButton';
1919
import RadioButtonGroup from 'src/RadioButtonGroup';
2020
import {
2121
AsyncSelect,
22+
SELECT_SIZES,
2223
SingleSelect,
2324
} from 'src/Select';
2425
import TrackedButton from 'src/TrackedButton';
@@ -39,6 +40,7 @@ export {
3940
Popper,
4041
RadioButton,
4142
RadioButtonGroup,
43+
SELECT_SIZES,
4244
SingleSelect,
4345
TrackedButton,
4446
useFlash,

0 commit comments

Comments
 (0)