diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d2a36d2f..a3323930 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,6 +1,9 @@ name: CI Build -on: [push, pull_request] +on: + push: + branches: main + pull_request: jobs: build: @@ -17,4 +20,4 @@ jobs: - name: Typescript build run: yarn build - name: Storybook build - run: yarn storybook-to-ghpages --dry-run --ci + run: yarn build-storybook diff --git a/.github/workflows/storybook.yml b/.github/workflows/storybook.yml index a4a6b7c5..822baab6 100644 --- a/.github/workflows/storybook.yml +++ b/.github/workflows/storybook.yml @@ -10,14 +10,15 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@master + uses: actions/checkout@v3 with: - persist-credentials: false + fetch-depth: 0 - name: Yarn Install run: yarn install - name: Deploy Storybook - run: yarn storybook-to-ghpages --ci - env: - GH_TOKEN: ${{ secrets.ACCESS_TOKEN }} + uses: chromaui/action@v1 + with: + projectToken: ${{ secrets.CHROMATIC_PROJECT_TOKEN }} + token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.gitignore b/.gitignore index 3c0e15fc..595b2073 100644 --- a/.gitignore +++ b/.gitignore @@ -110,3 +110,6 @@ dist lib/ yarn-error.log storybook-static/ + +# IDEA files +.idea/ diff --git a/.storybook/main.js b/.storybook/main.js deleted file mode 100644 index 875e1891..00000000 --- a/.storybook/main.js +++ /dev/null @@ -1,15 +0,0 @@ -const path = require("path"); - -module.exports = { - stories: ["../stories/**/*.stories.@(ts|tsx)"], - addons: ["@storybook/addon-links", "@storybook/addon-essentials"], - webpackFinal: (config) => { - config.module.rules.push({ - test: /\.scss$/, - use: ["style-loader", "css-loader", "sass-loader"], - include: path.resolve(__dirname, "../"), - }); - - return config; - }, -}; diff --git a/.storybook/main.ts b/.storybook/main.ts new file mode 100644 index 00000000..f5898702 --- /dev/null +++ b/.storybook/main.ts @@ -0,0 +1,13 @@ +import type { StorybookConfig } from '@storybook/react-vite'; +const config: StorybookConfig = { + stories: ['../stories/**/*.stories.@(ts|tsx)', '../stories/**/*.mdx'], + addons: ['@storybook/addon-links', '@storybook/addon-essentials'], + framework: { + name: '@storybook/react-vite', + options: {}, + }, + docs: { + autodocs: true, + }, +}; +export default config; diff --git a/.storybook/manager.js b/.storybook/manager.ts similarity index 100% rename from .storybook/manager.js rename to .storybook/manager.ts diff --git a/.storybook/preview.js b/.storybook/preview.js deleted file mode 100644 index 0e55b437..00000000 --- a/.storybook/preview.js +++ /dev/null @@ -1,5 +0,0 @@ -import "./storybook.scss"; - -export const parameters = { - actions: { argTypesRegex: "^on[A-Z].*" }, -}; diff --git a/.storybook/preview.ts b/.storybook/preview.ts new file mode 100644 index 00000000..3bbe79e5 --- /dev/null +++ b/.storybook/preview.ts @@ -0,0 +1,14 @@ +import './storybook.scss'; +import { Preview } from '@storybook/react'; + +const preview: Preview = { + parameters: { + actions: { argTypesRegex: '^on[A-Z].*' }, + options: { + storySort: { + order: ['Welcome', 'Migration Guides', 'Components', 'FormBehaviour', 'Deprecated'], + }, + }, + }, +}; +export default preview; diff --git a/.storybook/theme.js b/.storybook/theme.js deleted file mode 100644 index 9c61ceb5..00000000 --- a/.storybook/theme.js +++ /dev/null @@ -1,36 +0,0 @@ -import { create } from "@storybook/theming/create"; -const version = require("../package.json").version; - -export default create({ - base: "light", - background: "white", - colorPrimary: "#005eb8", - colorSecondary: "#768692", - - // UI - appBg: "white", - appContentBg: "white", - appBorderColor: "grey", - appBorderRadius: 4, - - // Typography - fontCode: "monospace", - - // Text colors - textColor: "#212b32", - textInverseColor: "white", - - // Toolbar default and active colors - barTextColor: "rgba(255,255,255,0.8)", - barSelectedColor: "rgba(255,255,255,1)", - barBg: "#005eb8", - - // Form colors - inputBg: "white", - inputBorder: "#425563", - inputTextColor: "#212b32", - inputBorderRadius: 4, - - brandTitle: `NHS.UK React Components (v${version})`, - brandUrl: "https://github.com/NHSDigital/nhsuk-react-components", -}); diff --git a/.storybook/theme.ts b/.storybook/theme.ts new file mode 100644 index 00000000..5d3ea651 --- /dev/null +++ b/.storybook/theme.ts @@ -0,0 +1,36 @@ +import { create } from '@storybook/theming/create'; +const version = require('../package.json').version; + +export default create({ + base: 'light', + + colorPrimary: '#005eb8', + colorSecondary: '#768692', + + // UI + appBg: 'white', + appContentBg: 'white', + appBorderColor: 'grey', + appBorderRadius: 4, + + // Typography + fontCode: 'monospace', + + // Text colors + textColor: '#212b32', + textInverseColor: 'white', + + // Toolbar default and active colors + barTextColor: 'rgba(255,255,255,0.8)', + barSelectedColor: 'rgba(255,255,255,1)', + barBg: '#005eb8', + + // Form colors + inputBg: 'white', + inputBorder: '#425563', + inputTextColor: '#212b32', + inputBorderRadius: 4, + + brandTitle: `NHS.UK React Components (v${version})`, + brandUrl: 'https://github.com/NHSDigital/nhsuk-react-components', +}); diff --git a/README.md b/README.md index d55e75d1..7f81c3a7 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ NHS.UK Frontend ported to React -[![GitHub Actions CI Status](https://github.com/NHSDigital/nhsuk-react-components/workflows/CI/badge.svg)](https://github.com/NHSDigital/nhsuk-react-components/actions?query=workflow%3A%22CI+Build%22+branch%3Amain) [![Bundle Size](https://img.shields.io/bundlephobia/minzip/nhsuk-react-components.svg)](https://bundlephobia.com/result?p=nhsuk-react-components) +[![GitHub Actions CI Status](https://github.com/NHSDigital/nhsuk-react-components/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/NHSDigital/nhsuk-react-components/actions?query=workflow%3A%22CI+Build%22+branch%3Amain) [![Bundle Size](https://img.shields.io/bundlephobia/minzip/nhsuk-react-components.svg)](https://bundlephobia.com/result?p=nhsuk-react-components) ## Coming from 0.x? @@ -19,7 +19,7 @@ If you're coming from versions of the library prior to 1.0.0, please give [this ## Upgrading to 2.0 -If you're upgrading to 2.0, please be aware we have made some breaking changes. [This doc](/docs/upgrade-to-2.0.md) has the details. +If you're upgrading to 2.0, please be aware we have made some breaking changes. [This doc](/docs/upgrade-to-2.0.md) has the details. ## Installation @@ -51,7 +51,7 @@ class GetStartedButton extends PureComponent { ### Storybook -A storybook containing all of the components and their usage can be found [here](https://nhsdigital.github.io/nhsuk-react-components). +A storybook containing all of the components and their usage can be found [here](https://main--6422e711d7f854c1b681c505.chromatic.com). ## Maintainers @@ -61,6 +61,7 @@ A storybook containing all of the components and their usage can be found [here] - Sam Brown ([GitHub](https://github.com/samueldavidbrown)) - Luke Pearson ([GitHub](https://github.com/lukepearson)) - Kevin Kuszyk ([GitHub](https://github.com/kevinkuszyk)) +- Kai Spencer ([GitHub](https://github.com/KaiSpencer)) ## Preparing Releases @@ -72,3 +73,9 @@ To prepare a release create a new release TAG in github with your release versio - Create a new release with a tag like `major.minor.patch` against main. - If the change is a `beta` then select `pre-release` as true, this will make the `tag` point at `beta`. Otherwise the tag will be `latest`. + +## Thanks + +Chromatic + +Thanks to [Chromatic](https://www.chromatic.com/) for providing the visual testing platform that helps us review UI changes and catch visual regressions. diff --git a/package.json b/package.json index f867e47b..daabefcf 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "nhsuk-react-components", - "version": "2.2.0", + "version": "2.2.1", "author": { "email": "thomas.judd-cooper1@nhs.net", "name": "Thomas Judd-Cooper", @@ -9,23 +9,31 @@ "license": "MIT", "devDependencies": { "@babel/cli": "^7.13.16", - "@babel/core": "^7.14.0", - "@rollup/plugin-commonjs": "^19.0.0", - "@rollup/plugin-node-resolve": "^13.0.0", - "@storybook/addon-actions": "^6.2.9", - "@storybook/addon-essentials": "^6.2.9", - "@storybook/addon-links": "^6.2.9", - "@storybook/react": "^6.2.9", - "@storybook/storybook-deployer": "^2.8.7", + "@babel/core": "^7.19.6", + "@babel/preset-react": "^7.18.6", + "@rollup/plugin-commonjs": "^24.1.0", + "@rollup/plugin-node-resolve": "^15.0.2", + "@rollup/plugin-typescript": "^11.1.0", + "@storybook/addon-actions": "^7.0.2", + "@storybook/addon-essentials": "^7.0.2", + "@storybook/addon-links": "^7.0.2", + "@storybook/addons": "^7.0.2", + "@storybook/blocks": "^7.0.2", + "@storybook/preview-web": "^7.0.2", + "@storybook/react": "^7.0.2", + "@storybook/react-vite": "^7.0.2", + "@storybook/theming": "^7.0.2", "@types/enzyme": "^3.10.8", "@types/jest": "^26.0.23", "@types/jest-axe": "^3.5.1", "@types/node": "^15.0.2", "@types/react": "16.14.0", "@types/react-dom": "^16.9.12", + "@types/rollup-plugin-peer-deps-external": "^2.2.1", "@typescript-eslint/eslint-plugin": "^4.23.0", "@typescript-eslint/parser": "^4.23.0", "babel-loader": "^8.2.2", + "chromatic": "^6.17.3", "enzyme": "^3.11.0", "enzyme-adapter-react-16": "^1.15.6", "enzyme-to-json": "^3.6.2", @@ -45,14 +53,15 @@ "react": "^16.14.0", "react-dom": "^16.14.0", "regenerator-runtime": "^0.13.7", - "rollup": "^2.47.0", + "rollup": "^3.20.2", + "rollup-plugin-dts": "^5.3.0", "rollup-plugin-peer-deps-external": "^2.2.4", - "rollup-plugin-typescript2": "^0.30.0", "sass": "^1.32.12", - "sass-loader": "10.1.1", + "storybook": "^7.0.2", "ts-jest": "^26.5.6", "ts-node": "^9.1.1", - "typescript": "4.2.4" + "typescript": "4.2.4", + "vite": "^4.2.1" }, "peerDependencies": { "nhsuk-frontend": ">=4.0.0", @@ -62,9 +71,12 @@ "dependencies": { "classnames": "^2.2.6" }, + "resolutions": { + "@types/react": "16.14.0" + }, "scripts": { "cleanup": "rm -rf dist/ > /dev/null && rm -rf lib/ > /dev/null", - "storybook": "start-storybook -p 6006", + "storybook": "storybook dev -p 6006", "build:dist": "rollup -c", "build:lib": "NODE_ENV=production babel src --out-dir lib --extensions \".ts,.tsx\" --ignore \"**/__tests__,**/__mocks__,**/setupTests.ts\"", "build": "yarn cleanup && yarn build:dist && yarn build:lib", @@ -72,8 +84,8 @@ "test:ci": "jest --coverage", "lint": "eslint 'src/**/*.{js,ts,tsx}' 'stories/**/*.{js,ts,tsx}' --fix", "lint:ci": "eslint 'src/**/*.{js,ts,tsx}' 'stories/**/*.{js,ts,tsx}'", - "build-storybook": "build-storybook", - "prepublishOnly": "yarn lint:ci && yarn test:ci && yarn start-storybook --smoke-test" + "build-storybook": "storybook build", + "prepublishOnly": "yarn lint:ci && yarn test:ci && yarn storybook --smoke-test" }, "files": [ "dist", diff --git a/rollup.config.js b/rollup.config.mjs similarity index 67% rename from rollup.config.js rename to rollup.config.mjs index 2093ae85..3f6632d4 100644 --- a/rollup.config.js +++ b/rollup.config.mjs @@ -1,16 +1,15 @@ import commonjs from '@rollup/plugin-commonjs'; import peerDepsExternal from 'rollup-plugin-peer-deps-external'; import resolve from '@rollup/plugin-node-resolve'; -import typescript from 'rollup-plugin-typescript2'; - -// eslint-disable-next-line @typescript-eslint/no-var-requires -const packageJson = require('./package.json'); +import typescript from '@rollup/plugin-typescript'; +import dts from 'rollup-plugin-dts'; +import packageJson from './package.json' assert { type: 'json' }; const plugins = [ peerDepsExternal(), resolve(), commonjs(), - typescript({ typescript: require('typescript') }), + typescript({ tsconfig: './tsconfig.json' }), ]; export default [ @@ -30,4 +29,9 @@ export default [ ], plugins, }, + { + input: 'dist/lib/index.d.ts', + output: [{ file: 'dist/index.d.ts', format: 'esm' }], + plugins: [dts()], + }, ]; diff --git a/src/components/breadcrumb/README.md b/src/components/breadcrumb/README.md deleted file mode 100644 index cc6e1ca5..00000000 --- a/src/components/breadcrumb/README.md +++ /dev/null @@ -1,26 +0,0 @@ -# Breadcrumb - -This component can be found in the `nhsuk-frontend` repository [here](https://github.com/nhsuk/nhsuk-frontend/tree/master/packages/components/breadcrumb). - -## Implementation Notes - -The `Breadcrumb` component contains two subcomponents: `Breadcrumb.Item` and `Breadcrumb.Back`. These are both anchor elements. - -The base `Breadcrumb` component has the default prop `aria-label` set to `"Breadcrumb"`. This is only a default prop and can be overridden. - -## Usage - -```jsx -import { Breadcrumb } from "nhsuk-react-components"; - -const Link = () => { - return ( - - Level one - Level two - Level three - Back to Level three - - ); -} -``` diff --git a/src/components/button/README.md b/src/components/button/README.md deleted file mode 100644 index 24b6f4c9..00000000 --- a/src/components/button/README.md +++ /dev/null @@ -1,37 +0,0 @@ -# Button - -This component can be found in the `nhsuk-frontend` repository [here](https://github.com/nhsuk/nhsuk-frontend/tree/master/packages/components/button). - -## Implementation Notes - -When importing `Button` from `nhsuk-react-components`, the `ButtonWrapper` component is imported. This will either render a standard `Button` or `ButtonLink` component depending on whether a `href` prop is supplied. - -If you want to use a specific component instead of the wrapper, you can supply the `as="a"` or `as="button"` props. - -## Usage - -### Standard - -```jsx -import { Button } from "nhsuk-react-components"; - -const Element = () => { - return ( - - ); -} -``` - -### As a Link - -```jsx -import { Button } from "nhsuk-react-components"; - -const ButtonEl = () => ( - -); - -const ButtonEl2 = () => ( - -); -``` diff --git a/src/components/care-card/README.md b/src/components/care-card/README.md deleted file mode 100644 index bcd4c911..00000000 --- a/src/components/care-card/README.md +++ /dev/null @@ -1,42 +0,0 @@ -# CareCard - -This component can be found in the `nhsuk-frontend` repository [here](https://github.com/nhsuk/nhsuk-frontend/tree/master/packages/components/care-card). - -## Implementation Notes - -By default, CareCard components prepend hidden text before the title. These are: - -- ("non-urgent") Non-urgent advice: -- ("urgent") Urgent advice: -- ("immediate") Immediate acion required: - -If you wish to disable this behaviour, pass the prop `visuallyHiddenText={false}` to the `CareCard.Heading` component or specify your own visually hidden text by using `visuallyHiddenText="Custom"`. - -You can change the heading type (i.e. `h1`, `h2` and so on) of the title by passing the prop `headingLevel=""` to the `CareCard.Heading`. - -## Usage - -**Note:** More detailed implementations can be found in the [Storybook](https://tomdango.github.io/nhsuk-react-components). - -### Standard - -```jsx -import { CareCard } from "nhsuk-react-components"; - -const Element = () => { - return ( - - Speak to a GP if: - -
    -
  • you're not sure it's chickenpox
  • -
  • the skin around the blisters is red, hot or painful (signs of infection)
  • -
  • your child is dehydrated
  • -
  • you're concerned about your child or they get worse
  • -
-

Tell the receptionist you think it's chickenpox before going in. They may recommend a special appointment time if other patients are at risk.

-
-
- ); -} -``` diff --git a/src/components/checkboxes/README.md b/src/components/checkboxes/README.md deleted file mode 100644 index 3235d2d7..00000000 --- a/src/components/checkboxes/README.md +++ /dev/null @@ -1,29 +0,0 @@ -# Checkboxes - -This component can be found in the `nhsuk-frontend` repository [here](https://github.com/nhsuk/nhsuk-frontend/tree/master/packages/components/checkboxes). - -## Implementation Notes - -For details on the new form design pattern, check the documentation for the `Form` component. - -The `Checkbox` component provides a `CheckboxContext` context, which the `Checkbox.Box` components use. When each box initially renders, it will attempt to assign itself an `id` by calling the `getBoxId` method in the context. This will assign each box a sequential ID using either the `idPrefix` or `name` supplied to the Checkbox. If neither are provided, the element will generate it's own unique identifier. - -## Usage - -**Note:** More detailed implementations can be found in the [Storybook](https://tomdango.github.io/nhsuk-react-components). - -### Standard - -```jsx -import { Checkboxes } from "nhsuk-react-components"; - -const Element = () => { - return ( - - British - Irish - Citizen of another country - - ); -} -``` diff --git a/src/components/contents-list/README.md b/src/components/contents-list/README.md deleted file mode 100644 index e3298d63..00000000 --- a/src/components/contents-list/README.md +++ /dev/null @@ -1,41 +0,0 @@ -# ContentsList - -This component can be found in the `nhsuk-frontend` repository [here](https://github.com/nhsuk/nhsuk-frontend/tree/master/packages/components/contents-list). - -## Implementation Notes - -The `ContentsList` component has one subcomponent: `ContentsList.Item`. - -There are two default props set to the ContentsList: `role: 'navigation'` and `visuallyHiddenText: 'Contents'`. These are only default props and can be overriden. `visuallyHiddenText={false}` will disable the visually hidden text. - -## Usage - -**Note:** More detailed implementations can be found in the [Storybook](https://tomdango.github.io/nhsuk-react-components). - -### Standard - -```jsx -import { ContentsList } from "nhsuk-react-components"; - -const Element = () => { - return ( - - - What is AMD? - - - Symptoms - - - Getting diagnosed - - - Treatments - - - Living with AMD - - - ); -} -``` diff --git a/src/components/details/README.md b/src/components/details/README.md deleted file mode 100644 index ebf7c19e..00000000 --- a/src/components/details/README.md +++ /dev/null @@ -1,43 +0,0 @@ -# ContentsList - -This component can be found in the `nhsuk-frontend` repository [here](https://github.com/nhsuk/nhsuk-frontend/tree/master/packages/components/contents-list). - -## Implementation Notes - -The `Details` component has three subcomponents: - -- `Details.Summary` -- `Details.Text` -- `Details.ExpanderGroup` - -## Usage - -**Note:** More detailed implementations can be found in the [Storybook](https://tomdango.github.io/nhsuk-react-components). - -### Standard - -```jsx -import { Details } from "nhsuk-react-components"; - -const Element = () => { - return ( -
- Where can I find my NHS number? - -

An NHS number is a 10 digit number, like 485 777 3456.

-

- You can find your NHS number on any document sent to you by the NHS. This may include: -

-
    -
  • prescriptions
  • -
  • test results
  • -
  • hospital referral letters
  • -
  • appointment letters
  • -
  • your NHS medical card
  • -
-

Ask your GP practice for help if you can't find your NHS number.

-
-
- ); -} -``` diff --git a/src/components/do-dont-list/DoDontList.tsx b/src/components/do-dont-list/DoDontList.tsx index 86fb3665..1d4aa308 100644 --- a/src/components/do-dont-list/DoDontList.tsx +++ b/src/components/do-dont-list/DoDontList.tsx @@ -2,6 +2,8 @@ import React, { HTMLProps, createContext, useContext } from 'react'; import classNames from 'classnames'; import { Tick, Cross } from '../icons'; import HeadingLevel, { HeadingLevelType } from '../../util/HeadingLevel'; +import useDevWarning from '../../util/hooks/UseDevWarning'; +import { NHSUKFrontendV5UpgradeWarnings } from '../../deprecated/warnings'; type ListType = 'do' | 'dont'; @@ -24,22 +26,25 @@ const DoDontList: DoDontList = ({ heading, headingLevel, ...rest -}) => ( -
- - {heading || (listType === 'do' ? 'Do' : "Don't")} - - -
-); +}) => { + useDevWarning(NHSUKFrontendV5UpgradeWarnings.DoDontListPrefix, () => listType === 'dont'); + return ( +
+ + {heading || (listType === 'do' ? 'Do' : "Don't")} + + +
+ ); +}; interface DoDontItemProps extends HTMLProps { listItemType?: ListType; diff --git a/src/components/do-dont-list/README.md b/src/components/do-dont-list/README.md deleted file mode 100644 index 845cd10a..00000000 --- a/src/components/do-dont-list/README.md +++ /dev/null @@ -1,33 +0,0 @@ -# DoDontList - -This component can be found in the `nhsuk-frontend` repository [here](https://github.com/nhsuk/nhsuk-frontend/tree/master/packages/components/do-dont-list). - -## Implementation Notes - -The `DoDontList` component has one subcomponent: `DoDontList.Item`. - -As long as a `listType` is supplied to the `DoDontList` component, all subcomponents will render as desired. If you require a `DoDontList.Item` to be different, a `listItemType` prop can be supplied to force the type. - -## Usage - -**Note:** More detailed implementations can be found in the [Storybook](https://tomdango.github.io/nhsuk-react-components). - -### Standard - -```jsx -import { DoDontList } from "nhsuk-react-components"; - -const Element = () => { - return ( - - - cover blisters that are likely to burst with a soft plaster or dressing - - wash your hands before touching a burst blister - - allow the fluid in a burst blister to drain before covering it with a plaster or dressing - - - ); -} -``` diff --git a/src/components/do-dont-list/__tests__/DoDontList.test.tsx b/src/components/do-dont-list/__tests__/DoDontList.test.tsx index 4707a17b..93429a67 100644 --- a/src/components/do-dont-list/__tests__/DoDontList.test.tsx +++ b/src/components/do-dont-list/__tests__/DoDontList.test.tsx @@ -1,6 +1,7 @@ import React from 'react'; import { shallow, mount } from 'enzyme'; import DoDontList from '..'; +import { NHSUKFrontendV5UpgradeWarnings } from '../../../deprecated/warnings'; describe('DoDontList', () => { it('matches snapshot', () => { @@ -65,3 +66,24 @@ describe('DoDontList', () => { }); }); }); + +describe('dont list dev warning', () => { + jest.spyOn(console, 'warn').mockImplementation(); + afterEach(() => { + jest.clearAllMocks(); + }); + + it('should warn when using dont list', () => { + const element = mount(); + expect(console.warn).toHaveBeenCalled(); + expect((console.warn as jest.Mock).mock.calls[0][0]).toBe( + NHSUKFrontendV5UpgradeWarnings.DoDontListPrefix, + ); + element.unmount(); + }); + it('should not warn when using do list', () => { + const element = mount(); + expect(console.warn).not.toHaveBeenCalled(); + element.unmount(); + }); +}); diff --git a/src/components/do-dont-list/__tests__/__snapshots__/DoDontList.test.tsx.snap b/src/components/do-dont-list/__tests__/__snapshots__/DoDontList.test.tsx.snap index c635ec0e..8dd07a86 100644 --- a/src/components/do-dont-list/__tests__/__snapshots__/DoDontList.test.tsx.snap +++ b/src/components/do-dont-list/__tests__/__snapshots__/DoDontList.test.tsx.snap @@ -13,7 +13,6 @@ exports[`DoDontList matches snapshot: DoDontList-Do 1`] = ` > Do @@ -33,7 +32,6 @@ exports[`DoDontList matches snapshot: DoDontList-Dont 1`] = ` > Don't diff --git a/src/components/error-message/README.md b/src/components/error-message/README.md deleted file mode 100644 index c1f8f041..00000000 --- a/src/components/error-message/README.md +++ /dev/null @@ -1,23 +0,0 @@ -# ErrorMessage - -This component can be found in the `nhsuk-frontend` repository [here](https://github.com/nhsuk/nhsuk-frontend/tree/master/packages/components/error-message). - -## Implementation Notes - -The `ErrorMessage` component has a default `visuallyHiddenText` of "Error: ". This can be overriden, or disabled using `visuallyHiddenText={false}`. - -## Usage - -**Note:** More detailed implementations can be found in the [Storybook](https://tomdango.github.io/nhsuk-react-components). - -### Standard - -```jsx -import { ErrorMessage } from "nhsuk-react-components"; - -const Element = () => { - return ( - Error! - ); -} -``` diff --git a/src/components/error-summary/ErrorSummary.tsx b/src/components/error-summary/ErrorSummary.tsx index f9cff476..eb82250c 100644 --- a/src/components/error-summary/ErrorSummary.tsx +++ b/src/components/error-summary/ErrorSummary.tsx @@ -1,4 +1,4 @@ -import React, { HTMLProps } from 'react'; +import React, {forwardRef, HTMLProps, PropsWithoutRef, RefAttributes} from 'react'; import classNames from 'classnames'; const ErrorSummaryTitle: React.FC> = ({ className, ...rest }) => ( @@ -19,20 +19,23 @@ const ErrorSummaryListItem: React.FC> = (props) => ); -interface ErrorSummary extends React.FC> { +interface ErrorSummary extends React.ForwardRefExoticComponent> & RefAttributes> { Title: React.FC>; Body: React.FC>; List: React.FC>; Item: React.FC>; } -const ErrorSummary: ErrorSummary = ({ className, ...rest }) => ( -
-); - -ErrorSummary.Title = ErrorSummaryTitle; -ErrorSummary.Body = ErrorSummaryBody; -ErrorSummary.List = ErrorSummaryList; -ErrorSummary.Item = ErrorSummaryListItem; +const ErrorSummaryDiv = forwardRef>(({className, ...rest}, ref) => +
+) +ErrorSummaryDiv.displayName = "ErrorSummary" + +const ErrorSummary: ErrorSummary = Object.assign(ErrorSummaryDiv, { + Title: ErrorSummaryTitle, + Body: ErrorSummaryBody, + List: ErrorSummaryList, + Item: ErrorSummaryListItem, +}) export default ErrorSummary; diff --git a/src/components/error-summary/README.md b/src/components/error-summary/README.md deleted file mode 100644 index 608cf832..00000000 --- a/src/components/error-summary/README.md +++ /dev/null @@ -1,41 +0,0 @@ -# ErrorSummary - -This component can be found in the `nhsuk-frontend` repository [here](https://github.com/nhsuk/nhsuk-frontend/tree/master/packages/components/error-summary). - -## Implementation Notes - -The `ErrorSummary` component has four subcomponents: - -- `ErrorSummary.Title` -- `ErrorSummary.Body` -- `ErrorSummary.List` -- `ErrorSummary.Item` - -## Usage - -**Note:** More detailed implementations can be found in the [Storybook](https://tomdango.github.io/nhsuk-react-components). - -### Standard - -```jsx -import { ErrorSummary } from "nhsuk-react-components"; - -const Element = () => { - return ( - - There is a problem - -

Optional description of the errors and how to correct them

- - - Link to error with explanation - - - Link to error with explanation - - -
-
- ); -} -``` diff --git a/src/components/error-summary/__tests__/ErrorSummary.test.tsx b/src/components/error-summary/__tests__/ErrorSummary.test.tsx index 7c7cd184..05b39055 100644 --- a/src/components/error-summary/__tests__/ErrorSummary.test.tsx +++ b/src/components/error-summary/__tests__/ErrorSummary.test.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import { shallow } from 'enzyme'; +import { mount, shallow } from 'enzyme'; import ErrorSummary from '..'; describe('ErrorSummary', () => { @@ -9,6 +9,13 @@ describe('ErrorSummary', () => { element.unmount(); }); + it('forwards refs', () => { + const ref = React.createRef(); + const element = mount(); + expect(ref.current).not.toBeNull(); + element.unmount(); + }); + describe('ErrorSummary.Title', () => { it('matches snapshot', () => { const element = shallow(Title); diff --git a/src/components/fieldset/README.md b/src/components/fieldset/README.md deleted file mode 100644 index 600d1b07..00000000 --- a/src/components/fieldset/README.md +++ /dev/null @@ -1,27 +0,0 @@ -# Fieldset - -This component can be found in the `nhsuk-frontend` repository [here](https://github.com/nhsuk/nhsuk-frontend/tree/master/packages/components/fieldset). - -## Implementation Notes - -The `Fieldset` component has one subcomponent: `Fieldset.Legend`. - -The `Fieldset.Legend` component has one default prop: `headingLevel: 'h1'`. This can be overridden and any valid heading level can be used (i.e. `h1`, `h2`). - -## Usage - -**Note:** More detailed implementations can be found in the [Storybook](https://tomdango.github.io/nhsuk-react-components). - -### Standard - -```jsx -import { Fieldset } from "nhsuk-react-components"; - -const Element = () => { - return ( -
- What is your address? -
- ); -} -``` diff --git a/src/components/footer/Footer.tsx b/src/components/footer/Footer.tsx index dfcb654a..90704625 100644 --- a/src/components/footer/Footer.tsx +++ b/src/components/footer/Footer.tsx @@ -1,21 +1,26 @@ import React, { HTMLProps } from 'react'; import classNames from 'classnames'; import { Container } from '../layout'; +import useDevWarning from '../../util/hooks/UseDevWarning'; +import { NHSUKFrontendV5UpgradeWarnings } from '../../deprecated/warnings'; interface FooterListProps extends HTMLProps { columns?: boolean; } -const FooterList: React.FC = ({ className, columns, ...rest }) => ( -