GithubHelp home page GithubHelp logo

govuk-react / govuk-react Goto Github PK

View Code? Open in Web Editor NEW
401.0 14.0 87.0 45.78 MB

An implementation of the GOV.UK Design System in React using CSSinJS

Home Page: http://govuk-react.github.io/govuk-react/

License: MIT License

JavaScript 3.47% Shell 0.42% TypeScript 95.88% MDX 0.16% HTML 0.07%
govuk react govuk-frontend component-library storybook styled-components

govuk-react's Introduction

govuk-react

An implementation of the GOV.UK Design System in React using CSSinJS using Object notation (with styled-components).

codecov Join the community on Spectrum

We aim to track the following projects (in priority order) as to which components to implement and how they should look/behave. Where possible we are using the existing CSS as a guide. When we need to modify to suit custom markup, we aim to provide a comment in our code as to why this was done.

This project is being or has been used by:

The project is currently maintained for free by a small number of volunteers. If you would like to contribute, help maintain or sponsor this project, please get in touch via Discussions or Twitter.

Usage

npm install govuk-react styled-components @types/styled-components --save
import { Button } from 'govuk-react'

const MyComponent = ({title}) => (<div>
  <h1>{title}</h1>
  <Button />
</div>)

See the Storybook for examples of all available components.

Also see the Example Application for basic usage.

Using Link with a Router Link

We provide a Link component which creates an element styled as a GDS link. As we are using styled-components it is possible to apply that style to an existing component using the as prop. Other props will be passed through.

For example;

import { BrowserRouter, Link as RouterLink } from 'react-router';
import { Link } from '@govuk-react/link';

const MyComponent = () => (
  <nav>
    <BrowserRouter>
      <Link as={RouterLink} to="https://example.com">example</Link>
    </BrowserRouter>
  </nav>
);

Assumptions

Use of these components assumes the following from the peer project:

  • The govuk-react GlobalStyle component is included on all pages.
  • The GDS Transport font face is included (for gov.uk domains only)
  • Optionally, either normalize.css or sanitize.css is used as a CSS reset. We don't test for this, so please raise an issue if you find any problems with compatibility.
  • Other than the reset, no other styles affecting generic elements (without classes, IDs etc) are present in the CSS.

Why CSS-in-JS?

See A Unified Styling Language.

This project is part of a larger initiative to componetise large scale React applications. Using CSSinJS allows us to include styles inside a module bundle that can be published (using npm publish) and consumed by a peer application, without putting dependencies on the peer application to implement a specific CSS build system.

Why not use GDS styles/classes directly

  1. We want to be free to write different DOM structure and/or CSS that is more in keeping with a React and bem-ish architecture. (e.g. in React you often don't need to specify IDs for field inputs, and can wrap inputs with labels so that they are automatically associated. We want to leave the decision of whether to use input IDs to the parent project. GDS styles don't wrap inputs with labels and require IDs and for attributes).
  2. We want a parent project to not have to worry about a specific build system (e.g. for handling import styles.css, particularly if you want universal support) or including certain CSS files. We want a simple npm install govuk-react to be enough to get govuk styled components on to your page, irrespective of your build system.
  3. We want to distribute React applications as modules that have self contained styles. CSS in JS allows all styles to be contained in distributable JS modules that can be ported across projects.

Why is this a monorepo?

Components are published to npm independently. This means users have the ability to upgrade govuk-react and still use older components.

This is particularly relevant in a large application where:

  • some code is reliant on a component that has either been deprecated or had breaking changes
  • you aren't able to refactor the existing code, e.g. it is a large job or managed by another team
  • you don't want to hold back from upgrading to the newest version of govuk-react

e.g. for DateField, you import it separately as follows:

import { H1, Paragraph } from 'govuk-react';
import DateField from '@govuk-react/date-field';

Then in your package.json, you can update govuk-react, but specify the older version of '@govuk-react/date-field'.

About the GDS font

Unfortunately the GDS transport font has a relatively restrictive license described on the gov.uk blog. We are investigating rendering an elegant alternative before falling back to Arial on issue 272.

Related sites and projects

GOV.UK

Other React component libraries

Acknowledgements

We use Chromaticqa for visual regression testing and it is awesome, you should too!

Deploys by Netlify

Contributors

Want to contribute? Checkout our Contributing page.

govuk-react's People

Contributors

anishamalde avatar davidwinter avatar dependabot[bot] avatar djangofs avatar dmoore04 avatar domdomegg avatar dsm23 avatar gavinorland avatar greenkeeper[bot] avatar jsrobertson avatar linusnorton avatar loque- avatar marksy avatar penx avatar petergphillips avatar richardharperinfinityworks avatar richrace avatar rifaidev avatar rottitime avatar simonmoorecic avatar stevesims avatar taranchauhan avatar thomasbickley-bjss avatar tomvaughan77 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  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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

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

govuk-react's Issues

Should Glamorous be a dependency rather than peerDependency

This ticket is to discuss potentially moving Glamorous from peerDependencies to dependencies.

This was initially raised on Slack by @lennym:

You could achieve something similar though (I think) by moving the peer dependency to a main dependency, but with the same leniency for versions. npm would dedupe to the parent projectโ€™s version if it satisfies (which itโ€™d need to anyway to satisfy the peer dependency) but would install latest if no parent version were present.

Button types

it might be useful to have Button types, such as;

  • primary {blue}
  • secondary {white with blue border}
  • default {green}
  • muted {grey}
  • text {transparent with black or white text (depending on the bg somehow or manual)}

to be used like;

<Button styleType="primary">Okay</Button>
<Button styleType="muted">Cancel</Button>

Which would look like:
screen shot 2018-04-12 at 12 00 18

screen shot 2018-04-12 at 12 08 52

Input component propTypes

Input component propTypes should include error: PropTypes.bool

(arguably maybe not a bool, as one might want it to just be truthy, but we're using it as a flag so stuff that uses it should really behave properly ๐Ÿ˜ )

Breadcrumb where last item is *not* a link?

Usual usage of breadcrumbs has the last item in the list being the current page name/title, and thus not a link.

The current storybook examples for the Breadcrumb component don't follow this pattern, but instead have every item as a link.

If it's possible to do conventional breadcrumbs (with last item being just the page title) with the Breadcrumb component we should update the storybook examples accordingly.

If it's not possible we should adjust the component and then also adjust the storybook examples. ๐Ÿ˜

List styles don't match GDS

The style of the UnorderedList component doesn't match GDS.

The GDS style does not proscribe a width, plus it has padding and margin values which are have not been included.

Additionally we don't currently have an OrderedList component, or support for numbered lists.

remove wrapping tags in hoc components

asAnchor and asPaginationItem currently use a glamorous styled wrapper to style the nested components. We should be able to add styling without added unnecessary tags into the code

Move to HomeOffice GitHub

Blocked by #96

Using Settings > Transfer Ownership

We need to be confident that the CI pipelines will continue to work or are easily fixed, and that we can revert ownership if there are any blocking issues.

Make svg icons more modular

Currently each svg has the same tag & attributes so would be beneficial to make a resuable component which passes in props. Just the path would be different for each icon

Convert to monorepo

Convert to a monorepo with each component being published individually, for more reliable sharing and updating of components across projects using semver.

Supporting heading-secondary?

The GDS styles have the concept of a secondary heading - typically they appear inside an h1 element as a span with a class of heading-secondary before the text of the primary title. They are styled grey and in a smaller font size than the primary title.

This can be seen clearly on this page:
https://govuk-elements.herokuapp.com/typography/example-typography/

On this page the secondary heading is "Typography", with the primary title as "Example: Typography".

The heading-secondary class varies it's size depending upon the class given to the heading element itself. There are only definitions present for .heading-large .heading-secondary and .heading-xlarge .heading-secondary.

It would be good to support these secondary headings - ideally with them being contextually aware and automatically picking appropriate font sizes depending on the size given to their parent.

Visual regression testing

Add support for visual regression testing by:

  1. for each component that has an 'example.js' file, generate an image snapshot with Pupeteer component-image (this is done as part of API docs)
  2. plug component-image in to a dockerized puppeteer so that identical images are always generated independent of host platform
  3. make the CI server check that the generated images in the docs folder match the current image snapshots for example.js

turn the HOC into a monorepo

currently the HOC components are all in one repo, @govuk-react/hoc but they should be in their own repositories @govuk-react/with-white-space

remove 'index' from imports

some components have unnecessary '/index' in the import
e.g. etc

  • src/components/InputField/index.js
  • scripts/createComponent.js

Localisation of text in LoadingBox

Text should be localisable, i.e. can be passed in as a prop.

We have text in icons, e.g. the Spinner has 'Loading'.

When a parent component uses an icon, we need to allow this text to be customised by the parent prop.

In the case of the LoadingBox, it should accept a title or similar prop that gets passed down to the spinner icon.

Console error in RadioGroup

In the Radio components of storybook, the story "Usage with Final/Redux Form - multi checkbox validation" shows a console error:

Failed prop type: Invalid prop options of type array supplied to RadioGroup, expected object.

Add unit tests and include build script packages in code coverage checks

Build scripts were not previously thought of as something that needed unit tests.

However, now that some of these build scripts are packages within the monorepo, that could be used by other component libraries that follow a similar structure, they should have unit tests added to them.

Codecoverage on these packages has been disabled for now to replicate previous structure, but this task is to add some basic unit tests and enable the projects in the code coverage report again.

Specifically:

      "!<rootDir>/packages/api-docs/**",

Maybe:

      "!<rootDir>/packages/storybook-components/**"

Support single package build

At the moment you can't build a single package as rimraf and babel are not in the path:

i.e.

cd components/back-link
npm run build

We need to add these as devDependencies to every package.

This can be done with lerna add --dev

If LoadingBox minimum height

If LoadingBox contains no children and is loading, or the children are less than a certain height, then it should default to a sensible height.

Perhaps this is just setting a min height of 100px ish.

Plos show this in storybook.

Get to version 1

This serves as a checklist of what we need to do to get to version 1.

  • implement all standard components we're aware of
  • example site should show usage of all exported components
  • all form components and validation should be working with final form in example site as expected
  • collaborator review of all markup/props used by example site
  • storybook review
  • generate list of all exported components + props (api documentation)
  • working usage in an internal tool
  • decision on grid tooling decided
  • API documentation #64
  • Form fields and inputs have a naming convention, documented in the readme, and follow the same prop structure
  • asAnchor pattern is consistent, working and compared with how other libraries manage this
    • a common approach for active links (as per react-router NavLink) decided

Conventions are consistent and present in README:

  • white space
  • anchors
  • form fields vs. inputs

Code coverage inaccurate

After moving to a monorepo, the code coverage report is not working correctly.

This is because:

  • package A relies on package B
  • package A includes unit tests that use code from package B so should be included in codecov
  • package A uses /lib folder from package B due to being a package dependency rather than relative path
  • tests on /lib folder in package B don't count as code coverage on the src folder.

Perhaps we should be ensuring code coverage for a package is 100% solely using unit tests within that package, however for e.g. the constants package I'm not sure how we would do this.

Use .babelrc.js rather than multiple babel configs

We currently have 2 babel configs, a default and one at config/babel.es.json

To better support a monorepo structure, we should have a single .babelrc.js at the root, that uses environment variables to determine settings.

Console error Radio

In the Radio components of storybook, the story "Radio preselected" shows a console error:

Failed form propType: You provided a checked prop to a form field without an onChange handler. This will render a read-only field. If the field should be mutable use defaultChecked. Otherwise, set either onChange or readOnly. Check the render method of glamorous(input).

White space

All components should have default margin-bottom such that when they are used together they space themselves out automatically.

marginBottom should be an optional prop on these components that uses a number 0 to 9 representing the spacing units listed at:

https://govuk-design-system-production.cloudapps.digital/styles/spacing/

(to discuss - :last-child components should always have a margin bottom of 0?)

We will likely use Cosmos' implementation as a guide for handling this.

Update all form fields with consistent Fields vs Inputs API

(edit Sep 2021: I think a proposal implementation for govuk-frontend-react should be done first)

All form components that bundle a wrapper, error message, hint and input(s) should be usable in these 2 ways, both of which should be in Storybook and docs for the component:

  1. Single component compatible with final-form API

on the default export

<ComponentName />

or on a Field export

<ComponentName.Field />

This would be a component that contains the wrapper, error message, hint and input(s), that could be used via the final-form API as:

import { Field } from 'react-final-form';

const AnimalsField= ({required}) => <Field
  name="likesAnimals"
  label="Do you like animals?"
  hint="You must tell us"
  component={ComponentName}
  options={[
    { title: 'Yep', value: 'yes' },
    { title: 'Nope', value: 'no' },
  ]}
  validate={required}
  inline
/>
  1. A compound/composable component

on named exports

<ComponentName.Root>
  <ComponentName.Label>Example Label</ComponentName.Label>
  <ComponentName.Hint>Example Hint</ComponentName.Hint>
  {error && <ComponentName.Error>{error}</ComponentName.Error>}
  <ComponentName.Input onChange={e => setValue(e.target.value)} value={value} />
</ComponentName.Root>

Also see https://medium.com/@penx/form-elements-in-presentational-component-packages-a618e9aa7416

Automate synchronisation of styles with govuk-frontend

We want to:

  • ensure govuk-react (CSSinJS) provides the same features as govuk-frontend (CSS Modules) but with React specific components/templates
  • reduce the maintenance burden of keeping in line with govuk-frontend, ideally by automating the process.

And in the process, ensure we continue to support:

  • SSR, both with next.js and bespoke
  • tree shaking, critical rendering and path splitting compatibility via create-react-app

Options

1. Script the conversion of govuk-frontend to CSSinJS

WIP: https://github.com/penx/govuk-frontend-emotion

The main issues with this approach so far:

  • Using the CSS classes directly, we would always get declarations such as font. How would this work with theming + freedom of font choice for non GDS domains?
  • how to deal with js-enabled class

2. Use CSS Modules

WIP: https://github.com/penx/govuk-frontend-react

We had previously avoided CSS modules because:

  • govuk-frontend was in closed alpha and we weren't aware of it
  • we didn't want to reuse any other existing govuk CSS projects
  • CSS modules assume that the parent application's build system is configured to handle import styles from 'my-css-file.css' including any processors (sass, postcss)

Sass and CSS modules are now supported in create-react-app now, which means there is an established pattern for handling the import of CSS files that contain Sass.

The plan with this approach would be to use CSS modules for the core style import and continue using CSSinJS for any custom styles (e.g. the spinner).

Blocked by:

3. Use govuk-frontend CSS classes directly

This could be done either via importing the CSS files from each React component or just using the CSS classes and assuming they are present in the DOM. The latter, I think, is what govuk-react-components does.

We would still fall back to CSSinJS where we want custom styles.

We may not get any benefit from tree shaking or critical rendering.

Last time we checked, there was some cascading element selectors in govuk-frontend that we wanted to avoid.

We could look in to this route temporarily before transitioning to CSS modules later

4. Keep govuk-react bespoke

We could still have unit tests to check that the output is in line, e.g.

  • #450 for markup
  • puppeteer for visual

Add contributing md

This ticket is for thoughts on what needs to be added to contributing.md and then eventually for someone to add it :-)

Consider using nwb

Publishing Components to npm

Create React App doesn't provide any built-in functionality to publish a component to npm. If you're ready to extract a component from your project so other people can use it, we recommend moving it to a separate directory outside of your project and then using a tool like nwb to prepare it for publishing.
https://github.com/facebook/create-react-app/blob/master/packages/react-scripts/template/README.md#publishing-components-to-npm

https://github.com/insin/nwb#react-components-and-libraries

https://github.com/insin/nwb/blob/master/docs/guides/ReactComponents.md#developing-react-components-and-libraries-with-nwb

Create ExampleApplication component

Now this is a monorepo I think it may make sense to have packages/example being the govuk-react-example project.

Lerna lets you import another repo keeping commit history, we should probably import using this.

dont update doc images if not necessary

not sure how this would be possible but it would be good to check to see:

  1. is there a component image? If so,
  2. has the component changed since the last image was rendered?

this is because i keep accidentally committing re-rendered images which aren't necessary (no visual diff). I guess this is mostly a user error, because it could be avoided if i (1. wasn't lazy and did git add ., 2. used a visual git application like git Tower which i have installed), but it would be catch if not too hard to do.

๐ŸŽ

use JSX fragments

Fragments allow returning a group of children without extra DOM elements, e.g.

return (
  <div>
    <p>thisThing</p>
    <p>thatThing</p>
  </div>
);

which outputs to:

<div>
  <p>thisThing</p>
  <p>thatThing</p>
</div>

===
is replaced with:

return (
  <React.Fragment>
    <p>thisThing</p>
    <p>thatThing</p>
  </React.Fragment>
)

which outputs to:

<p>thisThing</p>
<p>thatThing</p>

Breadcumb enhancement: strip empty/duff children

When attempting to use the Breadcrumb component I had code like the following:

<Breadcrumb>
  <Link to="/">Home</Link>
  {crumbs}
  {currentPage}
</Breadcrumb>

crumbs here was the result of mapping a different array of pages to create links back to them. This works fine when there are actually pages given, but when the list is empty you get an empty crumb, and see something like: Home > > currentPage

I worked around this by building up an array of children instead, and using <Breadcrumb children={crumbs} />

It may be a good enhancement to have the Breadcrumb strip out "empty" children.

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.