Skip to content

Commit 798b95e

Browse files
montezumekodiakhq[bot]
authored andcommitted
feat(checkbox-input): support isReadOnly prop (#1157)
* feat(checkbox-input): support isReadOnly prop * chore: readme
1 parent 24e40d1 commit 798b95e

8 files changed

+100
-44
lines changed

src/components/field-label/README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ The `hintIcon` also accepts a custom `color` while defaulting to `warning` in th
5555
| `hint` | `string` or `node` | - | - | - | Hint for the label. Provides a supplementary but important information regarding the behaviour of the input (e.g warn about uniqueness of a field, when it can only be set once), whereas `description` can describe it in more depth. Can also receive a `hintIcon`. |
5656
| `description` | `string` or `node` | - | - | - | Provides a description for the title. |
5757
| `onInfoButtonClick` | `function` | - | - | - | Function called when info button is pressed. Info button will only be visible when this prop is passed. |
58-
| `tone` | `string` | - | `['primary', 'inverted']` | _ | Indicates the tone to be applied to the label |
58+
| `tone` | `string` | - | `['primary', 'inverted']` | \_ | Indicates the tone to be applied to the label |
5959
| `hintIcon` | `node` | - | - | - | Icon to be displayed beside the hint text. Will only get rendered when `hint` is passed as well. |
6060
| `badge` | `node` | - | - | - | Badge to be displayed beside the label. Might be used to display additional information about the content of the field (E.g verified email) |
6161
| `hasRequiredIndicator` | `bool` | - | - | `false` | Indicates if the labeled field is required in a form |

src/components/inputs/checkbox-input/README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ import { CheckboxInput } from '@commercetools-frontend/ui-kit/switches';
3232
| `name` | `string` | - | - | - | Used as HTML `name` property. |
3333
| `children` | `node` | - | - | - | The descriptive text of the CheckboxInput |
3434
| `isDisabled` | `bool` | - | - | `false` | Disables the CheckboxInput |
35-
| `isHovered` | `bool` | - | - | `false` | Forces CheckboxInput to be rendered in a hovered state. That's needed for the cases when hovered appearance should be triggered by the parent component and not the CheckboxInput itself. CheckboxInput is capable of handling it's own hovering without the need to pass this prop. |
35+
| `isReadOnly` | `bool` | - | - | `false` | Makes the CheckboxInput readonly | | `isHovered` | `bool` | - | - | `false` | Forces CheckboxInput to be rendered in a hovered state. That's needed for the cases when hovered appearance should be triggered by the parent component and not the CheckboxInput itself. CheckboxInput is capable of handling it's own hovering without the need to pass this prop. |
3636
| `isIndeterminate` | `bool` | - | - | `false` | If `true`, this state is shown as a dash in the checkbox, and indicates that its state is neither checked nor unchecked. This is most often used when the checkbox is tied to a collection of items in mixed states (E.g nested checkboxes). This takes precedence visually in case `isChecked` is marked as `true` |
3737
| `isChecked` | `bool` | - | - | `false` | The checked property sets the checked state of a checkbox. |
3838
| `hasError` | `bool` | - | - | `false` | Indicates that the checkbox has an error |

src/components/inputs/checkbox-input/checkbox-input.js

+2
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ class CheckboxInput extends React.PureComponent {
5050
// by a corresponding :hover selector in the syles of this component.
5151
isHovered: PropTypes.bool,
5252
isDisabled: PropTypes.bool,
53+
isReadOnly: PropTypes.bool,
5354
hasError: PropTypes.bool,
5455
children: PropTypes.node,
5556
};
@@ -84,6 +85,7 @@ class CheckboxInput extends React.PureComponent {
8485
value={this.props.value}
8586
onChange={this.props.onChange}
8687
isDisabled={this.props.isDisabled}
88+
isReadOnly={this.props.isReadOnly}
8789
isChecked={this.props.isChecked}
8890
isIndeterminate={this.props.isIndeterminate}
8991
{...filterDataAttributes(this.props)}

src/components/inputs/checkbox-input/checkbox-input.spec.js

+11
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,17 @@ it('should not call onChange when text is clicked while disabled', () => {
3535
expect(onChange).not.toHaveBeenCalled();
3636
});
3737

38+
it('should not call onChange when text is clicked while readOnly', () => {
39+
const onChange = jest.fn();
40+
const { getByLabelText } = render(
41+
<CheckboxInput onChange={onChange} isChecked={false} isReadOnly={true}>
42+
Accept Terms
43+
</CheckboxInput>
44+
);
45+
getByLabelText('Accept Terms').click();
46+
expect(onChange).not.toHaveBeenCalled();
47+
});
48+
3849
it('should call onChange when outside label is clicked', () => {
3950
const onChange = jest.fn();
4051
const { getByLabelText } = render(

src/components/inputs/checkbox-input/checkbox-input.story.js

+1
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ storiesOf('Components|Inputs', module)
3434
isIndeterminate={boolean('isIndeterminate', false)}
3535
isHovered={boolean('isHovered', false)}
3636
isDisabled={boolean('isDisabled', false)}
37+
isReadOnly={boolean('isReadOnly', false)}
3738
hasError={boolean('hasError', false)}
3839
>
3940
{text('Label', 'This is a label')}

src/components/inputs/checkbox-input/checkbox-input.styles.js

+15
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,21 @@ const getCheckboxWrapperStyles = (props, theme) => {
3333
`,
3434
];
3535
}
36+
if (props.isReadOnly) {
37+
return [
38+
baseStyles,
39+
css`
40+
svg [id$='borderAndContent'] > [id$='content'] {
41+
fill: ${overwrittenVars[designTokens.fontColorForInputWhenReadonly]};
42+
}
43+
svg [id$='borderAndContent'] > [id$='border'] {
44+
stroke: ${overwrittenVars[
45+
designTokens.borderColorForInputWhenReadonly
46+
]};
47+
}
48+
`,
49+
];
50+
}
3651
if (props.hasError) {
3752
return [
3853
baseStyles,

src/components/inputs/checkbox-input/checkbox-input.visualroute.js

+25
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,31 @@ export const component = ({ themes }) => (
9797
I want mezcal with a worm
9898
</CheckboxInput>
9999
</Spec>
100+
<Spec label="when readonly">
101+
<CheckboxInput onChange={() => {}} value="value" isReadOnly={true}>
102+
I want tequila
103+
</CheckboxInput>
104+
</Spec>
105+
<Spec label="when checked and readonly">
106+
<CheckboxInput
107+
onChange={() => {}}
108+
value="value"
109+
isReadOnly={true}
110+
isChecked={true}
111+
>
112+
I want mezcal
113+
</CheckboxInput>
114+
</Spec>
115+
<Spec label="when indeterminate and readonly">
116+
<CheckboxInput
117+
onChange={() => {}}
118+
value="value"
119+
isReadOnly={true}
120+
isIndeterminate={true}
121+
>
122+
I want mezcal with a worm
123+
</CheckboxInput>
124+
</Spec>
100125
<ThemeProvider theme={themes.darkTheme}>
101126
<Spec label="with custom (dark) theme">
102127
<CheckboxInput onChange={() => {}} value="value">

src/components/inputs/checkbox-input/checkbox.js

+44-42
Original file line numberDiff line numberDiff line change
@@ -11,48 +11,50 @@ const Input = styled.input`
1111
}
1212
`;
1313

14-
class Checkbox extends React.Component {
15-
static displayName = 'Checkbox';
16-
17-
static propTypes = {
18-
id: PropTypes.string,
19-
name: PropTypes.string,
20-
value: PropTypes.string,
21-
isChecked: PropTypes.bool,
22-
isIndeterminate: PropTypes.bool,
23-
onChange: PropTypes.func.isRequired,
24-
isDisabled: PropTypes.bool,
25-
};
26-
27-
componentDidMount() {
28-
if (this.props.isIndeterminate) {
29-
this.ref.current.indeterminate = true;
14+
const Checkbox = props => {
15+
const ref = React.useRef();
16+
React.useEffect(() => {
17+
if (props.isIndeterminate) {
18+
ref.current.indeterminate = true;
3019
}
31-
}
32-
33-
componentDidUpdate(prevProps) {
34-
if (prevProps.isIndeterminate !== this.props.isIndeterminate) {
35-
this.ref.current.indeterminate = this.props.isIndeterminate;
36-
}
37-
}
38-
39-
ref = React.createRef();
40-
41-
render() {
42-
return (
43-
<Input
44-
css={accessibleHiddenInputStyles}
45-
id={this.props.id}
46-
name={this.props.name}
47-
value={this.props.value}
48-
disabled={this.props.isDisabled}
49-
checked={this.props.isChecked && !this.props.isIndeterminate}
50-
onChange={this.props.onChange}
51-
ref={this.ref}
52-
{...this.props}
53-
/>
54-
);
55-
}
56-
}
20+
}, [props.isIndeterminate]);
21+
22+
const { onChange } = props;
23+
24+
const handleChange = React.useCallback(
25+
event => !props.isReadOnly && onChange && onChange(event),
26+
[props.isReadOnly, onChange]
27+
);
28+
29+
return (
30+
<Input
31+
css={accessibleHiddenInputStyles}
32+
id={props.id}
33+
name={props.name}
34+
value={props.value}
35+
disabled={props.isDisabled || props.isReadOnly}
36+
readOnly={props.isReadOnly}
37+
checked={props.isChecked && !props.isIndeterminate}
38+
onChange={handleChange}
39+
ref={ref}
40+
/* ARIA */
41+
aria-readonly={props.isReadOnly}
42+
{...props}
43+
/>
44+
);
45+
};
46+
47+
Checkbox.displayName = 'Checkbox';
48+
49+
Checkbox.propTypes = {
50+
id: PropTypes.string,
51+
name: PropTypes.string,
52+
value: PropTypes.string,
53+
isChecked: PropTypes.bool,
54+
isIndeterminate: PropTypes.bool,
55+
onChange: PropTypes.func.isRequired,
56+
isDisabled: PropTypes.bool,
57+
isReadOnly: PropTypes.bool,
58+
};
5759

5860
export default Checkbox;

0 commit comments

Comments
 (0)