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>
);
}