javascript - Anpassad kryssruta utlöser inte onChange
Jag har skrivit en anpassad kryssruta med TypeScript och styled-components, koden ser ut som följer
import React, { FC } from "react";
import styled from "styled-components";
import { Box, BoxProps } from "../Box";
import { Flex } from "../Flex";
import { Text } from "../Text";
import {
BackgroundProps,
BorderProps,
ColorProps,
FlexboxProps,
GridProps,
LayoutProps,
PositionProps,
ShadowProps,
SpaceProps,
TypographyProps,
background,
border,
color,
flexbox,
grid,
layout,
position,
shadow,
space,
typography,
} from "styled-system";
export interface CheckBoxProps
extends BackgroundProps,
BorderProps,
ColorProps,
FlexboxProps,
GridProps,
LayoutProps,
PositionProps,
ShadowProps,
SpaceProps,
TypographyProps,
Omit<React.HTMLProps<HTMLInputElement>, "color" | "height" | "size" | "width" | "as" | "ref"> {
[key: string]: any;
className?: string;
label?: string;
letterSpacing?: string;
indeterminate?: boolean;
}
const StyledCheckBox = styled.input<CheckBoxProps>`
position: absolute;
opacity: 0.5;
cursor: pointer;
`;
const _Box = styled(Box)<BoxProps>`
positionL absolute;
top: 0;
left: 0;
height: inherit;
width: inherit;
cursor: pointer;
border: ${({ theme }) => `2px solid ${theme.colors.neutral[70]}`};
border-radius: 4px;
display: inline-block;
&:hover{
border: ${({ theme }) => `2px solid ${theme.colors.blue[400]}`};
}
&::after{
content: "";
position: absolute;
right: 0;
left: 0;
top: 0;
bottom: 2px;
margin: auto;
width: 5px;
height: 10px;
border: solid ${({ theme }) => `${theme.colors.neutral[0]}`};
border-width: 0 2px 2px 0;
-webkit-transform: rotate(45deg);
-ms-transform: rotate(45deg);
transform: rotate(36deg);
}
`;
const CheckboxContainer = styled(Box)<CheckBoxProps>`
position: relative;
& ${StyledCheckBox}:checked ~ ${_Box} {
background-color: ${({ theme }) => `${theme.colors.blue[400]}`};
border: ${({ theme }) => `2px solid ${theme.colors.blue[500]}`};
}
& ${StyledCheckBox}:checked ~ ${_Box}::after {
display: block;
}
& ${StyledCheckBox}.intermediate:checked ~ ${_Box}::after {
display: block;
content: "";
position: absolute;
right: 0;
left: 0;
top: 0;
bottom: 2px;
margin: auto;
border: solid ${({ theme }) => `${theme.colors.neutral[0]}`};
border-width: 0px 2px 0px 0px;
transform: rotate(90deg);
}
& ${StyledCheckBox}[disabled] ~ ${_Box}::after {
border-color: ${({ theme }) => `${theme.colors.neutral[60]}`};
}
& ${StyledCheckBox}.intermediate[disabled] ~ ${_Box}::after {
border-color: ${({ theme }) => `${theme.colors.neutral[60]}`};
}
& ${StyledCheckBox}[disabled] ~ ${_Box} {
cursor: default;
background-color: ${({ theme }) => `${theme.colors.neutral[30]}`};
border: ${({ theme }) => `2px solid ${theme.colors.neutral[60]}`};
}
${space}
${color}
${layout}
${background}
${position}
${grid}
${border}
${flexbox}
${shadow}
${typography}
`;
export const Checkbox: FC<CheckBoxProps> = ({ onChange, label, disabled, letterSpacing, ...props }) => (
<Flex alignItems={"center"} gridGap={"8px"}>
<CheckboxContainer width={18} height={18} marginTop={"2px"} {...props}>
<StyledCheckBox
disabled={disabled}
{...props}
type="checkbox"
checked={props.checked}
onChange={onChange}
className={props.indeterminate ? "intermediate" : ""}
/>
<_Box as="span"></_Box>
</CheckboxContainer>
{label && (
<Text
as="span"
sizeVariant="h5"
letterSpacing={letterSpacing}
cursor={disabled ? "not-allowed" : "default"}
colorVariant={disabled ? "disable" : "default"}
>
{label}
</Text>
)}
</Flex>
);
Och vi använder storybook för att visualisera komponenten, koden ser ut som följer
import { Checkbox } from "./Checkbox";
import React from "react";
import type { StoryObj } from "@storybook/react";
export default {
title: "Checkbox",
component: Checkbox,
argTypes: {
checked: {
name: "checked",
type: { name: "checked", required: true },
defaultValue: false,
description: "Set state for check box",
control: "boolean",
},
indeterminate: {
name: "indeterminate",
type: { name: "indeterminate", required: false },
defaultValue: false,
description: "Set indeterminate state for check box",
control: "boolean",
},
disabled: {
name: "disabled",
type: { name: "disabled", required: false },
defaultValue: false,
description: "Set disabled state for check box",
control: "boolean",
},
onChange: {
name: "onChange",
type: { name: "onChange", required: true },
defaultValue: "() => {}",
description: "Set onChange for check box",
action: "clicked",
},
id: {
name: "id",
type: { name: "id", required: true },
defaultValue: "",
description: "Set id for check box",
control: "text",
},
name: {
name: "name",
type: { name: "name", required: false },
defaultValue: "",
description: "Set name for check box",
control: "text",
},
className: {
name: "className",
type: { name: "className", required: true },
defaultValue: "",
description: "Set className for check box",
control: "text",
},
},
};
type Story = StoryObj<typeof Checkbox>;
const CheckBoxTemplate: Story = {
render: (args) => {
return (
<Checkbox
{...args}
onChange={function (): void {
console.log("not implemented");
}}
/>
);
},
};
export const Default = {
...CheckBoxTemplate,
args: {
checked: true,
disabled: false,
className: "",
label: "",
onChange: {
action: "clicked",
},
},
};
export const Intermediate = {
...CheckBoxTemplate,
args: {
checked: true,
disabled: false,
label: "Checkbox",
indeterminate: true,
},
};
När man klickar på kryssrutan i storybook skrivs inte konsolloggen ('not implemented') ut eftersom onChange-funktionen inte triggas. Kan någon vänligen hjälpa mig här. Tack på förhand.
