This commit is contained in:
decamel 2022-07-29 10:00:50 +03:00
parent 6677695b78
commit faeb9330a4
2 changed files with 87 additions and 61 deletions

View File

@ -0,0 +1,58 @@
import React from 'react';
import { ComponentMeta, ComponentStory } from '@storybook/react';
import Checkbox from './Checkbox';
export default {
// Title inside navigation bar
title: 'Checkbox',
// Component to test
component: Checkbox,
// Clarifying the way how to process specific
// properties of your component and which values
// it can accept.
argTypes: {
checked: {
options: [true, false],
control: { type: 'radio' },
},
},
} as ComponentMeta<typeof Checkbox>;
/**
* This is a way to define a tempalte for your component.
*
* This template should cover all the states.
*
* In most cases you should just distruct args attribute
* on a returning component.
*/
const Template: ComponentStory<typeof Checkbox> = (args) => (
<Checkbox {...args} />
);
/* -------------------------------------------------------------------------- */
/* States of your component */
/* -------------------------------------------------------------------------- */
export const Unchecked = Template.bind({});
Unchecked.args = {
label: "On/off lights",
checked: false,
children: undefined,
}
export const Checked = Template.bind({});
Checked.args = {
children: "On/off lights",
checked: true,
label: undefined,
}
export const EitherLabelChildren = Template.bind({});
EitherLabelChildren.args = {
children: "On/off lights",
checked: true,
label: "Label!",
}
// GO Further

View File

@ -1,71 +1,39 @@
import classNames from "classnames";
import React from "react";
type Props = {
/**
* The way to provide `children` inside a component
* via attribute instead of enclosed tag
*/
label?: React.ReactNode;
/**
* When you will have both `children` and `label`
* defined on a component it will choose `children`
* to display
*/
children?: React.ReactNode;
} & Omit<React.ComponentPropsWithoutRef<"input">, "type">;
/**
* [*] A Checkbox Component
* Customized `input[type="checkbox"]` component with label
*
* [*] when the label is clicked => The checkbox will be checked
* All common input properties are inherited.
*
* [*] for each item(row) you have to put the following in App.tsx:
* const [isCheckedA, setIsCheckedA] = useState(true);
const handleChangeA = (e: React.ChangeEvent<HTMLInputElement>) => {
setIsCheckedA(e.target.checked);
};
*
* [*] to create this component, you have to provide the following:
* [1] label
* [2] if the item is checked or not.
*
* [*] A good example will be:
const App: React.FC = () =>
{
const [isCheckedA, setIsCheckedA] = useState(true);
const handleChangeA = (e: React.ChangeEvent<HTMLInputElement>) => {
setIsCheckedA(e.target.checked);
};
* To define a label content either provide `label` attribute
* or use common `children` property
*/
const Checkbox = ({label, children, className, ...props}: Props) => {
if(label && !children) {
children = label;
}
const [isCheckedB, setIsCheckedB] = useState(true);
const handleChangeB = (e: React.ChangeEvent<HTMLInputElement>) => {
setIsCheckedB(e.target.checked);
};
return (
<div className="App">
<Checkbox
handleChange={handleChangeA}
isChecked={isCheckedA}
label=" Leo Tolstoy "
/>
<Checkbox
handleChange={handleChangeB}
isChecked={isCheckedB}
label=" Fyodor Dostoevsky "
/>
</div>
);
};
*/
interface Props {
isChecked: boolean;
handleChange: (event: React.ChangeEvent<HTMLInputElement>) => void;
label: string;
}
const Checkbox = (props: Props) => {
return (
<div>
<input
type="checkbox"
id={props.label}
checked={props.isChecked}
onChange={props.handleChange}
/>
<label htmlFor={props.label}>{props.label}</label>
</div>
<label className={classNames(className, "flex items-center")}>
<input type="checkbox" {...props} />
{children !== undefined && <span>{children}</span>}
</label>
);
};
export default Checkbox;