Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SelectField: extend to accept more data structures as children and to fix placeholder #796

Merged
merged 43 commits into from
Jan 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
b167dd8
trying to support and object for renderValue
vmilan Oct 6, 2023
9cb6aed
Merge branch 'master' into feature/extend-selectfield
vmilan Nov 6, 2023
ad201d6
fix object data handling
vmilan Nov 7, 2023
2e00bb0
fix icon styles and export multiple select field component
vmilan Nov 8, 2023
e934af8
export multiple select field component
vmilan Nov 8, 2023
d24bf77
remove placeholder passed twice
vmilan Nov 8, 2023
d3e7d6d
remove unneeded props
vmilan Nov 27, 2023
3ddac4e
trying different approach
vmilan Nov 27, 2023
ad88662
trying different approach: types
vmilan Nov 27, 2023
c43720b
export select field 2
vmilan Nov 27, 2023
0f49259
fix placeholder warning
vmilan Nov 27, 2023
ce5ee53
add aria label for helper text
vmilan Nov 27, 2023
dcdc533
remove unneeded proptype
vmilan Nov 27, 2023
aba4a8b
fix types
vmilan Nov 27, 2023
cac8a57
fix types
vmilan Nov 28, 2023
a79611d
Merge branch 'master' into feature/extend-selectfield
vmilan Nov 28, 2023
be1f98c
defaultRenderValue
vmilan Nov 29, 2023
7ed6456
tentative fix for renderValue
vmilan Nov 29, 2023
1a069bf
tentative fix for renderValue
vmilan Nov 29, 2023
a7dc144
attemp to fix renderValue
vmilan Nov 29, 2023
0531ca9
another way to buil placeholder
vmilan Nov 29, 2023
c57daf0
another way to buil placeholder
vmilan Nov 29, 2023
2e4d64c
add aria attributes
vmilan Nov 30, 2023
c5917b6
cleanup code
vmilan Dec 1, 2023
9454f55
Merge branch 'master' into feature/extend-selectfield
vmilan Dec 1, 2023
fff4d83
add missing prop
vmilan Dec 1, 2023
78fe391
add missing prop
vmilan Dec 1, 2023
9e61d9e
color for debug
vmilan Dec 1, 2023
81e586a
cleanup code
vmilan Dec 11, 2023
06b4d32
Merge branch 'master' into feature/extend-selectfield
vmilan Dec 11, 2023
0607d31
fix required prop
vmilan Dec 11, 2023
976bc8e
add prefix case to Storybook and fix Label styles
vmilan Dec 13, 2023
15a6b92
Merge branch 'master' into feature/extend-selectfield
vmilan Dec 15, 2023
fb50c3a
changelog description
vmilan Dec 15, 2023
42ea9a7
rollabck multiple selectfield export
vmilan Dec 15, 2023
aecf93a
fix selectfield types
vmilan Dec 19, 2023
1cdb07b
fix hover background
vmilan Dec 21, 2023
65f91ab
fix LabelWithIndicator for Design QA of SelectField
vmilan Dec 26, 2023
bb2159a
Merge branch 'master' into feature/extend-selectfield
vmilan Dec 26, 2023
d8bda60
Merge branch 'master' into feature/extend-selectfield
vmilan Jan 2, 2024
5039257
Merge branch 'master' into feature/extend-selectfield
vmilan Jan 2, 2024
1279f16
remove temporary background color
vmilan Jan 2, 2024
0283cb5
cleanup Label styles
vmilan Jan 3, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

## Not released

- SelectField: extend to accept more data structures as children and to fix placeholder [#796](https://github.com/CartoDB/carto-react/pull/796)

## 2.3

### 2.3.5 (2024-01-02)
Expand Down
13 changes: 9 additions & 4 deletions packages/react-ui/src/components/atoms/LabelWithIndicator.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
import React from 'react';
import PropTypes from 'prop-types';
import { styled } from '@mui/material/styles';
import { Box, styled } from '@mui/material';

import Typography from './Typography';

const Root = styled(Box)(({ theme }) => ({
display: 'flex',
alignItems: 'center',
gap: theme.spacing(0.5)
}));

const LabelIndicator = styled(Typography)(({ theme }) => ({
marginLeft: theme.spacing(0.5),
'.Mui-disabled &': {
color: theme.palette.text.disabled
}
Expand All @@ -15,7 +20,7 @@ const LabelWithIndicator = ({ label, type }) => {
const isRequired = type === 'required';

return (
<>
<Root>
{label}
<LabelIndicator
component='span'
Expand All @@ -25,7 +30,7 @@ const LabelWithIndicator = ({ label, type }) => {
>
{isRequired ? '(required)' : '(optional)'}
</LabelIndicator>
</>
</Root>
);
};

Expand Down
25 changes: 13 additions & 12 deletions packages/react-ui/src/components/atoms/SelectField.d.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
import { MenuProps } from '@mui/material';
import { SelectProps } from '@mui/material/Select';
import { TextFieldProps } from '@mui/material/TextField';
import React from 'react';
import { InputProps, MenuProps } from '@mui/material';
import { SelectProps } from '@mui/material/Select';

export type SelectFieldProps = Omit<TextFieldProps, 'placeholder'> &
Omit<SelectProps, 'placeholder'> & {
placeholder?: React.ReactNode;
size?: 'small' | 'medium';
selectProps?: Partial<SelectProps<unknown>>;
renderValue?: (value: string[]) => React.ReactNode;
menuProps?: Partial<MenuProps>;
};
export type SelectFieldProps<Value = unknown> = Omit<
SelectProps<Value>,
'placeholder'
> & {
placeholder?: React.ReactNode | string;
size?: 'small' | 'medium';
menuProps?: Partial<MenuProps>;
inputProps?: Partial<InputProps>;
helperText?: React.ReactNode | string;
};

declare const SelectField: (props: SelectFieldProps) => JSX.Element;
declare const SelectField: <Value>(props: SelectFieldProps<Value>) => JSX.Element;
export default SelectField;
138 changes: 91 additions & 47 deletions packages/react-ui/src/components/atoms/SelectField.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,55 @@
import React, { forwardRef } from 'react';
import React, { forwardRef, useState } from 'react';
import PropTypes from 'prop-types';
import { TextField } from '@mui/material';
import {
FormControl,
FormHelperText,
InputLabel,
MenuItem,
Select,
styled
} from '@mui/material';
import Typography from './Typography';
import uniqueId from 'lodash/uniqueId';

const StyledSelect = styled(Select)(({ theme }) => ({
'& .MuiInputAdornment-positionStart': {
paddingLeft: theme.spacing(2),

'&.MuiInputAdornment-sizeSmall': {
paddingLeft: theme.spacing(1.5)
}
},
'& .MuiInputBase-inputAdornedStart': {
paddingLeft: '0px !important'
},
'& .MuiSelect-select .MuiMenuItem-root:hover': {
backgroundColor: 'transparent'
}
}));

const PlaceholderItem = styled(MenuItem)(() => ({
display: 'none'
}));

const SelectField = forwardRef(
(
{
children,
onChange,
placeholder,
size,
multiple,
displayEmpty,
selectProps,
renderValue,
menuProps,
inputProps,
labelId,
label,
helperText,
name,
error,
focused,
disabled,
fullWidth,
required,
'aria-label': ariaLabel,
...otherProps
},
ref
Expand All @@ -24,40 +59,34 @@ const SelectField = forwardRef(

const isSmall = size === 'small';

const defaultRenderValue = React.useCallback(
(selected) => {
if (selected.length === 0) {
return (
<Typography
variant={isSmall ? 'body2' : 'body1'}
color='text.hint'
component='span'
noWrap
>
{placeholder}
</Typography>
);
}
return selected.join(', ');
},
[isSmall, placeholder]
);
// Accessibility attributes
const [defaultId] = useState(uniqueId('select-label-'));
const ariaLabelledBy = label ? labelId || defaultId : undefined;

return (
<TextField
{...otherProps}
select
onChange={onChange}
ref={ref}
<FormControl
size={size}
placeholder={placeholder}
SelectProps={{
...selectProps,
multiple: multiple,
displayEmpty: displayEmpty || !!placeholder,
size: size,
renderValue: renderValue || defaultRenderValue,
MenuProps: {
error={error}
focused={focused}
disabled={disabled}
fullWidth={fullWidth}
required={required}
>
{label && <InputLabel id={ariaLabelledBy}>{label}</InputLabel>}

<StyledSelect
{...otherProps}
labelId={ariaLabelledBy}
name={name}
ref={ref}
size={size}
fullWidth={fullWidth}
displayEmpty={displayEmpty || !!placeholder}
inputProps={{
...inputProps,
'aria-label': ariaLabel
}}
MenuProps={{
...menuProps,
anchorOrigin: {
vertical: 'bottom',
Expand All @@ -67,25 +96,40 @@ const SelectField = forwardRef(
vertical: -4,
horizontal: 'left'
}
}
}}
>
{children}
</TextField>
}}
>
{placeholder && (
<PlaceholderItem disabled value=''>
<Typography
variant={isSmall ? 'body2' : 'body1'}
color='text.hint'
component='span'
>
{placeholder}
</Typography>
</PlaceholderItem>
)}

{children}
</StyledSelect>

{helperText && (
<FormHelperText aria-label={`${name}-helper`}>{helperText}</FormHelperText>
)}
</FormControl>
);
}
);

SelectField.defaultProps = {
multiple: false,
size: 'small'
};
SelectField.propTypes = {
placeholder: PropTypes.string,
placeholder: PropTypes.oneOfType([PropTypes.string, PropTypes.element]),
size: PropTypes.oneOf(['small', 'medium']),
selectProps: PropTypes.object,
renderValue: PropTypes.func,
menuProps: PropTypes.object
menuProps: PropTypes.object,
inputProps: PropTypes.object,
helperText: PropTypes.oneOfType([PropTypes.string, PropTypes.element])
};

export default SelectField;
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, { useState } from 'react';
import MultipleSelectField from '../../../src/components/atoms/MultipleSelectField';
import { DocContainer, DocHighlight, DocLink } from '../../utils/storyStyles';
import { DocContainer, DocHighlight } from '../../utils/storyStyles';
import Typography from '../../../src/components/atoms/Typography';

const options = {
Expand Down
Loading