Functional Weave
Code in Rust

react.form.fieldset@1.0.1

impl/typescript.tsx

1,753 bytes · the TypeScript implementation · view raw

Imports name this capability’s declared dependencies, which fune builds next to it in your project; each one links to its page.

import { useId, type JSX, type ReactNode } from "react";
import { fieldIds } from "./react_form_form_field.ts";  ← from react.form.form-field ^1.0.0 · built alongside by fune
import type { FieldsetProps } from "./react_form_fieldset_types.ts";

function present(node: ReactNode): boolean {
  return node !== null && node !== undefined && node !== false && node !== "";
}

/**
 * The GOV.UK fieldset: a legend that asks the question, then the hint and the
 * error message, then the inputs. The hint and error describe the fieldset
 * itself, so a screen reader announces them once on entering the group
 * rather than on every input. With isPageHeading the legend holds the page's
 * h1, the pattern for a page that asks one question.
 */
export function Fieldset(props: FieldsetProps): JSX.Element {
  const auto = useId();
  const { legend, hint, error, isPageHeading, children, className } = props;
  const id = props.id ?? auto;
  const ids = fieldIds(id, present(hint), present(error));
  const classes = ["fune-field", ids.error ? "fune-field--error" : null, className || null].filter(Boolean).join(" ");
  return (
    <div className={classes}>
      <fieldset className="fune-fieldset" aria-describedby={ids.describedBy ?? undefined}>
        <legend className={isPageHeading ? "fune-legend fune-legend--heading" : "fune-legend"}>
          {isPageHeading ? <h1 className="fune-legend-heading">{legend}</h1> : legend}
        </legend>
        {ids.hint ? (
          <div className="fune-hint" id={ids.hint}>
            {hint}
          </div>
        ) : null}
        {ids.error ? (
          <p className="fune-error-message" id={ids.error}>
            <span className="fune-visually-hidden">Error:</span> {error}
          </p>
        ) : null}
        {children}
      </fieldset>
    </div>
  );
}