From af3010abaa37f7db4144820469422bdbb432adfc Mon Sep 17 00:00:00 2001 From: Mohamed Bassem Date: Sat, 27 Dec 2025 16:30:11 +0200 Subject: feat: add customizable tag styles (#2312) * feat: add customizable tag styles * add tag lang setting * ui settings cleanup * fix migration * change look of the field * more fixes * fix tests --- apps/web/components/ui/field.tsx | 244 +++++++++++++++++++++++++++++++++ apps/web/components/ui/radio-group.tsx | 43 ++++++ 2 files changed, 287 insertions(+) create mode 100644 apps/web/components/ui/field.tsx create mode 100644 apps/web/components/ui/radio-group.tsx (limited to 'apps/web/components/ui') diff --git a/apps/web/components/ui/field.tsx b/apps/web/components/ui/field.tsx new file mode 100644 index 00000000..a52897f5 --- /dev/null +++ b/apps/web/components/ui/field.tsx @@ -0,0 +1,244 @@ +"use client"; + +import type { VariantProps } from "class-variance-authority"; +import { useMemo } from "react"; +import { Label } from "@/components/ui/label"; +import { Separator } from "@/components/ui/separator"; +import { cn } from "@/lib/utils"; +import { cva } from "class-variance-authority"; + +function FieldSet({ className, ...props }: React.ComponentProps<"fieldset">) { + return ( +
[data-slot=checkbox-group]]:gap-3 has-[>[data-slot=radio-group]]:gap-3", + className, + )} + {...props} + /> + ); +} + +function FieldLegend({ + className, + variant = "legend", + ...props +}: React.ComponentProps<"legend"> & { variant?: "legend" | "label" }) { + return ( + + ); +} + +function FieldGroup({ className, ...props }: React.ComponentProps<"div">) { + return ( +
[data-slot=field-group]]:gap-4", + className, + )} + {...props} + /> + ); +} + +const fieldVariants = cva( + "group/field flex w-full gap-3 data-[invalid=true]:text-destructive", + { + variants: { + orientation: { + vertical: ["flex-col [&>*]:w-full [&>.sr-only]:w-auto"], + horizontal: [ + "flex-row items-center", + "[&>[data-slot=field-label]]:flex-auto", + "has-[>[data-slot=field-content]]:[&>[role=checkbox],[role=radio]]:mt-px has-[>[data-slot=field-content]]:items-start", + ], + responsive: [ + "@md/field-group:flex-row @md/field-group:items-center @md/field-group:[&>*]:w-auto flex-col [&>*]:w-full [&>.sr-only]:w-auto", + "@md/field-group:[&>[data-slot=field-label]]:flex-auto", + "@md/field-group:has-[>[data-slot=field-content]]:items-start @md/field-group:has-[>[data-slot=field-content]]:[&>[role=checkbox],[role=radio]]:mt-px", + ], + }, + }, + defaultVariants: { + orientation: "vertical", + }, + }, +); + +function Field({ + className, + orientation = "vertical", + ...props +}: React.ComponentProps<"div"> & VariantProps) { + return ( +
+ ); +} + +function FieldContent({ className, ...props }: React.ComponentProps<"div">) { + return ( +
+ ); +} + +function FieldLabel({ + className, + ...props +}: React.ComponentProps) { + return ( +