GithubHelp home page GithubHelp logo

surevine / govuk-react-jsx Goto Github PK

View Code? Open in Web Editor NEW
2.0 3.0 0.0 3.43 MB

govuk-frontend compatible React components

Home Page: https://govuk-react-jsx.netlify.app/

License: MIT License

JavaScript 99.16% Shell 0.67% SCSS 0.17%
govuk-frontend govuk-design-system react reactjs hacktoberfest

govuk-react-jsx's Introduction

GOV.UK React components (govuk-react-jsx)

This package is no longer maintained and will not receive updates bringing it beyond govuk-frontend 4.0.1. If you are using this in your project the simplest way forward is to copy and paste the components from here into your project allowing you to keep them up to date with govuk-frontend yourselves.

View the readme

govuk-frontend 4.0.1 version (Pipeline) MIT License

Please note - the version number of govuk-react-jsx is independent of the govuk-frontend version number.

View demo at https://govuk-react-jsx.netlify.app/

View example app at https://surevine.github.io/govuk-react-jsx-examples/ (for which the source code is at https://github.com/surevine/govuk-react-jsx-examples)

WARNING

If you do not need the characteristics of a Single Page App framework like React, please consider using something else. Government services should be progressively enhanced, and should function without JavaScript enabled.

If you have an explicit requirement that cannot be delivered effectively in a progressively enhanced manner then you might have a case for using React. If you have plans to build your React app in a progressively enhanced way, you might be fine. Whatever you do, be prepared to defend it at a service assessment.

Quick install

$ npm install govuk-react-jsx

(See installation and usage for more details)

Motivation

This repository contains govuk-frontend compatible React components. The aim of this package is to steer closely to govuk-frontend by consuming the CSS directly from the govuk-frontend npm package. And to strike a balance between mirroring the GOV.UK Nunjucks params vs ideomatic React props.

This has the following benefits

  • Generated markup is identical to the output from the govuk-frontend macros. This allows us to benefit from the hard work that GDS has put into forming good markup patterns, including use of aria attributes.
  • Keeping up to date with upstream changes in govuk-frontend is as simple as updating the package.json version and mirroring any markup changes made. The test suite helps with this by comparing our output against the reference Nunjucks output - any differences constitute a test failure.
  • Anyone that knows the GOV.UK Nunjucks macros will quickly feel familiar with the structure of these components

Comparison with govuk-react

govuk-react is the other main option in this space. Naturally the first thing people ask is why one might use this repository instead of govuk-react. Here's my take on the matter:

govuk-react govuk-react-jsx (This repository)
An implementation of the govuk design system.
CSS, JS and Markup patterns have all been rewritten from scratch.
Aria attributes missing.
Directly consumes the govuk-frontend CSS/JS and accurately mirrors their markup patterns, including Aria attributes
Upstream CSS/JS changes in govuk-frontend need to be manually transferred across and/or rebuilt Upstream CSS/JS changes are pulled in automatically. Only markup changes need to manually transferred (But are validated as correct by the test suite)
Relatively complex code Simpler code - just plain JSX ports of the Nunjucks
Uses StyledComponents
Great if you like them and use them. But if you prefer a different library then you would end up needing both in your toolchain.
Increased maintenance burden on govuk-react team
Uses plain Sass compilation of the govuk-frontend code.
You are free to use a CSSinJS library of your choice for your own styles if you wish
Cleaner component props since it has been designed from the ground up for React Props mostly mirror the govuk-frontend Nunjucks params with some exceptions as below. This has been done in order to steer as closely to govuk-frontend as possible, and to facilitate the test suite checking the output against the original.

This is possibly the main argument against this repository and for govuk-react. It's a tradeoff. One that is worth making in my opinion but make your own call on that.
More comprehensive set of components.
Includes components for headings, paragraphs, spacing etc
Only includes components that are direct equivalents of the Nunjucks templates in govuk-frontend.
(Although a future release is planned that will include grid, headings and paragraphs etc.)
Spacing classes will likely never be a component in this repository - some things like that I feel are already sufficiently well served by just using the CSS classes directly. This repository does not attempt to abstract you away from the fact that you are using govuk-frontend CSS.
Allows code splitting of the styles, since they are defined in each component No code splitting - all GOV.UK CSS is loaded. Although - it is relatively easy to omit the Scss files that you don't need so this is only a small downside
No complications from integrating with other libraries As per the React docs on Integrating with other libraries there is a very small chance that the integration of the GOV.UK JS might result in bugs if React tries to update a component that the GOV.UK JS has also updated. This is fairly unlikely but is something to be mindful of.

Assumptions

These components assume you:

  • Have compiled the govuk-frontend scss and have included it in your page (create-react-app is able to compile the gov.uk Sass files)
  • Are using react-router
  • Have read the exceptions below

Known issues

  • The "None of these" JavaScript initialised as part of govuk-frontend does not currently function with these components. Because external JS cannot influence the checked state of controlled components in React, the govuk-frontend approach does not work here. If you need this functionality in your service it would be best to implement it within the form framework you are using (E.g. Formik and the like).

Exceptions

Exceptions to the conformance with govuk-frontend nunjucks params are as follows:

  • Links - Anywhere that accepts an href / text combo of params to create a hyperlink, will also accept a to prop instead of href, which will be used in a react-router <Link> element.
  • Header links - homepageUrl and serviceUrl become homepageUrlHref / homepageUrlTo and serviceUrlHref / serviceUrlTo, with the To variants being passed to a react-router <Link> the Href variants being a plain html <a> tag
  • Anywhere that accepts an html or text param in Nunjucks will instead accept a children prop which should be passed either a string, or JSX. Params such as summaryText or summaryHtml become summaryChildren
  • classes becomes className
  • spellcheck becomes spellCheck
  • inputmode becomes inputMode
  • describedBy becomes aria-describedby
  • colspan and rowspan become colSpan and rowSpan
  • autocomplete becomes autoComplete
  • ariaLabel becomes aria-label
  • List keys - Anywhere that you specify an array of items such as a list of links, you may optionally specify a reactListKey for each item. This will be used instead of the index when doing .map over the items. React uses these keys internally to work out whether to re-render items. This is crucial for dynamic components where you might re-sort the list items for example. For static data it is less important and the key can be omitted. (See https://reactjs.org/docs/lists-and-keys.html#keys for more) (The only exception to this rule is the tab component, where the tabs are already sufficiently keyed by id)
  • The <Select> component and <Radios> components take a top level value prop, instead of setting checked or selected on the individual items. This is more in line with React and React-based form libraries
  • The <ErrorSummary> component does not automatically focus itself when errors occur - it is up to the calling app to focus it when appropriate, such as when a submit button is pressed.
  • The <Table> component data structure is changed slightly to accomodate react list keys on table rows. Note the addition of a cells key inside each row, rather than a simple nested array of rows / cells.

See utils/processExampleData.js for the complete list of transformations.

Installation & Usage

Installation

npm install govuk-react-jsx

NB: govuk-react-jsx has a number of peer dependencies that you will need to install yourself:

  • govuk-frontend
  • react-router
  • react
  • react-router-dom
  • react-helmet

A full list can be found in the dependencies section of /scripts/package.json

An example of setting up create-react-app to use govuk-react-jsx can be viewed in this commit over on govuk-react-jsx-examples.

Using Styles

govuk-react-jsx uses the same styles as govuk-frontend, the only difference being styles need to be applied using className rather than class as it's React.

e.g. to use govuk-frontend typography styles:

<p className="govuk-body">
  Use this design system to make your service consistent with GOV.UK.
</p>

An example of using govuk-frontend styles with govuk-react-jsx can be viewed at https://surevine.github.io/govuk-react-jsx-examples/.

Using Components

All components are documented in Storybook with example usage code.

e.g. to render a panel component

import { Panel } from 'govuk-react-jsx';

<Panel titleChildren="Application complete">
  Your reference number: HDJ2123F
</Panel>

Using with form libraries

An example of using govuk-react-jsx to create forms using Formik and react-hook-form, complete with error validation can be viewed at https://surevine.github.io/govuk-react-jsx-examples/.

Refs for form components

In the case of form components React.forwardRef is used to forward any ref passed to a component onto the underlying DOM element. For example:

const ref = useRef();
<Input
  ref={ref}
  id="input-example"
  label={{
    children: [
      'National Insurance number'
    ]
  }}
  name="test-name"
  type="text"
/>

In this code, ref will contain a reference to the actual DOM input element. You could use this to then call .focus() on the element.

For components such as DateInput, Radios, Checkboxes and anywhere that uses an items prop to represent many form elements to be returned by the component, each object in the items array can accept a ref key which will then return a reference to the rendered form element for that item.

Rather than adding them everywhere I have currently restricted it to form components where I can imagine a use case. Please open an issue if you need refs forwarded onto other types of elements - I may have missed a use case.

Versioning

This repository is versioned separately and follows standard semver procedures.

Tests

The test suite passes the example data from the govuk-frontend repository through the JSX components and compares the output with the reference output provided in govuk-frontend. Any differences here constitute a failure.

Tests run in Github actions.

Currently used by

Contributors

Andy Mantell (Primary maintainer)

Dave Hudson

Mick Jones (Helped to build the original JSX ports found at https://github.com/LandRegistry/govuk-react-components)

Development sponsored by

Surevine

HM Land Registry

govuk-react-jsx's People

Contributors

andymantell avatar davehudson avatar dependabot[bot] avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

govuk-react-jsx's Issues

Build package publishing pipeline

Github actions preferably, but maybe Travis if that doesn't work out.
Needs to:

  • run tests
  • run linting
  • deploy github pages when code hits master
  • release packages when tags are created

Cache govuk-frontend examples from github

govuk-frontend examples are fetched from github every time the tests run. Since they are coming from a tagged version this is unnecessary - they should be cached. (Currently writing this ticket from a train!)

Forward ref for checkboxes

Hello,
I am trying to use checkboxes (https://surevine.github.io/govuk-react-jsx/?path=/story/checkboxes--with-optional-form-group-classes-showing-group-error) and with React-hook-form (https://react-hook-form.com/get-started/).

I am having problems passing a ref attribute and getting this error:

index.js:1 Warning: Function components cannot be given refs. Attempts to access this ref will fail. Did you mean to use React.forwardRef()?

I am trying to do this:


        <Checkboxes
          items={[
            {
              children: ['Email'],
              conditional: {
                children: [
                  <label key="0" className="govuk-label" htmlFor="context-email">
                    Email address
                  </label>,
                  <span key="1" className="govuk-error-message" id="contact-phone-error">
                    Problem with input
                  </span>,
                  <input ref={register({required: true})} key="2" className="govuk-input govuk-!-width-one-third" id="context-email" name="context-email" type="text" />,
                ],
              },
              value: 'email',
            },
          ]}
          name="email"
        />

Adding ref={register({required: true})} to other components like Input works before you are forwarding the refs but don't appear to be doing it for checkboxes (and probably radio buttons)

How to turn on validation errors for conditional fields

Hello,
I am struggling to work out how to turn on validation errors for conditional fields.

For example: https://surevine.github.io/govuk-react-jsx/?path=/story/checkboxes--with-optional-form-group-classes-showing-group-error

The phone number should only show if the checkbox is 'touched' and the input is blank (or fails validation). The error is part of the children array for the conditional and not sure how to make this array contain the error span only if the checkbox has been checked.

By the way, I am using react-form-hooks package for form state management but I have tried just simplifying it without this package just to see how I can make the error message conditional but no luck.

Compatibility with Next JS

Build fails when adding project to Next Js app.

require is being used to load an asset file, which is why its return value is typically assigned to a variable:
Better to put your image inside your project asset folder or use CDN to store that image and put the fullpath like: https://cdn.com/path/to/image in prop src in tag img.

Next JS doesn't seem to support it, see
https://nextjs.org/docs/basic-features/static-file-serving

In your code node_modules/govuk-react-jsx/govuk/template/index.js

var _favicon = _interopRequireDefault(require("govuk-frontend/govuk/assets/images/favicon.ico"));

var _govukMaskIcon = _interopRequireDefault(require("govuk-frontend/govuk/assets/images/govuk-mask-icon.svg"));

var _govukAppleTouchIcon180x = _interopRequireDefault(require("govuk-frontend/govuk/assets/images/govuk-apple-touch-icon-180x180.png"));

var _govukAppleTouchIcon167x = _interopRequireDefault(require("govuk-frontend/govuk/assets/images/govuk-apple-touch-icon-167x167.png"));

var _govukAppleTouchIcon152x = _interopRequireDefault(require("govuk-frontend/govuk/assets/images/govuk-apple-touch-icon-152x152.png"));

var _govukAppleTouchIcon = _interopRequireDefault(require("govuk-frontend/govuk/assets/images/govuk-apple-touch-icon.png"));

var _govukOpengraphImage = _interopRequireDefault(require("govuk-frontend/govuk/assets/images/govuk-opengraph-image.png"));

and prop src from tag img should receive URL, not a module.

Error message text is:-

info  - Creating an optimized production build  
Failed to compile.

./node_modules/govuk-frontend/govuk/assets/images/favicon.ico 1:0
Module parse failed: Unexpected character '' (1:0)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
(Source code omitted for this binary file)


> Build error occurred
Error: > Build failed because of webpack errors
    at /govuk-nextjs-example/node_modules/next/dist/build/index.js:15:918
    at async /govuk-nextjs-example/node_modules/next/dist/build/tracer.js:1:1441

See - Next js test project to reproduce:
https://github.com/dawudr/govuk-nextjs-example.git

Compatibility with react-hook-form

There are some issues around compatibility with react-hook-form. (See #45 for original thread).

Initial issue appears to be around the fact that react-hook-form uses uncontrolled inputs but we assume controlled.

Need to build out a demo of some the various form components using react-hook-form and iron out this and any other issues encountered.

Add "worst case" examples for each component

The examples coming from the govuk-frontend yaml files cover a lot of bases but have in the past missed a couple of parameter combinations. Would be good to build a worst case scenario for each component that definitely exercised all of the parameters - so we can ensure that our rendering is correct against the reference nunjucks

Consider onBlur, onInput and other form field specific events for DateInput, Radios and Checkboxes

Consider onBlur, onInput and other form field specific events for DateInput, Radios and Checkboxes. Since these components are effectively "compound" fields, we don't by default spread the top level props into the individual inputs (Since they are built from the items prop). This means that putting top level onBlur handlers in doesn't actually work. onChange works because I have specifically catered for this, but we should consider other events.

People can inject them via the individual items, but I think it would be cleaner not to require people to go to this extra effort.

Note: Make sure that any handlers specified on the individual items aren't wiped out by the top level one (i.e. insert the top level one and spread the individual item attributes afterwards)

Transition away from Codesandbox for demos

Codesandbox seems to have some strange behaviour, resulting in bugs like #42 which runs fine locally, but breaks in codesandbox. The best bet for removing any issues like this would be to move away from Codesandbox and perhaps have a dedicated demo repository on github pages.

Include differences between this project and govuk-react/govuk-react in the README

Hello,
Is it possible to include pros and cons of this repo, compared to https://github.com/govuk-react/govuk-react. In the motivation section, maybe say why you started this repo instead of contributing to govuk-react repo as the aim is the same.

Both look to me can do the job (i.e. react-based GDS components). Downside for me with https://github.com/govuk-react/govuk-react is that not much activity is going on but the weekly downloads are higher (update: just realised this repo is only 2 months old so downloads aren't useful metric). On the other hand, this repo appears to be using the latest GDS stylesheets.

Thanks

Consider hand crafting the storybook demos instead of using govuk examples (Relegating these to tests only)

As per the comment at #45 (comment) it is not immediately clear upon viewing the storybook that you can pass components to children props and not just html. The html in the demos is technically in JSX form, implying that components could be used also but it's very easy to miss that and just see html.

Might be worth considering hand crafting a smaller set of clearer demos, and relegating the govuk examples to the test suite only.

Button issue with Formik

Hi there - I've noticed in the Formik example (and in a different Formik example I've been asked to review) that there's a recurrent Cannot read property 'addEventListener' of null at e.init (button.js:718) error being pumped into the console - I've been having the devil's own job chasing it down - has anybody there figured out what's causing it?

Error module parse failed: Unexpected charcter

Hello,
Firstly, I don't think this is a problem with this lib but if you can help, I would be grateful.

I am working on a React project that has been setup up manually (i.e. without the use of create-react-app), and when I try to import a component from this library like Input or Button, I am getting this error:

Uncaught error: Module parse failed: Unexpected character '  ' (1:0)
You may need an appropriate loader to handle this file type.
(Soure code omitted for this binary file)
    at Object.<anonymous> (HamletUtils.js:536)
    at __webpack_require__(bootstrap_ff7b80..:678)
    .....

The webpack config has the following loaders:

  • babel-loader
  • url-loader
  • style-loader
  • eslint-loader

I got no idea where to start with this error has it feel little generic. Any hints would be appreciated.

Controlled radio demo needs an onchange handler

The new controlled radio input demo is currently read only as there is no onChange handler. Needs sorting out. It's only an issue in the demo, not in the installed version, but is easily fixed.

Invalid Hook Call Warning

Whilst attempting to use this library within a Gatsby application I was receiving the error outlined here

https://reactjs.org/warnings/invalid-hook-call-warning.html

Specifically I think the issue was "3. You might have more than one copy of React in the same app.". At the above link it mentions that libraries should list react as peer dependencies rather than dependencies.

Indeed, when I modified govuk-react-jsx\package.json to look like

"dependencies": {
"govuk-frontend": "3.4.0",
"react-helmet": "5",
"react-router": "5",
"react-router-dom": "5"
},
"peerDependencies": {
"react": "16"
},

The issue appears to be resolved.

Not all dynamic imports receive proper names at build time

Govuk js is imported dynamically and given names with webpack magic comments as follows:

      if (typeof document !== 'undefined') {
        const { default: ButtonJS } = await import(
          /* webpackChunkName: "govuk-frontend-button" */
          /* webpackMode: "lazy" */
          /* webpackPrefetch: true */
          'govuk-frontend/govuk/components/button/button'
        );

        new ButtonJS(buttonRef.current).init();
      }

However, not all of the output files have their names assigned correctly. For example, this is the build output from govuk-react-jsx-examples:

image

Need to work out why...

More documentation

Any readme at all would be better than the nothing that is currently in place

Bad handling of focus on ErrorSummary component

Hi Andy - sorry to fill your issues thread mate, but I've come across a more general issue with the Formik example (which shows I'm persevering though eh?) - there's a validation snafu which I think is related to the issue identified in this thread on Formik's site ( jaredpalmer/formik#882 ) - The form validates fine but there's an issue when you come to fix the errors it points out - as soon as you type a character in one of the failing fields the field loses the focus, stopping you from typing until you click back in the field. The thread I've highlighted (which is primarily concerned with styled components) suggests creating the component outside of the Formik component then referencing it - I've tried this with no success... Wondering where to go next.

Test suite complains about lack of onChange handlers on form elements

Test suite complains about lack of onChange handlers on form elements. Doesn't affect validity of test results but the red warnings are alarming if you don't know what they are. And a habit of ignoring warnings may lead to genuine things being missed in future. Need to sort this out...

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.