├── CODE_OF_CONDUCT.md ├── proposals ├── 000-template.md ├── 001-use-rfcs-and-adrs-to-discuss-proposals-and-record-decisions.md ├── README.md ├── 006-initialise-javascript-using-govuk-namespaced-data-module-attributes.md ├── 008-simplifying-imports-to-improve-compilation-performance.md ├── 005-namespace-govuk-frontend-nunjucks-sass-using-a-nested-folder-structure.md ├── 003-make-override-classes-consistent.md ├── 004-enable-importing-css-modules-via-filename-convention-used-in-common-frameworks.md └── 002-publish-one-npm-package-instead-of-multiple-npm-packages.md ├── README.md ├── decision-records ├── 000-template.md ├── README.md ├── 004-new-version-font.md ├── 002-restructure-based-on-single-package.md ├── 009-throw-errors-component-constructors.md ├── 001-javascript-for-less-capable-browsers.md ├── 008-reset-the-javascript-api.md ├── 010-remove-init-method.md ├── 007-javascript-file-formats.md ├── 003-templating-languages.md ├── 005-repository-organisation-for-v5.md └── 006-javascript-compatibility.md └── LICENSE /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | ## Code of Conduct 2 | 3 | This project follows the ['alphagov' GitHub organisation Code of Conduct][coc]. 4 | 5 | [coc]: https://github.com/alphagov/code-of-conduct 6 | -------------------------------------------------------------------------------- /proposals/000-template.md: -------------------------------------------------------------------------------- 1 | # Proposal Title 2 | 3 | **Closing date:** 4 | 5 | **Status:** 6 | 7 | ## Summary 8 | 9 | 10 | 11 | ## Problem 12 | 13 | 14 | 15 | ## Proposal 16 | 17 | 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # GOV.UK Design System Architecture 2 | 3 | We use this repository as a forum to discuss and record technical decisions that 4 | affect the products supported by the GOV.UK Design System team, including: 5 | 6 | - GOV.UK Design System 7 | - GOV.UK Frontend 8 | - GOV.UK Prototype Kit 9 | 10 | This repository is open to enable involvement from the wider community and as a 11 | reference for other teams within GDS and wider government. 12 | 13 | There are 2 types of documentation: 14 | 15 | - [Proposals](/proposals), often referred to as 'requests for comments', which 16 | allow us and the wider community to suggest and refine ideas. 17 | - [Decision Records](/decision-records), which document decisions that have been 18 | made, along with any context. 19 | 20 | ## Code of Conduct 21 | 22 | This project follows the ['alphagov' GitHub organisation Code of Conduct][coc]. 23 | 24 | [coc]: https://github.com/alphagov/code-of-conduct 25 | -------------------------------------------------------------------------------- /decision-records/000-template.md: -------------------------------------------------------------------------------- 1 | # [Decision Title] 2 | 4 | 5 | **Date:** 6 | 7 | **Status:** 8 | 9 | ## Decision 10 | 11 | 12 | 13 | ## Rationale 14 | 15 | 16 | 17 | ## Risks and constraints 18 | 19 | 20 | 21 | ## Alternatives considered 22 | 23 | 24 | 25 | ## Implications 26 | 27 | 28 | 29 | ## Contributors 30 | 31 | 32 | 33 | ## Associated issues and pull requests (PRs) 34 | 35 | 36 | 37 | ## Outcomes 38 | 39 | 40 | -------------------------------------------------------------------------------- /decision-records/README.md: -------------------------------------------------------------------------------- 1 | # Decision Records 2 | 3 | Records of the architectural decisions that affect one or more of our products. 4 | 5 | These records could reflect the outcomes of the accepted proposals but they 6 | might also reflect ad-hoc decisions or decisions made without going through the 7 | RFC process. 8 | 9 | ## Process 10 | 11 | 1. Create a new branch on this repository and copy 12 | `decision-records/000-template.md` to a new file with the next free number, 13 | such as `001-my-decision-record.md`. 14 | 2. Modify the template to add detail about the decision. 15 | 3. Include any images etc in a separate directory with the same name as your 16 | record (`000-my-decision-record`) and link to them. 17 | 4. Make a Pull Request (PR) for your branch. 18 | 5. The record will be reviewed. As decision records are documenting a decision 19 | that has already been made, any reviews should be focus on ensuring that the 20 | documentation is clear and understandable. If you disagree with the decision, 21 | you should raise a proposal instead. 22 | 6. Once approved using the Github review system, the PR can be merged. 23 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Crown Copyright (Government Digital Service) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /proposals/001-use-rfcs-and-adrs-to-discuss-proposals-and-record-decisions.md: -------------------------------------------------------------------------------- 1 | # Use RFCs and ADRs to discuss proposals and record decisions 2 | 3 | **Closing date:** 2018-03-16 4 | **Status:** Accepted 5 | 6 | ## Summary 7 | 8 | Use the Request for Comments (RFC) and Architecture Decision Record (ADR) 9 | formats to discuss and record technical decisions for the products we support. 10 | 11 | ## Problem 12 | 13 | We need to make and record decisions in the open, because: 14 | 15 | - it will help us to answer questions from our users as to why things are the 16 | way they are 17 | - it makes it less likely that approaches will be changed in the future without 18 | a full understanding of the context or the rationale for the original decision 19 | - it provides a valuable resource to others, both in government and the wider 20 | community, who are embarking on similar projects 21 | 22 | Whilst some of this is recorded in documents in e.g. Google Drive, this is 23 | not publicly available; there is no consistent approach to how this 24 | documentation is written; and there is no consistent approach to how it is 25 | filed. 26 | 27 | ## Proposal 28 | 29 | We will create a new public repository on GitHub 30 | (`alphagov/govuk-design-system-architecture`) as a place to discuss proposals 31 | and record decisions. 32 | 33 | We will use a simplified version of the existing Request for Comments (RFC) 34 | publication format as a platform for suggesting and refining ideas whilst 35 | involving the wider community. 36 | 37 | We will use the existing Architecture Decision Records (ADR) publication format 38 | as a way to document decisions that have been made. 39 | 40 | We will use markdown for both of these publication types. 41 | 42 | We will aim to simplify the language where possible to reduce the barrier of 43 | entry to contribution and involvement. For example, we will refer to RFCs as 44 | proposals unless we are talking specifically about the format used; we will 45 | simplify 'architecture decision records' to 'decision records'. 46 | 47 | ## Related links 48 | 49 | - [Inspiration: React RFCs](https://github.com/reactjs/rfcs) 50 | - [Inspiration: Swift Evolution](https://github.com/apple/swift-evolution) 51 | -------------------------------------------------------------------------------- /proposals/README.md: -------------------------------------------------------------------------------- 1 | # Proposals 2 | 3 | Most changes to GOV.UK Design System, GOV.UK Frontend or GOV.UK Prototype Kit 4 | can be implemented and reviewed via the normal GitHub pull request workflow 5 | without raising a proposal. 6 | 7 | Where changes would represent a substantial change to the architecture of a 8 | product or the way the products work together we would expect a proposal to be 9 | raised to gather feedback from the community and to ensure that the consequences 10 | of the change are fully thought-out. 11 | 12 | ## Process 13 | 14 | 1. Create a new branch on this repository and copy `proposals/000-template.md` 15 | to a new file with the next free number, such as `001-my-proposal.md`. 16 | 2. Modify the template to add detail about your proposal. 17 | 3. Include any images etc in a separate directory with the same name as your 18 | proposal (`000-my-proposal`) and link to them. 19 | 4. Make a Pull Request (PR) for your branch. 20 | 5. Post a link to your PR in #govuk-design-system channel on Slack. 21 | 6. The Design System team and the wider community are able to discuss your 22 | proposal using both inline comments against your document and the general PR 23 | comments section. You will need to create a free GitHub account in order to 24 | comment. 25 | 7. As changes are requested and agreed in comments, make the changes in your RFC 26 | and push them as new commits. 27 | 8. Stay active in the discussion and encourage and remind other relevant people 28 | to participate. If you start a proposal it’s up to you to push it through the 29 | process and engage people. 30 | 9. Once consensus is reached and approvals given using the Github review system, 31 | the PR can be merged. 32 | 33 | ## Rejecting proposals 34 | 35 | A proposal can be rejected by the Design System team. This can happen for many 36 | reasons, including if a consensus isn’t reached, or if people agree that 37 | rejecting it is the right thing to do. It might be that there are already plans 38 | to address a given problem in a different way, or that it's just not the right 39 | time to make the change. In this case the PR should be closed with a suitable 40 | comment. 41 | 42 | ## Recording changes 43 | 44 | Proposals should be considered an immutable record of a point in time. If we 45 | want to change a decision that was made in a previous proposal, a new proposal 46 | should be raised. If that proposal is accepted, the old proposal may be updated 47 | to reflect the fact that it has been superseded, but should otherwise be left 48 | intact. 49 | -------------------------------------------------------------------------------- /proposals/006-initialise-javascript-using-govuk-namespaced-data-module-attributes.md: -------------------------------------------------------------------------------- 1 | # Consistently initialise JavaScript using `govuk-` namespaced data-module attributes 2 | 3 | **Closing date:** 2019-06-11 4 | 5 | **Status:** accepted 6 | 7 | ## Summary 8 | 9 | We want to change the way that JavaScript in GOV.UK Frontend is initialised against elements in the DOM. 10 | 11 | We're doing this to help users avoid conflicts in their application. 12 | 13 | This would be a breaking change in the 3.0.0 release. 14 | 15 | ## Problem 16 | 17 | Currently to initialise the JavaScript for a component we look for a 18 | `data-module` attribute on the element. 19 | 20 | For example, the accordion HTML looks like this: 21 | 22 | ```html 23 |
24 | [..] 25 |
26 | ``` 27 | 28 | And we initialise the JavaScript like this: 29 | 30 | ```javascript 31 | // Find all global accordion components to enhance. 32 | var $accordions = scope.querySelectorAll('[data-module="accordion"]') 33 | $accordions.forEach($accordion => { 34 | new Accordion($accordion).init() 35 | }) 36 | ``` 37 | 38 | This works, but there's a risk of conflict if `[data-module="accordion"]` is used by anything else in the application. 39 | 40 | This [happened on GOV.UK](https://github.com/alphagov/collections/pull/1042), resulting in two 'open all' links appearing on a single accordion. 41 | 42 | --- 43 | 44 | Not all components are initialised in this way. The JavaScript for the button component, for example, sets up event listeners against the `scope` (usually `document`). 45 | 46 | This is inconsistent, and means that some components have a higher chance of conflicting as they e.g. affect anything with `role="button"` 47 | 48 | ## Proposal 49 | 50 | We intend to move to using a `govuk-` namespace for the `data-module` attribute. 51 | 52 | ```html 53 |
54 | [..] 55 |
56 | ``` 57 | 58 | ```javascript 59 | // Find all global accordion components to enhance. 60 | var $accordions = scope.querySelectorAll('[data-module="govuk-accordion"]') 61 | $accordions.forEach($accordion => { 62 | new Accordion($accordion).init() 63 | }) 64 | ``` 65 | 66 | We also intend to initialise all components that use JavaScript in the same way. 67 | 68 | For example, the JavaScript for buttons would be updated to initialise against `[data-module="govuk-button"]`. 69 | 70 | ```html 71 | Continue 72 | ``` 73 | 74 | ```js 75 | var $buttons = scope.querySelectorAll('[data-module="govuk-button"]') 76 | $buttons.forEach($button => { 77 | new Button($button).init() 78 | }) 79 | ``` 80 | -------------------------------------------------------------------------------- /decision-records/004-new-version-font.md: -------------------------------------------------------------------------------- 1 | # New version of font 2 | 3 | **Date:** 2019-07-29 4 | 5 | **Status:** Accepted 6 | 7 | ## Context 8 | 9 | There were a [number of issues with "NTA"](https://github.com/alphagov/govuk-frontend/issues/1012), the previous version of the font: 10 | 11 | 1. The file size for all versions of the font was larger than it needed to be. 12 | 2. A separate font was required for tabular numbers. 13 | 3. The glyphs sat too high in the fonts bounding box (baseline) which led to the need for adjustments in CSS. 14 | 4. Hinting requirement for oldIE (EOT) increased the file size even further. 15 | 16 | ## Decision 17 | 18 | - Replace the "NTA" font with a new version, called "GDS Transport", which fixes the above issues. 19 | - Specifically, stop serving Transport font to IE8 due to a [large file required for hinting](https://designnotes.blog.gov.uk/2019/07/29/weve-updated-the-gov-uk-colours-and-font/). The font now [falls back to Arial](https://github.com/alphagov/govuk-frontend/blob/master/CHANGELOG.md#gds-transport-now-falls-back-to-arial-in-internet-explorer-8-ie8) for IE8. 20 | 21 | ## Consequences 22 | - Font files are now smaller: WOFF2 files are ~33kb and ~31kb, compared with ~66kb and ~54kb of the previous version of the font 🎉 23 | - The vertical alignment of the font has been corrected. This removes the need for manually adjusting the baseline of the font. 24 | - Tabular numbers are now part of the [`govuk-font` mixin](http://govuk-frontend-review.herokuapp.com/docs/#helpers-mixin-govuk-font), instead of a separate font family. 25 | - The previous version of the font is now deprecated. Service teams using the legacy code bases [can still use the previous version in compatibility mode](https://github.com/alphagov/govuk-frontend/blob/master/docs/installation/compatibility.md). 26 | 27 | ## Advantages 28 | 29 | - Improved page performance due to smaller font files. 30 | - No need to adjust the font baseline manually. This means simpler code and less design / development work. 31 | - With the baseline adjustments removed, the font can be swapped for a different one such as Arial without manually having to remove the baseline adjustments. An example would be if [the service is not on gov.uk](https://www.gov.uk/service-manual/design/making-your-service-look-like-govuk#if-your-service-isnt-on-govuk). 32 | - Simpler documentation for using tabular numbers which are now part of the `govuk-font` mixin. Using tabular numbers no longer requires loading in a separate font, leading to performance gains. 33 | - IE8 will not download the font files but falls back to a default font, leading to performance gains. 34 | 35 | ## Disadvantages 36 | 37 | - Service teams might need to make adjustments in their custom components which contain corrections to the baseline of the font. 38 | -------------------------------------------------------------------------------- /decision-records/002-restructure-based-on-single-package.md: -------------------------------------------------------------------------------- 1 | # Restructure single GOV.UK Frontend package 2 | 3 | **Date:** 2018-05-10 4 | 5 | **Status:** Accepted 6 | 7 | ## Context 8 | 9 | We implemented the [002 Proposal](https://github.com/alphagov/govuk-design-system-architecture/blob/master/proposals/002-publish-one-npm-package-instead-of-multiple-npm-packages.md) in https://github.com/alphagov/govuk-frontend/pull/680 10 | 11 | We have then restructured the code base in https://github.com/alphagov/govuk-frontend/pull/693 12 | 13 | This is to: 14 | 15 | - solve issues around components importing files that export CSS 16 | - take advantage of the single package - the old structure was based around each folder being it's own package. 17 | - make the entry points to files clearer. 18 | - better reflect conventions by giving each layer it's own folder, this moves them out of a confusingly named 'global' parent folder. 19 | 20 | ## Decision 21 | 22 | ### Structure 23 | 24 | GOV.UK Frontend is broken into a number of layers in order to help provide a 25 | logical structure, loosely following the conventions of [ITCSS]. 26 | 27 | 1. [Settings](#settings) 28 | 2. [Tools](#tools) 29 | 3. [Helpers](#helpers) 30 | 4. [Core](#core) 31 | 5. [Objects](#objects) 32 | 6. [Components](#components) 33 | 7. [Utilities](#utilities) 34 | 8. [Overrides](#overrides) 35 | 36 | Each folder has its own entry point (`_all.scss`). 37 | 38 | ### Settings 39 | 40 | Global variables for the project, for example colour palettes and spacing and 41 | typography scales. 42 | 43 | This layer should not output any CSS. 44 | 45 | ### Tools 46 | 47 | Mixins or functions that implement either logic (e.g. conditionally outputting 48 | CSS) or calculations, and that need to be made available globally. 49 | 50 | This layer should not output any CSS. 51 | 52 | ### Helpers 53 | 54 | Mixins that abstract common styling (for example, focus states or visually 55 | hidden content) 56 | 57 | This layer should not output any CSS. 58 | 59 | ### Core 60 | 61 | Basic content styles for typography, links etc. The classes defined in this 62 | layer would generally correspond to an HTML element - for example paragraphs, 63 | headings, lists or links. 64 | 65 | ### Objects 66 | 67 | Objects can range from something as simple as a wrapper element, to layout 68 | systems. 69 | 70 | They may be used in any number of unrelated contexts to the one you can 71 | currently see it in. This means that making modifications to these types of 72 | class could potentially have knock-on effects in other places. 73 | 74 | ### Components 75 | 76 | Discrete pieces of UI. In most cases these will map to the components in the 77 | Design System. 78 | 79 | ### Utilities 80 | 81 | Utility classes – for example clearing floats, visually hiding content. 82 | 83 | ### Overrides 84 | 85 | Classes that map to a specific property – for example margin or font weight - 86 | and override all other layers. Rules in this layer will generally be marked as 87 | !important. 88 | 89 | Class names within this layer use an additional prefix `-!-`, for example 90 | `.govuk-!-w-regular`. 91 | 92 | [ITCSS]: (http://www.creativebloq.com/web-design/manage-large-css-projects-itcss-101517528) 93 | 94 | ## Consequences 95 | 96 | The paths to import the project are changed, this has been detailed in the release notes for GOV.UK Frontend. 97 | -------------------------------------------------------------------------------- /decision-records/009-throw-errors-component-constructors.md: -------------------------------------------------------------------------------- 1 | # Throw errors from component constructors 2 | 3 | **Date:** 2023-07-20 4 | 5 | **Status:** Accepted 6 | 7 | ## Decision 8 | 9 | In v5.0, we will update the constructor of every component to throw errors if the arguments passed to the constructor are invalid, rather than silently returning. 10 | 11 | ## Rationale 12 | 13 | Currently, if we encounter something unexpected during instantiation of an object we return early. For example: 14 | 15 | ```js 16 | if (!($module instanceof HTMLElement) || !document.body.classList.contains('govuk-frontend-supported')) { 17 | return this 18 | } 19 | ``` 20 | 21 | This can make unexpected behaviour difficult to debug for users – because we silently return, the user has no idea why the accordion isn't doing anything. 22 | 23 | The user also has a reference to an instantiated component in an invalid state. 24 | 25 | As we introduce new methods to the public API, we would need to handle the possibility that the component is in an invalid state as part of every individual method: 26 | 27 | ```js 28 | const accordion = new Accordion(aNonExistentElement) 29 | accordion.openAllSections() // what do we do here?! 30 | ``` 31 | 32 | Throwing an error from the constructor means that: 33 | 34 | - we are following the 'fail fast' principle 35 | - any unexpected behaviour is easier to debug 36 | - the user can never have a reference to an instantiated component that threw exceptions from the constructor (because the assignment will fail), which means we can assume the component is in a valid state when writing other public methods 37 | 38 | ## Risks and constraints 39 | 40 | ### Changes prevent some users from upgrading 41 | 42 | Users who are relying on being able to access now private class or instance properties from from their own code will need to either: 43 | 44 | - wait until we introduce an equivalent way to achieve the same thing using the public API before they can upgrade beyond v5 45 | - continue to use the private properties 'at risk', and manually test or verify changes between releases 46 | 47 | ### Changes cause unhandled JavaScript errors in services 48 | 49 | If thrown exceptions are left unhandled this will stop script execution, including JavaScript for other components on the page. Some of our components can [fail closed if JavaScript is enabled in the browser but the script fails to run](https://github.com/alphagov/govuk-frontend/issues/999). 50 | 51 | We will treat this as a breaking change and ensure that it is well documented in the release notes. 52 | 53 | This doesn't mean that introducing additional scenarios where the constructor may throw will always be breaking changes. The breaking change is that it's now possible that the constructor may throw, when it never would before. 54 | 55 | ## Alternatives considered 56 | 57 | None. 58 | 59 | ## Implications 60 | 61 | If we see users struggling with error handling when instantiating instances we may consider introducing a 'fail-safe' way of instantiating, for example using a static method on the class that simply logs errors to the console. 62 | 63 | ## Contributors 64 | 65 | - Brett Kyle (@domoscargin) 66 | - Colin Rotherham (@colinrotherham) 67 | - Oliver Byford (@36degrees) 68 | - Romaric Pascal (@romaricpascal) 69 | 70 | ## Associated issues and pull requests (PRs) 71 | 72 | 73 | 74 | ## Outcomes 75 | 76 | - Update the constructors of each component to throw errors if the arguments passed to the constructor are invalid 77 | -------------------------------------------------------------------------------- /decision-records/001-javascript-for-less-capable-browsers.md: -------------------------------------------------------------------------------- 1 | # JavaScript for less-capable browsers 2 | 3 | **Date:** 2018-05-16 4 | 5 | **Status:** Superseded by [006 - JavaScript browser compatibility](https://github.com/alphagov/govuk-design-system-architecture/blob/main/decision-records/006-javascript-compatibility.md) 6 | 7 | ## Note 8 | 9 | polyfill.io was reported as compromised on 25th June 2024 and we are no longer recommending it as a polyfilling service. Additionally, we have removed the polyfills we created with it from govuk-frontend v5+. 10 | 11 | ## Context 12 | 13 | Before GOV.UK Frontend, our projects used jQuery for DOM interactions, events and data manipulation. 14 | 15 | We’re taking a step back from jQuery due to its lack of support for the browsers we support, its large file size, lack of security updates and from conversations with the community. 16 | 17 | ## Decision 18 | 19 | We’re now writing standard ES5 JavaScript instead, that we polyfill where necessary. 20 | 21 | This means that in places where we would have previously used [`$.each`](http://api.jquery.com/jquery.each/) we’re using [`.forEach`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach) instead, and polyfilling the missing gaps. 22 | 23 | We use polyfills provided by the Financial Times’ [Polyfill service](https://polyfill.io). 24 | 25 | This approach ensures that multiple polyfills can be sourced from this service with greater confidence that they’ll work without conflicting with each other. 26 | 27 | The Polyfill service does not do runtime detection in browsers and instead opts to do this on the server via user-agent sniffing. It only ships the code needed for that browser, which means newer browsers don’t have to run anything. We may investigate lazy-loading in the future, but for now we’re using a bundled approach based on the lowest common denominator. 28 | 29 | We are vendoring these polyfills to avoid any [single point of failure](https://en.wikipedia.org/wiki/Single_point_of_failure) issues that could arise from relying on a CDN. By doing this, we can detect if polyfills are needed at runtime, which results in all browsers getting the same polyfill bundle. 30 | 31 | We hope that our approach can be automated or moved into a reusable npm package, based on the Financial Times [npm package](https://github.com/Financial-Times/polyfill-service#library). 32 | 33 | Here is an [example of polyfilling `addEventListener`](https://github.com/alphagov/govuk-frontend/blob/master/docs/polyfilling.md). 34 | 35 | Any polyfills included in GOV.UK Frontend will be tested to work in supported browsers and devices, including assistive technology. Any community discussion and documentation around potential bugs or downsides will also be considered before deciding to include a polyfill in GOV.UK Frontend. 36 | 37 | ## Consequences 38 | 39 | ### Advantages 40 | 41 | - We’re not forcing projects to include and rely on a specific library 42 | - Developers don’t need to know or learn a specific library 43 | - The JavaScript code is standard and transferable 44 | - It’s very easy to remove the polyfills when older browser support is dropped while keeping the same JavaScript code 45 | - Approach can be easily maintained and used by the community 46 | - Polyfills are widely maintained by the industry 47 | 48 | ### Disadvantages 49 | 50 | - There are risks modifying globals or native object prototypes 51 | - https://www.w3.org/2001/tag/doc/polyfills/#always-encapsulate 52 | - http://perfectionkills.com/whats-wrong-with-extending-the-dom/ 53 | - We cannot be sure if our polyfills work with other third party code 54 | 55 | ## References 56 | 57 | - [Polyfills and the evolution of the Web](https://www.w3.org/2001/tag/doc/polyfills/) 58 | - [Polyfill approach discussion on GitHub](https://github.com/alphagov/govuk-frontend/issues/676) 59 | -------------------------------------------------------------------------------- /decision-records/008-reset-the-javascript-api.md: -------------------------------------------------------------------------------- 1 | # Reset the JavaScript API for our components 2 | 3 | **Date:** 2023-07-20 4 | 5 | **Status:** Accepted 6 | 7 | ## Decision 8 | 9 | In v4.x, for each component class, we will mark all class and instance properties other than the constructor and the `init` method as deprecated. 10 | 11 | In v5.0 we will then add JSDoc annotations to mark the deprecated properties as private. We will also annotate any 'internal' classes or functions (like the `I18n` class and the `mergeConfigs` function) as internal. 12 | 13 | In future releases we will then gradually introduce a new public JavaScript API for components, which is: 14 | 15 | - based on the needs of users 16 | - clearly defined and documented 17 | - comprehensively tested 18 | 19 | ## Rationale 20 | 21 | The JavaScript API for our components has not been designed to be called externally and does not clearly differentiate between public and private methods. 22 | 23 | Many of the methods exposed on the classes or objects can only be called internally as they need to be passed internal state, or are designed to be used internally by the component as event handlers. 24 | 25 | We also have little or no test coverage for calling these methods externally. 26 | 27 | This means that: 28 | 29 | - it's unclear for users whether they are allowed to call or interact with each property 30 | - it's difficult for us to judge what constitutes a breaking change 31 | 32 | 'Resetting' the public API by marking everything else as private gives us the freedom to refactor the internals of the component before then introducing a properly designed, tested and documented public API. 33 | 34 | ## Risks and constraints 35 | 36 | Users who are relying on being able to access now private class or instance properties from from their own code will need to either: 37 | 38 | - wait until we introduce an equivalent way to achieve the same thing using the public API before they can upgrade beyond v5 39 | - continue to use the private properties 'at risk', and manually test or verify changes between releases 40 | 41 | ## Alternatives considered 42 | 43 | ### Do nothing 44 | 45 | We could leave the API as ambiguous, however we know that following other recent major changes to the way that we write JavaScript, we will want to be able to refactor the components to take advantage of newer JavaScript features and to reduce the amount of duplication between components. 46 | 47 | Doing this without a clear definition of the public API will be difficult, as it will be hard to reason whether a particular change is breaking or not. 48 | 49 | ### Maintain the existing API 50 | 51 | We could aim to introduce a new full-featured public API before we remove any of the existing properties. However, it would be difficult to do this without significant refactoring of the existing code, which would almost certainly require the removal or renaming of existing methods and variables. We would also need to introduce comprehensive testing of the existing methods to ensure their behaviour was maintained. 52 | 53 | Aside from the constructor and the `init`` method, none of the existing class or object properties have been designed to be called externally or documented. We believe that the vast majority of our users only interact with the constructor and init methods. 54 | 55 | Therefore we believe the additional engineering effort required to preserve the existing 'accidental' API is not justified. 56 | 57 | ## Contributors 58 | 59 | - Brett Kyle (@domoscargin) 60 | - Colin Rotherham (@colinrotherham) 61 | - Oliver Byford (@36degrees) 62 | - Romaric Pascal (@romaricpascal) 63 | 64 | ## Associated issues and pull requests (PRs) 65 | 66 | - [#3478: Clarify our JavaScript components' public API](https://github.com/alphagov/govuk-frontend/issues/3478) 67 | 68 | ## Outcomes 69 | 70 | 1. In v4.x, deprecate all properties except the constructor and the init method. 71 | 2. In v5.0, mark the deprecated properties as private. 72 | 3. In v5.0, mark internal classes and functions as internal. 73 | 4. In future releases, gradually introduce a properly designed API. 74 | -------------------------------------------------------------------------------- /proposals/008-simplifying-imports-to-improve-compilation-performance.md: -------------------------------------------------------------------------------- 1 | # Simplifying imports within GOV.UK Frontend to improve compilation performance 2 | 3 | **Closing date:** 1 May 2020 4 | 5 | **Status:** Accepted 6 | 7 | ## Summary 8 | 9 | **This is an iteration of [proposal #7](https://github.com/alphagov/govuk-design-system-architecture/pull/21), based on the feedback we received from that proposal.** 10 | 11 | We’re making changes to the way that the base layers (settings, tools and helpers) are imported within different parts of GOV.UK Frontend’s Sass, to reduce the time it takes to compile to CSS. 12 | 13 | Most of you will not be affected by these changes, and if you import "node_modules/govuk-frontend/govuk/all" you will not need to do anything to benefit from these performance improvements. 14 | 15 | It will have the most impact on you if you import only specific parts of GOV.UK Frontend. 16 | 17 | ## Problem 18 | 19 | It can take a long time to compile GOV.UK Frontend’s Sass to CSS. This is because many of the individual files within GOV.UK Frontend import their own dependencies, even if they would usually have already been imported. We originally did this so that you could import specific bits of GOV.UK Frontend without having to separately import their dependencies. 20 | 21 | Reducing the number of imports within GOV.UK Frontend has been shown to significantly improve the compilation time, as demonstrated in [#1671 Slow compilation of SCSS files in Rails apps](https://github.com/alphagov/govuk-frontend/issues/1671). 22 | 23 | This should particularly improve things for you if you use Sprockets to package your assets, although we expect these changes to improve the compilation time for everyone. 24 | 25 | ## Proposal 26 | 27 | We will implement changes in two stages. 28 | 29 | 1. We can make changes to the imports within components without it being a breaking change, so we’ll do this as part of a v3.x release. 30 | 2. We’ll make the breaking changes to the core, objects and overrides layers in the v4.0 release. 31 | 32 | ### Changes in GOV.UK Frontend v3.x 33 | 34 | We’ll add a new file called `_index.scss` to each component, which contains the component’s styles but does not import the settings, helpers and tools layers. 35 | 36 | We’ll update the existing _[component].scss files to import the settings, helpers and tools layers and import _index.scss. This will preserve the existing behaviour, and continue to provide a single entry point for individual components that can be used in contexts such as React. 37 | 38 | We’ll update `components/_all.scss` to include every component’s `_index.scss` file, avoiding the unnecessary imports of the settings, helpers and tools layers within each component. 39 | 40 | You can still import `/govuk-frontend/govuk/all`, and if you’re doing this you will not need to make any changes to benefit from these improvements. 41 | 42 | You can still import components individually (for example `govuk-frontend/govuk/components/button/button`), but you should update your code to import the index file for each component (instead of the [component].scss) if you want to benefit from the performance improvements: 43 | 44 | ```scss 45 | @import "govuk/settings/all"; 46 | @import "govuk/tools/all"; 47 | @import "govuk/helpers/all"; 48 | 49 | @import "govuk/components/accordion/index"; 50 | @import "govuk/components/button/index"; 51 | ``` 52 | 53 | In preparation for GOV.UK Frontend v4.0, we’ll add deprecation warnings if you import files from the core and overrides layers without first importing the settings, helpers and tools layers. 54 | 55 | ### Changes in GOV.UK Frontend v4.0 56 | 57 | We’ll move the template styles from the core/_template.scss to objects/_template.scss, so that we treat it as an object rather than core styling. 58 | 59 | We’ll remove the imports of the settings, helpers and tools layers from files in core and overrides. 60 | 61 | If you selectively import individual files from core or overrides, you’ll need to import the settings, tools and helpers layers first: 62 | 63 | ```scss 64 | @import "govuk/settings/all"; 65 | @import "govuk/tools/all"; 66 | @import "govuk/helpers/all"; 67 | 68 | @import "core/typography"; 69 | ``` 70 | 71 | We’ll continue to import the settings, helpers and tools layers from files within the objects layer, so that they can act as single entry points that can be used in contexts such as React. 72 | -------------------------------------------------------------------------------- /proposals/005-namespace-govuk-frontend-nunjucks-sass-using-a-nested-folder-structure.md: -------------------------------------------------------------------------------- 1 | # Namespace GOV.UK Frontend Nunjucks and Sass using a nested folder structure 2 | 3 | **Closing date:** 2019-06-12 4 | 5 | **Status:** accepted 6 | 7 | ## Summary 8 | 9 | We want to namespace `govuk-frontend` by changing the folder structure for the `govuk-frontend` npm package. 10 | 11 | We are doing this to make it easier for users to import things, in a way that is explicit and avoids conflicts in their application. 12 | 13 | This would be a breaking change in the 3.0.0 release. 14 | 15 | ## Problem 16 | 17 | To import things from GOV.UK Frontend, your application needs to know where to find those things in the filesystem. 18 | 19 | You can do this by providing the full path to the file, for example 20 | 21 | ```javascript 22 | {% from "node_modules/govuk-frontend/components/accordion/macro.njk" import govukAccordion %} 23 | ``` 24 | 25 | You can also tell your application which 'include paths' to look in to find things, which allows you to simplify the import path. 26 | 27 | In GOV.UK Frontend, you add the following paths to your 'include paths': 28 | 29 | - `node_modules/govuk-frontend/` 30 | - `node_modules/govuk-frontend/components/` 31 | 32 | You can then import things like this: 33 | 34 | ```javascript 35 | {% from "accordion/macro.njk" import govukAccordion %} 36 | ``` 37 | 38 | However, there are 2 issues with this approach at the minute. 39 | 40 | 1. It's no longer clear where the thing is coming from. Those new to the codebase may not realise that it's being imported from an external dependency, because it's not explicit. 41 | 42 | 2. If you create your own accordion component, your application will not know which one to import (or it'll just try and import the first one it finds) as there will be two paths that both match. 43 | 44 | There are 2 ways to get around these issues at the moment: 45 | 46 | 1. You could add the `node_modules` path to your 'include paths'. 47 | 48 | This then allows you to include things referencing govuk-frontend, like this: 49 | 50 | ```javascript 51 | {% from "govuk-frontend/components/accordion/macro.njk" import govukAccordion %} 52 | ``` 53 | 54 | However, this is not practical since your application has to search all of the packages in the `node_modules` folder to try and find the thing, which can be very slow. 55 | 56 | 2. Using a custom namespacing in the your codebase, for example: 57 | 58 | ```javascript 59 | {% from "app-accordion/macro.njk" import appAccordion %} 60 | ``` 61 | 62 | ## Proposal 63 | 64 | Create a new folder called `govuk/` and move all the GOV.UK Frontend source files into it. 65 | 66 | ```bash 67 | . 68 | ├── README.md 69 | ├── govuk 70 | │ ├── all-ie8.scss 71 | │ ├── all.js 72 | │ ├── all.scss 73 | │ ├── assets 74 | │ ├── common.js 75 | │ ├── components 76 | │ ├── core 77 | │ ├── helpers 78 | │ ├── objects 79 | │ ├── overrides 80 | │ ├── settings 81 | │ ├── template.njk 82 | │ ├── tools 83 | │ ├── utilities 84 | │ └── vendor 85 | ├── govuk-prototype-kit.config.json 86 | └── package.json 87 | ``` 88 | 89 | Then you could add the following path to your 'include paths': 90 | 91 | - `node_modules/govuk-frontend/` 92 | 93 | You could then import components like this: 94 | 95 | **Nunjucks:** 96 | ```javascript 97 | {% from "govuk/components/accordion/macro.njk" import govukAccordion %} 98 | ``` 99 | 100 | **Sass:** 101 | 102 | ```scss 103 | @import "govuk/components/accordion/accordion" 104 | ``` 105 | 106 | **JavaScript:** 107 | 108 | ```javascript 109 | import Accordion from "govuk/components/accordion/accordion" 110 | ``` 111 | 112 | Because we can specify [the primary entry point in the package.json](https://docs.npmjs.com/files/package.json#main), you could also import components like this: 113 | 114 | ```javascript 115 | import { Accordion } from "govuk-frontend" 116 | ``` 117 | 118 | You can see the [proposed package folder structure](https://github.com/alphagov/govuk-frontend/tree/fb0476423e28eb0410c6810d4ff6ef4ef17d2df2) on GitHub. 119 | 120 | If you'd like to try this out in your application, you can install a pre-release: 121 | 122 | ```bash 123 | npm install --save alphagov/govuk-frontend#fb047642 124 | ``` 125 | 126 | ## Acknowledgements / Further reading 127 | 128 | This proposal builds on the contributions from the community. 129 | 130 | Specifically [this proposal is also based on an investigation by HMRC](https://gist.github.com/rpowis/71f3782166e7d835b12ffe7740f6b23e#3-prepend-a-directory-at-the-package-root) 131 | 132 | You can see the [original discussion on GitHub](https://github.com/alphagov/govuk-frontend/issues/870). 133 | -------------------------------------------------------------------------------- /decision-records/010-remove-init-method.md: -------------------------------------------------------------------------------- 1 | # Remove `init()` method from JavaScript components 2 | 4 | 5 | **Date:** 2023-07-20 6 | 7 | **Status:** Accepted 8 | 9 | ## Decision 10 | 11 | 12 | 13 | We'll be removing the `init()` method from our JavaScript components, 14 | in favour of them initialising automatically during instantiation. 15 | 16 | This simplifies individual component's initialisation from: 17 | 18 | ```js 19 | new Accordion($element).init() 20 | ``` 21 | 22 | To: 23 | 24 | ```js 25 | new Accordion($element) 26 | ``` 27 | 28 | ## Rationale 29 | 30 | The `init()` method adds an unnecessary step for our components' initialisation, without tangible benefits for what our components do. Without it we can simplify both how our components are initialised, as well as their internal implementation as we're looking to [throw errors at instantiation](./009-throw-errors-component-constructors.md). 31 | 32 | The `init()` method enables the following, that none of our components benefit from, so we can remove that extra step: 33 | 34 | - delaying the initialisation of the component after its instantiation 35 | - allowing the initialisation code to be `async` (which a `constructor` cannot be) 36 | 37 | With our intent to [throw errors at construction](./009-throw-errors-component-constructors.md), having a separate `init()` method requires careful separation between validation of the component in the `constructor()` and initialisation code in a subsequent call. By having only the constructor, the initialisation code can simply `throw` from within `constructor()` to ensure users always get functional instances of our components. 38 | 39 | 40 | 41 | ## Risks and constraints 42 | 43 | ### Reduce or delay the adoption of v5 44 | 45 | This change requires code changes from our users, that they may not have the capacity to implement. 46 | 47 | This is mitigated by the changes being quite small (removing a `.init()` call following the current instantiation of the component) and [only affects a portion of our users](#users-need-to-update-their-code), who use our component classes directly rather than through `initAll()`. 48 | 49 | 50 | 51 | ## Alternatives considered 52 | 53 | ### Deprecating the init method in v5 for future removal in v6 54 | 55 | Because there wasn't really an alternative for users to switch to if we'd deprecated in v4 (if people stopped calling `init()`, there'd be no initialisation), we couldn't make the deprecation in v4. 56 | 57 | Implementing an empty `init()` to document its deprecation in v5 would only delay the update users need to make in their code. This will come at the detriment of the next release: on top of focusing on the topic of that new release, people will also have to update their JavaScript (which is the focus of v5). 58 | 59 | The scope of the change users have to make, which will be documented, as well as our continued support for v4 during a year after we ship v5 seems enough of a mitigation to directly remove the method. 60 | 61 | ### Keeping the `init` method to make use of `async` 62 | 63 | The `init()` method could be made asynchronous, which would isolate the initialisation of each component and allow it to wait for asynchronous calls without blocking the main thread. 64 | 65 | However, since: 66 | 67 | - Asynchronous code requires a deeper understanding of concurrency 68 | - Deferred errors from Promises must be awaited before they throw 69 | - None of our components make asynchronous calls 70 | 71 | We can currently consider the `init()` method unnecessary. That said, we may add asynchronous methods to our components in future. 72 | 73 | 74 | 75 | ## Implications 76 | 77 | 78 | 79 | ### Users need to update their code 80 | 81 | Component initialisation will be reduced to `new Example()` instead of `new Example().init()`. Only users that call component `init()` themselves will need to update their code to reflect this. 82 | 83 | The `initAll()` method will not be affected. 84 | 85 | ## Contributors 86 | 87 | - Brett Kyle (@domoscargin) 88 | - Colin Rotherham (@colinrotherham) 89 | - Oliver Byford (@36degrees) 90 | - Romaric Pascal (@romaricpascal) 91 | 92 | ## Associated issues and pull requests (PRs) 93 | 94 | 95 | 96 | ## Outcomes 97 | 98 | 99 | - Implement the removal of the `init()` method for each of our component 100 | - Document the code update `govuk-frontend` users will need to implement following our removal 101 | -------------------------------------------------------------------------------- /proposals/003-make-override-classes-consistent.md: -------------------------------------------------------------------------------- 1 | # Make override classes consistent 2 | 3 | **Closing date:** N/A 4 | 5 | **Status:** Accepted (originally raised as a [gist](https://gist.github.com/nickcolley/f135e89ed4b679355b0ab47135b38ee8)) 6 | 7 | ## Summary 8 | 9 | We're getting close to 1.0.0 and are tidying up and loose ends for the public API. 10 | 11 | One of the final things we're auditing is the consistency between class names, 12 | we believe if they're more consistent they'll be easier to remember and more intuative. 13 | 14 | ## Problem 15 | 16 | Right now our override classes look like: 17 | 18 | ``` 19 | .govuk-!-display-inline {} 20 | .govuk-!-display-inline-block {} 21 | .govuk-!-display-block {} 22 | .govuk-!-m-rN {} 23 | .govuk-!-p-rN {} 24 | .govuk-!-f-N {} 25 | .govuk-!-w-regular {} 26 | .govuk-!-w-bold {} 27 | .govuk-!-width-three-quarters {} 28 | .govuk-!-width-two-thirds {} 29 | .govuk-!-width-one-half {} 30 | .govuk-!-width-one-third {} 31 | .govuk-!-width-one-quarter {} 32 | ``` 33 | 34 | (Note for sake of demonstration I've not included all the [spacing classes](https://design-system.service.gov.uk/styles/spacing/#using-the-override-classes)) 35 | 36 | Some examples of the short hand classes are: 37 | 38 | - `.govuk-!-w-bold` which sets the font weight to 'bold') 39 | - `.govuk-!-f-30` which sets the font size to 24 (responsively) 40 | - `.govuk-!-mb-r3` which sets the margin bottom to the spacing scale of 3 (responsively) 41 | 42 | ## Proposal 43 | 44 | We're considering making all overrides consistent, this would look like either: 45 | 46 | ### Option 1: Consistently longhand 47 | 48 | ``` 49 | .govuk-!-display-inline {} 50 | .govuk-!-display-inline-block {} 51 | .govuk-!-display-block {} 52 | .govuk-!-margin-5 {} 53 | .govuk-!-margin-bottom-5 {} 54 | .govuk-!-padding-0 {} 55 | .govuk-!-padding-bottom-0 {} 56 | .govuk-!-font-size-30 {} 57 | .govuk-!-font-weight-regular {} 58 | .govuk-!-font-weight-bold {} 59 | .govuk-!-width-three-quarters {} 60 | .govuk-!-width-two-thirds {} 61 | .govuk-!-width-one-half {} 62 | .govuk-!-width-one-third {} 63 | .govuk-!-width-one-quarter {} 64 | ``` 65 | 66 | #### Pros 67 | - easier to understand what the classes are doing when seeing them for the first time 68 | 69 | #### Cons 70 | - since override classes tend to be used together, verbose class names could make markup verbose 71 | 72 | ### Option 2: Consistently shorthand 73 | 74 | ``` 75 | .govuk-!-d-i {} 76 | .govuk-!-d-ib {} 77 | .govuk-!-d-b {} 78 | .govuk-!-m-5 {} 79 | .govuk-!-mb-5 {} 80 | .govuk-!-p-0 {} 81 | .govuk-!-pb-0 {} 82 | .govuk-!-fs-30 {} 83 | .govuk-!-fw-regular {} 84 | .govuk-!-fw-bold {} 85 | .govuk-!-w-3/4 {} 86 | .govuk-!-w-2/3 {} 87 | .govuk-!-w-1/2 {} 88 | .govuk-!-w-1/3 {} 89 | .govuk-!-w-1/4 {} 90 | ``` 91 | 92 | #### Pros 93 | - once the naming convention is understood, it is faster to type 94 | - less verbose when composing classes together. 95 | 96 | #### Cons 97 | - higher overhead to learn and remember this naming convention 98 | 99 | ### Composing classes 100 | To explore what it would look like to use the long hand I took some real examples of using overrides from the GOV.UK Design System and put them side by side. 101 | 102 | 103 | #### Service unavailable pages example 104 | 105 | No change: 106 | 107 | ```html 108 |

Service unavailable

109 |

The submit an employment intermediary report service has closed.

110 |

Contact us if you need to speak to someone about the service and your reports.

111 |

Telephone:

112 |

0808 157 3900

113 |

Opening times:

114 |

Monday to Friday: 8:30am to 4:30pm

115 | ``` 116 | 117 | Expanded: 118 | 119 | ```html 120 |

Service unavailable

121 |

The submit an employment intermediary report service has closed.

122 |

Contact us if you need to speak to someone about the service and your reports.

123 |

Telephone:

124 |

0808 157 3900

125 |

Opening times:

126 |

Monday to Friday: 8:30am to 4:30pm

127 | ``` 128 | 129 | #### Phase banner example 130 | 131 | https://github.com/alphagov/govuk-design-system/blob/cf049adba070d349513313af43ad962fde16914c/views/partials/_banner.njk 132 | 133 | 134 | No change: 135 | 136 | ```javascript 137 | {{ govukPhaseBanner({ 138 | tag: { 139 | text: "preview", 140 | classes: "app-tag--review" 141 | }, 142 | classes: "govuk-!-pl-r3 govuk-!-pr-r3", 143 | html: phaseBannerText 144 | }) }} 145 | ``` 146 | 147 | Expanded: 148 | 149 | ```javascript 150 | {{ govukPhaseBanner({ 151 | tag: { 152 | text: "preview", 153 | classes: "app-tag--review" 154 | }, 155 | classes: "govuk-!-padding-left-3 govuk-!-padding-right-3", 156 | html: phaseBannerText 157 | }) }} 158 | ``` 159 | 160 | #### Start page example 161 | 162 | https://github.com/alphagov/govuk-design-system/blob/cf049adba070d349513313af43ad962fde16914c/src/design-system/patterns/start-pages/default/index.njk 163 | 164 | No change: 165 | 166 | ```html 167 |

Registering takes around 5 minutes.

168 | 169 | {{ govukButton({ 170 | text: "Start now", 171 | href: "#", 172 | classes: "govuk-button--start govuk-!-mt-r2 govuk-!-mb-r8" 173 | }) }} 174 | 175 |

Before you start

176 | ``` 177 | 178 | Expanded: 179 | 180 | ```html 181 |

Registering takes around 5 minutes.

182 | 183 | {{ govukButton({ 184 | text: "Start now", 185 | href: "#", 186 | classes: "govuk-button--start govuk-!-margin-top-2 govuk-!-margin-bottom-8" 187 | }) }} 188 | 189 |

Before you start

190 | ``` 191 | 192 | ### Related 193 | - https://tachyons.io/ (https://github.com/tachyons-css/tachyons-verbose) 194 | - http://basscss.com 195 | 196 | What do you think? Should we keep these overrides as they are? Or should we make them consistent one way or the other? 197 | -------------------------------------------------------------------------------- /proposals/004-enable-importing-css-modules-via-filename-convention-used-in-common-frameworks.md: -------------------------------------------------------------------------------- 1 | # Enable importing CSS Modules via filename convention used in common frameworks 2 | 3 | **Closing date:** 2019-02-06 4 | **Status:** Rejected 5 | 6 | ## Summary 7 | 8 | This proposal is a continuation of the [initial conversation raised on the GOV.UK Frontend repository](https://github.com/alphagov/govuk-frontend/issues/1052). 9 | 10 | [CSS Modules](https://github.com/css-modules/css-modules) is a standard way to allow users to import CSS into JavaScript files (commonly known as CSS-in-JS). 11 | 12 | Files imported as CSS Modules automatically are encapsulated by the build tool. 13 | 14 | In order to differentiate between files that should be imported as regular CSS and CSS modules some popular frameworks use a filename convention ‘filename.module.css’. 15 | 16 | This means that end users do not need to provide custom setup to a build tool such as webpack to import the file as a CSS Module. 17 | 18 | Examples of these projects include: 19 | 20 | - [create-react-app](https://facebook.github.io/create-react-app/docs/adding-a-css-modules-stylesheet) 21 | - [Neutrino](https://neutrinojs.org/packages/web/) 22 | - [Gatsby](https://github.com/gatsbyjs/gatsby) 23 | 24 | This may become a standard convention recommended by the CSS Modules specification: [css-modules/css-modules#229](https://github.com/css-modules/css-modules/issues/229) 25 | 26 | ## Problem 27 | 28 | Users can currently import GOV.UK Frontend files into components using a standard import, for example using the [webpack css loader](https://github.com/webpack-contrib/css-loader). 29 | 30 | Downstream projects such as [govuk-react](https://github.com/govuk-react/govuk-react) want to import only the files necessary for each component, then publish these components as separate npm packages. 31 | 32 | If a project like this imported CSS with a default loader conflicts would appear if the components use different versions of GOV.UK Frontend. 33 | 34 | In popular frameworks this is the default unless you use the `filename.module.css` convention, which automatically encapsulates classes. 35 | 36 | Multiple packages is something we [decided against when publishing GOV.UK Frontend](https://github.com/alphagov/govuk-design-system-architecture/blob/master/proposals/002-publish-one-npm-package-instead-of-multiple-npm-packages.md) as we are not sure people having inconsistent parts of the system would be a good idea, and multiple packages is not a requirement to have modular builds (including code splitting). 37 | 38 | However we can’t anticipate how people might want to use GOV.UK Frontend in the future. 39 | 40 | One issue that may arise from a project such as govuk-react trying to use CSS Modules will be that [some of our component CSS selectors reference other components](https://github.com/penx/govuk-frontend/blob/37e44dd2dacecb956299a129c5766aebaed40c06/src/components/character-count/_character-count.scss#L9) CSS selectors, which may not work. 41 | 42 | After speaking to Alasdair McLeay (lead of govuk-react) we agreed that to make components like the Character Count work correctly with CSS Modules we’d have to change the markup, resulting in a breaking change for our other users. 43 | 44 | With this in mind we think CSS Modules will for the most part still be useful for projects in the future and if this form of using CSS becomes more popular in the future we can consider making breaking changes to improve interoperability with CSS Modules but this should not block implementing an imperfect support. 45 | 46 | ## Proposal 47 | 48 | 49 | We would broadly implement support for CSS Modules by doing the following: 50 | 51 | ### 1a. Option 1: Manually create new `.module.scss` entry points for all SCSS files that output CSS 52 | 53 | - Core 54 | - Objects 55 | - Components 56 | - Utilities 57 | - Overrides 58 | 59 | For example: 60 | 61 | ```scss 62 | // header.module.scss 63 | 64 | @import “./header.scss” 65 | ``` 66 | 67 | Benefit of this options is it avoids any opaque build step transforms and allows for reasonable adjustments to the module files in the future if necessary. 68 | 69 | ### 1b. Option 2: Automatically create new `.module.scss` entry points for all SCSS files that output CSS with duplicate content 70 | 71 | - Core 72 | - Objects 73 | - Components 74 | - Utilities 75 | - Overrides 76 | 77 | Benefit of this option is the source directory is simpler. 78 | 79 | ### 2. Write guidance in the govuk-frontend installation documentation indicating that we support this CSS Modules filename convention 80 | 81 | ### Guidance 82 | 83 | Since we’re worried that many tools that use CSS Modules also do not support [building projects to the standards we expect](https://www.gov.uk/service-manual/technology/using-progressive-enhancement), we will take a neutral stance in any guidance detailing this functionality to avoid accidentally promoting specific frameworks. 84 | 85 | We would also make a note that this is an alpha / experimental feature. 86 | 87 | ### Pros 88 | - Projects such as govuk-react can have more confidence when their projects are used in common tools that support the CSS Modules file name convention. 89 | - Adds additional future proofing to GOV.UK Frontend 90 | 91 | ### Cons 92 | 93 | #### GOV.UK Frontend is not designed to be imported via CSS Modules 94 | 95 | Some parts of GOV.UK Frontend are not written in a way that work out the box with css modules, and the fixes necessary would be breaking changes for all users. 96 | 97 | #### Duplicate files in published package could be confusing 98 | 99 | If we ensure the guidance is clear we don’t have to make users make a decision and only make CSS Modules a feature for people looking for it. 100 | 101 | #### Risk that recommend tools that don't meet our standards 102 | 103 | We are going to have a neutral stance on css modules in relation to frameworks/tools/bundlers, and leave it to teams to pick the right tools for what they’re building. 104 | 105 | #### Option 2 only: A bigger npm package could mean slower npm installs for all users 106 | 107 | We think the risk of this is low as the files uploaded to npm are first compressed. 108 | 109 | Since duplicated plain text files are easy to compress we hope this would mean the increased size would not impact install time by a large amount. 110 | 111 | We can confirm this by investigating using `npm pack` will create a compressed zip which is the same as published to npm. 112 | 113 | #### Option 2 only: makes the build pipeline more complicated: takes longer, src gets further away from package 114 | 115 | While it does add complexity, it would mostly involve copying and renaming files so we think it’s not a big risk. 116 | -------------------------------------------------------------------------------- /decision-records/007-javascript-file-formats.md: -------------------------------------------------------------------------------- 1 | # JavaScript file names and formats 2 | 3 | **Date:** 2023-06-27 4 | 5 | **Status:** Accepted 6 | 7 | ## Decision 8 | 9 | We will consolidate all published JavaScript in the [`govuk-frontend` npm package](https://www.npmjs.com/package/govuk-frontend) into a single `govuk` directory. 10 | 11 | We will publish JavaScript in the following formats: 12 | 13 | 1. ECMAScript (ES) modules 14 | 2. ECMAScript (ES) modules, bundled 15 | 3. Universal Module Definition (UMD), bundled 16 | 17 | We will use ECMAScript (ES) modules by default and only bundle JavaScript files that are considered "entry points" into GOV.UK Frontend, such as `all.mjs` and exported components (for example `accordion.mjs`). 18 | 19 | We will change our [GitHub release](https://github.com/alphagov/govuk-frontend/releases) JavaScript `govuk-frontend-${version}.min.js` to ECMAScript (ES) modules format and add it to the published [`govuk-frontend` npm package](https://www.npmjs.com/package/govuk-frontend) without a version number. 20 | 21 | For consistency, we will clearly update our file extensions to: 22 | 23 | 1. Add prefix `.bundle` to bundled JavaScript file extensions 24 | 2. Add prefix `.min` to minified JavaScript file extensions 25 | 3. Always use `*.mjs` for ES modules (except for our [GitHub release](https://github.com/alphagov/govuk-frontend/releases), see constraints below) 26 | 27 | See the example directory listing below to show how files in `govuk-frontend/dist` will be named, further to our [decision to restructure `govuk-frontend`](./005-repository-organisation-for-v5.md): 28 | 29 | ```shell 30 | govuk-frontend/dist 31 | └── govuk 32 | ├── govuk-frontend.min.js # ECMAScript (ES) module bundle, minified 33 | │ 34 | ├── all.mjs # ECMAScript (ES) module 35 | ├── all.bundle.mjs # ECMAScript (ES) module bundle 36 | ├── all.bundle.js # Universal Module Definition (UMD) bundle 37 | │ 38 | └── components 39 | ├── accordion 40 | │   ├── accordion.mjs # ECMAScript (ES) module 41 | │   ├── accordion.bundle.mjs # ECMAScript (ES) module bundle 42 | │   └── accordion.bundle.js # Universal Module Definition (UMD) bundle 43 | │ 44 | └── button 45 | ├── button.mjs # ECMAScript (ES) module 46 | ├── button.bundle.mjs # ECMAScript (ES) module bundle 47 | └── button.bundle.js # Universal Module Definition (UMD) bundle 48 | ``` 49 | 50 | ## Rationale 51 | 52 | We can avoid future breaking changes by changing file names and extensions to clearly show: 53 | 54 | * different "flavours" of JavaScript like ES modules 55 | * which files are standalone, bundled or minified 56 | 57 | For example, as explained in our [**JavaScript browser compatibility** decision](./006-javascript-compatibility.md) we may need to add polyfills or transpilation helpers in future. 58 | 59 | Service users can optionally either import `*.bundle.mjs` (ES modules, bundled) or require `*.bundle.js` (UMD, bundled) to include all the polyfills they need, or alternatively import `*.mjs` (ES modules) to use their own bundler. 60 | 61 | ## Risks and constraints 62 | 63 | ### Browser Content-Type headers and `*.mjs` extensions 64 | 65 | Due to poor web server `Content-Type` header support for `*.mjs` files, we've kept the `*.js` extension for our [GitHub release](https://github.com/alphagov/govuk-frontend/releases) JavaScript `govuk-frontend-${version}.min.js` bundle. 66 | 67 | For reference: 68 | 69 | * [Apache issue, resolved May 2022](https://bz.apache.org/bugzilla/show_bug.cgi?id=61383) 70 | * [Nginx issue, unresolved](https://trac.nginx.org/nginx/ticket/2216) 71 | 72 | ### GitHub release format changed to ES modules 73 | 74 | We've changed our [GitHub release](https://github.com/alphagov/govuk-frontend/releases) JavaScript `govuk-frontend-${version}.min.js` bundle format from Universal Module Definition (UMD) to ES modules, but there is a risk that service users will still require UMD. 75 | 76 | ### Maintaining CommonJS compatibilty 77 | 78 | We know that CommonJS compatibility is important for both [Node.js `require('govuk-frontend')` package resolution](https://github.com/alphagov/govuk-frontend/issues/3755) and for test runners that do not support ES modules yet. 79 | 80 | For example, by making our npm package "ESM only" we'd hit issues such as: 81 | 82 | 1. [Jest ECMAScript modules support](https://jestjs.io/docs/ecmascript-modules) needing `--experimental-vm-modules` 83 | 2. [Mocha current limitations](https://mochajs.org/#current-limitations) like [`--watch` mode](https://github.com/mochajs/mocha/issues/4374) only works with CommonJS 84 | 85 | Due to this constraint we've maintained CommonJS support by continuing to package Universal Module Definition (UMD) bundles. 86 | 87 | ## Alternatives considered 88 | 89 | ### Using directories for JavaScript formats 90 | 91 | We considered using directories to show different JavaScript formats but preferred file names and extensions: 92 | 93 | ```shell 94 | govuk-frontend/dist 95 | └── govuk 96 | ├── cjs 97 | ├── mjs 98 | └── umd 99 | ``` 100 | 101 | ### Using file extension prefixes for JavaScript formats 102 | 103 | We considered always using `*.js` file extensions and adding JavaScript formats as prefixes, but preferred using prefixes to clearly show standalone, bundled or minified files instead: 104 | 105 | ```shell 106 | govuk-frontend/dist 107 | └── govuk 108 | ├── all.cjs.js 109 | ├── all.mjs.js 110 | └── all.umd.js 111 | ``` 112 | 113 | ### Separate CommonJS modules 114 | 115 | We acknowledge the Node.js support constraint above prevents us from removing CommonJS support. That said, we chose not to publish separate `*.cjs` (CommonJS modules) since CommonJS support is still provided by our Universal Module Definition (UMD) bundles. 116 | 117 | ## Implications 118 | 119 | - Users that follow our [**Add the JavaScript file to your HTML**](https://frontend.design-system.service.gov.uk/importing-css-assets-and-javascript/#add-the-javascript-file-to-your-html) or [**Importing JavaScript**](https://github.com/alphagov/govuk-frontend/blob/main/packages/govuk-frontend/README.md#importing-javascript) documentation will need to replace `govuk/all.js` with `govuk/all.bundle.js`. 120 | - Users that directly import/require `govuk/**/*.js` UMD bundles will need to add the `.bundle` extension prefix as `govuk/**/*.bundle.js`. 121 | - Users that directly import `govuk-esm/**/*.mjs` ES modules will need to remove the `-esm` directory suffix as `govuk/**/*.mjs`. 122 | 123 | **Note:** Users that import/require `govuk-frontend` by name are unaffected. 124 | 125 | ## Contributors 126 | 127 | - Brett Kyle (@domoscargin) 128 | - Colin Rotherham (@colinrotherham) 129 | - Oliver Byford (@36degrees) 130 | - Romaric Pascal (@romaricpascal) 131 | 132 | ## Associated issues and pull requests (PRs) 133 | 134 | - https://github.com/alphagov/govuk-frontend/issues/3721 135 | - https://github.com/alphagov/govuk-frontend/pull/3726 136 | - https://github.com/alphagov/govuk-design-system-architecture/pull/28 137 | 138 | ## Outcomes 139 | 140 | 141 | -------------------------------------------------------------------------------- /decision-records/003-templating-languages.md: -------------------------------------------------------------------------------- 1 | # Templating languages 2 | 3 | **Date:** 2018-07-05 (Historical) 4 | 5 | **Status:** Accepted 6 | 7 | ## Context 8 | 9 | Before GOV.UK Frontend, you needed to use 3 different libraries to build a 10 | service that looked like GOV.UK: 11 | 12 | - GOV.UK Frontend Toolkit 13 | - GOV.UK Template 14 | - GOV.UK Elements 15 | 16 | GOV.UK Template provides the boilerplate, header, footer and related assets like 17 | the favicon, and is available in a number of different formats: 18 | 19 | - a gem containing a Rails engine 20 | - a tarball containing Play Framework templates 21 | - a folder containing Mustache templates 22 | - a tarball containing Liquid templates 23 | - a tarball containing Mustache Inheritance templates 24 | - a tarball containing Jinja templates 25 | - a tarball containing plain HTML and assets 26 | - a tarball containing Embedded JavaScript (EJS) templates 27 | - a JAR file containing assets but no templates, structured as per WebJars 28 | - a tarball containing Django templates 29 | 30 | Making GOV.UK Template available in a number of formats provides a convenient 31 | way for service teams across government to start a new GOV.UK project, despite 32 | the number of different tech-stacks being used. 33 | 34 | These different formats are automatically generated from a base ruby ERB 35 | template through the use of different '[compilers][template-compilers]', 36 | '[packagers][template-packagers]' and '[publishers][template-publishers]' for 37 | each target format. 38 | 39 | GOV.UK Elements, which contains the rest of the UI Elements that you would need 40 | to use, does not support any sort of templating language. The only thing that it 41 | provides is an [npm package containing the Sass][elements-sass]. It relies on 42 | users copying and pasting HTML from the examples in the online documentation. 43 | 44 | The way that the different formats in GOV.UK Template are generated is fairly 45 | simple. It supports the substitution of blocks and variables, but is unable to 46 | handle loops, complex logic or many of the other features provided by most 47 | templating languages. For this reason, we do not think that we could use the 48 | same technique to provide the components in GOV.UK Frontend in multiple formats. 49 | We investigated other ways of doing this in alpha, which are outlined below, but 50 | found that doing so in a reliable way would involve significant work. 51 | 52 | Overall we do not think that the pain points involved in maintaining a setup of 53 | this nature are worth the benefit if we are only able to provide the 'header, 54 | footer and boilerplate in multiple formats, given how rarely they change. The 55 | [HTML in GOV.UK Template has not changed very much][template-changes] in the 56 | years it has existed. 57 | 58 | 59 | ### Pain points 60 | 61 | - The team do not have working knowledge of a number of the target languages and 62 | frameworks. This would make it difficult to fix issues that might be reported, 63 | or to update the template to work with new versions of the different 64 | frameworks that might be released. 65 | 66 | - There are integration tests for some of the target languages and frameworks, 67 | but not all. This makes it difficult to make substantial changes to Template 68 | whilst being confident that those changes will work everywhere unless you do 69 | substantial manual testing. It would be possible to set up test harnesses for 70 | every target language and framework, but this would be significant work. 71 | 72 | - The build pipeline is reasonably complex with a number of downstream builds 73 | being kicked off in other repositories, making it hard to diagnose when issues 74 | arise. It also publishes to a number of different package managers using a 75 | variety of different methods. 76 | 77 | ### Transpiling templates 78 | 79 | [Transpilation][transpilation] is the act of taking source code written in one 80 | language and producing an equivalent version in another language. 81 | 82 | In [alpha][alpha] the team explored ways of doing this by using [shawnbot/meta- 83 | template][meta-template] which converts the source template into an [abstract 84 | syntax tree][ast] and uses that to generate the destination template. We created 85 | a [working example][alpha-transpilation] which involved [adding an ERB 86 | formatter][meta-template-pr] to meta-template. 87 | 88 | However, meta-template was in its infancy and not something we could adopt 89 | without doing significant work. It was also difficult to establish which 90 | templating language features, for example, default variables for variables, were 91 | going to be available in every templating language we wanted or might want to 92 | support, and therefore which features were safe to use in the source template. 93 | 94 | There is also the risk of making contribution more difficult, as contributors 95 | may discover issues with transpilation during development that they do not know 96 | how to solve. For example, tests may fail because they're using a new feature 97 | that either doesn't work in another templating language, or that the transpiler 98 | doesn't know how to transpile. 99 | 100 | 101 | ## References 102 | 103 | There's a [talk by Alice Bartlett from Patterns Day 2017][alice-talk] that 104 | touches on some of these challenges (the most relevant section starts at 105 | around 10 minutes in). 106 | 107 | 108 | ## Decision 109 | 110 | We will use a single templating language which will allow us to define the 111 | markup for a component in a single place. 112 | 113 | We will not build integrations into other languages or frameworks. Our 114 | 'deliverable' will be in the form of one or more npm packages containing the 115 | Sass and JavaScript. 116 | 117 | We may decide to look at transpilation again in the future, based on the 118 | feedback that we get from our users. 119 | 120 | ## Consequences 121 | 122 | We think there is still going to be a need for either libraries or example apps 123 | to help users integrate GOV.UK Frontend into their project, but we hope that 124 | they can: 125 | 126 | - be built and supported by teams and individuals within the community who have 127 | a good working knowledge of the framework or language in question. 128 | - be built in such a way that they do not vendor GOV.UK Frontend, so that they 129 | do not need to be updated every time GOV.UK Frontend is updated. 130 | 131 | 132 | [template-compilers]: https://github.com/alphagov/govuk_template/tree/master/build_tools/compiler 133 | [template-packagers]: https://github.com/alphagov/govuk_template/tree/master/build_tools/packager 134 | [template-publishers]: https://github.com/alphagov/govuk_template/tree/master/build_tools/publisher 135 | [elements-sass]: https://www.npmjs.com/package/govuk-elements-sass 136 | [template-changes]: https://github.com/alphagov/govuk_template/commits/master/source/views/layouts/govuk_template.html.erb 137 | [transpilation]: https://en.wikipedia.org/wiki/Source-to-source_compiler 138 | [ast]: https://en.wikipedia.org/wiki/Abstract_syntax_tree 139 | [meta-template]: https://github.com/shawnbot/meta-template 140 | [meta-template-pr]: https://github.com/shawnbot/meta-template/pull/6 141 | [alpha]: https://github.com/alphagov/govuk_frontend_alpha 142 | [alpha-transpilation]: https://github.com/alphagov/govuk_frontend_alpha/tree/master/lib/transpilation 143 | [alice-talk]: https://vimeo.com/226575101 144 | 145 | 146 | -------------------------------------------------------------------------------- /decision-records/005-repository-organisation-for-v5.md: -------------------------------------------------------------------------------- 1 | # Restructure govuk-frontend repository for v5 2 | 3 | **Date:** 2023-04-21 4 | 5 | **Status:** Accepted 6 | 7 | ## Decision 8 | 9 | 10 | 11 | To prepare the codebase for v5, we've agreed to make the following changes to the files in our repository and their location: 12 | 13 | 1. Create `govuk-frontend` and `govuk-frontend-review` packages 14 | - Create a `govuk-frontend` npm package. 15 | - Move source files (currently `src` ) and built package files (currently `package`) to this package. 16 | - Keep shipping only the built files to npm for now. We'll use the `files` field of `package.json` to include directories in the shipped package, and `.npmignore` to exclude specific files (like tests) 17 | - Create a `govuk-frontend-review` package for the review app 18 | - Store these in a `packages` folder 19 | 2. Create shared `config`, `lib`, `tasks` and `helpers` packages 20 | 3. Remove the built package files (currently `package`) from version control 21 | 4. Update our release process to make sure we keep checking the changes (possibly manually) between the package to be released and the previous version 22 | 5. Leave `dist` in its current location for now (we may revisit whether it's in version control or at the root in the future). These are compiled files for use without npm. 23 | 24 | This will yield the following structure for our repository: 25 | 26 | ``` 27 | govuk-frontend // Repository root 28 | ├── ... 29 | ├── dist // Built files for use without npm 30 | ├── packages // Parent folder for packages 31 | │ ├── govuk-frontend // The GOV.UK Frontend package 32 | │ │ ├── dist // [Previously `/package`] Generated build files, not in version control, ships to npm 33 | │ │ ├── src // [Previously `/src`] Source files, in version control, not shipped to npm 34 | │ │ ├── tasks // Build, release and Gulp tasks for the GOV.UK Frontend Package 35 | │ │ ├── package.json // Ensures dependencies of src, dist and tasks are in-sync 36 | │ │ └── ... 37 | │ ├── govuk-frontend-review // The Review App package 38 | │ │ ├── dist // Not in version control. Some tasks need the review app to build (tests, for example) 39 | │ │ ├── src // [Previously `app/src`] Source files for review app 40 | │ │ ├── tasks // Build and watch tasks for the review app 41 | │ │ ├── package.json 42 | │ │ └── ... 43 | ├── shared // Parent folder for packages shared across the monorepo 44 | │ ├── config // [Previously `/config`] Stores config info like filepaths and ports 45 | │ ├── helpers // Helper functions for development 46 | │ ├── lib // [Previously `/lib`] Shared libraries 47 | │ └── tasks // [Previously `/tasks`] Shared tasks 48 | ├── src // Contains symlinks to new source file locations 49 | └── package.json // Workspaces configuration and top-level dependencies 50 | ``` 51 | 52 | ## Rationale 53 | 54 | 55 | 56 | ### Creating `govuk-frontend` and `govuk-frontend-review` packages 57 | 58 | #### **Overview** 59 | These are the packages we "ship" in some form (we publish `govuk-frontend` to npm, and we deploy `govuk-frontend-review` to Heroku), so it makes sense to group them, and the `packages` folder is a convention seen across other repos. This also allows us to better organise our dependencies between the two. 60 | 61 | #### **`govuk-frontend`** 62 | We may need to ship with dependencies in the future. For example: 63 | 64 | - peer dependencies to a polyfill library if we shipped a version compiled with `import` statements for the polyfills (rather than having the polyfills bundled in) 65 | - dependencies to other libraries, if we were shipping a Babel preset or PostCSS configuration 66 | 67 | Moving the source and built files within the same package helps us ensure these dependencies are resolved consistently. 68 | 69 | While we don't yet have any dependencies, moving these files changes the shape of our package, requiring users to update their import paths for Nunjucks, making it a breaking change. Taking advantage of the breaking nature of the v5 release sets us up so we don't have to worry about future dependencies. 70 | 71 | This doesn't force us to ship the source files, which we've decided to exclude (at least for now). We can choose which folders to include via the `files` field in `package.json`, and use `.npmignore` to exclude specific files. 72 | 73 | #### **`govuk-frontend-review`** 74 | The review app uses relative paths (`../../src/...`) to access the components of GOV.UK Frontend. While we cannot make it consume `govuk-frontend` the exact same way our users do (downloading from an `npm` registry), we can get pretty close using workspaces. Making it use `govuk-frontend` directly helps ensure that: 75 | - we're consuming the built files, not rebuilding from source with a process that we have to keep in sync with how the `govuk-frontend` package is built 76 | - the actual files work as intended 77 | - `entries` in `package.json` are properly configured 78 | - dependencies get resolved as expected (we'll still need a different route to test `peerDependency` if we introduce them, though) 79 | 80 | ### Creating config, helpers, lib and tasks packages 81 | 82 | These are all internal tooling packages which we don't ship, which are used across our shipped packages. Grouping them in a `shared` folder is a convenience; the main benefit of splitting them this way is dependency organisation. 83 | 84 | ### Removing built package files from version control 85 | 86 | Since we will be consuming `govuk-frontend` from the `govuk-frontend-review` app, we need to rebuild the `govuk-frontend` package regularly, rather than only at the point of release. 87 | 88 | If we were to leave these built files in version control, we'd risk committing built files that are somewhere between the previous release and the next one. Removing them ensures we can rebuild at will. 89 | 90 | ### Updating our release process 91 | 92 | Including the built files in version control serves as a way to check that there's no weird code sneaking in. Changes to the package get highlighted during the review of the pull request raised to commit the new build of the package and the release. 93 | 94 | We'll need to keep checking for unexplained changes to the package as we release, even if it is by manually diffing for a while (before further automation). 95 | 96 | ### Leaving `dist` in its current location 97 | 98 | `dist` doesn't need to move to enable the previous points, and with the amount of changes in v5, we'll leave it out of the equation for now. 99 | 100 | ## Risks and constraints 101 | 102 | 103 | 104 | - There may be some named-based confusion. 105 | - We previously used `package` as folder to build into, rather than manually edit files. Now, the `packages` folder contains sources. 106 | - Similarly, we'll have a `dist` folder at root, as well as in each package's folder. This will be mitigated somewhat by removing the non-root `dist` folders from version control, but we might want to consider renaming the root `dist` folder to something like `release`. 107 | - External contributors may be used to the current structure of the repository and confused by the relocation. We will help with this by leaving hints in README files and symlinks to the new locations. 108 | 109 | ## Alternatives considered 110 | 111 | 112 | 113 | ### Creating `govuk-frontend` and `govuk-frontend-review` packages 114 | 115 | - Keeping the review app in the `app` folder and repurposing the `package` folder for the `govuk-frontend` package 116 | - This would create some naming confusion since we previously used `package` for automatically built code 117 | - We'd be splitting packages across the base directory, `shared` and `package`, which might be a bit confusing 118 | - Holding off on `govuk-frontend` source files and built package files within the same package 119 | - This would mean waiting for the next breaking change to do it. We may need to have peer dependencies before that release 120 | 121 | ### Creating config, helpers, lib and tasks packages 122 | 123 | - Moving the `shared` folder into the `packages` folder 124 | - The location of the shared folder was kept to root to distinguish it from the "shipped" packages in the `packages` folder 125 | 126 | ### Removing built package files from version control 127 | 128 | - We could also have built the package to a separate folder that's not in version control (for ex. `govuk-frontend-local-build`) to ensure we consume the built files without impacting `package`. We'd have to duplicate efforts to maintain two `package.json` files and lose testing our dependency resolution, package exports and complicate the linting and Dependabot updates. 129 | - Each PR could get a package deployed to the [Github npm registry](https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-npm-registry) allowing its installation by the review app down the line. This requires extra infrastructure though, and doesn't help when running locally. 130 | 131 | ## Implications 132 | 133 | 134 | 135 | - Users will need to update their import paths when migrating to v5, which we can document as part of the release notes/migration docs. 136 | - Ongoing new components (Exit This Page, Tasklist) will need to have their sources relocated before they can be merged in the new code structure. We can help with moving things and can release Exit This Page from a support branch if it needs to go before v5. 137 | - We need to keep making sure our configuration for the GOV.UK Prototype Kit gets recognised by the Kit and picks up our files as necessary. 138 | 139 | ## Contributors 140 | 141 | 142 | - Brett Kyle (@domoscargin) 143 | - Colin Rotherham (@colinrotherham) 144 | - Oliver Byford (@36degrees) 145 | - Romaric Pascal (@romaricpascal) 146 | 147 | ## Associated issues and pull requests (PRs) 148 | 149 | 150 | - https://github.com/alphagov/govuk-frontend/issues/3291 151 | - https://github.com/alphagov/govuk-frontend/issues/2886 152 | - https://github.com/alphagov/govuk-frontend/issues/3547 153 | - https://github.com/alphagov/govuk-frontend/issues/3548 154 | - https://github.com/alphagov/govuk-frontend/pull/3498 155 | 156 | 157 | ## Outcomes 158 | 159 | 160 | 161 | Part of the discussion around this decision clarified that the review `app` does not need to take responsibility for all development processes. Performance monitoring, for example, can happily happen in its own workspace and feed the app something to serve if necessary. Same could go for testing that the different compiled versions work appropriately if/when we start shipping more than one variant of compiled files. 162 | 163 | It was also mentioned, discussing the possibility of dependencies, that we'll need to be mindful of the implications of the dependencies we add (provenance, maintenance...). 164 | -------------------------------------------------------------------------------- /proposals/002-publish-one-npm-package-instead-of-multiple-npm-packages.md: -------------------------------------------------------------------------------- 1 | # Publish one npm package instead of multiple npm packages 2 | 3 | **Closing date:** 2018-03-27 4 | 5 | **Status:** Accepted 6 | 7 | ## Contents 8 | - [Summary](#summary) 9 | - [Current architecture](#current-architecture) 10 | - [Problems associated with publishing individual packages](#problems-associated-with-publishing-individual-packages) 11 | - [Versioning](#versioning) 12 | - [Conflicts](#conflicts) 13 | - [Pancake](#pancake) 14 | - [Proposal: Publishing one package](#proposal-publishing-one-package) 15 | - [Currently](#currently) 16 | - [Steps to build everything](#steps-to-build-everything) 17 | - [Steps to build only one component](#steps-to-build-only-one-component) 18 | - [After proposed change](#after-proposed-change) 19 | - [Steps to build everything](#steps-to-build-everything) 20 | - [Steps to build only one component](#steps-to-build-only-one-component) 21 | - [Risks with moving to a single package](#risks-with-moving-to-a-single-package) 22 | - [Breaking changes that impact many packages could make it difficult to upgrade only parts at a time.](#breaking-changes-that-impact-many-packages-could-make-it-difficult-to-upgrade-only-parts-at-a-time) 23 | - [Options](#options) 24 | - [Reference](#reference) 25 | - [Examples of modular projects that use single packages](#examples-of-modular-projects-that-use-single-packages) 26 | - [Examples of modular projects that use multiple packages](#examples-of-modular-projects-that-use-multiple-packages) 27 | - [With thanks to](#with-thanks-to) 28 | 29 | 30 | ## Summary 31 | 32 | Publish one package with all of GOV.UK Frontend while still allowing for building individual components only. 33 | 34 | GOV.UK Frontend is currently made up of multiple npm packages such as “date-input” and “footer” (see [packages/](https://github.com/alphagov/govuk-frontend/tree/master/packages)). 35 | 36 | This proposal is interested in doing the minimum in order to ship a public release of GOV.UK Frontend. 37 | With the hope that this decision can be changed in the future given more time or better evidence of the need for this. 38 | 39 | ### Current architecture 40 | 41 | GOV.UK Frontend can be consumed in two main ways: 42 | - All at once 43 | - By individual components 44 | 45 | Allowing for individual components is important to: 46 | - Test that they are isolated and do not 'leak' and break other components / elements on a page. 47 | - Makes it easier to deprecate and remove in the future. 48 | - Easier to port to [insert your favourite templating approach here] 49 | - Make it easy to upgrade parts at a time, for example only the new(er) radio components. 50 | - Have smaller builds that only include what is used. 51 | 52 | We have two main aspects of the architecture that allows for this. 53 | 54 | 1. Modular project structure 55 | 2. Individually published packages to npm 56 | 57 | ## Problems associated with publishing individual packages 58 | 59 | ### Versioning 60 | We do not currently have a process to version our individual components before publishing them. If we decide we want to persist with the multiple packages approach, we’ll need to work this out. 61 | 62 | Our current process is to give all packages the same version in lockstep. 63 | 64 | This means all our packages have the same version number, regardless if they have actually changed in a release. 65 | 66 | ### Conflicts 67 | 68 | This is explained really well in [npm and the front end] (thanks Dominik Wilkowski! 💌) 69 | 70 | Currently `button` component and `input` component both depend on the `label` component. 71 | 72 | ```bash 73 | label 74 | ├── button 75 | └── input 76 | ``` 77 | 78 | In the current case, these are all versioned in lock-step so when you install the button and input you get a dependency tree that looks like the following: 79 | 80 | ```bash 81 | npm install --save button input 82 | ``` 83 | ```bash 84 | label@1.0.0 85 | ├── button@1.0.0 86 | └── input@1.0.0 87 | ``` 88 | 89 | However if we made a breaking change to the `label` component, the `button` and `input` component may also require a breaking version update. 90 | 91 | If a user then installs only the `input` component update, this is where we run into issues: 92 | 93 | ```bash 94 | npm install --save button@1.0.0 input@2.0.0 95 | ``` 96 | ```bash 97 | label@1.0.0 98 | └── button@1.0.0 99 | 100 | label@2.0.0 101 | └── input@2.0.0 102 | ``` 103 | 104 | Now we have a duplication of the label component, and since CSS is a global language depending on how they are imported into a project it'd result in a broken behaviour. 105 | 106 | We use an 'export' pattern that ensures an imported scss partial is only included once (https://github.com/alphagov/govuk-frontend/blob/e583c8b3e4038c09c53d4ffbbc129ea8495efbe9/src/globals/tools/_exports.scss) 107 | 108 | ```css 109 | .govuk-c-label { ... } /* @2.0.0 */ 110 | .govuk-c-input { ... } /* @2.0.0 */ 111 | .govuk-c-button { ... } /* @1.0.0 */ 112 | ``` 113 | 114 | As explained in [npm and the front end] npm was designed in a world where this is not a huge concern. 115 | Since backend code can have different versions of the same dependency and not have any global conflicts. 116 | This duplicate backend code is also not sent over the wire and run by users. 117 | 118 | ### Pancake 119 | [Pancake] is a really interesting solution to the above problem built on top of npm, it works around the many issues around `peerDependencies` (see the [npm blog post]) 120 | 121 | However, we found in research that many people have big existing build pipelines so adding more tools could be a problem. 122 | 123 | We’d need to do more research to see if pancake would make these problems worse. 124 | 125 | At the moment we’re not clear that the time invested would be worth the problems it solves, however this proposal assumes we could move towards a system like pancake from a single package if a clearer need was presented to us. 126 | 127 | See below for ‘problems with a single package’. 128 | 129 | ## Proposal: Publishing one package 130 | 131 | ### Currently 132 | 133 | #### Steps to build everything 134 | ```bash 135 | $ npm install --save @govuk-frontend/all 136 | ``` 137 | 138 | ```scss 139 | // application.scss 140 | @import "@govuk-frontend/all/all"; 141 | ``` 142 | 143 | ```bash 144 | $ node-sass --include-path=node_modules application.scss > application.css 145 | ``` 146 | 147 | #### Steps to build only one component 148 | ```bash 149 | $ npm install --save @govuk-frontend/button 150 | ``` 151 | 152 | ```scss 153 | // button.scss 154 | @import "@govuk-frontend/button/button"; 155 | ``` 156 | 157 | ```bash 158 | $ node-sass --include-path=node_modules button.scss > button.css 159 | ``` 160 | 161 | ### After proposed change 162 | 163 | https://github.com/alphagov/govuk-frontend/compare/spike-rfc-packages 164 | 165 | #### Steps to build everything 166 | ```bash 167 | $ npm install --save @govuk-frontend 168 | ``` 169 | 170 | ```scss 171 | // application.scss 172 | @import "@govuk-frontend/all/all.scss"; 173 | ``` 174 | 175 | ```bash 176 | $ node-sass --include-path=node_modules application.scss > application.css 177 | ``` 178 | 179 | #### Steps to build only one component 180 | ```bash 181 | $ npm install --save @govuk-frontend 182 | ``` 183 | 184 | ```scss 185 | // button.scss 186 | @import "@govuk-frontend/button/button.scss"; 187 | ``` 188 | 189 | ```bash 190 | $ node-sass --include-path=node_modules button.scss > button.css 191 | ``` 192 | 193 | This also means when moving from individual components to multiple components, 194 | you only need to add additional `@import` statements, and would not need to run `npm install` again. 195 | 196 | ### Risks with moving to a single package 197 | 198 | The time it takes to install a big package is longer than individual packages. 199 | Individual packages force us to keep code modular, we would need to ensure our testing makes up for this. 200 | Mental model of custom builds may not be as well understood, we need to do more to make it clear you don’t need the whole project. 201 | 202 | #### Breaking changes that impact many packages could make it difficult to upgrade only parts at a time. 203 | 204 | > “If you’re still creating one version for the entire thing, then when you fix an accessibility bug in one component everyone will have to update the entire thing.” - Dominik Wilkowski GOV.AU 205 | 206 | > “We come from a monolithic CSS (Bootstrap), and the reason for us moving to individual components was that it reduces ‘upgrade anxiety’ and helps with adoption. “ - Dominik Wilkowski GOV.AU 207 | 208 | > "Each component has an API. This API is a combination of CSS classes, HTML structure, Sass mixins, and JavaScript methods. Whenever any of these APIs needs to be deprecated, we release a new Node module with a new version by following semantic versioning. 209 | 210 | > These sorts of breaking changes require our clients to change THEIR code before they can upgrade to the new version. 211 | 212 | >By versioning each component separately....YOU are in control of when you upgrade each component. This gives you flexibility in your timeline. If you are under some time constraint to launch a new feature, then you might wait to upgrade the component. 213 | 214 | > You don't have to feel pressured to upgrade everything right away." - Lynn Jespen, Tech Lead for Material Components Web (via Jani Kraner) 215 | 216 | This has come up multiple times, potentially the risk of this could be improved by releasing often and not ‘save all the big changes’ for a breaking change. 217 | 218 | For example, if we know we’ll be making a breaking change to Component 1 and Component 2. Release Component 1 as a new breaking change, then do another release for Component 2. 219 | 220 | Note: In this case if you only want updates for Component 2, you’ll be forced to also bring in updates for Component 1. 221 | 222 | With a release process that encourages releasing after merging to master this could be possible. 223 | 224 | Without this it would require careful orchestration of releases which could create blockers in our workflow. 225 | 226 | It would also mean we would need to do more to communicate breaking changes that are big fundamental changes, this could be done with release names (see ubuntu for example of ‘code names’ https://wiki.ubuntu.com/Releases) 227 | 228 | This seems to be the biggest risk to publishing one package. 229 | 230 | Please contribute with any risks we have not considered here. 231 | 232 | ## Options 233 | 234 | - Continue with current approach: Flatten and remove conflicts after install ([pancake]) 235 | - Approve the proposed change: Publish one package 236 | 237 | ### Reference 238 | 239 | - Transcript of the conversation with the GOV.AU team: https://gist.github.com/nickcolley/eb61fedb20d273a5266cdf4f71cfbb30 240 | - npm blog post introducing the problems relating to the issues described in this RFC: http://blog.npmjs.org/post/101775448305/npm-and-front-end-packaging 241 | - Blog post from Dominik explaining their solution to this problem: https://medium.com/dailyjs/npm-and-the-front-end-950c79fc22ce 242 | - Pancake: https://github.com/govau/pancake/ 243 | 244 | #### Examples of modular projects that use single packages 245 | - Bootstrap - High barrier to entry https://getbootstrap.com/docs/4.0/getting-started/build-tools/#tooling-setup 246 | - Foundation - Much better documentation https://foundation.zurb.com/sites/docs/sass.html#adjusting-css-output 247 | - Carbon Design System - http://carbondesignsystem.com/getting-started/developers 248 | 249 | #### Examples of modular projects that use multiple packages 250 | - https://github.com/primer/primer 251 | - https://github.com/ElemeFE/mint-ui - Instructions make no mention of installing individual packages 252 | - https://github.com/fyndiq/fyndiq-ui 253 | - https://github.com/material-components/material-components-web 254 | - https://github.com/govau/uikit 255 | 256 | ## With thanks to 257 | - GOV.AU team for spending time with us to talk through their decisions for their project. 258 | - Lynn Jespen, Tech Lead for Material Components Web 259 | - GOV.UK Design System team 260 | 261 | [npm blog post]: http://blog.npmjs.org/post/101775448305/npm-and-front-end-packaging 262 | [npm and the front end]: https://medium.com/dailyjs/npm-and-the-front-end-950c79fc22ce 263 | [pancake]: https://github.com/govau/pancake/ 264 | -------------------------------------------------------------------------------- /decision-records/006-javascript-compatibility.md: -------------------------------------------------------------------------------- 1 | # JavaScript browser compatibility 2 | 3 | Date: 27/06/23 4 | 5 | Status: Accepted 6 | 7 | ## Decision 8 | 9 | We will publish JavaScript that can be parsed without errors in browsers supporting `