import { z } from 'zod' import { FieldBlockDefinition, ResolvableBoolean, ResolvableNumber, ResolvableString, } from '@ministryofjustice/hmpps-forge/core/components' import { nunjucksComponent } from '../../utils/nunjucksComponent' import { normaliseGovukErrorMessage, normaliseGovukTextParam } from '../../utils/govukParamNormalisers' /** * GOV.UK Textarea component. * A multi-line text input field. * * @see https://design-system.service.gov.uk/components/textarea/ * @example * ```typescript * GovUKTextareaInput({ * code: 'comments', * label: 'Please provide any additional comments', * hint: 'Include as much detail as possible', * rows: '8', * }) * ``` */ export interface GovUKTextareaInput extends FieldBlockDefinition { /** * The ID of the textarea. Defaults to the value of `code` if not provided. * * @example 'user-feedback' */ id?: ResolvableString /** * Optional field to enable or disable the `spellcheck` attribute on the textarea. * When not specified, browsers will use their default behavior. * * @example true // Enable spellcheck */ spellcheck?: ResolvableBoolean /** * Optional number of textarea rows. Defaults to 5 rows if not specified. * Controls the initial height of the textarea. * * @example 8 // Taller textarea * @example 3 // Shorter textarea */ rows?: ResolvableNumber | ResolvableString /** * The label used by the textarea component. * Can be a simple string or a complex object with additional properties. * * @example 'Your comments' // Simple string label * @example { text: 'Feedback', classes: 'govuk-label--l' } // Object with styling */ label?: | ResolvableString | { /** Text content of the label */ text?: ResolvableString /** HTML content of the label (takes precedence over text) */ html?: ResolvableString /** Additional CSS classes for the label */ classes?: ResolvableString /** Whether to render the label as a page heading (wrapped in h1) */ isPageHeading?: ResolvableBoolean /** Additional HTML attributes for the label */ attributes?: Record } /** * Can be used to add a hint to the textarea component. * Provides additional context or instructions for the user. * * @example 'Include as much detail as possible' // Simple string hint * @example { html: 'See guidance for examples' } // Rich HTML hint */ hint?: | ResolvableString | { /** Unique ID for the hint (auto-generated if not provided) */ id?: ResolvableString /** Text content of the hint */ text?: ResolvableString /** HTML content of the hint (takes precedence over text) */ html?: ResolvableString /** Additional CSS classes for the hint */ classes?: ResolvableString /** Additional HTML attributes for the hint */ attributes?: Record } /** Additional options for the form group containing the textarea component. */ formGroup?: { /** Classes to add to the form group wrapper. */ classes?: ResolvableString /** HTML attributes to add to the form group wrapper */ attributes?: Record /** Content to add before the textarea input */ beforeInput?: { /** Text content to add before the textarea */ text?: ResolvableString /** HTML content to add before the textarea (takes precedence over text) */ html?: ResolvableString } /** Content to add after the textarea input. */ afterInput?: { /** Text content to add after the textarea */ text?: ResolvableString /** HTML content to add after the textarea (takes precedence over text) */ html?: ResolvableString } } /** Additional CSS classes to add to the textarea element */ classes?: ResolvableString /** * If `true`, textarea will be disabled and cannot be edited by the user. * * @example true // Disable the textarea */ disabled?: ResolvableBoolean /** * Attribute to meet WCAG success criterion 1.3.5: Identify input purpose. * Helps browsers provide appropriate autofill suggestions. * * @see https://www.w3.org/WAI/WCAG22/Understanding/identify-input-purpose.html * @see https://html.spec.whatwg.org/multipage/form-control-infrastructure.html#autofill * @example 'street-address' // For address fields * @example 'off' // Disable autocomplete */ autocomplete?: ResolvableString /** * One or more element IDs to add to the `aria-describedby` attribute. * Used to provide additional descriptive information for screenreader users. * * @example 'comments-guidance' */ describedBy?: ResolvableString /** Additional HTML attributes (such as data attributes) to add to the textarea element. */ attributes?: Record } /** * GOV.UK Textarea component. * A multi-line text input field. * * @see https://design-system.service.gov.uk/components/textarea/ * @example * ```typescript * GovUKTextareaInput({ * code: 'comments', * label: 'Please provide any additional comments', * hint: 'Include as much detail as possible', * rows: '8', * }) * ``` */ export const GovUKTextareaInput = nunjucksComponent('govukTextarea', { field: true, inputSchema: z.string(), // The rendered textarea's id matches the render params below, so error summary links land on it. errorAnchor: props => props.id ?? props.code, render: (props, nunjucksEnv) => { const params = { id: props.id ?? props.code, name: props.code, spellcheck: props.spellcheck, rows: props.rows || '5', value: props.value, disabled: props.disabled, label: normaliseGovukTextParam(props.label), hint: normaliseGovukTextParam(props.hint), errorMessage: normaliseGovukErrorMessage(props.errors), formGroup: props.formGroup, classes: props.classes, autocomplete: props.autocomplete, describedBy: props.describedBy, attributes: props.attributes, } return nunjucksEnv.render('govuk/components/textarea/template.njk', { params, }) }, })