diff --git a/package-lock.json b/package-lock.json index 6f0ebba0..ac0212a9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,6 +10,8 @@ "license": "ISC", "dependencies": { "@radix-ui/react-checkbox": "^1.0.4", + "@radix-ui/react-label": "^2.0.2", + "@radix-ui/react-radio-group": "^1.1.3", "class-variance-authority": "^0.7.0", "clsx": "^2.0.0", "tailwind-merge": "^1.14.0" @@ -3599,7 +3601,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.0.3.tgz", "integrity": "sha512-3SzW+0PW7yBBoQlT8wNcGtaxaD0XSu0uLUFgrtHY08Acx05TaHaOmVLR73c0j/cqpDy53KBMO7s0dx2wmOIDIA==", - "dev": true, "dependencies": { "@babel/runtime": "^7.13.10", "@radix-ui/react-compose-refs": "1.0.1", @@ -3660,7 +3661,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.0.1.tgz", "integrity": "sha512-RXcvnXgyvYvBEOhCBuddKecVkoMiI10Jcm5cTI7abJRAHYfFxeu+FBQs/DvdxSYucxR5mna0dNsL6QFlds5TMA==", - "dev": true, "dependencies": { "@babel/runtime": "^7.13.10" }, @@ -3750,7 +3750,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.0.1.tgz", "integrity": "sha512-tI7sT/kqYp8p96yGWY1OAnLHrqDgzHefRBKQ2YAkBS5ja7QLcZ9Z/uY7bEjPUatf8RomoXM8/1sMj1IJaE5UzQ==", - "dev": true, "dependencies": { "@babel/runtime": "^7.13.10", "@radix-ui/react-use-layout-effect": "1.0.1" @@ -3765,6 +3764,29 @@ } } }, + "node_modules/@radix-ui/react-label": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-label/-/react-label-2.0.2.tgz", + "integrity": "sha512-N5ehvlM7qoTLx7nWPodsPYPgMzA5WM8zZChQg8nyFJKnDO5WHdba1vv5/H6IO5LtJMfD2Q3wh1qHFGNtK0w3bQ==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/react-primitive": "1.0.3" + }, + "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-popper": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.1.2.tgz", @@ -3869,11 +3891,42 @@ } } }, + "node_modules/@radix-ui/react-radio-group": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-radio-group/-/react-radio-group-1.1.3.tgz", + "integrity": "sha512-x+yELayyefNeKeTx4fjK6j99Fs6c4qKm3aY38G3swQVTN6xMpsrbigC0uHs2L//g8q4qR7qOcww8430jJmi2ag==", + "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-direction": "1.0.1", + "@radix-ui/react-presence": "1.0.1", + "@radix-ui/react-primitive": "1.0.3", + "@radix-ui/react-roving-focus": "1.0.4", + "@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-roving-focus": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.0.4.tgz", "integrity": "sha512-2mUg5Mgcu001VkGy+FfzZyzbmuUWzgWkj3rvv4yu+mLw03+mTzbxZHvfcGyFp2b8EkQeMkpRQ5FiA2Vr2O6TeQ==", - "dev": true, "dependencies": { "@babel/runtime": "^7.13.10", "@radix-ui/primitive": "1.0.1", @@ -18217,7 +18270,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.0.3.tgz", "integrity": "sha512-3SzW+0PW7yBBoQlT8wNcGtaxaD0XSu0uLUFgrtHY08Acx05TaHaOmVLR73c0j/cqpDy53KBMO7s0dx2wmOIDIA==", - "dev": true, "requires": { "@babel/runtime": "^7.13.10", "@radix-ui/react-compose-refs": "1.0.1", @@ -18246,7 +18298,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.0.1.tgz", "integrity": "sha512-RXcvnXgyvYvBEOhCBuddKecVkoMiI10Jcm5cTI7abJRAHYfFxeu+FBQs/DvdxSYucxR5mna0dNsL6QFlds5TMA==", - "dev": true, "requires": { "@babel/runtime": "^7.13.10" } @@ -18290,12 +18341,20 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.0.1.tgz", "integrity": "sha512-tI7sT/kqYp8p96yGWY1OAnLHrqDgzHefRBKQ2YAkBS5ja7QLcZ9Z/uY7bEjPUatf8RomoXM8/1sMj1IJaE5UzQ==", - "dev": true, "requires": { "@babel/runtime": "^7.13.10", "@radix-ui/react-use-layout-effect": "1.0.1" } }, + "@radix-ui/react-label": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-label/-/react-label-2.0.2.tgz", + "integrity": "sha512-N5ehvlM7qoTLx7nWPodsPYPgMzA5WM8zZChQg8nyFJKnDO5WHdba1vv5/H6IO5LtJMfD2Q3wh1qHFGNtK0w3bQ==", + "requires": { + "@babel/runtime": "^7.13.10", + "@radix-ui/react-primitive": "1.0.3" + } + }, "@radix-ui/react-popper": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.1.2.tgz", @@ -18344,11 +18403,28 @@ "@radix-ui/react-slot": "1.0.2" } }, + "@radix-ui/react-radio-group": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-radio-group/-/react-radio-group-1.1.3.tgz", + "integrity": "sha512-x+yELayyefNeKeTx4fjK6j99Fs6c4qKm3aY38G3swQVTN6xMpsrbigC0uHs2L//g8q4qR7qOcww8430jJmi2ag==", + "requires": { + "@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-direction": "1.0.1", + "@radix-ui/react-presence": "1.0.1", + "@radix-ui/react-primitive": "1.0.3", + "@radix-ui/react-roving-focus": "1.0.4", + "@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" + } + }, "@radix-ui/react-roving-focus": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.0.4.tgz", "integrity": "sha512-2mUg5Mgcu001VkGy+FfzZyzbmuUWzgWkj3rvv4yu+mLw03+mTzbxZHvfcGyFp2b8EkQeMkpRQ5FiA2Vr2O6TeQ==", - "dev": true, "requires": { "@babel/runtime": "^7.13.10", "@radix-ui/primitive": "1.0.1", diff --git a/package.json b/package.json index d821fc21..59f244c5 100644 --- a/package.json +++ b/package.json @@ -61,6 +61,8 @@ }, "dependencies": { "@radix-ui/react-checkbox": "^1.0.4", + "@radix-ui/react-label": "^2.0.2", + "@radix-ui/react-radio-group": "^1.1.3", "class-variance-authority": "^0.7.0", "clsx": "^2.0.0", "tailwind-merge": "^1.14.0" diff --git a/src/assets/build/-radio-selected.icon.tsx b/src/assets/build/-radio-selected.icon.tsx new file mode 100644 index 00000000..a6e6514d --- /dev/null +++ b/src/assets/build/-radio-selected.icon.tsx @@ -0,0 +1,13 @@ +/* 🤖 this file was generated by svg-to-ts */ +export const RadioSelected = (props: any) => ( + + + + + +) diff --git a/src/assets/index.ts b/src/assets/index.ts index 97d82c1a..3b1ad572 100644 --- a/src/assets/index.ts +++ b/src/assets/index.ts @@ -1,3 +1,4 @@ /* 🤖 this file was generated by svg-to-ts */ export * from './build/-check.icon'; export * from './build/-minus.icon'; +export * from './build/-radio-selected.icon'; diff --git a/src/assets/svg-icons/radio-selected.svg b/src/assets/svg-icons/radio-selected.svg new file mode 100644 index 00000000..6834a336 --- /dev/null +++ b/src/assets/svg-icons/radio-selected.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/src/components/Label/index.tsx b/src/components/Label/index.tsx new file mode 100644 index 00000000..ef0e2741 --- /dev/null +++ b/src/components/Label/index.tsx @@ -0,0 +1,26 @@ +'use client' + +import * as React from 'react' +import * as LabelPrimitive from '@radix-ui/react-label' +import type { LabelProps } from '@radix-ui/react-label' +import { cva, type VariantProps } from 'class-variance-authority' + +import { cn } from '@/lib/utils' + +const labelVariants = cva( + 'text-sm font-medium leading-normal peer-disabled:cursor-not-allowed peer-disabled:opacity-70 dark:text-foreground-inverse' +) +const Label = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef & + VariantProps +>(({ className, ...props }, ref) => ( + +)) +Label.displayName = LabelPrimitive.Root.displayName + +export { Label, LabelProps } diff --git a/src/components/Radio/RadioGroup.tsx b/src/components/Radio/RadioGroup.tsx new file mode 100644 index 00000000..f89d5a26 --- /dev/null +++ b/src/components/Radio/RadioGroup.tsx @@ -0,0 +1,20 @@ +import * as React from 'react' +import * as RadioGroupPrimitive from '@radix-ui/react-radio-group' + +import { cn } from '@/lib/utils' + +const RadioGroup = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => { + return ( + + ) +}) +RadioGroup.displayName = RadioGroupPrimitive.Root.displayName + +export { RadioGroup } diff --git a/src/components/Radio/RadioGroupItem.tsx b/src/components/Radio/RadioGroupItem.tsx new file mode 100644 index 00000000..b4fbc7b9 --- /dev/null +++ b/src/components/Radio/RadioGroupItem.tsx @@ -0,0 +1,26 @@ +import * as React from 'react' +import * as RadioGroupPrimitive from '@radix-ui/react-radio-group' +import { cn } from '@/lib/utils' +import { RadioSelected } from '@/assets' +const RadioGroupItem = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => { + return ( + + + + + + ) +}) +RadioGroupItem.displayName = RadioGroupPrimitive.Item.displayName + +export { RadioGroupItem as Radio } diff --git a/src/components/Radio/index.tsx b/src/components/Radio/index.tsx new file mode 100644 index 00000000..9cac04d3 --- /dev/null +++ b/src/components/Radio/index.tsx @@ -0,0 +1,2 @@ +export { RadioGroup } from './RadioGroup' +export { Radio } from './RadioGroupItem' diff --git a/stories/Label/Label.example.tsx b/stories/Label/Label.example.tsx new file mode 100644 index 00000000..eae13033 --- /dev/null +++ b/stories/Label/Label.example.tsx @@ -0,0 +1,20 @@ +import { Checkbox } from '@/components/Checkbox' +import { Label, LabelProps } from '@/components/Label' + +interface LabelDemoProps extends LabelProps { + labelText: string +} +const LabelDemo = (props: LabelDemoProps) => { + return ( + <> +
+ + +
+ + ) +} + +export { LabelDemo } diff --git a/stories/Label/Label.stories.ts b/stories/Label/Label.stories.ts new file mode 100644 index 00000000..8c7a110d --- /dev/null +++ b/stories/Label/Label.stories.ts @@ -0,0 +1,27 @@ +import type { Meta, StoryObj } from '@storybook/react' + +import { LabelDemo } from './Label.example' + +// More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction#default-export +const meta = { + title: 'Components/Label', + component: LabelDemo, + 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'] + // 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 = { + args: { + labelText: 'A Label with a Checkbox', + htmlFor: 'checkbox' + } +} diff --git a/stories/Radio/Radio.example.tsx b/stories/Radio/Radio.example.tsx new file mode 100644 index 00000000..09b37124 --- /dev/null +++ b/stories/Radio/Radio.example.tsx @@ -0,0 +1,39 @@ +import { Label } from '@/components/Label' +import { Radio, RadioGroup } from '@/components/Radio' +import { useState } from 'react' +export const RadioGroupDemo = ({ + defaultValue, + disabled, + loop +}: { + defaultValue?: string + disabled?: boolean + loop?: boolean +}): JSX.Element => { + const [value, setValue] = useState(defaultValue) + const handleValueChange = (newValue: string) => { + console.log(newValue) + setValue(newValue) + } + return ( + + + + + + + ) +} +const RadioWithLabel = ({ value }: { value: string }) => { + return ( + + + + + ) +} diff --git a/stories/Radio/Radio.stories.ts b/stories/Radio/Radio.stories.ts new file mode 100644 index 00000000..688da44b --- /dev/null +++ b/stories/Radio/Radio.stories.ts @@ -0,0 +1,32 @@ +import type { Meta, StoryObj } from '@storybook/react' + +import { RadioGroupDemo } from './Radio.example' + +// More on how to set up stories at: https://storybook.js.org/docs/react/writing-stories/introduction#default-export +const meta = { + title: 'Components/RadioGroup', + component: RadioGroupDemo, + 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'] + // 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 NoDefault: Story = {} +export const DefaultSet: Story = { + args: { + defaultValue: 'goodbye' + } +} +export const RadioButtonDisabled: Story = { + args: { + disabled: true + } +} diff --git a/stories/tailwind.config.js b/stories/tailwind.config.js index d4faf329..7ce338e8 100644 --- a/stories/tailwind.config.js +++ b/stories/tailwind.config.js @@ -1,5 +1,5 @@ const config = require('../tailwind.config') -config.content.push('./stories/**/*.tsx') +config.content.push('./stories/**/*.{tsx, ts}') module.exports = config diff --git a/tailwind.config.js b/tailwind.config.js index e58291cc..3f26f712 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -4,6 +4,8 @@ import defaultTheme from 'tailwindcss/defaultTheme' module.exports = { content: ['./src/**/*.tsx'], + darkMode: 'class', + plugins: [], theme: { colors: colors, boxShadow: { @@ -40,8 +42,6 @@ module.exports = { 'accordion-down': 'accordion-down 0.2s ease-out', 'accordion-up': 'accordion-up 0.2s ease-out' } - }, - darkMode: 'class', - plugins: [] + } } }