diff --git a/CHANGELOG.md b/CHANGELOG.md index c8a3fef2..7f30cc86 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,59 +2,65 @@ ## Unreleased +This version updates nhsuk-frontend to version 9. + +For a full list of changes in this release please refer to the [migration doc](https://github.com/NHSDigital/nhsuk-react-components/blob/main/docs/upgrade-to-5.0.md). + +## 4.1.3 - 23 September 2024 + :wrench: **Fixes** -* Remove the unnecessary aria-labelledby tags from radio items. PR [#253](https://github.com/NHSDigital/nhsuk-react-components/pull/253) +- Remove the unnecessary aria-labelledby tags from radio items. PR [#253](https://github.com/NHSDigital/nhsuk-react-components/pull/253) ## 4.1.2 - 3 September 2024 :wrench: **Fixes** -* Fix issues with SkipLink (always set the href) and bring into line with NHSUK frontend. PR [#248](https://github.com/NHSDigital/nhsuk-react-components/pull/248) +- Fix issues with SkipLink (always set the href) and bring into line with NHSUK frontend. PR [#248](https://github.com/NHSDigital/nhsuk-react-components/pull/248) ## 4.1.1 - 9 August 2024 :wrench: **Fixes** -* Remove the unnecessary aria-labelledby tags from DateInput fields. PR [#246](https://github.com/NHSDigital/nhsuk-react-components/pull/246) +- Remove the unnecessary aria-labelledby tags from DateInput fields. PR [#246](https://github.com/NHSDigital/nhsuk-react-components/pull/246) ## 4.1.0 - 11 June 2024 :wrench: **Fixes** -* Add js shims for buttons. PR [#231](https://github.com/NHSDigital/nhsuk-react-components/pull/231), Fixes [#218](https://github.com/NHSDigital/nhsuk-react-components/issues/218) -* Fix errors not being linked to inputs. PR [#230](https://github.com/NHSDigital/nhsuk-react-components/pull/230), Fixes [#227](https://github.com/NHSDigital/nhsuk-react-components/issues/227) -* Fix inputs incorrectly using `aria-labelledby`. PR [#230](https://github.com/NHSDigital/nhsuk-react-components/pull/230), Fixes [#212](https://github.com/NHSDigital/nhsuk-react-components/issues/212) -* Update Storybook docs for several components. +- Add js shims for buttons. PR [#231](https://github.com/NHSDigital/nhsuk-react-components/pull/231), Fixes [#218](https://github.com/NHSDigital/nhsuk-react-components/issues/218) +- Fix errors not being linked to inputs. PR [#230](https://github.com/NHSDigital/nhsuk-react-components/pull/230), Fixes [#227](https://github.com/NHSDigital/nhsuk-react-components/issues/227) +- Fix inputs incorrectly using `aria-labelledby`. PR [#230](https://github.com/NHSDigital/nhsuk-react-components/pull/230), Fixes [#212](https://github.com/NHSDigital/nhsuk-react-components/issues/212) +- Update Storybook docs for several components. :new: **New features** -* Added a CHANGELOG to keep track of changes between releases. [Keep a changelog](https://keepachangelog.com) -* Added support for `preventDoubleClick` debouncing on buttons. PR [#231](https://github.com/NHSDigital/nhsuk-react-components/pull/231) -* Error summaries now automatically set role, tabindex, and aria-labelledby. PR [#229](https://github.com/NHSDigital/nhsuk-react-components/pull/237), Fixes [#228](https://github.com/NHSDigital/nhsuk-react-components/issues/229) -* Storybook link in readme now points to latest version. PR [#226](https://github.com/NHSDigital/nhsuk-react-components/pull/226) +- Added a CHANGELOG to keep track of changes between releases. [Keep a changelog](https://keepachangelog.com) +- Added support for `preventDoubleClick` debouncing on buttons. PR [#231](https://github.com/NHSDigital/nhsuk-react-components/pull/231) +- Error summaries now automatically set role, tabindex, and aria-labelledby. PR [#229](https://github.com/NHSDigital/nhsuk-react-components/pull/237), Fixes [#228](https://github.com/NHSDigital/nhsuk-react-components/issues/229) +- Storybook link in readme now points to latest version. PR [#226](https://github.com/NHSDigital/nhsuk-react-components/pull/226) ## 4.0.2 - 21 May 2024 :wrench: **Fixes** -* Fix error message role by @edwardhorsford in [#219](https://github.com/NHSDigital/nhsuk-react-components/pull/219) +- Fix error message role by @edwardhorsford in [#219](https://github.com/NHSDigital/nhsuk-react-components/pull/219) ## 4.0.1 - 20 May 2024 :wrench: **Fixes** -* Fix issue with the footer copyright not being rendered in the correct location if there are multiple link columns by @jakeb-nhs in [#223](https://github.com/NHSDigital/nhsuk-react-components/pull/223) +- Fix issue with the footer copyright not being rendered in the correct location if there are multiple link columns by @jakeb-nhs in [#223](https://github.com/NHSDigital/nhsuk-react-components/pull/223) ## 4.0.0 - 15 May 2024 This version updates nhsuk-frontend to version 8. -For a full list of changes in this release please refer to the [migration doc](https://github.com/NHSDigital/nhsuk-react-components/blob/feature/nhsuk-frontend-v8/docs/upgrade-to-4.0.md). +For a full list of changes in this release please refer to the [migration doc](https://github.com/NHSDigital/nhsuk-react-components/blob/main/docs/upgrade-to-4.0.md). -* Migrate enzyme to react-testing-library by @JoshuaBates-NHS in [#198](https://github.com/NHSDigital/nhsuk-react-components/pull/198) -* Allow support for module directives in build process by @JoshuaBates-NHS in [#199](https://github.com/NHSDigital/nhsuk-react-components/pull/199) -* Update modified components since NHS UK frontend v5 by @jakeb-nhs in [#197](https://github.com/NHSDigital/nhsuk-react-components/pull/197) -* Add new components since NHS UK frontend v5 by @jakeb-nhs in [#202](https://github.com/NHSDigital/nhsuk-react-components/pull/202) -* Migrate some patterns to components, rework removed components from frontend v8 by @jakeb-nhs in [#203](https://github.com/NHSDigital/nhsuk-react-components/pull/203) -* Improve unit test coverage by @jakeb-nhs in [#204](https://github.com/NHSDigital/nhsuk-react-components/pull/204) +- Migrate enzyme to react-testing-library by @JoshuaBates-NHS in [#198](https://github.com/NHSDigital/nhsuk-react-components/pull/198) +- Allow support for module directives in build process by @JoshuaBates-NHS in [#199](https://github.com/NHSDigital/nhsuk-react-components/pull/199) +- Update modified components since NHS UK frontend v5 by @jakeb-nhs in [#197](https://github.com/NHSDigital/nhsuk-react-components/pull/197) +- Add new components since NHS UK frontend v5 by @jakeb-nhs in [#202](https://github.com/NHSDigital/nhsuk-react-components/pull/202) +- Migrate some patterns to components, rework removed components from frontend v8 by @jakeb-nhs in [#203](https://github.com/NHSDigital/nhsuk-react-components/pull/203) +- Improve unit test coverage by @jakeb-nhs in [#204](https://github.com/NHSDigital/nhsuk-react-components/pull/204) diff --git a/README.md b/README.md index 4dd88788..8d29ceec 100644 --- a/README.md +++ b/README.md @@ -38,10 +38,11 @@ class GetStartedButton extends PureComponent { ## Upgrading -* [Upgrading to 1.0](/docs/upgrade-to-1.0.md) -* [Upgrading to 2.0](/docs/upgrade-to-2.0.md) -* [Upgrading to 3.0](/docs/upgrade-to-3.0.md) -* [Upgrading to 4.0](/docs/upgrade-to-4.0.md) +- [Upgrading to 1.0](/docs/upgrade-to-1.0.md) +- [Upgrading to 2.0](/docs/upgrade-to-2.0.md) +- [Upgrading to 3.0](/docs/upgrade-to-3.0.md) +- [Upgrading to 4.0](/docs/upgrade-to-4.0.md) +- [Upgrading to 5.0](/docs/upgrade-to-5.0.md) ## Maintainers diff --git a/docs/upgrade-to-5.0.md b/docs/upgrade-to-5.0.md new file mode 100644 index 00000000..a7654702 --- /dev/null +++ b/docs/upgrade-to-5.0.md @@ -0,0 +1,42 @@ +# Upgrading to 5.0 + +## Breaking changes + +## New Features + +### FormGroup + +In order to provide consumers of this library more control over when to render fieldsets, some behaviour of the previous `Fieldset` component has been extracted into a new `FormGroup` component. This makes `FormGroup` responsible for rendering the error decorator line for groups of inputs, and `Fieldset` is now a simpler component which makes use of this component. + +No changes are required for existing usages of `Fieldset`. For examples of the usage of `FormGroup`, please see storybook. + +For example, this: + +``` +
+ What is your address? + + +
+``` + +Would become this: + +``` + +
+ What is your address? + + +
+
+``` + +Which also allows consumers to omit the `Fieldset` if rendering a single input: + +``` + + What is your address? + + +``` diff --git a/src/__tests__/index.test.ts b/src/__tests__/index.test.ts index 4b340050..80446756 100644 --- a/src/__tests__/index.test.ts +++ b/src/__tests__/index.test.ts @@ -36,6 +36,7 @@ describe('Index', () => { 'Fieldset', 'Footer', 'Form', + 'FormGroup', 'Header', 'Hero', 'HintText', diff --git a/src/components/content-presentation/do-and-dont-list/DoAndDontList.tsx b/src/components/content-presentation/do-and-dont-list/DoAndDontList.tsx index 38191e5d..28c037a2 100644 --- a/src/components/content-presentation/do-and-dont-list/DoAndDontList.tsx +++ b/src/components/content-presentation/do-and-dont-list/DoAndDontList.tsx @@ -2,7 +2,7 @@ import React, { FC, HTMLProps, createContext, useContext, ReactNode } from 'react'; import classNames from 'classnames'; import { Tick, Cross } from '@components/content-presentation/icons'; -import HeadingLevel, { HeadingLevelType } from '@util/HeadingLevel'; +import HeadingLevel, { HeadingLevelType } from '@components/utils/HeadingLevel'; type ListType = 'do' | 'dont'; diff --git a/src/components/content-presentation/hero/Hero.tsx b/src/components/content-presentation/hero/Hero.tsx index 15999056..09a60434 100644 --- a/src/components/content-presentation/hero/Hero.tsx +++ b/src/components/content-presentation/hero/Hero.tsx @@ -1,7 +1,7 @@ import React, { FC, HTMLProps } from 'react'; import classNames from 'classnames'; import { Container, Row, Col } from '../../layout'; -import HeadingLevel, { HeadingLevelType } from '@util/HeadingLevel'; +import HeadingLevel, { HeadingLevelType } from '@components/utils/HeadingLevel'; interface HeroContentProps extends HTMLProps { hasImage: boolean; diff --git a/src/components/content-presentation/table/components/TablePanel.tsx b/src/components/content-presentation/table/components/TablePanel.tsx index 7b60290b..7542a14e 100644 --- a/src/components/content-presentation/table/components/TablePanel.tsx +++ b/src/components/content-presentation/table/components/TablePanel.tsx @@ -1,6 +1,6 @@ import React, { FC, ComponentProps, HTMLProps } from 'react'; import classNames from 'classnames'; -import HeadingLevel from '@util/HeadingLevel'; +import HeadingLevel from '@components/utils/HeadingLevel'; export interface TablePanelProps extends HTMLProps { heading?: string; diff --git a/src/components/content-presentation/tabs/Tabs.tsx b/src/components/content-presentation/tabs/Tabs.tsx index db921a0c..edfcf250 100644 --- a/src/components/content-presentation/tabs/Tabs.tsx +++ b/src/components/content-presentation/tabs/Tabs.tsx @@ -1,7 +1,7 @@ 'use client'; import classNames from 'classnames'; import React, { FC, HTMLAttributes, useEffect } from 'react'; -import HeadingLevel, { HeadingLevelType } from '@util/HeadingLevel'; +import HeadingLevel, { HeadingLevelType } from '@components/utils/HeadingLevel'; import TabsJs from '@resources/tabs'; type TabsProps = HTMLAttributes; diff --git a/src/components/content-presentation/tabs/__tests__/Tabs.test.tsx b/src/components/content-presentation/tabs/__tests__/Tabs.test.tsx index 33e5ee9c..7f332f2a 100644 --- a/src/components/content-presentation/tabs/__tests__/Tabs.test.tsx +++ b/src/components/content-presentation/tabs/__tests__/Tabs.test.tsx @@ -1,7 +1,7 @@ import React from 'react'; import { fireEvent, render } from '@testing-library/react'; import Tabs from '../Tabs'; -import { HeadingLevelType } from '@util/HeadingLevel'; +import { HeadingLevelType } from '@components/utils/HeadingLevel'; describe('The tabs component', () => { it('Matches the snapshot', () => { diff --git a/src/components/content-presentation/warning-callout/WarningCallout.tsx b/src/components/content-presentation/warning-callout/WarningCallout.tsx index d63f5283..e908c6ee 100644 --- a/src/components/content-presentation/warning-callout/WarningCallout.tsx +++ b/src/components/content-presentation/warning-callout/WarningCallout.tsx @@ -1,6 +1,6 @@ import React, { FC, HTMLProps } from 'react'; import classNames from 'classnames'; -import HeadingLevel, { HeadingLevelType } from '@util/HeadingLevel'; +import HeadingLevel, { HeadingLevelType } from '@components/utils/HeadingLevel'; interface WarningCalloutLabelProps extends HTMLProps { headingLevel?: HeadingLevelType; diff --git a/src/components/form-elements/checkboxes/Checkboxes.tsx b/src/components/form-elements/checkboxes/Checkboxes.tsx index b2b1083e..4b10e37b 100644 --- a/src/components/form-elements/checkboxes/Checkboxes.tsx +++ b/src/components/form-elements/checkboxes/Checkboxes.tsx @@ -3,7 +3,7 @@ import React, { HTMLProps, useEffect } from 'react'; import classNames from 'classnames'; import { FormElementProps } from '@util/types/FormTypes'; -import FormGroup from '@util/FormGroup'; +import SingleInputFormGroup from '@components/utils/SingleInputFormGroup'; import CheckboxContext, { ICheckboxContext } from './CheckboxContext'; import Box from './components/Box'; import Divider from './components/Divider'; @@ -53,7 +53,7 @@ const Checkboxes = ({ children, idPrefix, ...rest }: CheckboxesProps) => { }; return ( - inputType="checkboxes" {...rest}> + inputType="checkboxes" {...rest}> {/* eslint-disable-next-line @typescript-eslint/no-unused-vars */} {({ className, name, id, idPrefix, error, ...restRenderProps }) => { resetCheckboxIds(); @@ -69,7 +69,7 @@ const Checkboxes = ({ children, idPrefix, ...rest }: CheckboxesProps) => { ); }} - + ); }; diff --git a/src/components/form-elements/date-input/DateInput.tsx b/src/components/form-elements/date-input/DateInput.tsx index a4f8adb3..50f2040b 100644 --- a/src/components/form-elements/date-input/DateInput.tsx +++ b/src/components/form-elements/date-input/DateInput.tsx @@ -3,7 +3,7 @@ import React, { HTMLProps, ChangeEvent, useEffect, useState } from 'react'; import classNames from 'classnames'; import { DayInput, MonthInput, YearInput } from './components/IndividualDateInputs'; -import FormGroup from '@util/FormGroup'; +import SingleInputFormGroup from '@components/utils/SingleInputFormGroup'; import DateInputContext, { IDateInputContext } from './DateInputContext'; import { FormElementProps } from '@util/types/FormTypes'; @@ -90,7 +90,10 @@ const DateInput = ({ }; return ( - > inputType="dateinput" {...rest}> + > + inputType="dateinput" + {...rest} + > {/* eslint-disable-next-line @typescript-eslint/no-unused-vars */} {({ className, name, id, error, autoSelectNext, ...restRenderProps }) => { const contextValue: IDateInputContext = { @@ -116,7 +119,7 @@ const DateInput = ({ ); }} - + ); }; diff --git a/src/components/form-elements/fieldset/Fieldset.tsx b/src/components/form-elements/fieldset/Fieldset.tsx index 2451c40a..6107096e 100644 --- a/src/components/form-elements/fieldset/Fieldset.tsx +++ b/src/components/form-elements/fieldset/Fieldset.tsx @@ -1,8 +1,8 @@ -import React, { FC, HTMLProps, MutableRefObject, useMemo, useState } from 'react'; +import React, { FC, HTMLProps, MutableRefObject } from 'react'; import classNames from 'classnames'; import { NHSUKSize } from '@util/types/NHSUKTypes'; -import HeadingLevel, { HeadingLevelType } from '@util/HeadingLevel'; -import FieldsetContext, { IFieldsetContext } from './FieldsetContext'; +import HeadingLevel, { HeadingLevelType } from '@components/utils/HeadingLevel'; +import FormGroup from '@components/utils/FormGroup'; interface LegendProps extends Omit, 'size'> { isPageHeading?: boolean; @@ -41,63 +41,14 @@ const Legend: FC = ({ interface FieldsetProps extends HTMLProps { fieldsetRef?: MutableRefObject; - disableErrorLine?: boolean; } -const FieldSet = ({ className, disableErrorLine, fieldsetRef, ...rest }: FieldsetProps) => { - const [registeredComponents, setRegisteredComponents] = useState([]); - const [erroredComponents, setErroredComponents] = useState([]); - - const passError = (componentId: string, error: boolean): void => { - const existingError = erroredComponents.includes(componentId); - if (existingError && !error) { - setErroredComponents(erroredComponents.filter((id) => id !== componentId)); - return; - } - if (!existingError && error) { - setErroredComponents([...erroredComponents, componentId]); - } - }; - - const registerComponent = (componentId: string, deregister = false): void => { - let newComponents = [...registeredComponents]; - if (deregister) { - newComponents = newComponents.filter((id) => id !== componentId); - } else if (!registeredComponents.includes(componentId)) { - newComponents = [...newComponents, componentId]; - } - setRegisteredComponents(newComponents); - }; - - const contextValue: IFieldsetContext = useMemo(() => { - return { - isFieldset: true, - registerComponent: registerComponent, - passError: passError, - }; - }, [registerComponent, passError]); - - const containsFormElements = registeredComponents.length > 0; - const containsError = erroredComponents.length > 0; - +const FieldSet = ({ className, fieldsetRef, ...rest }: FieldsetProps) => { + rest.children; return ( - - {containsFormElements ? ( -
-
-
- ) : ( -
- )} - + +
+ ); }; diff --git a/src/components/form-elements/fieldset/__tests__/Fieldset.test.tsx b/src/components/form-elements/fieldset/__tests__/Fieldset.test.tsx index c71ada1f..ed69c322 100644 --- a/src/components/form-elements/fieldset/__tests__/Fieldset.test.tsx +++ b/src/components/form-elements/fieldset/__tests__/Fieldset.test.tsx @@ -5,7 +5,11 @@ import TextInput from '@components/form-elements/text-input'; describe('Fieldset', () => { it('matches snapshot', () => { - const { container } = render(
Text
); + const { container } = render( +
+ +
, + ); expect(container).toMatchSnapshot('Fieldset'); }); diff --git a/src/components/form-elements/fieldset/__tests__/__snapshots__/Fieldset.test.tsx.snap b/src/components/form-elements/fieldset/__tests__/__snapshots__/Fieldset.test.tsx.snap index e3e9f750..347741cd 100644 --- a/src/components/form-elements/fieldset/__tests__/__snapshots__/Fieldset.test.tsx.snap +++ b/src/components/form-elements/fieldset/__tests__/__snapshots__/Fieldset.test.tsx.snap @@ -12,10 +12,23 @@ exports[`Fieldset Fieldset.Legend matches snapshot: FieldsetLegend 1`] = ` exports[`Fieldset matches snapshot: Fieldset 1`] = `
-
- Text -
+
+
+ +
+
+
`; diff --git a/src/components/form-elements/radios/Radios.tsx b/src/components/form-elements/radios/Radios.tsx index b8bf2aa3..a2e59370 100644 --- a/src/components/form-elements/radios/Radios.tsx +++ b/src/components/form-elements/radios/Radios.tsx @@ -2,7 +2,7 @@ import React, { HTMLProps, useState } from 'react'; import classNames from 'classnames'; import { FormElementProps } from '@util/types/FormTypes'; import { RadiosContext, IRadiosContext } from './RadioContext'; -import FormGroup from '@util/FormGroup'; +import SingleInputFormGroup from '@components/utils/SingleInputFormGroup'; import Divider from './components/Divider'; import Radio from './components/Radio'; import { generateRandomName } from '@util/RandomID'; @@ -53,7 +53,7 @@ const Radios = ({ children, idPrefix, ...rest }: RadiosProps) => { }; return ( - inputType="radios" {...rest}> + inputType="radios" {...rest}> {/* eslint-disable-next-line @typescript-eslint/no-unused-vars */} {({ className, inline, name, id, error, ...restRenderProps }) => { resetRadioIds(); @@ -76,7 +76,7 @@ const Radios = ({ children, idPrefix, ...rest }: RadiosProps) => { ); }} - + ); }; diff --git a/src/components/form-elements/select/Select.tsx b/src/components/form-elements/select/Select.tsx index 38ad6af7..daac61e5 100644 --- a/src/components/form-elements/select/Select.tsx +++ b/src/components/form-elements/select/Select.tsx @@ -2,7 +2,7 @@ import React, { FC, HTMLProps, MutableRefObject } from 'react'; import classNames from 'classnames'; import { FormElementProps } from '@util/types/FormTypes'; -import FormGroup from '@util/FormGroup'; +import SingleInputFormGroup from '@components/utils/SingleInputFormGroup'; // SelectProps = HTMLProps & FormElementProps; interface ISelectProps extends HTMLProps, FormElementProps { @@ -14,7 +14,7 @@ interface ISelect extends FC { } const Select: ISelect = ({ children, ...rest }) => ( - inputType="select" {...rest}> + inputType="select" {...rest}> {({ className, error, selectRef, ...restRenderProps }) => ( )} - + ); const Option: FC> = (props) =>