Skip to content

Commit

Permalink
Mixed checkbox, style fixes and example
Browse files Browse the repository at this point in the history
  • Loading branch information
michaelpande committed Mar 8, 2024
1 parent 9ff2337 commit 6ef9fbc
Show file tree
Hide file tree
Showing 4 changed files with 155 additions and 22 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,12 @@
align-items: center;
justify-content: center;
}

.checked {
background-color: var(--px-color-surface-action);
color: white;
}

.strong {
font-weight: 600;
}
78 changes: 65 additions & 13 deletions libs/pxweb2-ui/src/lib/components/Checkbox/Checkbox.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type { Meta, StoryFn } from '@storybook/react';
import { Checkbox } from './Checkbox';
import { Checkbox, MixedCheckbox } from './Checkbox';
import React from 'react';

/* import { within } from '@storybook/testing-library';
import { expect } from '@storybook/jest'; */
Expand All @@ -11,25 +12,76 @@ const meta: Meta<typeof Checkbox> = {
export default meta;

export const Variants: StoryFn<typeof Checkbox> = () => {
const [selectedMalamute, setSelectedMalamute] = React.useState(true);
const [selectedHusky, setSelectedHusky] = React.useState(true);
const [selectedYorkshireTerrier, setSelectedYorkshireTerrier] =
React.useState(false);
const [allSelected, setAllSelected] = React.useState<
'mixed' | 'true' | 'false'
>('mixed');

React.useEffect(() => {
if (!selectedHusky && !selectedMalamute && !selectedYorkshireTerrier) {
setAllSelected('false');
} else if (selectedHusky && selectedMalamute && selectedYorkshireTerrier) {
setAllSelected('true');
} else {
setAllSelected('mixed');
}
}, [selectedMalamute, selectedHusky, selectedYorkshireTerrier]);

return (
<>
<Checkbox
id="test"
text="Variable 1"
onChange={(val) => {
console.log(val);
}}
value={true}
/>
<br />
<Checkbox
<MixedCheckbox
id="test"
text="Variable 2"
text="All dog breeds"
onChange={(val) => {
console.log(val);
if (selectedHusky && selectedMalamute && selectedYorkshireTerrier) {
setSelectedHusky(false);
setSelectedMalamute(false);
setSelectedYorkshireTerrier(false);
}
if (
!selectedHusky ||
!selectedMalamute ||
!selectedYorkshireTerrier
) {
setSelectedHusky(true);
setSelectedMalamute(true);
setSelectedYorkshireTerrier(true);
}
}}
value={true}
ariaControls={['var1', 'var2', 'var3']}
value={allSelected}
strong={true}
/>
<div style={{ marginLeft: '10px' }}>
<Checkbox
id="var1"
text="Husky"
onChange={(val) => {
setSelectedHusky(val);
}}
value={selectedHusky}
/>
<Checkbox
id="var2"
text="Malamute"
onChange={(val) => {
setSelectedMalamute(val);
}}
value={selectedMalamute}
/>
<Checkbox
id="var3"
text="Yorkshire Terrier"
onChange={(val) => {
setSelectedYorkshireTerrier(val);
}}
value={selectedYorkshireTerrier}
/>
</div>
<br />
</>
);
Expand Down
89 changes: 80 additions & 9 deletions libs/pxweb2-ui/src/lib/components/Checkbox/Checkbox.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import React from 'react';
import cl from 'clsx';
import styles from './Checkbox.module.scss';
import { Icon } from '../Icon/Icon';
import Label from '../Typography/Label/Label';
Expand All @@ -9,6 +10,7 @@ interface CheckboxProps {
value: boolean;
onChange: (str: boolean) => void;
tabIndex?: number;
strong?: boolean;
}

export const Checkbox: React.FC<CheckboxProps> = ({
Expand All @@ -17,33 +19,102 @@ export const Checkbox: React.FC<CheckboxProps> = ({
text,
onChange,
tabIndex,
strong,
}) => {
return (
<div
id={id}
role="checkbox"
aria-checked={value}
aria-labelledby={id + '-label'}
className={styles.checkboxWrapper}
tabIndex={tabIndex ? tabIndex : 0}
onKeyUp={(event) => {
if (event.key === ' ' || event.key === 'Enter') {
event.preventDefault();
onChange(!value);
}
}}
onClick={(event) => {
event.preventDefault();
onChange(!value);
}}
>
<span
className={cl(styles.checkmark, {
[styles.checked]: value,
})}
>
{value && <Icon iconName="CheckMark"></Icon>}
</span>
<span id={id + '-label'}>
<Label>
<span className={cl({ [styles.strong]: strong })}>{text}</span>
</Label>
</span>
</div>
);
};
interface MixedCheckboxProps {
id: string;
text: string;
value: 'mixed' | 'false' | 'true';
onChange: (str: string) => void;
ariaControls: string[];
tabIndex?: number;
strong?: boolean;
}
export const MixedCheckbox: React.FC<MixedCheckboxProps> = ({
id,
value,
text,
onChange,
ariaControls,
tabIndex,
strong,
}) => {
const [checked, setChecked] = React.useState(value);

return (
<div
id={id}
role="checkbox"
aria-checked={checked}
aria-checked={value}
aria-labelledby={id + '-label'}
aria-controls={ariaControls.join(' ')}
className={styles.checkboxWrapper}
tabIndex={tabIndex ? tabIndex : 0}
onKeyUp={(event) => {
if (event.key === ' ' || event.key === 'Enter') {
event.preventDefault();
setChecked(!checked);
onChange(checked);
if (value === 'false') {
onChange('true');
}
if (value === 'mixed' || value === 'true') {
onChange('false');
}
}
}}
onClick={(event) => {
event.preventDefault();
setChecked(!checked);
if (value === 'false') {
onChange('true');
}
if (value === 'mixed' || value === 'true') {
onChange('false');
}
}}
>
<span className={styles.checkmark}>
{checked && <Icon iconName="CheckMark"></Icon>}
<span
className={cl(styles.checkmark, {
[styles.checked]: value === 'mixed' || value === 'true',
})}
>
{value === 'true' && <Icon iconName="CheckMark"></Icon>}
{value === 'mixed' && <Icon iconName="IndeterminateCheckMark"></Icon>}
</span>
<span id={id + '-label'}>
<Label>{text}</Label>
<Label>
<span className={cl({ [styles.strong]: strong })}>{text}</span>
</Label>
</span>
</div>
);
Expand Down
1 change: 1 addition & 0 deletions libs/pxweb2-ui/src/lib/components/Icon/Icons.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export const QuestionMarkCircleFilled = <path fill-rule="evenodd" clip-rule="eve
export const InformationCircle = <path fill-rule="evenodd" clip-rule="evenodd" d="M20.25 12C20.25 16.5563 16.5563 20.25 12 20.25C7.44365 20.25 3.75 16.5563 3.75 12C3.75 7.44365 7.44365 3.75 12 3.75C16.5564 3.75 20.25 7.44365 20.25 12ZM12 21.75C17.3848 21.75 21.75 17.3848 21.75 12C21.75 6.61522 17.3848 2.25 12 2.25C6.61523 2.25 2.25 6.61522 2.25 12C2.25 17.3848 6.61522 21.75 12 21.75ZM11 8C11 7.44771 11.4477 7 12 7C12.5523 7 13 7.44771 13 8C13 8.55228 12.5523 9 12 9C11.4477 9 11 8.55229 11 8ZM12 10.25C12.4142 10.25 12.75 10.5858 12.75 11L12.75 16.5C12.75 16.9142 12.4142 17.25 12 17.25C11.5858 17.25 11.25 16.9142 11.25 16.5L11.25 11C11.25 10.5858 11.5858 10.25 12 10.25Z" />;
export const InformationCircleFilled = <path fill-rule="evenodd" clip-rule="evenodd" d="M12 3C7.02944 3 3 7.02944 3 12C3 16.9706 7.02944 21 12 21C16.9706 21 21 16.9706 21 12C21 7.02944 16.9706 3 12 3ZM11 8C11 7.44771 11.4477 7 12 7C12.5523 7 13 7.44772 13 8C13 8.55228 12.5523 9 12 9C11.4477 9 11 8.55229 11 8ZM12 10.25C12.4142 10.25 12.75 10.5858 12.75 11L12.75 16.5C12.75 16.9142 12.4142 17.25 12 17.25C11.5858 17.25 11.25 16.9142 11.25 16.5L11.25 11C11.25 10.5858 11.5858 10.25 12 10.25Z" />;
export const CheckMark = <path d="M10.3333 17L6 12.7447L7.51667 11.2553L10.3333 14.0213L17.4833 7L19 8.48936L10.3333 17Z" />
export const IndeterminateCheckMark = <><rect x="6" y="10" width="12" height="4" rx="0.5"/></>
export const CheckMarkCircle = <path fill-rule="evenodd" clip-rule="evenodd" d="M3.75 12C3.75 7.44365 7.44365 3.75 12 3.75C16.5563 3.75 20.25 7.44365 20.25 12C20.25 16.5563 16.5563 20.25 12 20.25C7.44365 20.25 3.75 16.5563 3.75 12ZM12 2.25C6.61522 2.25 2.25 6.61522 2.25 12C2.25 17.3848 6.61522 21.75 12 21.75C17.3848 21.75 21.75 17.3848 21.75 12C21.75 6.61522 17.3848 2.25 12 2.25ZM16.5725 9.48446C16.8401 9.16825 16.8007 8.69502 16.4845 8.42746C16.1683 8.1599 15.695 8.19934 15.4275 8.51554L10.454 14.3933L8.03033 11.9697C7.73744 11.6768 7.26256 11.6768 6.96967 11.9697C6.67678 12.2626 6.67678 12.7374 6.96967 13.0303L9.96967 16.0303C10.118 16.1786 10.3216 16.2581 10.5312 16.2494C10.7407 16.2406 10.9371 16.1446 11.0725 15.9845L16.5725 9.48446Z" />;
export const CheckMarkCircleFilled = <path fill-rule="evenodd" clip-rule="evenodd" d="M12 21.75C17.3848 21.75 21.75 17.3848 21.75 12C21.75 6.61522 17.3848 2.25 12 2.25C6.61522 2.25 2.25 6.61522 2.25 12C2.25 17.3848 6.61522 21.75 12 21.75ZM16.9536 9.27485C17.2434 8.93229 17.2007 8.41962 16.8582 8.12977C16.5156 7.83991 16.0029 7.88263 15.7131 8.22519L10.3251 14.5928L7.69952 11.9672C7.38222 11.6499 6.86778 11.6499 6.55048 11.9672C6.23317 12.2845 6.23317 12.7989 6.55048 13.1162L9.80048 16.3662C9.96114 16.5269 10.1817 16.6129 10.4088 16.6035C10.6358 16.594 10.8485 16.49 10.9953 16.3165L16.9536 9.27485Z" />;
export const ExclamationMark = <path fill-rule="evenodd" clip-rule="evenodd" d="M12 2.25C12.2731 2.25 12.5245 2.3984 12.6565 2.63743L22.1828 19.8874C22.3111 20.1198 22.3071 20.4026 22.1722 20.6312C22.0373 20.8597 21.7917 21 21.5263 21H2.47372C2.20832 21 1.96268 20.8597 1.8278 20.6312C1.69292 20.4026 1.68888 20.1198 1.81719 19.8874L11.3435 2.63743C11.4755 2.3984 11.7269 2.25 12 2.25ZM20.2553 19.5L12 4.55142L3.74468 19.5H20.2553ZM12 8.75C12.4142 8.75 12.75 9.08579 12.75 9.5V13.5C12.75 13.9142 12.4142 14.25 12 14.25C11.5858 14.25 11.25 13.9142 11.25 13.5V9.5C11.25 9.08579 11.5858 8.75 12 8.75ZM12 15.5C11.4477 15.5 11 15.9477 11 16.5C11 17.0523 11.4477 17.5 12 17.5C12.5523 17.5 13 17.0523 13 16.5C13 15.9477 12.5523 15.5 12 15.5Z" />;
Expand Down

0 comments on commit 6ef9fbc

Please sign in to comment.