Functional Weave
Code in Python

react.form.checkbox@1.0.0

impl/typescript.tsx

2,207 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.

"use client";

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 { CheckboxProps } from "./react_form_checkbox_types.ts";

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

/**
 * One GOV.UK checkbox on its own: the error message above, then the box with
 * its label to the right and its hint under the label. It cannot use
 * FormField, whose label comes before the control, so it takes the same ids
 * from fieldIds. Unlike a checkbox in a group, it is a control of its own, so
 * the error describes it and marks it aria-invalid.
 */
export function Checkbox(props: CheckboxProps): JSX.Element {
  const auto = useId();
  const { label, value, checked, defaultChecked, onChange, onBlur, hint, error, required, disabled, 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}>
      {ids.error ? (
        <p className="fune-error-message" id={ids.error}>
          <span className="fune-visually-hidden">Error:</span> {error}
        </p>
      ) : null}
      <div className="fune-checkbox">
        <input
          className="fune-checkbox-input"
          id={ids.control}
          name={props.name ?? id}
          type="checkbox"
          value={value ?? "yes"}
          checked={checked}
          defaultChecked={defaultChecked}
          required={required}
          disabled={disabled}
          aria-describedby={ids.describedBy ?? undefined}
          aria-invalid={ids.error ? true : undefined}
          onBlur={onBlur ? () => onBlur() : undefined}
          onChange={(event) => onChange?.(event.target.checked)}
        />
        <label className="fune-label fune-checkbox-label" htmlFor={ids.control}>
          {label}
        </label>
        {ids.hint ? (
          <div className="fune-hint fune-checkbox-hint" id={ids.hint}>
            {hint}
          </div>
        ) : null}
      </div>
    </div>
  );
}