From 44d175828e4d7528dfec3fa2b89b4ececa68a925 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20=C5=A0ime=C4=8Dek?= Date: Sat, 24 Feb 2024 13:41:35 +0100 Subject: [PATCH] Added checkbox component --- .changeset/tidy-monkeys-reply.md | 5 ++ package-lock.json | 31 +++++++++++++ packages/ui/package.json | 1 + .../components/checkbox/Checkbox.stories.tsx | 29 ++++++++++++ .../components/checkbox/Checkbox.styles.ts | 46 +++++++++++++++++++ .../ui/src/components/checkbox/Checkbox.tsx | 32 +++++++++++++ .../ui/src/components/input/Input.styles.tsx | 2 +- .../ui/src/components/label/Label.styles.tsx | 2 +- .../ui/src/components/switch/Switch.styles.ts | 4 +- packages/ui/src/index.ts | 3 ++ packages/ui/src/overrides.ts | 2 + 11 files changed, 153 insertions(+), 4 deletions(-) create mode 100644 .changeset/tidy-monkeys-reply.md create mode 100644 packages/ui/src/components/checkbox/Checkbox.stories.tsx create mode 100644 packages/ui/src/components/checkbox/Checkbox.styles.ts create mode 100644 packages/ui/src/components/checkbox/Checkbox.tsx diff --git a/.changeset/tidy-monkeys-reply.md b/.changeset/tidy-monkeys-reply.md new file mode 100644 index 0000000..8aeb4c2 --- /dev/null +++ b/.changeset/tidy-monkeys-reply.md @@ -0,0 +1,5 @@ +--- +"@utima/ui": minor +--- + +Added `Checkbox` component diff --git a/package-lock.json b/package-lock.json index cc80166..29bc779 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3644,6 +3644,36 @@ } } }, + "node_modules/@radix-ui/react-checkbox": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-checkbox/-/react-checkbox-1.0.4.tgz", + "integrity": "sha512-CBuGQa52aAYnADZVt/KBQzXrwx6TqnlwtcIPGtVt5JkkzQwMOLJjPukimhfKEr4GQNd43C+djUh5Ikopj8pSLg==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/primitive": "1.0.1", + "@radix-ui/react-compose-refs": "1.0.1", + "@radix-ui/react-context": "1.0.1", + "@radix-ui/react-presence": "1.0.1", + "@radix-ui/react-primitive": "1.0.3", + "@radix-ui/react-use-controllable-state": "1.0.1", + "@radix-ui/react-use-previous": "1.0.1", + "@radix-ui/react-use-size": "1.0.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-collection": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.0.3.tgz", @@ -22860,6 +22890,7 @@ "@radix-ui/react-alert-dialog": "^1.0.5", "@radix-ui/react-aspect-ratio": "^1.0.3", "@radix-ui/react-avatar": "^1.0.4", + "@radix-ui/react-checkbox": "^1.0.4", "@radix-ui/react-dropdown-menu": "^2.0.6", "@radix-ui/react-label": "^2.0.2", "@radix-ui/react-popover": "^1.0.7", diff --git a/packages/ui/package.json b/packages/ui/package.json index dd7819f..460eb6b 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -71,6 +71,7 @@ "@radix-ui/react-alert-dialog": "^1.0.5", "@radix-ui/react-aspect-ratio": "^1.0.3", "@radix-ui/react-avatar": "^1.0.4", + "@radix-ui/react-checkbox": "^1.0.4", "@radix-ui/react-dropdown-menu": "^2.0.6", "@radix-ui/react-label": "^2.0.2", "@radix-ui/react-popover": "^1.0.7", diff --git a/packages/ui/src/components/checkbox/Checkbox.stories.tsx b/packages/ui/src/components/checkbox/Checkbox.stories.tsx new file mode 100644 index 0000000..46a4d95 --- /dev/null +++ b/packages/ui/src/components/checkbox/Checkbox.stories.tsx @@ -0,0 +1,29 @@ +import type { Meta, StoryObj } from '@storybook/react'; + +import { Checkbox } from './Checkbox'; +import { Label } from '../label/Label'; + +const meta: Meta = { + component: Checkbox, + tags: ['autodocs'], + title: 'Components/Checkbox', + args: { + id: 'checkbox-id', + disabled: false, + required: false, + }, + decorators: [ + Story => ( +
+ + +
+ ), + ], +}; + +export default meta; + +type Story = StoryObj; + +export const Basic: Story = {}; diff --git a/packages/ui/src/components/checkbox/Checkbox.styles.ts b/packages/ui/src/components/checkbox/Checkbox.styles.ts new file mode 100644 index 0000000..ee12b43 --- /dev/null +++ b/packages/ui/src/components/checkbox/Checkbox.styles.ts @@ -0,0 +1,46 @@ +import { cva } from 'class-variance-authority'; + +import { twOverrides } from '@/overrides'; + +export const checkboxDef = twOverrides( + { + checkbox: + 'peer transition-all shrink-0 rounded-sm border border-input-border focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 hover:bg-input-border/25', + indicator: 'flex items-center justify-center text-current', + icon: '', + iconSize: { + xs: 'h-2 w-2', + sm: 'h-3 w-3', + md: 'h-4 w-4', + lg: 'h-5 w-5', + }, + variants: { + variant: { + primary: + 'hover:data-[state=checked]:bg-primary/80 active:data-[state=checked]:bg-primary/90 data-[state=checked]:bg-primary data-[state=checked]:text-primary-fg data-[state=checked]:border-primary', + secondary: + 'hover:data-[state=checked]:bg-secondary/80 active:data-[state=checked]:bg-secondary/90 data-[state=checked]:bg-secondary data-[state=checked]:text-secondary-fg data-[state=checked]:border-secondary', + muted: + 'hover:data-[state=checked]:bg-muted/80 active:data-[state=checked]:bg-muted/90 data-[state=checked]:bg-muted data-[state=checked]:text-muted-fg data-[state=checked]border:text-muted', + success: + 'hover:data-[state=checked]:bg-success/80 active:data-[state=checked]:bg-success/90 data-[state=checked]:bg-success data-[state=checked]:text-success-fg data-[state=checked]:border-success', + danger: + 'hover:data-[state=checked]:bg-danger/80 active:data-[state=checked]:bg-danger/90 data-[state=checked]:bg-danger data-[state=checked]:text-danger-fg data-[state=checked]:border-danger', + warning: + 'hover:data-[state=checked]:bg-warning/80 active:data-[state=checked]:bg-warning/90 data-[state=checked]:bg-warning data-[state=checked]:text-warning-fg data-[state=checked]:border-warning', + info: 'hover:data-[state=checked]:bg-info/80 active:data-[state=checked]:bg-info/90 data-[state=checked]:bg-info data-[state=checked]:text-info-fg data-[state=border]:text-info', + }, + size: { + xs: 'h-3 w-3', + sm: 'h-4 w-4', + md: 'h-5 w-5', + lg: 'h-6 w-6', + }, + }, + }, + 'checkbox', +); + +export const checkboxStyles = cva(checkboxDef.checkbox, { + variants: checkboxDef.variants, +}); diff --git a/packages/ui/src/components/checkbox/Checkbox.tsx b/packages/ui/src/components/checkbox/Checkbox.tsx new file mode 100644 index 0000000..ec3e03c --- /dev/null +++ b/packages/ui/src/components/checkbox/Checkbox.tsx @@ -0,0 +1,32 @@ +import { Root, Indicator } from '@radix-ui/react-checkbox'; +import type { VariantProps } from 'class-variance-authority'; +import { CheckIcon } from 'lucide-react'; +import { + forwardRef, + type ElementRef, + type ComponentPropsWithoutRef, +} from 'react'; + +import { cn } from '@/utils'; + +import { checkboxDef, checkboxStyles } from './Checkbox.styles'; + +type CheckboxProps = ComponentPropsWithoutRef & + Omit, 'thumbSize'>; + +export const Checkbox = forwardRef, CheckboxProps>( + ({ className, variant = 'primary', size = 'md', ...props }, ref) => ( + + + + + + ), +); diff --git a/packages/ui/src/components/input/Input.styles.tsx b/packages/ui/src/components/input/Input.styles.tsx index 7bf717e..791deab 100644 --- a/packages/ui/src/components/input/Input.styles.tsx +++ b/packages/ui/src/components/input/Input.styles.tsx @@ -5,7 +5,7 @@ import { twOverrides } from '@/overrides'; export const inputDef = twOverrides( { input: - 'transition-all text-input-fg font-normal flex w-full rounded-md border placeholder-placeholder bg-input ring-offset-input focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-input-border focus:ring-offset-1 focus-visible:border-input-fg disabled:cursor-not-allowed disabled:opacity-60', + 'peer transition-all text-input-fg font-normal flex w-full rounded-md border placeholder-placeholder bg-input ring-offset-input focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-input-border focus:ring-offset-1 focus-visible:border-input-fg disabled:cursor-not-allowed disabled:opacity-60', variants: { size: { xs: 'h-6 px-2 py-1.5 text-xs', diff --git a/packages/ui/src/components/label/Label.styles.tsx b/packages/ui/src/components/label/Label.styles.tsx index 4f73d5b..01bb84e 100644 --- a/packages/ui/src/components/label/Label.styles.tsx +++ b/packages/ui/src/components/label/Label.styles.tsx @@ -5,7 +5,7 @@ import { twOverrides } from '@/overrides'; export const labelDef = twOverrides( { label: - 'text-foreground font-medium peer-disabled:cursor-not-allowed peer-disabled:opacity-70', + 'cursor-pointer text-foreground font-medium peer-disabled:cursor-not-allowed peer-disabled:opacity-70', variants: { size: { xs: 'text-xs leading-3', diff --git a/packages/ui/src/components/switch/Switch.styles.ts b/packages/ui/src/components/switch/Switch.styles.ts index e864488..c64d08d 100644 --- a/packages/ui/src/components/switch/Switch.styles.ts +++ b/packages/ui/src/components/switch/Switch.styles.ts @@ -5,9 +5,9 @@ import { twOverrides } from '@/overrides'; export const switchDef = twOverrides( { switch: - 'peer inline-flex shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent shadow-sm transition-colors focus-visible:outline-none focus:ring-2 focus:ring-offset-1 ring-input-border disabled:cursor-not-allowed disabled:opacity-65 data-[state=unchecked]:bg-input-fg/15 hover:data-[state=unchecked]:bg-input-fg/10', + 'peer inline-flex shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent transition-colors focus-visible:outline-none focus:ring-2 focus:ring-offset-1 ring-input-border disabled:cursor-not-allowed disabled:opacity-65 data-[state=unchecked]:bg-muted hover:data-[state=unchecked]:bg-muted/80', thumb: - 'pointer-events-none block rounded-full bg-input shadow-lg ring-0 transition-transform data-[state=unchecked]:translate-x-0', + 'pointer-events-none block rounded-full bg-input ring-0 transition-transform data-[state=unchecked]:translate-x-0', thumbSize: { xs: 'h-2 w-2 data-[state=checked]:translate-x-3', sm: 'h-3 w-3 data-[state=checked]:translate-x-3', diff --git a/packages/ui/src/index.ts b/packages/ui/src/index.ts index 28a00f2..c4608ab 100644 --- a/packages/ui/src/index.ts +++ b/packages/ui/src/index.ts @@ -51,3 +51,6 @@ export * as Popover from './components/popover'; // Separator export { Separator } from './components/separator/Separator'; + +// Checkbox +export { Checkbox } from './components/checkbox/Checkbox'; diff --git a/packages/ui/src/overrides.ts b/packages/ui/src/overrides.ts index 63e810c..5ddc4c2 100644 --- a/packages/ui/src/overrides.ts +++ b/packages/ui/src/overrides.ts @@ -6,6 +6,7 @@ import type { aspectRatioDef } from './components/aspectRatio/AspectRatio.styles import type { avatarDef } from './components/avatar/Avatar.styles'; import type { badgeDef } from './components/badge/Badge.styles'; import type { buttonDef } from './components/button/Button.styles'; +import type { checkboxDef } from './components/checkbox/Checkbox.styles'; import type { dropdownDef } from './components/dropdown/Dropdown.styles'; import type { inputDef } from './components/input/Input.styles'; import type { labelDef } from './components/label/Label.styles'; @@ -36,6 +37,7 @@ type ComponentOverridesDef = { dropdown: typeof dropdownDef; popover: typeof popoverDef; separator: typeof separatorDef; + checkbox: typeof checkboxDef; }; export type ComponentOverrides = PartialDeep;