Browse Source

fix: connected labels to inputs, improving accessibility and testability

pull/475/head
Dan Ditomaso 1 year ago
parent
commit
fa85e83817
  1. 39
      src/components/Form/DynamicForm.tsx
  2. 1
      src/components/Form/FormInput.tsx
  3. 2
      src/components/Form/FormPasswordGenerator.tsx
  4. 2
      src/components/Form/FormSelect.tsx
  5. 1
      src/components/Form/FormToggle.tsx
  6. 4
      src/components/Form/FormWrapper.tsx
  7. 2
      src/components/PageComponents/Config/Security/Security.tsx
  8. 4
      src/components/UI/Generator.tsx

39
src/components/Form/DynamicForm.tsx

@ -98,24 +98,27 @@ export function DynamicForm<T extends FieldValues>({
<Subtle>{fieldGroup.description}</Subtle> <Subtle>{fieldGroup.description}</Subtle>
</div> </div>
{fieldGroup.fields.map((field) => ( {fieldGroup.fields.map((field) => {
<FieldWrapper return (
key={field.label} <FieldWrapper
label={field.label} key={field.label}
description={field.description} label={field.label}
valid={ fieldName={field.name}
field.validationText === undefined || description={field.description}
field.validationText === "" valid={
} field.validationText === undefined ||
validationText={field.validationText} field.validationText === ""
> }
<DynamicFormField validationText={field.validationText}
field={field} >
control={control} <DynamicFormField
disabled={isDisabled(field.disabledBy, field.disabled)} field={field}
/> control={control}
</FieldWrapper> disabled={isDisabled(field.disabledBy, field.disabled)}
))} />
</FieldWrapper>
);
})}
</div> </div>
))} ))}
{hasSubmitButton && <Button type="submit">Submit</Button>} {hasSubmitButton && <Button type="submit">Submit</Button>}

1
src/components/Form/FormInput.tsx

@ -53,6 +53,7 @@ export function GenericInput<T extends FieldValues>({
} }
step={field.properties?.step} step={field.properties?.step}
value={field.type === "number" ? Number.parseFloat(value) : value} value={field.type === "number" ? Number.parseFloat(value) : value}
id={field.name}
onChange={(e) => { onChange={(e) => {
if (field.inputChange) field.inputChange(e); if (field.inputChange) field.inputChange(e);
onChange( onChange(

2
src/components/Form/FormPasswordGenerator.tsx

@ -11,6 +11,7 @@ import { Controller, type FieldValues } from "react-hook-form";
export interface PasswordGeneratorProps<T> extends BaseFormBuilderProps<T> { export interface PasswordGeneratorProps<T> extends BaseFormBuilderProps<T> {
type: "passwordGenerator"; type: "passwordGenerator";
id: string;
hide?: boolean; hide?: boolean;
bits?: { text: string; value: string; key: string }[]; bits?: { text: string; value: string; key: string }[];
devicePSKBitCount: number; devicePSKBitCount: number;
@ -41,6 +42,7 @@ export function PasswordGenerator<T extends FieldValues>({
render={({ field: { value, ...rest } }) => ( render={({ field: { value, ...rest } }) => (
<Generator <Generator
type={field.hide && !passwordShown ? "password" : "text"} type={field.hide && !passwordShown ? "password" : "text"}
id={field.id}
action={ action={
field.hide field.hide
? { ? {

2
src/components/Form/FormSelect.tsx

@ -50,7 +50,7 @@ export function SelectInput<T extends FieldValues>({
{...remainingProperties} {...remainingProperties}
{...rest} {...rest}
> >
<SelectTrigger> <SelectTrigger id={field.name}>
<SelectValue /> <SelectValue />
</SelectTrigger> </SelectTrigger>
<SelectContent> <SelectContent>

1
src/components/Form/FormToggle.tsx

@ -33,6 +33,7 @@ export function ToggleInput<T extends FieldValues>({
<Switch <Switch
checked={value} checked={value}
onCheckedChange={onChangeHandler(onChange)} onCheckedChange={onChangeHandler(onChange)}
id={field.name}
disabled={disabled} disabled={disabled}
{...field.properties} {...field.properties}
{...rest} {...rest}

4
src/components/Form/FormWrapper.tsx

@ -2,6 +2,7 @@ import { Label } from "@components/UI/Label.tsx";
export interface FieldWrapperProps { export interface FieldWrapperProps {
label: string; label: string;
fieldName: string;
description?: string; description?: string;
disabled?: boolean; disabled?: boolean;
children?: React.ReactNode; children?: React.ReactNode;
@ -11,6 +12,7 @@ export interface FieldWrapperProps {
export const FieldWrapper = ({ export const FieldWrapper = ({
label, label,
fieldName,
description, description,
children, children,
valid, valid,
@ -19,7 +21,7 @@ export const FieldWrapper = ({
<div className="pt-6 sm:pt-5"> <div className="pt-6 sm:pt-5">
<fieldset aria-labelledby="label-notifications"> <fieldset aria-labelledby="label-notifications">
<div className="sm:grid sm:grid-cols-3 sm:items-baseline sm:gap-4"> <div className="sm:grid sm:grid-cols-3 sm:items-baseline sm:gap-4">
<Label>{label}</Label> <Label htmlFor={fieldName}>{label}</Label>
<div className="sm:col-span-2"> <div className="sm:col-span-2">
<div className="max-w-lg"> <div className="max-w-lg">
<p className="text-sm text-slate-500">{description}</p> <p className="text-sm text-slate-500">{description}</p>

2
src/components/PageComponents/Config/Security/Security.tsx

@ -164,6 +164,7 @@ export const Security = () => {
fields: [ fields: [
{ {
type: "passwordGenerator", type: "passwordGenerator",
id: "pskInput",
name: "privateKey", name: "privateKey",
label: "Private Key", label: "Private Key",
description: "Used to create a shared key with a remote device", description: "Used to create a shared key with a remote device",
@ -234,6 +235,7 @@ export const Security = () => {
{ {
type: "passwordGenerator", type: "passwordGenerator",
name: "adminKey", name: "adminKey",
id: "adminKeyInput",
label: "Admin Key", label: "Admin Key",
description: description:
"The public key authorized to send admin messages to this node", "The public key authorized to send admin messages to this node",

4
src/components/UI/Generator.tsx

@ -15,6 +15,7 @@ export interface GeneratorProps extends React.BaseHTMLAttributes<HTMLElement> {
type: "text" | "password"; type: "text" | "password";
devicePSKBitCount?: number; devicePSKBitCount?: number;
value: string; value: string;
id: string;
variant: "default" | "invalid"; variant: "default" | "invalid";
actionButtons: { actionButtons: {
text: string; text: string;
@ -37,6 +38,7 @@ const Generator = React.forwardRef<HTMLInputElement, GeneratorProps>(
{ {
type, type,
devicePSKBitCount, devicePSKBitCount,
id = "pskInput",
variant, variant,
value, value,
actionButtons, actionButtons,
@ -73,7 +75,7 @@ const Generator = React.forwardRef<HTMLInputElement, GeneratorProps>(
<> <>
<Input <Input
type={type} type={type}
id="pskInput" id={id}
variant={variant} variant={variant}
value={value} value={value}
onChange={inputChange} onChange={inputChange}

Loading…
Cancel
Save