From 1cfc4dfdcd87d04f27fb9a681478b131f96ddcbd Mon Sep 17 00:00:00 2001 From: joshunrau Date: Tue, 24 Feb 2026 16:52:41 -0500 Subject: [PATCH 1/6] refactor: radio group --- src/components/RadioGroup/RadioGroup.tsx | 15 +++++---------- src/components/RadioGroup/RadioGroupItem.tsx | 20 +++++++------------- 2 files changed, 12 insertions(+), 23 deletions(-) diff --git a/src/components/RadioGroup/RadioGroup.tsx b/src/components/RadioGroup/RadioGroup.tsx index 5d48a76..137d0ed 100644 --- a/src/components/RadioGroup/RadioGroup.tsx +++ b/src/components/RadioGroup/RadioGroup.tsx @@ -1,21 +1,16 @@ import * as React from 'react'; -import * as RadioGroupPrimitive from '@radix-ui/react-radio-group'; +import { Root } from '@radix-ui/react-radio-group'; import { cn } from '#utils'; import { RadioGroupItem } from './RadioGroupItem.tsx'; -type RadioGroupProps = React.ComponentPropsWithoutRef; +type RadioGroupProps = React.ComponentProps; -const RadioGroupRoot = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(function RadioGroup({ className, ...props }, ref) { - return ( - - ); -}); +const RadioGroupRoot: React.FC = ({ className, ...props }) => { + return ; +}; export const RadioGroup = Object.assign(RadioGroupRoot, { Item: RadioGroupItem diff --git a/src/components/RadioGroup/RadioGroupItem.tsx b/src/components/RadioGroup/RadioGroupItem.tsx index e57a6c5..e2285a0 100644 --- a/src/components/RadioGroup/RadioGroupItem.tsx +++ b/src/components/RadioGroup/RadioGroupItem.tsx @@ -1,29 +1,23 @@ -import { forwardRef } from 'react'; - -import * as RadioGroupPrimitive from '@radix-ui/react-radio-group'; +import { Indicator, Item } from '@radix-ui/react-radio-group'; import { CircleIcon } from 'lucide-react'; import { cn } from '#utils'; -export const RadioGroupItem = forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(function RadioGroupItem({ className, ...props }, ref) { +export const RadioGroupItem: React.FC> = ({ className, ...props }) => { return ( - - + - - + + ); -}); +}; From 9172d881a83801d1f1f652d275df5c7364b4d6b1 Mon Sep 17 00:00:00 2001 From: joshunrau Date: Tue, 24 Feb 2026 16:53:05 -0500 Subject: [PATCH 2/6] chore: remove unused orientation prop --- src/components/Form/BaseRadioField.tsx | 23 +---------------------- 1 file changed, 1 insertion(+), 22 deletions(-) diff --git a/src/components/Form/BaseRadioField.tsx b/src/components/Form/BaseRadioField.tsx index c6deb5f..8633957 100644 --- a/src/components/Form/BaseRadioField.tsx +++ b/src/components/Form/BaseRadioField.tsx @@ -1,4 +1,3 @@ -import { cva } from 'class-variance-authority'; import type { Simplify } from 'type-fest'; import { Label } from '../Label/Label.tsx'; @@ -7,25 +6,12 @@ import { FieldGroup } from './FieldGroup/FieldGroup.tsx'; import type { BaseFieldComponentProps } from './types.ts'; -const baseRadioFieldVariants = cva('flex', { - defaultVariants: { - orientation: 'vertical' - }, - variants: { - orientation: { - horizontal: 'flex-col @3xl:flex-row @3xl:items-center @3xl:justify-between', - vertical: 'flex-col' - } - } -}); - export type BaseRadioFieldProps = Simplify< BaseFieldComponentProps & { description?: string; disabled?: boolean; label: string; options: { [K in T]: string }; - orientation?: 'horizontal' | 'vertical'; } >; @@ -36,24 +22,17 @@ export const BaseRadioField = ({ label, name, options, - orientation = 'vertical', readOnly, setValue, value }: BaseRadioFieldProps) => { - const optionsCount = Object.keys(options).length; return ( - 5 ? 'vertical' : orientation })} - name={name} - value={value ?? ''} - onValueChange={(value) => setValue(value as T)} - > + setValue(value as T)}> {Object.keys(options).map((option) => (
From 1b19300fd4037a3126725bb29c3470126d579d10 Mon Sep 17 00:00:00 2001 From: joshunrau Date: Tue, 24 Feb 2026 16:54:28 -0500 Subject: [PATCH 3/6] refactor: remove old logic --- src/components/Form/NumberField/NumberFieldRadio.tsx | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/components/Form/NumberField/NumberFieldRadio.tsx b/src/components/Form/NumberField/NumberFieldRadio.tsx index 23da611..a6b69ab 100644 --- a/src/components/Form/NumberField/NumberFieldRadio.tsx +++ b/src/components/Form/NumberField/NumberFieldRadio.tsx @@ -2,7 +2,6 @@ import type { NumberFormField } from '@douglasneuroinformatics/libui-form-types' import type { Simplify } from 'type-fest'; import { Label, RadioGroup } from '#components'; -import { cn } from '#utils'; import { FieldGroup } from '../FieldGroup/FieldGroup.tsx'; @@ -24,8 +23,6 @@ export const NumberFieldRadio = ({ setValue, value }: NumberFieldRadioProps) => { - const optionsCount = Object.keys(options).length; - return ( @@ -33,10 +30,7 @@ export const NumberFieldRadio = ({ 5 ? 'flex-col' : 'flex-col @3xl:flex-row @3xl:items-center @3xl:justify-between' - )} + className="flex gap-2" name={name} value={value?.toString() ?? ''} onValueChange={(value) => setValue(parseInt(value))} From 927824f6fff1906c75c4a7de201e8a333bd1a6b9 Mon Sep 17 00:00:00 2001 From: joshunrau Date: Tue, 24 Feb 2026 17:00:19 -0500 Subject: [PATCH 4/6] fix: update number field radio overflow styles --- src/components/Form/NumberField/NumberFieldRadio.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/components/Form/NumberField/NumberFieldRadio.tsx b/src/components/Form/NumberField/NumberFieldRadio.tsx index a6b69ab..b6756c3 100644 --- a/src/components/Form/NumberField/NumberFieldRadio.tsx +++ b/src/components/Form/NumberField/NumberFieldRadio.tsx @@ -39,16 +39,16 @@ export const NumberFieldRadio = ({ .map((val) => parseInt(val)) .toSorted((a, b) => a - b) .map((val) => { - const text = (disableAutoPrefix ? '' : `${val} - `) + options[val]; return ( -
+
); From 429bf60aae2e98fdaeea9c1fe4be93175b4c8b6a Mon Sep 17 00:00:00 2001 From: joshunrau Date: Tue, 24 Feb 2026 22:10:18 -0500 Subject: [PATCH 5/6] fix: automatically determine whether number radio field should be vertical or horizontal layout --- .../Form/NumberField/NumberFieldRadio.tsx | 31 +++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/src/components/Form/NumberField/NumberFieldRadio.tsx b/src/components/Form/NumberField/NumberFieldRadio.tsx index b6756c3..a845985 100644 --- a/src/components/Form/NumberField/NumberFieldRadio.tsx +++ b/src/components/Form/NumberField/NumberFieldRadio.tsx @@ -1,3 +1,5 @@ +import { useEffect, useRef, useState } from 'react'; + import type { NumberFormField } from '@douglasneuroinformatics/libui-form-types'; import type { Simplify } from 'type-fest'; @@ -23,6 +25,27 @@ export const NumberFieldRadio = ({ setValue, value }: NumberFieldRadioProps) => { + const radioGroupRef = useRef(null); + const [isColumnLayout, setIsColumnLayout] = useState(false); + const isColumnLayoutRef = useRef(isColumnLayout); + + const optionsCount = Object.keys(options).length; + + useEffect(() => { + const observer = new ResizeObserver(([entry]) => { + const { width: rootWidth } = entry!.target.getBoundingClientRect(); + const children = Array.from(entry!.target.children); + const totalChildWidth = children.reduce((sum, child) => sum + child.scrollWidth, 0); + const isOverflowing = totalChildWidth > rootWidth - children.length * 24; // to provide spacing between items + setIsColumnLayout(isOverflowing); + isColumnLayoutRef.current = isOverflowing; + }); + if (radioGroupRef.current) { + observer.observe(radioGroupRef.current); + } + return () => observer.disconnect(); + }, []); + return ( @@ -30,8 +53,12 @@ export const NumberFieldRadio = ({ setValue(parseInt(value))} > @@ -40,7 +67,7 @@ export const NumberFieldRadio = ({ .toSorted((a, b) => a - b) .map((val) => { return ( -
+