Skip to content

Commit

Permalink
4848 - Update Checkbox component (twentyhq#4883)
Browse files Browse the repository at this point in the history
# Summary
* Add hover state which defaults to **false**
* Add disable state


![chrome_KV2AltSmBK](https://github.com/twentyhq/twenty/assets/54629307/976fba28-b975-4acc-9d06-c14c4fe339d8)


closes twentyhq#4848

---------

Co-authored-by: Charles Bochet <[email protected]>
Co-authored-by: Lucas Bordeau <[email protected]>
  • Loading branch information
3 people authored May 29, 2024
1 parent ecff27f commit df2b76f
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 24 deletions.
82 changes: 63 additions & 19 deletions packages/twenty-front/src/modules/ui/input/components/Checkbox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,39 +22,63 @@ export enum CheckboxSize {
type CheckboxProps = {
checked: boolean;
indeterminate?: boolean;
hoverable?: boolean;
onChange?: (event: React.ChangeEvent<HTMLInputElement>) => void;
onCheckedChange?: (value: boolean) => void;
variant?: CheckboxVariant;
size?: CheckboxSize;
shape?: CheckboxShape;
className?: string;
disabled?: boolean;
};

const StyledInputContainer = styled.div`
align-items: center;
display: flex;
position: relative;
`;

type InputProps = {
checkboxSize: CheckboxSize;
variant: CheckboxVariant;
indeterminate?: boolean;
hoverable?: boolean;
shape?: CheckboxShape;
isChecked?: boolean;
disabled?: boolean;
};

const StyledInputContainer = styled.div<InputProps>`
--size: ${({ checkboxSize }) =>
checkboxSize === CheckboxSize.Large ? '32px' : '24px'};
align-items: center;
border-radius: ${({ theme, shape }) =>
shape === CheckboxShape.Rounded
? theme.border.radius.rounded
: theme.border.radius.sm};
cursor: ${({ disabled }) => (disabled ? 'not-allowed' : 'pointer')};
display: flex;
padding: ${({ checkboxSize }) =>
checkboxSize === CheckboxSize.Large ? '6px' : '5px'};
position: relative;
${({ hoverable, isChecked, theme, indeterminate, disabled }) => {
if (!hoverable || disabled === true) return '';
return `&:hover{
background-color: ${
indeterminate || isChecked
? theme.color.blue10
: theme.background.transparent.light
};
}}
}`;
}}
`;

const StyledInput = styled.input<InputProps>`
cursor: pointer;
cursor: ${({ disabled }) => (disabled ? 'not-allowed' : 'pointer')};
margin: 0;
opacity: 0;
position: absolute;
z-index: 10;
& + label {
--size: ${({ checkboxSize }) =>
checkboxSize === CheckboxSize.Large ? '18px' : '12px'};
cursor: pointer;
cursor: ${({ disabled }) => (disabled ? 'not-allowed' : 'pointer')};
height: calc(var(--size) + 2px);
padding: 0;
position: relative;
Expand All @@ -66,8 +90,16 @@ const StyledInput = styled.input<InputProps>`
checkboxSize === CheckboxSize.Large ? '18px' : '12px'};
background: ${({ theme, indeterminate, isChecked }) =>
indeterminate || isChecked ? theme.color.blue : 'transparent'};
border-color: ${({ theme, indeterminate, isChecked, variant }) => {
border-color: ${({
theme,
indeterminate,
isChecked,
variant,
disabled,
}) => {
switch (true) {
case disabled:
return theme.background.transparent.medium;
case indeterminate || isChecked:
return theme.color.blue;
case variant === CheckboxVariant.Primary:
Expand All @@ -83,21 +115,21 @@ const StyledInput = styled.input<InputProps>`
? theme.border.radius.rounded
: theme.border.radius.sm};
border-style: solid;
border-width: ${({ variant }) =>
variant === CheckboxVariant.Tertiary ? '2px' : '1px'};
border-width: ${({ variant, checkboxSize }) =>
checkboxSize === CheckboxSize.Large ||
variant === CheckboxVariant.Tertiary
? '1.43px'
: '1px'};
content: '';
cursor: pointer;
cursor: ${({ disabled }) => (disabled ? 'not-allowed' : 'pointer')};
display: inline-block;
height: var(--size);
width: var(--size);
}
& + label > svg {
--padding: ${({ checkboxSize, variant }) =>
checkboxSize === CheckboxSize.Large ||
variant === CheckboxVariant.Tertiary
? '2px'
: '1px'};
--padding: ${({ checkboxSize }) =>
checkboxSize === CheckboxSize.Large ? '2px' : '1px'};
--size: ${({ checkboxSize }) =>
checkboxSize === CheckboxSize.Large ? '16px' : '12px'};
height: var(--size);
Expand All @@ -117,7 +149,9 @@ export const Checkbox = ({
variant = CheckboxVariant.Primary,
size = CheckboxSize.Small,
shape = CheckboxShape.Squared,
hoverable = false,
className,
disabled = false,
}: CheckboxProps) => {
const [isInternalChecked, setIsInternalChecked] =
React.useState<boolean>(false);
Expand All @@ -135,7 +169,16 @@ export const Checkbox = ({
const checkboxId = 'checkbox' + v4();

return (
<StyledInputContainer className={className}>
<StyledInputContainer
checkboxSize={size}
variant={variant}
shape={shape}
isChecked={isInternalChecked}
hoverable={hoverable}
indeterminate={indeterminate}
className={className}
disabled={disabled}
>
<StyledInput
autoComplete="off"
type="checkbox"
Expand All @@ -149,6 +192,7 @@ export const Checkbox = ({
shape={shape}
isChecked={isInternalChecked}
onChange={handleChange}
disabled={disabled}
/>
<label htmlFor={checkboxId}>
{indeterminate ? (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ export const Default: Story = {
args: {
checked: false,
indeterminate: false,
hoverable: false,
disabled: false,
variant: CheckboxVariant.Primary,
size: CheckboxSize.Small,
shape: CheckboxShape.Squared,
Expand All @@ -34,19 +36,22 @@ export const Catalog: CatalogStory<Story, typeof Checkbox> = {
size: { control: false },
indeterminate: { control: false },
checked: { control: false },
hoverable: { control: false },
shape: { control: false },
},
parameters: {
catalog: {
dimensions: [
{
name: 'state',
values: ['unchecked', 'checked', 'indeterminate'],
values: ['disabled', 'unchecked', 'checked', 'indeterminate'],
props: (state: string) => {
if (state === 'disabled') {
return { disabled: true };
}
if (state === 'checked') {
return { checked: true };
}

if (state === 'indeterminate') {
return { indeterminate: true };
}
Expand All @@ -59,9 +64,14 @@ export const Catalog: CatalogStory<Story, typeof Checkbox> = {
props: (shape: CheckboxShape) => ({ shape }),
},
{
name: 'variant',
values: Object.values(CheckboxVariant),
props: (variant: CheckboxVariant) => ({ variant }),
name: 'isHoverable',
values: ['default', 'hoverable'],
props: (isHoverable: string) => {
if (isHoverable === 'hoverable') {
return { hoverable: true };
}
return {};
},
},
{
name: 'size',
Expand Down

0 comments on commit df2b76f

Please sign in to comment.