Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions src/components/atoms/HeadlessCheckbox/index.store.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { HeadlessCheckboxProps } from "@/components/atoms/HeadlessCheckbox";
import { createContext, useContext } from "react";

export const useCheckboxContext = () => {
const context = useContext(CheckboxContext);
return context;
};

export const CheckboxContext = createContext<HeadlessCheckboxProps>({
id: "",
isChecked: false,
onChange: () => {},
});
40 changes: 40 additions & 0 deletions src/components/atoms/HeadlessCheckbox/index.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/* eslint-disable react-hooks/rules-of-hooks */
/* eslint-disable storybook/prefer-pascal-case */
import type { Meta, StoryObj } from "@storybook/react";
import { HeadlessCheckbox } from ".";

const meta: Meta<typeof HeadlessCheckbox> = {
title: "atoms/HeadlessCheckbox",
component: HeadlessCheckbox,
parameters: {
// Optional parameter to center the component in the Canvas. More info: https://storybook.js.org/docs/react/configure/story-layout
layout: "centered",
},
// This component will have an automatically generated Autodocs entry: https://storybook.js.org/docs/react/writing-docs/autodocs
tags: ["autodocs"],
argTypes: {
isChecked: {
control: {
type: "boolean",
default: false,
description: "isChecked",
},
},
onChange: { action: "changed" },
},
};

export default meta;

type Story = StoryObj<typeof HeadlessCheckbox>;

export const Default: Story = {
render: (args) => {
return (
<HeadlessCheckbox {...args} id={"checkbox"}>
<HeadlessCheckbox.Checkbox />
<HeadlessCheckbox.Label>Checkbox</HeadlessCheckbox.Label>
</HeadlessCheckbox>
);
},
};
64 changes: 64 additions & 0 deletions src/components/atoms/HeadlessCheckbox/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import {
CheckboxContext,
useCheckboxContext,
} from "@/components/atoms/HeadlessCheckbox/index.store";
import { HTMLInputProps } from "@/components/atoms/Input";
import { HTMLLabelProps } from "@/components/atoms/Label";
import { PropsWithChildren } from "react";

export type HeadlessCheckboxContextProps = {
id: string;
isChecked: boolean;
onChange: () => void;
};

export type HeadlessCheckboxProps =
PropsWithChildren<HeadlessCheckboxContextProps>;

const HeadlessCheckboxWrapper = ({
id,
isChecked,
onChange,
children,
}: HeadlessCheckboxProps) => {
const value = {
id,
isChecked,
onChange,
};
return (
<CheckboxContext.Provider value={value}>
{children}
</CheckboxContext.Provider>
);
};

const Checkbox = ({ ...props }: HTMLInputProps) => {
const { id, isChecked, onChange } = useCheckboxContext();
return (
<input
type="checkbox"
id={id}
checked={isChecked}
onChange={onChange}
{...props}
/>
);
};

const Label = ({ children, ...props }: PropsWithChildren<HTMLLabelProps>) => {
const { id } = useCheckboxContext();
return (
<label htmlFor={id} {...props}>
{children}
</label>
);
};

HeadlessCheckboxWrapper.Checkbox = Checkbox;
HeadlessCheckboxWrapper.Label = Label;

export const HeadlessCheckbox = Object.assign(HeadlessCheckboxWrapper, {
Checkbox,
Label,
});
Loading