Skip to content

Commit

Permalink
fix: improve usability of checkbox, checkbox group, radio and radio g…
Browse files Browse the repository at this point in the history
…roup component
  • Loading branch information
ychhabra-eightfold committed May 31, 2022
1 parent 4307427 commit 134c1ab
Show file tree
Hide file tree
Showing 17 changed files with 567 additions and 506 deletions.
36 changes: 13 additions & 23 deletions src/__snapshots__/storybook.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -1168,29 +1168,25 @@ exports[`Storyshots Button Two State Button 1`] = `

exports[`Storyshots Check Box Check Box 1`] = `
<div
className="selector"
onKeyDown={[Function]}
className="selector my-checkbox-class"
>
<input
aria-label="Label"
checked={true}
defaultChecked={false}
disabled={false}
id="myCheckBoxId"
name="myCheckBoxName"
onChange={[Function]}
readOnly={true}
tabIndex={-1}
type="checkbox"
value="Label"
value="label"
/>
<label
className=""
htmlFor="myCheckBoxId"
>
<span
className="checkmark"
tabIndex={0}
/>
<span
className="selectorLabel"
Expand All @@ -1202,19 +1198,20 @@ exports[`Storyshots Check Box Check Box 1`] = `
`;

exports[`Storyshots Check Box Check Box Group 1`] = `
Array [
<div
className="checkboxGroup"
role="group"
>
<div
className="selector"
onKeyDown={[Function]}
>
<input
checked={true}
checked={false}
disabled={false}
id="test-1"
name="group"
onChange={[Function]}
readOnly={true}
tabIndex={-1}
type="checkbox"
value="First"
/>
Expand All @@ -1224,27 +1221,24 @@ Array [
>
<span
className="checkmark"
tabIndex={0}
/>
<span
className="selectorLabel"
>
First
</span>
</label>
</div>,
</div>
<div
className="selector"
onKeyDown={[Function]}
>
<input
checked={true}
checked={false}
disabled={false}
id="test-2"
name="group"
onChange={[Function]}
readOnly={true}
tabIndex={-1}
type="checkbox"
value="Second"
/>
Expand All @@ -1254,27 +1248,24 @@ Array [
>
<span
className="checkmark"
tabIndex={0}
/>
<span
className="selectorLabel"
>
Second
</span>
</label>
</div>,
</div>
<div
className="selector"
onKeyDown={[Function]}
>
<input
checked={true}
checked={false}
disabled={false}
id="test-3"
name="group"
onChange={[Function]}
readOnly={true}
tabIndex={-1}
type="checkbox"
value="Third"
/>
Expand All @@ -1284,16 +1275,15 @@ Array [
>
<span
className="checkmark"
tabIndex={0}
/>
<span
className="selectorLabel"
>
Third
</span>
</label>
</div>,
]
</div>
</div>
`;

exports[`Storyshots Config Provider Theming 1`] = `
Expand Down
35 changes: 21 additions & 14 deletions src/components/Selectors/CheckBox/CheckBox.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import React from 'react';
import React, { useState } from 'react';
import { Stories } from '@storybook/addon-docs';
import { ComponentStory, ComponentMeta } from '@storybook/react';
import { CheckBox, CheckBoxGroup } from '../index';
import { CheckBox, CheckBoxGroup } from '../';
import { CheckboxValueType } from './Checkbox.types';

export default {
title: 'Check Box',
Expand Down Expand Up @@ -74,10 +75,6 @@ export default {
defaultValue: true,
control: { type: 'boolean' },
},
defaultChecked: {
defaultValue: false,
control: { type: 'boolean' },
},
},
} as ComponentMeta<typeof CheckBox>;

Expand All @@ -87,9 +84,16 @@ const CheckBox_Story: ComponentStory<typeof CheckBox> = (args) => (

export const Check_Box = CheckBox_Story.bind({});

const CheckBoxGroup_Story: ComponentStory<typeof CheckBox> = (args) => (
<CheckBoxGroup {...args} />
);
const CheckBoxGroup_Story: ComponentStory<typeof CheckBoxGroup> = (args) => {
const [selected, setSelected] = useState<CheckboxValueType[]>([]);
return (
<CheckBoxGroup
{...args}
value={selected}
onChange={(newSelected) => setSelected([...newSelected])}
/>
);
};

export const Check_Box_Group = CheckBoxGroup_Story.bind({});

Expand All @@ -99,33 +103,36 @@ const checkBoxArgs: Object = {
classNames: 'my-checkbox-class',
disabled: false,
name: 'myCheckBoxName',
value: 'Label',
value: 'label',
label: 'Label',
id: 'myCheckBoxId',
defaultChecked: false,
};

Check_Box.args = {
...checkBoxArgs,
};

Check_Box_Group.args = {
...checkBoxArgs,
value: ['First'],
defaultChecked: ['First'],
items: [
{
checked: true,
name: 'group',
value: 'First',
label: 'First',
id: 'test-1',
},
{
checked: true,
name: 'group',
value: 'Second',
label: 'Second',
id: 'test-2',
},
{
checked: true,
name: 'group',
value: 'Third',
label: 'Third',
id: 'test-3',
},
],
Expand Down
129 changes: 75 additions & 54 deletions src/components/Selectors/CheckBox/CheckBox.tsx
Original file line number Diff line number Diff line change
@@ -1,58 +1,79 @@
import React, { FC, useState } from 'react';
import { CheckBoxProps } from '../';
import { mergeClasses, generateId } from '../../../shared/utilities';
import React, { FC, Ref, useEffect, useRef, useState } from 'react';
import { generateId, mergeClasses } from '../../../shared/utilities';
import { CheckboxProps } from './Checkbox.types';

import styles from './checkbox.module.scss';

export const CheckBox: FC<CheckBoxProps> = ({
ariaLabel,
checked = false,
defaultChecked,
disabled = false,
name,
value = '',
id,
onChange,
}) => {
const [checkBoxId] = useState<string>(id || generateId());
const [isChecked, setIsChecked] = useState<boolean>(checked);

const checkBoxCheckClassNames: string = mergeClasses([
styles.checkmark,
{ [styles.disabled]: disabled },
]);

const toggleChecked = (): void => {
if (!disabled) setIsChecked(!isChecked);
};

const handleKeyDown = (event: React.KeyboardEvent) => {
if (event.key !== 'Tab') event.preventDefault();
if (event.key === 'Enter' || event.key === ' ') toggleChecked();
};

return (
<div className={styles.selector} onKeyDown={handleKeyDown}>
<input
aria-label={ariaLabel}
checked={isChecked}
defaultChecked={defaultChecked}
disabled={disabled}
id={checkBoxId}
onChange={onChange ? onChange : toggleChecked}
name={name}
tabIndex={-1}
type={'checkbox'}
value={value}
readOnly
/>
<label
htmlFor={checkBoxId}
className={value === '' ? styles.labelNoValue : ''}
export const CheckBox: FC<CheckboxProps> = React.forwardRef(
(
{
ariaLabel,
checked = false,
defaultChecked,
disabled = false,
name,
value,
id,
onChange,
label,
classNames,
style,
'data-test-id': dataTestId,
},
ref: Ref<HTMLInputElement>
) => {
const checkBoxId = useRef<string>(id || generateId());
const [isChecked, setIsChecked] = useState<boolean>(
defaultChecked || checked
);

useEffect(() => {
setIsChecked(checked);
}, [checked]);

const checkboxWrapperClassNames: string = mergeClasses([
styles.selector,
classNames,
]);

const checkBoxCheckClassNames: string = mergeClasses([
styles.checkmark,
]);

const labelClassNames: string = mergeClasses([
{ [styles.labelNoValue]: value === '' },
]);

const toggleChecked = (
e: React.ChangeEvent<HTMLInputElement>
): void => {
setIsChecked(e.target.checked);
onChange?.(e);
};

return (
<div
className={checkboxWrapperClassNames}
style={style}
data-test-id={dataTestId}
>
<span className={checkBoxCheckClassNames} tabIndex={0}></span>
<span className={styles.selectorLabel}>{value}</span>
</label>
</div>
);
};
<input
ref={ref}
aria-label={ariaLabel}
checked={isChecked}
disabled={disabled}
id={checkBoxId.current}
onChange={toggleChecked}
name={name}
type={'checkbox'}
value={value}
readOnly
/>
<label htmlFor={checkBoxId.current} className={labelClassNames}>
<span className={checkBoxCheckClassNames} />
<span className={styles.selectorLabel}>{label}</span>
</label>
</div>
);
}
);
Loading

0 comments on commit 134c1ab

Please sign in to comment.