diff --git a/.yarnrc.yml b/.yarnrc.yml index 0acb263..3186f3f 100644 --- a/.yarnrc.yml +++ b/.yarnrc.yml @@ -1 +1 @@ -nodeLinker: node-modules +nodeLinker: node-modules diff --git a/src/shared/ui/.gitkeep b/src/shared/ui/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/src/shared/ui/Checkbox/Checkbox.stories.tsx b/src/shared/ui/Checkbox/Checkbox.stories.tsx new file mode 100644 index 0000000..1da3bc2 --- /dev/null +++ b/src/shared/ui/Checkbox/Checkbox.stories.tsx @@ -0,0 +1,35 @@ +import { Checkbox } from '@shared/ui/Checkbox/Checkbox'; +import type { Meta, StoryObj } from '@storybook/react-vite'; + +const meta = { + title: 'Shared/UI/Checkbox', + component: Checkbox, + argTypes: { + checked: { control: 'boolean' }, + disabled: { control: 'boolean' }, + label: { control: 'text' }, + }, +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const Default: Story = { + args: { + label: 'Checkbox', + }, +}; + +export const Checked: Story = { + args: { + checked: true, + label: 'Checkbox', + }, +}; + +export const Disabled: Story = { + args: { + disabled: true, + label: 'Checkbox', + }, +}; diff --git a/src/shared/ui/Checkbox/Checkbox.tsx b/src/shared/ui/Checkbox/Checkbox.tsx new file mode 100644 index 0000000..83c5ece --- /dev/null +++ b/src/shared/ui/Checkbox/Checkbox.tsx @@ -0,0 +1,50 @@ +import { checkboxVariants } from '@shared/ui/Checkbox/Checkbox.variants'; +import type { ComponentPropsWithoutRef } from 'react'; +import type { VariantProps } from 'tailwind-variants'; + +export type CheckboxProps = ComponentPropsWithoutRef<'input'> & + VariantProps & { + label?: string; + }; + +export const Checkbox = ({ + label, + checked, + disabled, + focus, + className, + ...props +}: CheckboxProps) => { + const { + root, + box, + icon, + label: labelStyle, + } = checkboxVariants({ + checked, + disabled, + focus, + }); + + return ( + + ); +}; diff --git a/src/shared/ui/Checkbox/Checkbox.variants.ts b/src/shared/ui/Checkbox/Checkbox.variants.ts new file mode 100644 index 0000000..c06c172 --- /dev/null +++ b/src/shared/ui/Checkbox/Checkbox.variants.ts @@ -0,0 +1,53 @@ +import { tv } from 'tailwind-variants'; + +export const checkboxVariants = tv({ + slots: { + root: ['inline-flex items-center', 'gap-[var(--spacing-xxs)]', 'cursor-pointer', 'select-none'], + + box: [ + 'flex items-center justify-center', + 'w-[20px] h-[20px]', + 'rounded-[4px]', + 'border', + 'transition-colors duration-[250ms] ease-out', + ], + + icon: ['w-[14px] h-[14px]', 'flex items-center justify-center', 'text-[var(--color-white)]'], + + label: ['typo-caption-1', 'text-[var(--color-gray-600)]'], + }, + + variants: { + checked: { + false: { + box: ['bg-transparent', 'border-[var(--color-gray-300)]'], + icon: ['hidden'], + }, + + true: { + box: ['bg-[var(--color-green-600)]', 'border-[var(--color-green-600)]'], + icon: ['block'], + }, + }, + + focus: { + true: { + box: ['ring-2', 'ring-[var(--color-green-600)]', 'ring-offset-2'], + }, + }, + + disabled: { + true: { + root: ['cursor-not-allowed'], + box: ['bg-[var(--color-gray-300)]', 'border-[var(--color-gray-300)]'], + label: ['text-[var(--color-gray-600)]', 'line-through'], + }, + }, + }, + + defaultVariants: { + checked: false, + focus: false, + disabled: false, + }, +});