diff --git a/package-lock.json b/package-lock.json index aaf31101..fc798886 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,6 +12,7 @@ "@radix-ui/react-checkbox": "^1.0.4", "@radix-ui/react-label": "^2.0.2", "@radix-ui/react-radio-group": "^1.1.3", + "@radix-ui/react-switch": "^1.0.3", "@radix-ui/react-tooltip": "^1.0.7", "class-variance-authority": "^0.7.0", "clsx": "^2.0.0", @@ -4111,6 +4112,35 @@ } } }, + "node_modules/@radix-ui/react-switch": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-switch/-/react-switch-1.0.3.tgz", + "integrity": "sha512-mxm87F88HyHztsI7N+ZUmEoARGkC22YVW5CaC+Byc+HRpuvCrOBPTAnXgf+tZ/7i0Sg/eOePGdMhUKhPaQEqow==", + "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-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-toggle": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/@radix-ui/react-toggle/-/react-toggle-1.0.3.tgz", diff --git a/package.json b/package.json index bab610d6..babfea0d 100644 --- a/package.json +++ b/package.json @@ -65,6 +65,7 @@ "@radix-ui/react-checkbox": "^1.0.4", "@radix-ui/react-label": "^2.0.2", "@radix-ui/react-radio-group": "^1.1.3", + "@radix-ui/react-switch": "^1.0.3", "@radix-ui/react-tooltip": "^1.0.7", "class-variance-authority": "^0.7.0", "clsx": "^2.0.0", diff --git a/src/components/Switch/index.tsx b/src/components/Switch/index.tsx new file mode 100644 index 00000000..0a24c5b5 --- /dev/null +++ b/src/components/Switch/index.tsx @@ -0,0 +1,67 @@ +import * as React from 'react' +import * as SwitchPrimitives from '@radix-ui/react-switch' + +import { cn } from '@/lib/utils' +import { cva } from 'class-variance-authority' + +const switchVariants = cva([ + [ + 'peer', + 'inline-flex', + 'h-5', + 'py-0.5', + 'w-10', + 'gap-[8px]', + 'shrink-0', + 'cursor-pointer', + 'items-center', + 'rounded-full', + 'border-none', + 'transition-colors ', + 'focus-visible:outline-none', + 'focus-visible:shadow-blue', + 'disabled:cursor-not-allowed' + ], + [ + 'dark:data-[state=checked]:bg-blue-300', //TODO: change to accent/dark when colour changes are made + 'dark:bg-foreground-subtle-dark', + 'dark:disabled:bg-grey-200' + ], + [ + 'data-[state=checked]:bg-accent', + 'data-[state=unchecked]:bg-foreground-subtle', + 'data-[disabled]:bg-grey-200' + ] +]) + +const Switch = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + + + +)) +Switch.displayName = SwitchPrimitives.Root.displayName + +export { Switch } diff --git a/src/index.ts b/src/index.ts index 2e7142c0..3c078fa7 100644 --- a/src/index.ts +++ b/src/index.ts @@ -7,3 +7,4 @@ export * from './components/Table' export * from './components/ButtonGroup' export * from './components/Tooltip' export * from './components/Input' +export * from './components/Switch' diff --git a/stories/Switch/Docs.mdx b/stories/Switch/Docs.mdx new file mode 100644 index 00000000..1cf56b1a --- /dev/null +++ b/stories/Switch/Docs.mdx @@ -0,0 +1,158 @@ +import { Canvas, Meta } from '@storybook/blocks' + +import * as SwitchStories from './Switch.stories' + + + +# Switch + +A switch is a small, typically toggleable element that allows users to turn a specific setting or feature on or off. It's often represented as a sliding button that visually switches between two states. Switches provide a simple and intuitive way for users to control various options in digital interfaces. + +## Default + + + +## Disabled + + + +## Attributes + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
AttributeTypeDefault
defaultChecked`boolean`-
checked`boolean`-
onCheckedChange`function`-
disabled`boolean`-
required`boolean`-
name`string`-
value`string`"on"
+ +## Data states + + + + + + + + + + + + + + + + + + + + +
AttributeTypeDefault
`[data-state]``"checked" | "unchecked"`-
`[data-disabled]`Present when disabled-
+ +## Switch + +```tsx +import * as React from 'react' +import * as SwitchPrimitives from '@radix-ui/react-switch' + +import { cn } from '@/lib/utils' +import { cva } from 'class-variance-authority' + +const switchVariants = cva([ + [ + 'peer', + 'inline-flex', + 'h-5', + 'py-0.5', + 'w-10', + 'gap-[8px]', + 'shrink-0', + 'cursor-pointer', + 'items-center', + 'rounded-full', + 'border-none', + 'transition-colors ', + 'focus-visible:outline-none', + 'focus-visible:shadow-blue', + 'disabled:cursor-not-allowed' + ], + [ + 'dark:data-[state=checked]:bg-blue-300', + 'dark:bg-foreground-subtle-dark', + 'dark:disabled:bg-grey-200' + ], + [ + 'data-[state=checked]:bg-accent', + 'data-[state=unchecked]:bg-foreground-subtle' + ] +]) + +const Switch = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + + + +)) +Switch.displayName = SwitchPrimitives.Root.displayName + +export { Switch } +``` diff --git a/stories/Switch/Switch.stories.ts b/stories/Switch/Switch.stories.ts new file mode 100644 index 00000000..5dcca204 --- /dev/null +++ b/stories/Switch/Switch.stories.ts @@ -0,0 +1,27 @@ +import type { Meta, StoryObj } from '@storybook/react' + +import { Switch } from '@/index' + +// More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction#default-export +const meta = { + title: 'Form/Switch', + component: Switch, + 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 + // More on argTypes: https://storybook.js.org/docs/react/api/argtypes +} satisfies Meta + +export default meta +type Story = StoryObj + +// More on writing stories with args: https://storybook.js.org/docs/react/writing-stories/args +export const Default: Story = {} + +export const Disabled: Story = { + args: { + disabled: true + } +}