會有以下幾種狀態:
import React, { Fragment } from "react";
import isNumber from 'lodash/isNumber';
import styled from "styled-jss";
import propTypes from "prop-types";
import FromLabel from "../FromLabel";
import FormGroup from "../FormGroup";
import breakpoint from "../constant/breakpoint";
const StyledCheck = styled("label")({
position: "relative",
display: "flex",
paddingLeft: 30,
opacity: ({ disabled }) => disabled ? 0.5 : 1,
marginBottom: ({ theme }) => theme.getSpacing(1),
paddingRight: ({ theme }) => theme.getSpacing(1),
alignItems: "center",
"&:before": {
position: "absolute",
content: '""',
left: 0,
width: 8,
height: 8,
margin: ({ theme }) => theme.getSpacing(1),
border: ({ theme, checked }) =>
`5px solid ${checked ? theme.colors.primary : theme.colors.grey1}`,
},
[breakpoint.mediaLG]: {
marginBottom: ({ theme }) => theme.getSpacing(0),
},
});
const CheckItems = ({ items, name, disabled, onChange, values: currentValues }) => {
return items.map((item, index) => {
const itemValue = isNumber(item.value) ? item.value.toString() : item.value;
const checked = currentValues.includes(itemValue);
const ID = `${name}_${item.value}_${index}`;
return (
<Fragment key={`radios_${index}`}>
<StyledCheck htmlFor={ID} checked={checked} disabled={disabled}>
{item.label}
</StyledCheck>
<input
type='checkbox'
id={ID}
name={name}
value={item.value}
onChange={onChange}
checked={checked}
disabled={disabled}
style={{ display: "none" }}
/>
</Fragment>
);
});
};
const CheckGroup = ({
name,
items,
label,
values,
onChange,
required,
disabled,
...props
}) => {
return (
<FormGroup>
<FromLabel required={required}>{label}</FromLabel>
<CheckItems values={values} items={items} name={name} disabled={disabled} onChange={onChange} />
</FormGroup>
);
};
CheckGroup.propTypes = {
label: propTypes.string,
disabled: propTypes.bool,
items: propTypes.arrayOf(
propTypes.shape({
label: propTypes.string,
value: propTypes.oneOfType([propTypes.number, propTypes.string]),
})
),
values: propTypes.arrayOf(
propTypes.oneOfType([propTypes.number, propTypes.string])
),
onChange: propTypes.func,
};
CheckGroup.defaultProps = {
label: "",
items: [],
values: [],
disabled: false,
onChange: () => false,
};
export default CheckGroup;
import React, { Fragment, useState } from "react";
import theme from "../../lib/theme";
import FormControl from "../../lib/FormControl";
import ThemeProvider from "../../lib/ThemeProvider";
import CheckGroup from "../../lib/CheckGroup";
const CheckItems = [
{
label: "Radio 1",
value: 1,
},
{
label: "Radio 2",
value: 2,
},
{
label: "Radio 3",
value: 3,
},
];
const handleOnChange = (values, setValue) => ({ target: { value } }) => {
const newValues = values.includes(value)
? values.filter((selectedValue) => selectedValue !== value)
: [value, ...values];
setValue(newValues);
};
const Provider = (props) => {
return <ThemeProvider theme={theme}>{props.children}</ThemeProvider>;
};
const TemplateForm = (args) => {
const [values, setValues] = useState([]);
const onChange = handleOnChange(values, setValues);
return (
<Provider>
<Fragment>
<FormControl>
<CheckGroup {...args} values={values} onChange={onChange} />
<CheckGroup {...args} name='disabledTest' values={values} onChange={onChange} disabled/>
</FormControl>
</Fragment>
</Provider>
);
};
const Template = (args) => {
const [values, setValues] = useState([]);
const onChange = handleOnChange(values, setValues);
return (
<Provider>
<Fragment>
<FormControl>
<CheckGroup {...args} values={values} onChange={onChange} />
</FormControl>
</Fragment>
</Provider>
);
};
export const Default = TemplateForm.bind({});
Default.args = {
name: "username",
items: CheckItems,
};
export const LabelCheck = Template.bind({});
LabelCheck.args = {
name: "labelItems",
items: CheckItems,
label: "label",
required: true,
};
// 你的頁面標題
export default {
component: CheckGroup,
title: "Form/Check",
};
結果如下:
import React, { Fragment } from "react";
import styled from "styled-jss";
import propTypes from "prop-types";
import FromLabel from "../FromLabel";
import FormGroup from "../FormGroup";
import breakpoint from "../constant/breakpoint";
const StyledRadio = styled("label")({
position: "relative",
display: "flex",
paddingLeft: 30,
opacity: ({ disabled }) => disabled ? 0.5:1,
marginBottom: ({ theme }) => theme.getSpacing(1),
paddingRight: ({ theme }) => theme.getSpacing(1),
alignItems: "center",
"&:before": {
position: "absolute",
content: '""',
left: 0,
width: 8,
height: 8,
borderRadius: 10,
margin: ({ theme }) => theme.getSpacing(1),
border: ({ theme, checked }) =>
`5px solid ${checked ? theme.colors.primary : theme.colors.grey1}`,
},
[breakpoint.mediaMD]: {
marginBottom: ({ theme }) => theme.getSpacing(0),
},
});
const RadioItems = ({
items,
name,
onChange,
disabled,
value: currentValue,
}) => {
return items.map((item, index) => {
const checked = currentValue === item.value;
const ID = `${name}_${item.value}_${index}`;
return (
<Fragment key={`radios_${index}`}>
<StyledRadio htmlFor={ID} checked={checked} disabled={disabled}>
{item.label}
</StyledRadio>
<input
type='radio'
id={ID}
name={name}
value={item.value}
onChange={onChange}
checked={checked}
disabled={disabled}
style={{ display: "none" }}
/>
</Fragment>
);
});
};
const RadioGroup = ({
name,
items,
label,
value,
onChange,
required,
disabled,
...props
}) => {
return (
<FormGroup>
<FromLabel required={required}>{label}</FromLabel>
<RadioItems
name={name}
value={value}
items={items}
onChange={onChange}
disabled={disabled}
/>
</FormGroup>
);
};
RadioGroup.propTypes = {
label: propTypes.string,
disabled: propTypes.bool,
items: propTypes.arrayOf(
propTypes.shape({
label: propTypes.string,
value: propTypes.oneOfType([propTypes.number, propTypes.string]),
})
),
value: propTypes.oneOfType([propTypes.number, propTypes.string]),
onChange: propTypes.func,
};
RadioGroup.defaultProps = {
label: "",
value: "",
items: [],
disabled: false,
onChange: () => false,
};
export default RadioGroup;
import React, { Fragment, useState } from "react";
import theme from "../../lib/theme";
import FormControl from "../../lib/FormControl";
import ThemeProvider from "../../lib/ThemeProvider";
import RadioGroup from '../../lib/RadioGroup';
const RadioItems = [
{
label: 'Radio 1',
value: 1
},
{
label: 'Radio 2',
value: 2
},
{
label: 'Radio 3',
value: 3
}
]
const handleOnChange = (setValue) => ({ target: { value }}) => {
setValue(parseInt(value, 10));
}
const Provider = (props) => {
return <ThemeProvider theme={theme}>{props.children}</ThemeProvider>;
};
const TemplateForm = (args) => {
const [value, setValue] = useState(1);
const onChange = handleOnChange(setValue);
return (
<Provider>
<Fragment>
<FormControl>
<RadioGroup {...args} value={value} onChange={onChange}/>
<RadioGroup {...args} disabled name='disableTest' value={value} onChange={onChange}/>
</FormControl>
</Fragment>
</Provider>
);
};
const Template = (args) => {
const [value, setValue] = useState(1);
const onChange = handleOnChange(setValue);
return (
<Provider>
<Fragment>
<FormControl>
<RadioGroup {...args} value={value} onChange={onChange}/>
</FormControl>
</Fragment>
</Provider>
);
};
export const Default = TemplateForm.bind({});
Default.args = {
name: 'username',
items: RadioItems
}
export const LabelRadio = Template.bind({});
LabelRadio.args = {
name: 'labelItems',
items: RadioItems,
label: 'label',
required: true,
}
// 你的頁面標題
export default {
component: RadioGroup,
title: "Form/Radio",
};
結果如下: