diff --git a/apps/client/src/stylesheets/style.css b/apps/client/src/stylesheets/style.css index 47368ca19..c5b24f88e 100644 --- a/apps/client/src/stylesheets/style.css +++ b/apps/client/src/stylesheets/style.css @@ -144,6 +144,10 @@ textarea, pointer-events: none; } +.form-group { + margin-bottom: 15px; +} + /* Add a gap between consecutive radios / check boxes */ label.tn-radio + label.tn-radio, label.tn-checkbox + label.tn-checkbox { diff --git a/apps/client/src/widgets/react/FormCheckbox.tsx b/apps/client/src/widgets/react/FormCheckbox.tsx index f064e2e79..b49f8af17 100644 --- a/apps/client/src/widgets/react/FormCheckbox.tsx +++ b/apps/client/src/widgets/react/FormCheckbox.tsx @@ -5,7 +5,7 @@ import { ComponentChildren } from "preact"; import { CSSProperties, memo } from "preact/compat"; interface FormCheckboxProps { - name: string; + id?: string; label: string | ComponentChildren; /** * If set, the checkbox label will be underlined and dotted, indicating a hint. When hovered, it will show the hint text. @@ -17,7 +17,7 @@ interface FormCheckboxProps { containerStyle?: CSSProperties; } -const FormCheckbox = memo(({ name, disabled, label, currentValue, onChange, hint, containerStyle }: FormCheckboxProps) => { +const FormCheckbox = memo(({ id, disabled, label, currentValue, onChange, hint, containerStyle }: FormCheckboxProps) => { const labelRef = useRef(null); // Fix: Move useEffect outside conditional @@ -55,9 +55,10 @@ const FormCheckbox = memo(({ name, disabled, label, currentValue, onChange, hint ref={labelRef} > ; label?: string; title?: string; className?: string; - children: ComponentChildren; + children: VNode; description?: string | ComponentChildren; disabled?: boolean; + style?: CSSProperties; } -export default function FormGroup({ label, title, className, children, description, labelRef, disabled }: FormGroupProps) { +export default function FormGroup({ name, label, title, className, children, description, labelRef, disabled, style }: FormGroupProps) { + const id = useUniqueName(name); + const childWithId = cloneElement(children, { id }); + return ( -
- { label - ? - : children} +
+ { label && + } + + {childWithId} {description && {description}}
diff --git a/apps/client/src/widgets/react/FormSelect.tsx b/apps/client/src/widgets/react/FormSelect.tsx index dc8916255..e4c9aa761 100644 --- a/apps/client/src/widgets/react/FormSelect.tsx +++ b/apps/client/src/widgets/react/FormSelect.tsx @@ -19,6 +19,7 @@ interface ValueConfig { } interface FormSelectProps extends ValueConfig { + id?: string; onChange: OnChangeListener; style?: CSSProperties; } @@ -26,9 +27,9 @@ interface FormSelectProps extends ValueConfig { /** * Combobox component that takes in any object array as data. Each item of the array is rendered as an item, and the key and values are obtained by looking into the object by a specified key. */ -export default function FormSelect({ onChange, style, ...restProps }: FormSelectProps) { +export default function FormSelect({ id, onChange, style, ...restProps }: FormSelectProps) { return ( - + ); @@ -37,9 +38,9 @@ export default function FormSelect({ onChange, style, ...restProps }: FormSel /** * Similar to {@link FormSelect}, but the top-level elements are actually groups. */ -export function FormSelectWithGroups({ values, keyProperty, titleProperty, currentValue, onChange }: FormSelectProps>) { +export function FormSelectWithGroups({ id, values, keyProperty, titleProperty, currentValue, onChange }: FormSelectProps>) { return ( - + {values.map(({ title, items }) => { return ( @@ -51,9 +52,10 @@ export function FormSelectWithGroups({ values, keyProperty, titleProperty, cu ) } -function FormSelectBody({ children, onChange, style }: { children: ComponentChildren, onChange: OnChangeListener, style?: CSSProperties }) { +function FormSelectBody({ id, children, onChange, style }: { id?: string, children: ComponentChildren, onChange: OnChangeListener, style?: CSSProperties }) { return (