feat(core): add single select component
This commit is contained in:
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { Select } from '.';
|
||||
|
||||
export default {
|
||||
title: 'Select',
|
||||
component: Select,
|
||||
};
|
||||
|
||||
const SELECT_ITEMS = [
|
||||
{
|
||||
label: "test 1",
|
||||
value: "test_1"
|
||||
},
|
||||
{
|
||||
label: "test 2",
|
||||
value: "test_2"
|
||||
},
|
||||
{
|
||||
label: "test 3",
|
||||
value: "test_3"
|
||||
}
|
||||
]
|
||||
|
||||
export const Default = () => (
|
||||
<Select label="Default" items={SELECT_ITEMS} />
|
||||
);
|
||||
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import React, { useState } from 'react';
|
||||
import {
|
||||
createStyles,
|
||||
makeStyles,
|
||||
withStyles,
|
||||
Theme,
|
||||
} from '@material-ui/core/styles';
|
||||
|
||||
import {
|
||||
FormControl,
|
||||
InputLabel,
|
||||
Select,
|
||||
MenuItem,
|
||||
InputBase,
|
||||
} from '@material-ui/core';
|
||||
|
||||
import ClosedDropdown from './static/ClosedDropdown';
|
||||
import OpenedDropdown from './static/OpenedDropdown';
|
||||
|
||||
const BootstrapInput = withStyles((theme: Theme) =>
|
||||
createStyles({
|
||||
root: {
|
||||
'label + &': {
|
||||
marginTop: theme.spacing(3),
|
||||
},
|
||||
},
|
||||
input: {
|
||||
borderRadius: 4,
|
||||
position: 'relative',
|
||||
backgroundColor: theme.palette.background.paper,
|
||||
border: '1px solid #ced4da',
|
||||
fontSize: 16,
|
||||
padding: '10px 26px 10px 12px',
|
||||
transition: theme.transitions.create(['border-color', 'box-shadow']),
|
||||
fontFamily: 'Helvetica Neue',
|
||||
'&:focus': {
|
||||
background: theme.palette.background.paper,
|
||||
borderRadius: 4,
|
||||
},
|
||||
},
|
||||
}),
|
||||
)(InputBase);
|
||||
|
||||
const useStyles = makeStyles((theme: Theme) =>
|
||||
createStyles({
|
||||
formControl: {
|
||||
margin: theme.spacing(1),
|
||||
minWidth: 315,
|
||||
},
|
||||
label: {
|
||||
transform: 'initial',
|
||||
fontWeight: 'bold',
|
||||
fontSize: 14,
|
||||
fontFamily: theme.typography.fontFamily,
|
||||
color: theme.palette.text.primary,
|
||||
'&.Mui-focused': {
|
||||
color: theme.palette.text.primary,
|
||||
},
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
type Item = {
|
||||
label: string;
|
||||
value: string | number;
|
||||
};
|
||||
|
||||
type Props = {
|
||||
multiple?: boolean;
|
||||
items: Item[];
|
||||
label: string;
|
||||
};
|
||||
|
||||
export const SelectComponent = (props: Props) => {
|
||||
const { multiple, items, label } = props;
|
||||
const classes = useStyles();
|
||||
const [value, setValue] = useState('');
|
||||
const [isOpen, setOpening] = useState(true);
|
||||
|
||||
const handleChange = (event: React.ChangeEvent<{ value: unknown }>) => {
|
||||
setValue(event.target.value as string);
|
||||
};
|
||||
|
||||
return (
|
||||
<FormControl className={classes.formControl}>
|
||||
<InputLabel className={classes.label} disableAnimation id="select-label">
|
||||
{label}
|
||||
</InputLabel>
|
||||
<Select
|
||||
id="select"
|
||||
value={value}
|
||||
multiple={multiple}
|
||||
onChange={handleChange}
|
||||
onOpen={() => setOpening(false)}
|
||||
onClose={() => setOpening(true)}
|
||||
input={<BootstrapInput />}
|
||||
IconComponent={() => (
|
||||
isOpen ? <ClosedDropdown /> : <OpenedDropdown />
|
||||
)}
|
||||
MenuProps={{
|
||||
anchorOrigin: {
|
||||
vertical: 'bottom',
|
||||
horizontal: 'left',
|
||||
},
|
||||
transformOrigin: {
|
||||
vertical: 'top',
|
||||
horizontal: 'left',
|
||||
},
|
||||
getContentAnchorEl: null,
|
||||
}}
|
||||
>
|
||||
{items &&
|
||||
items.map(item => (
|
||||
<MenuItem key={item.value} value={item.value}>
|
||||
{item.label}
|
||||
</MenuItem>
|
||||
))}
|
||||
</Select>
|
||||
</FormControl>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
export { SelectComponent as Select } from './Select';
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import React from 'react';
|
||||
import { SvgIcon, makeStyles, createStyles } from '@material-ui/core';
|
||||
|
||||
const useStyles = makeStyles(() =>
|
||||
createStyles({
|
||||
icon: {
|
||||
position: 'absolute',
|
||||
right: '4px',
|
||||
pointerEvents: "none"
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
const ClosedDropdown = () => {
|
||||
const classes = useStyles();
|
||||
return (
|
||||
<SvgIcon
|
||||
className={classes.icon}
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path d="M7.5 8L6 9.5L12.0703 15.5703L18.1406 9.5L16.6406 8L12.0703 12.5703L7.5 8Z" fill="#616161"/>
|
||||
</SvgIcon>
|
||||
);
|
||||
};
|
||||
|
||||
export default ClosedDropdown;
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import React from 'react';
|
||||
import { SvgIcon, makeStyles, createStyles } from '@material-ui/core';
|
||||
|
||||
const useStyles = makeStyles(() =>
|
||||
createStyles({
|
||||
icon: {
|
||||
position: 'absolute',
|
||||
right: '4px',
|
||||
pointerEvents: 'none',
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
const OpenedDropdown = () => {
|
||||
const classes = useStyles();
|
||||
return (
|
||||
<SvgIcon
|
||||
className={classes.icon}
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path d="M16.5 16L18 14.5L11.9297 8.42969L5.85938 14.5L7.35938 16L11.9297 11.4297L16.5 16Z" fill="#616161"/>
|
||||
</SvgIcon>
|
||||
);
|
||||
};
|
||||
|
||||
export default OpenedDropdown;
|
||||
Reference in New Issue
Block a user