Skip to content

Commit

Permalink
feat: add radio button
Browse files Browse the repository at this point in the history
  • Loading branch information
bearkfear committed Aug 8, 2024
1 parent 6f078e6 commit a312649
Show file tree
Hide file tree
Showing 6 changed files with 216 additions and 4 deletions.
9 changes: 6 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@continha/ui",
"version": "1.3.1",
"version": "1.4.0",
"private": false,
"repository": {
"url": "https://github.com/bearkfear/ui"
Expand All @@ -14,7 +14,9 @@
"main": "dist/index.js",
"module": "dist/index.mjs",
"types": "dist/index.d.ts",
"files": ["dist"],
"files": [
"dist"
],
"peerDependencies": {
"@continha/formbuilder": "^1.0.2",
"@radix-ui/colors": "^3.0.0",
Expand All @@ -31,7 +33,6 @@
"tailwind-merge": "^2.4.0"
},
"devDependencies": {
"@swc/core": "^1.3.35",
"@biomejs/biome": "^1.8.3",
"@storybook/addon-essentials": "^8.2.4",
"@storybook/addon-interactions": "^8.2.4",
Expand All @@ -42,6 +43,7 @@
"@storybook/nextjs": "^8.2.4",
"@storybook/react": "^8.2.4",
"@storybook/test": "^8.2.4",
"@swc/core": "^1.3.35",
"@types/lodash.get": "^4.4.9",
"@types/lodash.isequal": "^4.5.8",
"@types/node": "^20",
Expand All @@ -60,6 +62,7 @@
"@radix-ui/react-dialog": "^1.1.1",
"@radix-ui/react-label": "^2.1.0",
"@radix-ui/react-popover": "^1.1.1",
"@radix-ui/react-radio-group": "^1.2.0",
"@radix-ui/react-separator": "^1.1.0",
"@radix-ui/react-slot": "^1.1.0",
"@radix-ui/react-tooltip": "^1.1.2",
Expand Down
104 changes: 104 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

29 changes: 29 additions & 0 deletions src/components/ui/form/form-builder.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { Label } from "./label";
import { MultiSelector, SingleSelector } from "./selector";
import { Textarea } from "./textarea";
import { Checkbox } from "./checkbox";
import * as Radio from "./radio";

function FormControl(props: FormRenderProps) {
const disabled = props.field.disabled || props.fieldConfig.disabled;
Expand Down Expand Up @@ -99,6 +100,34 @@ function FormControl(props: FormRenderProps) {
);
}

if (props.fieldConfig.type === "radio") {
const options = props.fieldConfig.options || [];

return (
<Radio.Group
{...props.field}
value={`${props.field.value}`}
onValueChange={(newValue) =>
props.field.onChange(
options.find((option) => `${option.value}` === newValue)?.value,
)
}
>
{props.fieldConfig.options?.map((option) => {
const id = `radio-${props.fieldConfig.name}-option${option.value}`;
return (
<div className="flex space-x-2 items-center" key={option.value}>
<Radio.Item id={id} value={`${option.value}`} />
<Label htmlFor={id} className="font-medium">
{option.label}
</Label>
</div>
);
})}
</Radio.Group>
);
}

return null;
}

Expand Down
2 changes: 1 addition & 1 deletion src/components/ui/form/label.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { LuAsterisk } from "react-icons/lu";
import { cn } from "~/lib/utils";

const labelVariants = cva(
"text-xs text-black dark:text-white font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70",
"text-xs text-black dark:text-white leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70 font-bold",
);

const Label = React.forwardRef<
Expand Down
46 changes: 46 additions & 0 deletions src/components/ui/form/radio.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
"use client";

import * as React from "react";
import * as RadioGroupPrimitive from "@radix-ui/react-radio-group";
import { Circle } from "lucide-react";

import { cn } from "~/lib/utils";

const Group = React.forwardRef<
React.ElementRef<typeof RadioGroupPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof RadioGroupPrimitive.Root>
>(({ className, ...props }, ref) => {
return (
<RadioGroupPrimitive.Root
className={cn("grid gap-2", className)}
{...props}
ref={ref}
/>
);
});
Group.displayName = RadioGroupPrimitive.Root.displayName;

const Item = React.forwardRef<
React.ElementRef<typeof RadioGroupPrimitive.Item>,
React.ComponentPropsWithoutRef<typeof RadioGroupPrimitive.Item>
>(({ className, ...props }, ref) => {
return (
<RadioGroupPrimitive.Item
ref={ref}
className={cn(
"aspect-square h-4 w-4 rounded-full border border-gray-7 dark:border-graydark-7 text-primary ring-offset-gray-1 focus:outline-none focus-visible:ring-2 focus-visible:ring-blue-6 focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
className,
)}
{...props}
>
<RadioGroupPrimitive.Indicator className="flex items-center justify-center">
<Circle className="h-2.5 w-2.5 fill-current text-current" />
</RadioGroupPrimitive.Indicator>
</RadioGroupPrimitive.Item>
);
});
Item.displayName = RadioGroupPrimitive.Item.displayName;

const Root = RadioGroupPrimitive.Root;

export { Group, Item, Root };
30 changes: 30 additions & 0 deletions src/stories/form/form-item.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -211,3 +211,33 @@ export const Checkbox = () => {
</FormBuilder.Root>
);
};

export const Radio = () => {
const form = useForm({
defaultValues: {
gender: "",
},
});

return (
<FormBuilder.Root>
<FormBuilder.FormFields
control={form.control}
fields={[
{
name: "gender",
type: "radio",
label: "Your gender",
size: 12,
helperText: "You can select a gender",
required: true,
options: [
{ label: "Male", value: 1 },
{ label: "Female", value: 2 },
],
},
]}
/>
</FormBuilder.Root>
);
};

0 comments on commit a312649

Please sign in to comment.