Skip to content

Commit

Permalink
Add a checkbox component
Browse files Browse the repository at this point in the history
  • Loading branch information
jeppester committed Nov 27, 2023
1 parent ea94492 commit 101eeb1
Show file tree
Hide file tree
Showing 4 changed files with 122 additions and 0 deletions.
35 changes: 35 additions & 0 deletions components/Checkbox/index.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
.Checkbox {
// @apply border border-transparent text-base leading-4 focus:ring-1 focus:outline-none shadow-sm;
@apply appearance-none inline-flex items-center justify-center w-4 h-4 bg-white border-neutral-300 border rounded-sm border-[1px] outline-none;

&:focus {
@apply ring-2 ring-offset-2 ring-primary-400;
}

&::before {
@apply text-transparent;
content: "";
}

&:checked {
@apply border-none bg-primary-500;

&::before {
@apply text-white;
content: "";
}
}

&:disabled {
@apply select-none border-neutral-200 bg-neutral-100 cursor-not-allowed;

&:checked {
@apply bg-neutral-300;
}
}

// Variants
&--rounded {
@apply rounded-[4px];
}
}
21 changes: 21 additions & 0 deletions components/Checkbox/index.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import React from "react"
import { render } from "@testing-library/react"
import Checkbox, { CheckboxProps } from "."

const defaultProps: CheckboxProps = {
placeholder: "Checkbox placeholder",
}

describe(Checkbox, () => {
describe("when variant is set", () => {
it("adds variant class", () => {
const { getByPlaceholderText } = render(
<Checkbox {...defaultProps} variant="default" />
)

const checkbox = getByPlaceholderText(defaultProps.placeholder as string)

expect(checkbox).toHaveClass("Checkbox--default")
})
})
})
25 changes: 25 additions & 0 deletions components/Checkbox/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import React from "react"
import classNames from "classnames"
import "./index.scss"

const CheckboxVariants = ["default", "rounded"] as const
export type CheckboxVariant = (typeof CheckboxVariants)[number]

export interface CheckboxProps
extends Omit<React.InputHTMLAttributes<HTMLInputElement>, "size"> {
variant?: CheckboxVariant
}

export default function Checkbox(props: CheckboxProps): JSX.Element {
const { variant, className, ...rest } = props

const usedClassName = classNames(
"Checkbox",
{
[`Checkbox--${variant}`]: variant,
},
className
)

return <input type="checkbox" className={usedClassName} {...rest} />
}
41 changes: 41 additions & 0 deletions stories/components/Checkbox.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import React from "react"
import { ComponentStory, ComponentMeta } from "@storybook/react"

import Checkbox, { InputProps, CheckboxVariant } from "~/components/Checkbox"

// More on default export: https://storybook.js.org/docs/react/writing-stories/introduction#default-export
export default {
title: "Components/🚧 Checkbox",
component: Checkbox,
} as ComponentMeta<typeof Checkbox>

// More on component templates: https://storybook.js.org/docs/react/writing-stories/introduction#using-args
const Template: ComponentStory<typeof Checkbox> = (args) => (
<Checkbox {...args} />
)

const baseProps: Partial<InputProps> = {
variant: "default" as CheckboxVariant,
checked: false,
disabled: false,
}

export const Default = Template.bind({})
// More on args: https://storybook.js.org/docs/react/writing-stories/args
Default.args = {
...baseProps,
}

export const Rounded = Template.bind({})
// More on args: https://storybook.js.org/docs/react/writing-stories/args
Rounded.args = {
...baseProps,
variant: "rounded",
}

export const CheckboxWithLabel = (): JSX.Element => (
<label>
<Checkbox className="mr-2" />
<span className="select-none">Checkbox label</span>
</label>
)

0 comments on commit 101eeb1

Please sign in to comment.