├── .github └── ISSUE_TEMPLATE │ ├── bug_report.md │ ├── config.yml │ ├── documentation.md │ ├── feature_request.md │ ├── internal-story.md │ └── propose.md ├── .gitignore ├── .pa11yci.json ├── LICENSE ├── README.md ├── app ├── assets │ ├── docs │ │ ├── english_cookie_content.md │ │ └── welsh_cookie_content.md │ ├── images │ │ ├── add-another-thing │ │ │ ├── add-another-multi-page-change-remove.svg │ │ │ ├── add-another-multi-page.svg │ │ │ ├── add-another-single-page-change-remove.svg │ │ │ ├── add-another-single-page.svg │ │ │ └── order-pizza │ │ │ │ ├── _size.png │ │ │ │ ├── _toppings.png │ │ │ │ └── _who.png │ │ ├── app-header-crest.svg │ │ ├── app-icon-pointer.svg │ │ ├── calendar-date-picker.gif │ │ ├── cookies │ │ │ ├── cookies-accept-reject.png │ │ │ ├── cookies-accept.png │ │ │ ├── cookies-banner.png │ │ │ ├── cookies-footer.png │ │ │ └── cookies-reject.png │ │ ├── daniella-team.jpg │ │ ├── downtime-warning.png │ │ ├── dwp-apple-touch-icon-120x120.png │ │ ├── dwp-apple-touch-icon-152x152.png │ │ ├── dwp-apple-touch-icon-60x60.png │ │ ├── dwp-apple-touch-icon-76x76.png │ │ ├── favicon.ico │ │ ├── find-info-from-doc-illustration.sketch │ │ ├── helen-team.png │ │ ├── information-from-document.png │ │ ├── jon-team.png │ │ ├── key-information.png │ │ ├── martin-team.png │ │ ├── mikey-team.jpg │ │ ├── mitz-team.jpg │ │ ├── simone-team.jpg │ │ ├── structured-answers.gif │ │ ├── task-list.png │ │ └── time-out-modal.png │ ├── javascript │ │ ├── application.js │ │ ├── back-to-top.js │ │ ├── cookies-consent.js │ │ ├── copy-code-button.js │ │ ├── example.js │ │ ├── mobile-navigation.js │ │ ├── tabs.js │ │ ├── timeout-warning.js │ │ └── vendor │ │ │ ├── classList.js │ │ │ ├── common.js │ │ │ └── dialog-polyfill.js │ └── sass │ │ ├── _app-pane.scss │ │ ├── _app-phase-banner.scss │ │ ├── _back-to-top.scss │ │ ├── _contact-panel.scss │ │ ├── _cookie-banner.scss │ │ ├── _example.scss │ │ ├── _header.scss │ │ ├── _highlight.scss │ │ ├── _layout.scss │ │ ├── _masthead.scss │ │ ├── _mobile-navigation.scss │ │ ├── _navigation.scss │ │ ├── _sub-navigation.scss │ │ ├── _tabs.scss │ │ ├── _timeout-warning.scss │ │ ├── _toggle-to-welsh.scss │ │ ├── application-ie8.scss │ │ ├── application.scss │ │ └── vendor │ │ └── dialog-polyfill.0.5.0.css ├── middleware │ ├── accessibility.js │ ├── cookies │ │ ├── cookieDetails.js │ │ ├── cookiePolicy.js │ │ └── cookiesConsent.js │ ├── errorHandler.js │ ├── sitemap.js │ └── urlPartials.js ├── routes │ ├── auto.js │ ├── index.js │ └── redirects.js ├── utils │ ├── content-loader.js │ ├── file-helper.js │ ├── navigation-data-loader.js │ └── regexes.js └── views │ ├── _layouts │ ├── base.html │ ├── code.html │ ├── full-width.html │ └── sidebar-width.html │ ├── _partials │ ├── _accessibility.njk │ ├── _back-to-top.njk │ ├── _component-index.njk │ ├── _component-table.njk │ ├── _contact-panel.njk │ ├── _contribute-index.njk │ ├── _cookie-banner.njk │ ├── _cookie-details.njk │ ├── _cookie-policy.njk │ ├── _footer.njk │ ├── _header.html │ ├── _macros │ │ ├── backlog │ │ │ ├── macro.njk │ │ │ └── template.njk │ │ ├── example │ │ │ ├── README.md │ │ │ ├── macro.njk │ │ │ └── template.njk │ │ ├── mobile-navigation │ │ │ ├── macro.njk │ │ │ └── template.njk │ │ ├── navigation │ │ │ ├── macro.njk │ │ │ └── template.njk │ │ └── sub-navigation │ │ │ ├── macro.njk │ │ │ └── template.njk │ ├── _page-not-found.njk │ ├── _pattern-index.njk │ ├── _pattern-table.njk │ ├── _sitemap.njk │ └── scripts.html │ ├── community │ ├── README.md │ ├── backlog │ │ ├── README.md │ │ └── index.html │ ├── contribute │ │ ├── README.md │ │ └── index.html │ ├── index.html │ ├── latest-updates │ │ ├── README.md │ │ └── index.html │ ├── roadmap │ │ ├── README.md │ │ └── index.html │ └── team │ │ ├── README.md │ │ ├── _team-daniella.njk │ │ ├── _team-helen.njk │ │ ├── _team-jon.njk │ │ ├── _team-martin.njk │ │ ├── _team-mitz.njk │ │ ├── _team-simone.njk │ │ └── index.html │ ├── components │ ├── README.md │ ├── hint-text │ │ ├── README.md.njk │ │ ├── examples │ │ │ └── default │ │ │ │ ├── index.html │ │ │ │ ├── styles.css │ │ │ │ └── template.html │ │ └── index.html │ ├── index.html │ ├── internal-services-footer │ │ ├── README.md.njk │ │ ├── examples │ │ │ ├── default │ │ │ │ ├── index.html │ │ │ │ └── template.html │ │ │ ├── meta-links │ │ │ │ ├── index.html │ │ │ │ └── template.html │ │ │ └── nav-and-links │ │ │ │ ├── index.html │ │ │ │ └── template.html │ │ └── index.html │ ├── internal-services-header │ │ ├── README.md.njk │ │ ├── examples │ │ │ ├── default │ │ │ │ ├── index.html │ │ │ │ ├── styles.css │ │ │ │ └── template.html │ │ │ └── signin │ │ │ │ ├── index.html │ │ │ │ ├── styles.css │ │ │ │ └── template.html │ │ └── index.html │ ├── key-details-bar │ │ ├── README.md.njk │ │ ├── examples │ │ │ ├── default │ │ │ │ ├── index.html │ │ │ │ ├── styles.css │ │ │ │ └── template.html │ │ │ └── notdo │ │ │ │ ├── index.html │ │ │ │ └── template.html │ │ └── index.html │ └── timeline │ │ ├── README.md.njk │ │ ├── examples │ │ └── default │ │ │ ├── index.html │ │ │ ├── styles.css │ │ │ └── template.html │ │ └── index.html │ ├── get-started │ ├── README.md │ ├── html-and-css │ │ ├── README.md │ │ └── index.html │ ├── index.html │ └── npm │ │ ├── README.md │ │ └── index.html │ ├── index.html │ └── patterns │ ├── README.md │ ├── add-another-thing │ ├── README.md.njk │ ├── example │ │ ├── README.md.njk │ │ └── index.html │ └── index.html │ ├── index.html │ ├── make-a-declaration │ ├── README.md.njk │ ├── examples │ │ └── default │ │ │ ├── index.html │ │ │ └── template.html │ └── index.html │ ├── manage-a-session-timeout │ ├── README.md.njk │ ├── examples │ │ ├── default │ │ │ ├── index.html │ │ │ └── template.html │ │ ├── notsignedin │ │ │ ├── index.html │ │ │ └── template.html │ │ ├── signedin │ │ │ ├── index.html │ │ │ └── template.html │ │ ├── timedout-nojs │ │ │ ├── index.html │ │ │ └── template.html │ │ ├── timedout-notsignedin │ │ │ ├── index.html │ │ │ └── template.html │ │ └── timedout-signedin │ │ │ ├── index.html │ │ │ └── template.html │ ├── index.html │ ├── macro.njk │ ├── template.html │ └── timed-out.html │ ├── retired-patterns │ ├── README.md.njk │ ├── consent-to-cookies │ │ ├── README.md.njk │ │ └── index.html │ └── index.html │ └── toggle-to-welsh │ ├── README.md.njk │ ├── examples │ ├── default │ │ ├── index.html │ │ └── template.html │ └── start-page │ │ ├── index.html │ │ └── template.html │ └── index.html ├── config ├── content │ └── backlog-page.json └── navigation-data.json ├── gulp ├── clean.js ├── compile-app-js.js ├── copy-assets.js ├── sass.js ├── server.js └── watch.js ├── gulpfile.js ├── package-lock.json ├── package.json └── server.js /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: "🐛 Bug report" 3 | about: Report a bug or regression 4 | title: '' 5 | labels: "\U0001F41B bug, awaiting triage" 6 | assignees: '' 7 | 8 | --- 9 | 10 | 15 | 16 | ## Describe the issue 17 | 18 | 19 | ## Steps to reproduce the issue 20 | 21 | 22 | ## Actual vs expected behaviour 23 | 24 | 25 | ## Environment (where applicable) 26 | 27 | 28 | - Operating system: 29 | - Browser: 30 | - Browser version: -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | 2 | blank_issues_enabled: true 3 | contact_links: 4 | - name: Get in touch another way 5 | url: https://design-system.dwp.gov.uk/get-in-touch.html 6 | about: Find out how to get in touch via email or Slack -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/documentation.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: "📖 Documentation" 3 | about: Add new documentation, or report missing, incorrect or unclear documentation 4 | title: '' 5 | labels: "documentation, awaiting triage" 6 | assignees: '' 7 | 8 | --- 9 | 10 | 17 | 18 | ## Related documentation 19 | 20 | 21 | ## Suggestion 22 | 23 | 24 | ## Evidence (where applicable) 25 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: "✨ Feature request" 3 | about: Suggest a new feature or idea 4 | title: '' 5 | labels: "feature request, awaiting triage" 6 | assignees: '' 7 | 8 | --- 9 | 10 | 19 | 20 | ## Context 21 | 22 | 23 | ## Alternatives 24 | 25 | 26 | ## Additional information (if applicable) 27 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/internal-story.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: "Internal story template" 3 | about: For internal use only 4 | title: '' 5 | labels: "awaiting triage" 6 | assignees: '' 7 | 8 | --- 9 | 10 | 15 | 16 | ## What 17 | 18 | ## Why 19 | 20 | ## Done when 21 | 22 | - [ ] Thing to do 23 | 24 | ## Outcomes 25 | 26 | ## Who needs to know about this 27 | 28 | ## Related stories 29 | 30 | ## Anything else 31 | 32 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/propose.md: -------------------------------------------------------------------------------- 1 | 6 | 7 | ## What 8 | > Give a brief description of the style, component or pattern you want to propose. 9 | 10 | ## Why 11 | > Explain why you think this should be added to the DWP Design System. 12 | > 13 | > - What evidence do you have that it's needed by multiple services across DWP? 14 | > - What evidence do you have that it meets the needs of the users of those services? 15 | > - Have you checked that it doesn't already exist in the DWP Design System? 16 | 17 | ## Anything else 18 | > Include links to any examples, research or code to support your proposal, if available. 19 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | sass-cache 3 | .DS_Store 4 | public/ 5 | .vscode/ 6 | settings.json 7 | npm-debug.log 8 | pa11y-ci-report 9 | -------------------------------------------------------------------------------- /.pa11yci.json: -------------------------------------------------------------------------------- 1 | { 2 | "defaults": { 3 | "ignore": [ 4 | "color-contrast" 5 | ], 6 | "timeout": 10000, 7 | "reporters": [ 8 | "cli", 9 | [ 10 | "./node_modules/pa11y-ci-reporter-html", 11 | { 12 | "destination": "./pa11y-ci-report", 13 | "includeZeroIssues": true 14 | } 15 | ] 16 | ], 17 | "standard": "WCAG2AA", 18 | "runners": [ 19 | "htmlcs", 20 | "axe" 21 | ] 22 | }, 23 | "urls": [ 24 | "http://localhost:3000/", 25 | "http://localhost:3000/get-started", 26 | "http://localhost:3000/get-started/for-designers", 27 | "http://localhost:3000/community", 28 | "http://localhost:3000/community/roadmap", 29 | "http://localhost:3000/community/contribute", 30 | "http://localhost:3000/community/backlog", 31 | "http://localhost:3000/community/latest-updates", 32 | "http://localhost:3000/community/team", 33 | "http://localhost:3000/patterns", 34 | "http://localhost:3000/patterns/retired-patterns", 35 | "http://localhost:3000/patterns/retired-patterns/consent-to-cookies", 36 | "http://localhost:3000/patterns/add-another-thing", 37 | "http://localhost:3000/patterns/manage-a-session-timeout", 38 | "http://localhost:3000/patterns/manage-a-session-timeout/examples/default", 39 | "http://localhost:3000/patterns/manage-a-session-timeout/examples/signedin", 40 | "http://localhost:3000/patterns/manage-a-session-timeout/examples/timedout-signedin", 41 | "http://localhost:3000/patterns/manage-a-session-timeout/examples/notsignedin", 42 | "http://localhost:3000/patterns/manage-a-session-timeout/examples/timedout-notsignedin", 43 | "http://localhost:3000/patterns/manage-a-session-timeout/examples/timedout-nojs", 44 | "http://localhost:3000/patterns/make-a-declaration", 45 | "http://localhost:3000/patterns/make-a-declaration/examples/default", 46 | "http://localhost:3000/patterns/toggle-to-welsh", 47 | "http://localhost:3000/patterns/toggle-to-welsh/examples/default", 48 | "http://localhost:3000/patterns/toggle-to-welsh/examples/start-page", 49 | "http://localhost:3000/components/hint-text", 50 | "http://localhost:3000/components/timeline", 51 | "http://localhost:3000/components/timeline/examples/default", 52 | "http://localhost:3000/components/internal-services-header", 53 | "http://localhost:3000/components/internal-services-header/examples/default", 54 | "http://localhost:3000/components/internal-services-header/examples/signin", 55 | "http://localhost:3000/components/key-details-bar", 56 | "http://localhost:3000/components/key-details-bar/examples/default", 57 | "http://localhost:3000/cookie-details", 58 | "http://localhost:3000/cookie-policy" 59 | ] 60 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2020 DWP (The Department for Work and Pensions) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Design System 2 | 3 | One place for service teams to find and share the styles, components and patterns for designing DWP services. 4 | 5 | ## Get started 6 | 7 | `npm install && npm start` 8 | 9 | ## Accessibility 10 | 11 | The site uses `pa11y-ci` with `axe-core` and `htmlcs` (default) as runners. To run a11y tests: 12 | `npm run reports` 13 | 14 | This generates an HTML report for every website url in the `pa11y-ci-report` folder. -------------------------------------------------------------------------------- /app/assets/docs/english_cookie_content.md: -------------------------------------------------------------------------------- 1 | [Screen 1] 2 | 3 | How we use cookies 4 | 5 | A cookie is a small file which is stored on your device for a short time to make this service work. 6 | 7 | We use cookies that are: 8 | • Essential for the service to work, like remembering your answers to certain questions 9 | • Optional and will not stop the service from working, but will give us information to help us make it better 10 | 11 | We will not: 12 | • Use any essential cookies until you use the service 13 | • Use any optional cookies unless you tell us we can 14 | • Be able to identify you through using cookies 15 | 16 | Optional cookie settings 17 | 18 | Analytics cookies 19 | 20 | We use Google Analytics to get information about how you use this service and help us make it better. 21 | 22 | Can we use cookies to help us improve the service? 23 | Yes 24 | No 25 | 26 | Save and continue 27 | 28 | Find out more about cookies on this service 29 | 30 | 31 | [Banner 1] 32 | 33 | Can we use cookies in our services? 34 | 35 | We’d like to use analytics cookies to collect information about how you use our services. This helps us to make them better. 36 | You can read more about our cookies before you decide. 37 | 38 | Yes, I’m OK with analytics cookies 39 | No, do no use analytics cookies 40 | 41 | 42 | [Banner 2] 43 | 44 | ACCEPTED 45 | You’ve accepted analytics cookies. You can change your cookie settings at any time. 46 | 47 | Hide 48 | 49 | 50 | [Banner 3] 51 | 52 | REJECTED 53 | You’ve rejected analytics cookies. You can change your cookie settings at any time. 54 | 55 | Hide 56 | 57 | -------------------------------------------------------------------------------- /app/assets/docs/welsh_cookie_content.md: -------------------------------------------------------------------------------- 1 | [Screen 1] 2 | 3 | Sut rydym yn defnyddio cwcis 4 | 5 | Ffeil fach yw cwci sy'n cael ei storio ar eich dyfais am gyfnod byr i wneud i'r gwasanaeth hwn weithio. 6 | 7 | Rydym yn defnyddio cwcis sy’n: 8 | • Hanfodol i'r gwasanaeth weithio, fel cofio'ch atebion i gwestiynau penodol 9 | • Dewisol ac ni fydd yn atal y gwasanaeth rhag gweithio, ond bydd yn rhoi gwybodaeth i ni i'n helpu i'w wella 10 | 11 | Ni fyddwn yn: 12 | • Defnyddio unrhyw gwcis hanfodol hyd nes i chi ddefnyddio'r gwasanaeth 13 | • Defnyddio unrhyw gwcis dewisol oni bai eich bod yn dweud wrthym y gallwn 14 | • Gallu'ch adnabod trwy ddefnyddio cwcis 15 | 16 | Gosodiadau cwci dewisol 17 | 18 | Cwcis dadansoddeg 19 | 20 | Rydyn ni'n defnyddio Google Analytics i gael gwybodaeth am sut rydych yn defnyddio'r gwasanaeth hwn ac yn ein helpu i'w wella. 21 | 22 | A allwn ddefnyddio cwcis i'n helpu i wella'r gwasanaeth? 23 | Gallwch 24 | Na 25 | 26 | Arbed a pharhau 27 | 28 | Darganfyddwch fwy am gwcis ar y gwasanaeth hwn 29 | 30 | 31 | [Banner 1] 32 | 33 | A allwn ddefnyddio cwcis yn ein gwasanaethau? 34 | 35 | Hoffem ddefnyddio cwcis dadansoddeg i gasglu gwybodaeth am sut rydych yn defnyddio ein gwasanaethau. Mae hyn yn ein helpu i'w gwella. 36 | Gallwch ddarllen mwy am ein cwcis cyn i chi benderfynu. 37 | 38 | Ydw, rwy'n iawn gyda chwcis dadansoddeg 39 | Na, peidiwch â defnyddio cwcis dadansoddeg 40 | 41 | 42 | [Banner 2] 43 | 44 | DERBYNIWYD 45 | Rydych wedi derbyn cwcis dadansoddeg. Gallwch newid eich gosodiadau cwci ar unrhyw adeg. 46 | 47 | Cuddio 48 | 49 | 50 | [Banner 3] 51 | 52 | GWRTHODWYD 53 | Rydych wedi gwrthod cwcis dadansoddeg. Gallwch newid eich gosodiadau cwci ar unrhyw adeg. 54 | 55 | Cuddio 56 | -------------------------------------------------------------------------------- /app/assets/images/add-another-thing/order-pizza/_size.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dwp/design-system/5340efdeb36a7189b6ea274c1487a4ff768f6109/app/assets/images/add-another-thing/order-pizza/_size.png -------------------------------------------------------------------------------- /app/assets/images/add-another-thing/order-pizza/_toppings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dwp/design-system/5340efdeb36a7189b6ea274c1487a4ff768f6109/app/assets/images/add-another-thing/order-pizza/_toppings.png -------------------------------------------------------------------------------- /app/assets/images/add-another-thing/order-pizza/_who.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dwp/design-system/5340efdeb36a7189b6ea274c1487a4ff768f6109/app/assets/images/add-another-thing/order-pizza/_who.png -------------------------------------------------------------------------------- /app/assets/images/app-icon-pointer.svg: -------------------------------------------------------------------------------- 1 | 5 | -------------------------------------------------------------------------------- /app/assets/images/calendar-date-picker.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dwp/design-system/5340efdeb36a7189b6ea274c1487a4ff768f6109/app/assets/images/calendar-date-picker.gif -------------------------------------------------------------------------------- /app/assets/images/cookies/cookies-accept-reject.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dwp/design-system/5340efdeb36a7189b6ea274c1487a4ff768f6109/app/assets/images/cookies/cookies-accept-reject.png -------------------------------------------------------------------------------- /app/assets/images/cookies/cookies-accept.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dwp/design-system/5340efdeb36a7189b6ea274c1487a4ff768f6109/app/assets/images/cookies/cookies-accept.png -------------------------------------------------------------------------------- /app/assets/images/cookies/cookies-banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dwp/design-system/5340efdeb36a7189b6ea274c1487a4ff768f6109/app/assets/images/cookies/cookies-banner.png -------------------------------------------------------------------------------- /app/assets/images/cookies/cookies-footer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dwp/design-system/5340efdeb36a7189b6ea274c1487a4ff768f6109/app/assets/images/cookies/cookies-footer.png -------------------------------------------------------------------------------- /app/assets/images/cookies/cookies-reject.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dwp/design-system/5340efdeb36a7189b6ea274c1487a4ff768f6109/app/assets/images/cookies/cookies-reject.png -------------------------------------------------------------------------------- /app/assets/images/daniella-team.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dwp/design-system/5340efdeb36a7189b6ea274c1487a4ff768f6109/app/assets/images/daniella-team.jpg -------------------------------------------------------------------------------- /app/assets/images/downtime-warning.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dwp/design-system/5340efdeb36a7189b6ea274c1487a4ff768f6109/app/assets/images/downtime-warning.png -------------------------------------------------------------------------------- /app/assets/images/dwp-apple-touch-icon-120x120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dwp/design-system/5340efdeb36a7189b6ea274c1487a4ff768f6109/app/assets/images/dwp-apple-touch-icon-120x120.png -------------------------------------------------------------------------------- /app/assets/images/dwp-apple-touch-icon-152x152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dwp/design-system/5340efdeb36a7189b6ea274c1487a4ff768f6109/app/assets/images/dwp-apple-touch-icon-152x152.png -------------------------------------------------------------------------------- /app/assets/images/dwp-apple-touch-icon-60x60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dwp/design-system/5340efdeb36a7189b6ea274c1487a4ff768f6109/app/assets/images/dwp-apple-touch-icon-60x60.png -------------------------------------------------------------------------------- /app/assets/images/dwp-apple-touch-icon-76x76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dwp/design-system/5340efdeb36a7189b6ea274c1487a4ff768f6109/app/assets/images/dwp-apple-touch-icon-76x76.png -------------------------------------------------------------------------------- /app/assets/images/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dwp/design-system/5340efdeb36a7189b6ea274c1487a4ff768f6109/app/assets/images/favicon.ico -------------------------------------------------------------------------------- /app/assets/images/find-info-from-doc-illustration.sketch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dwp/design-system/5340efdeb36a7189b6ea274c1487a4ff768f6109/app/assets/images/find-info-from-doc-illustration.sketch -------------------------------------------------------------------------------- /app/assets/images/helen-team.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dwp/design-system/5340efdeb36a7189b6ea274c1487a4ff768f6109/app/assets/images/helen-team.png -------------------------------------------------------------------------------- /app/assets/images/information-from-document.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dwp/design-system/5340efdeb36a7189b6ea274c1487a4ff768f6109/app/assets/images/information-from-document.png -------------------------------------------------------------------------------- /app/assets/images/jon-team.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dwp/design-system/5340efdeb36a7189b6ea274c1487a4ff768f6109/app/assets/images/jon-team.png -------------------------------------------------------------------------------- /app/assets/images/key-information.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dwp/design-system/5340efdeb36a7189b6ea274c1487a4ff768f6109/app/assets/images/key-information.png -------------------------------------------------------------------------------- /app/assets/images/martin-team.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dwp/design-system/5340efdeb36a7189b6ea274c1487a4ff768f6109/app/assets/images/martin-team.png -------------------------------------------------------------------------------- /app/assets/images/mikey-team.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dwp/design-system/5340efdeb36a7189b6ea274c1487a4ff768f6109/app/assets/images/mikey-team.jpg -------------------------------------------------------------------------------- /app/assets/images/mitz-team.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dwp/design-system/5340efdeb36a7189b6ea274c1487a4ff768f6109/app/assets/images/mitz-team.jpg -------------------------------------------------------------------------------- /app/assets/images/simone-team.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dwp/design-system/5340efdeb36a7189b6ea274c1487a4ff768f6109/app/assets/images/simone-team.jpg -------------------------------------------------------------------------------- /app/assets/images/structured-answers.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dwp/design-system/5340efdeb36a7189b6ea274c1487a4ff768f6109/app/assets/images/structured-answers.gif -------------------------------------------------------------------------------- /app/assets/images/task-list.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dwp/design-system/5340efdeb36a7189b6ea274c1487a4ff768f6109/app/assets/images/task-list.png -------------------------------------------------------------------------------- /app/assets/images/time-out-modal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dwp/design-system/5340efdeb36a7189b6ea274c1487a4ff768f6109/app/assets/images/time-out-modal.png -------------------------------------------------------------------------------- /app/assets/javascript/application.js: -------------------------------------------------------------------------------- 1 | import common from './vendor/common'; 2 | import dialogPolyfill from './vendor/dialog-polyfill'; 3 | import BackToTop from './back-to-top'; 4 | import Example from './example'; 5 | import MobileNav from './mobile-navigation'; 6 | import CopyCodeButton from './copy-code-button'; 7 | import Tabs from './tabs'; 8 | import CookiesConsent from './cookies-consent'; 9 | import TimeoutWarning from './timeout-warning'; 10 | 11 | const { nodeListForEach } = common; 12 | 13 | // Initialise example frames 14 | const $examples = document.querySelectorAll('[data-module="app-example-frame"]'); 15 | nodeListForEach($examples, ($example) => { 16 | new Example($example).init(); 17 | }); 18 | 19 | // Register dialog polyfill 20 | const dialog = document.querySelector('.govuk-timeout-warning'); 21 | if (dialog) { 22 | dialogPolyfill.registerDialog(dialog); 23 | } 24 | 25 | // Initialise mobile navigation 26 | new MobileNav().init(); 27 | 28 | // Initialise back to top 29 | const $backToTop = document.querySelector('[data-module="app-back-to-top"]'); 30 | new BackToTop($backToTop).init(); 31 | 32 | document.querySelectorAll('.app-example__copy-code-button').forEach((button) => { 33 | new CopyCodeButton(button).init(); 34 | }); 35 | 36 | document.querySelectorAll('.app-tabs').forEach((tabs) => { 37 | new Tabs(tabs).init(); 38 | }); 39 | 40 | const cookieBanner = document.querySelector('.cookie-banner'); 41 | if (cookieBanner) { 42 | new CookiesConsent(cookieBanner).init(); 43 | } 44 | 45 | const timeoutWarnings = document.querySelectorAll('[data-module="govuk-timeout-warning"]'); 46 | nodeListForEach(timeoutWarnings, (timeoutWarning) => { 47 | new TimeoutWarning(timeoutWarning).init(); 48 | }); 49 | -------------------------------------------------------------------------------- /app/assets/javascript/back-to-top.js: -------------------------------------------------------------------------------- 1 | import 'govuk-frontend/govuk/vendor/polyfills/Function/prototype/bind'; 2 | 3 | function BackToTop($module) { 4 | this.$module = $module; 5 | } 6 | 7 | BackToTop.prototype.init = function () { 8 | if (!this.$module) { 9 | return; 10 | } 11 | 12 | // Check if we can use Intersection Observers 13 | if (!('IntersectionObserver' in window)) { 14 | // If there's no support fallback to regular behaviour 15 | // Since JavaScript is enabled we can remove the default hidden state 16 | return this.$module.classList.remove('app-back-to-top--hidden'); 17 | } 18 | 19 | const $footer = document.querySelector('.app-footer'); 20 | const $subNav = document.querySelector('.app-subnav'); 21 | 22 | // Check if there is anything to observe 23 | if (!$footer || !$subNav) { 24 | return; 25 | } 26 | 27 | let footerIsIntersecting = false; 28 | let subNavIsIntersecting = false; 29 | let subNavIntersectionRatio = 0; 30 | 31 | const observer = new window.IntersectionObserver((entries) => { 32 | // Find the elements we care about from the entries 33 | const footerEntry = entries.find((entry) => entry.target === $footer); 34 | const subNavEntry = entries.find((entry) => entry.target === $subNav); 35 | 36 | // If there is an entry this means the element has changed so lets check if it's intersecting. 37 | if (footerEntry) { 38 | footerIsIntersecting = footerEntry.isIntersecting; 39 | } 40 | if (subNavEntry) { 41 | subNavIsIntersecting = subNavEntry.isIntersecting; 42 | subNavIntersectionRatio = subNavEntry.intersectionRatio; 43 | } 44 | 45 | // If the subnav or the footer not visible then fix the back to top link to follow the user 46 | if (subNavIsIntersecting || footerIsIntersecting) { 47 | this.$module.classList.remove('app-back-to-top--fixed'); 48 | } else { 49 | this.$module.classList.add('app-back-to-top--fixed'); 50 | } 51 | 52 | // If the subnav is visible but you can see it all at once, then a back to top link is likely not as useful. 53 | // We hide the link but make it focusable for screen readers users who might still find it useful. 54 | if (subNavIsIntersecting && subNavIntersectionRatio === 1) { 55 | this.$module.classList.add('app-back-to-top--hidden'); 56 | } else { 57 | this.$module.classList.remove('app-back-to-top--hidden'); 58 | } 59 | }); 60 | 61 | observer.observe($footer); 62 | observer.observe($subNav); 63 | }; 64 | 65 | export default BackToTop; 66 | -------------------------------------------------------------------------------- /app/assets/javascript/cookies-consent.js: -------------------------------------------------------------------------------- 1 | function CookiesConsent($module) { 2 | this.$module = $module; 3 | this.cookieBannerButtonAcceptHide = this.$module.querySelector('.cookie-banner-accept--hide'); 4 | this.cookieBannerButtonRejectHide = this.$module.querySelector('.cookie-banner-reject--hide'); 5 | this.cookieBannerButtonAccept = this.$module.querySelector('.cookie-banner-button--accept'); 6 | this.cookieBannerButtonReject = this.$module.querySelector('.cookie-banner-button--reject'); 7 | this.cookieBannerAccept = this.$module.querySelector('.cookie-banner--accept'); 8 | this.cookieBannerReject = this.$module.querySelector('.cookie-banner--reject'); 9 | this.cookieBannerMain = this.$module.querySelector('.cookie-banner--main'); 10 | this.cookieBanner = document.querySelector('.cookie-banner'); 11 | } 12 | 13 | CookiesConsent.prototype.init = function () { 14 | if (!this.$module) { 15 | return; 16 | } 17 | 18 | if (document.cookie && document.cookie.indexOf('dwp_analytics') !== -1) { 19 | this.hideElement(this.cookieBanner); 20 | } 21 | 22 | if (this.cookieBannerButtonAcceptHide != null) { 23 | this.cookieBannerButtonAcceptHide.addEventListener('click', this.hideConfirmation.bind(this)); 24 | this.cookieBannerButtonRejectHide.addEventListener('click', this.hideConfirmation.bind(this)); 25 | } 26 | if (this.cookieBanner != null) { 27 | this.cookieBannerButtonAccept.addEventListener('click', this.showConfirmation.bind(this)); 28 | this.cookieBannerButtonReject.addEventListener('click', this.showConfirmation.bind(this)); 29 | } 30 | }; 31 | 32 | CookiesConsent.prototype.setCookie = function (type) { 33 | const date = new Date(); 34 | const days = 365; 35 | date.setTime(date.getTime() + 24 * days * 60 * 60 * 1e3); 36 | document.cookie = `dwp_analytics=${ 37 | encodeURIComponent(type) 38 | }; expires=${ 39 | date.toGMTString() 40 | }; path=/`; 41 | }; 42 | 43 | CookiesConsent.prototype.hideElement = function (element) { 44 | if (element) { 45 | element.classList.add('hidden'); 46 | } 47 | }; 48 | 49 | CookiesConsent.prototype.showElement = function (element) { 50 | element.setAttribute('tabindex', -1); 51 | element.classList.remove('hidden'); 52 | }; 53 | 54 | CookiesConsent.prototype.hideConfirmation = function (e) { 55 | e.preventDefault(); 56 | this.hideElement(this.cookieBanner); 57 | }; 58 | 59 | CookiesConsent.prototype.showConfirmation = function (e) { 60 | e.preventDefault(); 61 | const cookieValue = e.target.value; 62 | this.hideElement(this.cookieBannerMain); 63 | if (cookieValue === 'accept') { 64 | this.setCookie('accept'); 65 | this.showElement(this.cookieBannerAccept); 66 | } 67 | if (cookieValue === 'reject') { 68 | this.setCookie('reject'); 69 | this.showElement(this.cookieBannerReject); 70 | } 71 | }; 72 | 73 | export default CookiesConsent; 74 | -------------------------------------------------------------------------------- /app/assets/javascript/copy-code-button.js: -------------------------------------------------------------------------------- 1 | function CopyCodeButton($module) { 2 | this.$module = $module; 3 | } 4 | 5 | CopyCodeButton.prototype.init = function () { 6 | if (!this.$module) { 7 | return; 8 | } 9 | 10 | this.$module.addEventListener('click', () => { 11 | this.$module.textContent = 'Code copied'; 12 | setTimeout(() => { 13 | this.$module.textContent = 'Copy code'; 14 | }, 2000); 15 | const code = document.getElementsByClassName('app-js-visible')[0].querySelector('pre').textContent; 16 | navigator.clipboard.writeText(code); 17 | }); 18 | }; 19 | 20 | export default CopyCodeButton; 21 | -------------------------------------------------------------------------------- /app/assets/javascript/example.js: -------------------------------------------------------------------------------- 1 | import 'govuk-frontend/govuk/vendor/polyfills/Event'; 2 | 3 | function ExamplePage($module) { 4 | this.$module = $module; 5 | } 6 | ExamplePage.prototype.init = function () { 7 | const { $module } = this; 8 | if (!$module) { 9 | return; 10 | } 11 | const $form = $module.querySelector('form[action="/form-handler"]'); 12 | this.preventFormSubmission($form); 13 | }; 14 | ExamplePage.prototype.preventFormSubmission = function ($form) { 15 | // we should only have one form per example 16 | if (!$form) { 17 | return false; 18 | } 19 | $form.addEventListener('submit', (e) => { 20 | e.preventDefault(); 21 | }); 22 | }; 23 | 24 | new ExamplePage(document).init(); 25 | -------------------------------------------------------------------------------- /app/assets/javascript/mobile-navigation.js: -------------------------------------------------------------------------------- 1 | import common from './vendor/common'; 2 | 3 | const { nodeListForEach } = common; 4 | 5 | const navActiveClass = 'app-mobile-nav--active'; 6 | const navTogglerActiveClass = 'app-header-mobile-nav-toggler--active'; 7 | const subNavActiveClass = 'app-mobile-nav__subnav--active'; 8 | const subNavTogglerActiveClass = 'app-mobile-nav__subnav-toggler--active'; 9 | 10 | function MobileNav($module) { 11 | this.$module = $module || document; 12 | this.$nav = this.$module.querySelector('.js-app-mobile-nav'); 13 | this.$navToggler = this.$module.querySelector('.js-app-mobile-nav-toggler'); 14 | } 15 | 16 | MobileNav.prototype.bindUIEvents = function () { 17 | const { $nav } = this; 18 | const { $navToggler } = this; 19 | 20 | if ($navToggler) { 21 | $navToggler.addEventListener('click', (event) => { 22 | if ($nav.classList.contains(navActiveClass)) { 23 | $nav.classList.remove(navActiveClass); 24 | $nav.setAttribute('aria-hidden', 'true'); 25 | 26 | $navToggler.classList.remove(navTogglerActiveClass); 27 | $navToggler.setAttribute('aria-expanded', 'false'); 28 | } else { 29 | $nav.classList.add(navActiveClass); 30 | $nav.setAttribute('aria-hidden', 'false'); 31 | 32 | $navToggler.setAttribute('aria-expanded', 'true'); 33 | $navToggler.classList.add(navTogglerActiveClass); 34 | } 35 | }); 36 | } 37 | 38 | if ($nav) { 39 | $nav.addEventListener('click', (event) => { 40 | const $toggler = event.target; 41 | if (!$toggler.classList.contains('js-mobile-nav-subnav-toggler')) { 42 | return; 43 | } 44 | // The presentational touch area of the toggler is on it's parent. 45 | const $togglerLinkArea = $toggler.parentNode; 46 | 47 | const $nextSubNav = $togglerLinkArea.parentNode.querySelector('.js-app-mobile-nav-subnav'); 48 | 49 | if ($nextSubNav) { 50 | if ($nextSubNav.classList.contains(subNavActiveClass)) { 51 | $nextSubNav.classList.remove(subNavActiveClass); 52 | $togglerLinkArea.classList.remove(subNavTogglerActiveClass); 53 | 54 | $nextSubNav.setAttribute('aria-hidden', 'true'); 55 | $toggler.setAttribute('aria-expanded', 'false'); 56 | } else { 57 | $nextSubNav.classList.add(subNavActiveClass); 58 | $togglerLinkArea.classList.add(subNavTogglerActiveClass); 59 | 60 | $nextSubNav.setAttribute('aria-hidden', 'false'); 61 | $toggler.setAttribute('aria-expanded', 'true'); 62 | } 63 | event.preventDefault(); 64 | } 65 | }); 66 | } 67 | }; 68 | 69 | MobileNav.prototype.includeAria = function () { 70 | if (this.$nav) { 71 | this.$nav.setAttribute('aria-hidden', 'true'); 72 | } 73 | 74 | const { $navToggler } = this; 75 | if (this.$navToggler) { 76 | $navToggler.setAttribute('aria-expanded', 'false'); 77 | } 78 | 79 | const $subNavTogglers = this.$module.querySelectorAll('.js-mobile-nav-subnav-toggler'); 80 | 81 | nodeListForEach($subNavTogglers, ($toggler, index) => { 82 | const $nextSubNav = $toggler.parentNode.parentNode.querySelector('.js-app-mobile-nav-subnav'); 83 | 84 | if ($nextSubNav) { 85 | const navIsOpen = $nextSubNav.classList.contains(subNavActiveClass); 86 | const subNavTogglerId = `js-mobile-nav-subnav-toggler-${index}`; 87 | const nextSubNavId = `js-mobile-nav__subnav-${index}`; 88 | 89 | $nextSubNav.setAttribute('id', nextSubNavId); 90 | $nextSubNav.setAttribute('aria-hidden', navIsOpen ? 'false' : 'true'); 91 | 92 | $toggler.setAttribute('id', subNavTogglerId); 93 | $toggler.setAttribute('aria-expanded', navIsOpen ? 'true' : 'false'); 94 | $toggler.setAttribute('aria-controls', nextSubNavId); 95 | } 96 | }); 97 | }; 98 | 99 | MobileNav.prototype.init = function () { 100 | // Since the Mobile navigation is not included in IE8 101 | // We detect features we need to use only available in IE9+ https://caniuse.com/#feat=addeventlistener 102 | // http://responsivenews.co.uk/post/18948466399/cutting-the-mustard 103 | const featuresNeeded = ( 104 | 'querySelector' in document 105 | && 'addEventListener' in window 106 | ); 107 | 108 | if (!featuresNeeded) { 109 | return; 110 | } 111 | 112 | this.includeAria(); 113 | this.bindUIEvents(); 114 | }; 115 | 116 | export default MobileNav; 117 | -------------------------------------------------------------------------------- /app/assets/javascript/vendor/common.js: -------------------------------------------------------------------------------- 1 | (function (global, factory) { 2 | typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) 3 | : typeof define === 'function' && define.amd ? define('GOVUKFrontend', ['exports'], factory) 4 | : (factory((global.GOVUKFrontend = {}))); 5 | }(this, ((exports) => { 6 | /** 7 | * TODO: Ideally this would be a NodeList.prototype.forEach polyfill 8 | * This seems to fail in IE8, requires more investigation. 9 | * See: https://github.com/imagitama/nodelist-foreach-polyfill. 10 | * 11 | * @param nodes 12 | * @param callback 13 | */ 14 | function nodeListForEach(nodes, callback) { 15 | if (window.NodeList.prototype.forEach) { 16 | return nodes.forEach(callback); 17 | } 18 | for (let i = 0; i < nodes.length; i++) { 19 | callback.call(window, nodes[i], i, nodes); 20 | } 21 | } 22 | 23 | // Used to generate a unique string, allows multiple instances of the component without 24 | // Them conflicting with each other. 25 | // https://stackoverflow.com/a/8809472 26 | function generateUniqueID() { 27 | let d = new Date().getTime(); 28 | if (typeof window.performance !== 'undefined' && typeof window.performance.now === 'function') { 29 | d += window.performance.now(); // use high-precision timer if available 30 | } 31 | return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => { 32 | const r = (d + Math.random() * 16) % 16 | 0; 33 | d = Math.floor(d / 16); 34 | return (c === 'x' ? r : (r & 0x3 | 0x8)).toString(16); 35 | }); 36 | } 37 | 38 | exports.nodeListForEach = nodeListForEach; 39 | exports.generateUniqueID = generateUniqueID; 40 | }))); 41 | -------------------------------------------------------------------------------- /app/assets/sass/_app-pane.scss: -------------------------------------------------------------------------------- 1 | $toc-width: 260px; 2 | $toc-width-tablet: 210px; 3 | 4 | .app-pane .app-pane--enabled { 5 | @include govuk-media-query($from: tablet) { 6 | display: flex; 7 | flex-direction: column; 8 | } 9 | } 10 | 11 | .app-pane__body { 12 | @include govuk-media-query($from: tablet) { 13 | display: flex; 14 | position: relative; 15 | min-height: 0; 16 | overflow: inherit; 17 | } 18 | 19 | @include govuk-media-query(1160px) { 20 | width: 100%; 21 | } 22 | } 23 | 24 | .app-pane__subnav { 25 | @include govuk-media-query($until: tablet) { 26 | display: none; 27 | } 28 | @include govuk-media-query($from: tablet) { 29 | width: $toc-width-tablet; 30 | flex: 0 0 auto; 31 | } 32 | @include govuk-media-query($from: desktop) { 33 | width: $toc-width; 34 | } 35 | } 36 | 37 | .app-pane__subnav-mobile-overview { 38 | @include govuk-media-query($from: tablet) { 39 | display: none; 40 | } 41 | } 42 | 43 | .app-pane__content { 44 | @include govuk-media-query($from: tablet) { 45 | display: flex; 46 | min-width: 0; 47 | flex: 1 1 100%; 48 | flex-direction: column; 49 | } 50 | } 51 | 52 | .no-flexbox.no-flexboxtweener { 53 | .app-pane { 54 | height: auto; 55 | overflow: visible; 56 | @include govuk-clearfix; 57 | } 58 | 59 | .app-pane__body { 60 | display: block; 61 | } 62 | 63 | .app-pane__subnav { 64 | width: $toc-width; 65 | float: left; 66 | overflow-x: hidden; 67 | border-right: 0; 68 | } 69 | 70 | .app-pane__content { 71 | margin-left: -1px; 72 | overflow-x: hidden; 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /app/assets/sass/_app-phase-banner.scss: -------------------------------------------------------------------------------- 1 | .app-phase-banner { 2 | @include govuk-media-query($until: tablet) { 3 | margin-right: 0; 4 | margin-left: 0; 5 | } 6 | 7 | @include govuk-media-query($from: tablet) { 8 | border-bottom: 0; 9 | } 10 | } 11 | 12 | .app-phase-banner--no-border { 13 | border-bottom: 0; 14 | } -------------------------------------------------------------------------------- /app/assets/sass/_back-to-top.scss: -------------------------------------------------------------------------------- 1 | .app-back-to-top { 2 | margin-top: govuk-spacing(4); 3 | margin-bottom: govuk-spacing(6); 4 | } 5 | 6 | @include govuk-media-query($from: tablet) { 7 | .app-back-to-top { 8 | position: absolute; 9 | bottom: 0; 10 | left: 0; 11 | margin-top: auto; 12 | margin-bottom: govuk-spacing(8); 13 | } 14 | 15 | .js-enabled .app-back-to-top--fixed { 16 | position: fixed; 17 | top: calc(100% - #{govuk-spacing(8)}); 18 | bottom: auto; 19 | left: auto; 20 | } 21 | 22 | .js-enabled .app-back-to-top--hidden .app-back-to-top__link { 23 | @include govuk-visually-hidden-focusable; 24 | } 25 | } 26 | 27 | .app-back-to-top__icon { 28 | display: inline-block; 29 | width: .8em; 30 | height: 1em; 31 | margin-top: -(govuk-spacing(1)); 32 | margin-right: govuk-spacing(2); 33 | vertical-align: middle; 34 | } 35 | -------------------------------------------------------------------------------- /app/assets/sass/_contact-panel.scss: -------------------------------------------------------------------------------- 1 | /* ========================================================================== 2 | #CONTACT PANEL 3 | ========================================================================== */ 4 | 5 | .app-contact-panel { 6 | @include govuk-responsive-padding(3); 7 | background-color: govuk-colour("purple"); 8 | color: govuk-colour("white"); 9 | } 10 | 11 | 12 | .app-contact-panel__heading, 13 | .app-contact-panel__body, 14 | .app-contact-panel__link { 15 | color: govuk-colour("white"); 16 | } 17 | 18 | 19 | .app-contact-panel__heading { 20 | @extend .govuk-heading-m; 21 | } 22 | 23 | 24 | .app-contact-panel__body { 25 | @include govuk-font(19); 26 | margin-bottom: 0; 27 | } 28 | 29 | 30 | .app-contact-panel__link:link, 31 | .app-contact-panel__link:active, 32 | .app-contact-panel__link:visited { 33 | color: govuk-colour("white"); 34 | } 35 | 36 | 37 | .app-contact-panel__link:hover { 38 | color: lighten(govuk-colour("purple"), 45%); 39 | } 40 | 41 | 42 | .app-contact-panel__link:focus { 43 | color: govuk-colour("black"); 44 | } 45 | -------------------------------------------------------------------------------- /app/assets/sass/_cookie-banner.scss: -------------------------------------------------------------------------------- 1 | /* Cookie banner */ 2 | .cookie-banner, 3 | .cookie-banner-noscript { 4 | background: #f3f2f1; 5 | & form { 6 | display: inline; 7 | } 8 | } 9 | 10 | .cookie-banner--main, 11 | .cookie-banner--accept, 12 | .cookie-banner--reject { 13 | margin-bottom: 0; 14 | } 15 | 16 | .hidden { 17 | display: none; 18 | } 19 | 20 | .cookie-banner--reject:focus, 21 | .cookie-banner--accept:focus { 22 | outline: none; 23 | } 24 | .cookie-banner--reject p, 25 | .cookie-banner--accept p, 26 | .cookie-banner-accept--hide, 27 | .cookie-banner-reject--hide, 28 | .cookie-banner--hide { 29 | display: inline-block; 30 | } 31 | 32 | .cookie-banner--hide, 33 | .cookie-banner-accept--hide, 34 | .cookie-banner-reject--hide { 35 | float: none; 36 | } 37 | 38 | @media (min-width: 840px) { 39 | .cookie-banner--hide, 40 | .cookie-banner-accept--hide, 41 | .cookie-banner-reject--hide { 42 | float: right; 43 | margin-right: 30px; 44 | width: auto; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /app/assets/sass/_example.scss: -------------------------------------------------------------------------------- 1 | /* ========================================================================== 2 | #EXAMPLE 3 | ========================================================================== */ 4 | .app-example-wrapper { 5 | @include govuk-responsive-margin(6, "top"); 6 | @include govuk-responsive-margin(6, "bottom"); 7 | 8 | // HACK - this feels like a hack, will need revisiting 9 | @supports (margin: max(0px)) { 10 | .govuk-width-container { 11 | margin-right: max(30px, 15px); 12 | margin-left: max(30px, 15px); 13 | } 14 | } 15 | } 16 | 17 | .app-example { 18 | position: relative; 19 | border: 1px solid $govuk-border-colour; 20 | border-bottom: 0; 21 | // Add a 'checkerboard' background 22 | background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAAJUlEQVQoU2P88ePHfwY0wMHBwYguxjgUFKI7GsTH5m4M3w1ChQAZTSeO0/AZpgAAAABJRU5ErkJggg==") repeat; 23 | } 24 | 25 | .app-example--tabs { 26 | @include govuk-responsive-margin(0, "bottom"); 27 | } 28 | 29 | .app-example__toolbar { 30 | padding: 10px; 31 | border-bottom: 1px solid $govuk-border-colour; 32 | background: $govuk-body-background-colour; 33 | } 34 | 35 | pre, 36 | .app-example__code { 37 | background-color: govuk-colour("light-grey"); 38 | padding: 10px 10px 0 0; 39 | position: relative; 40 | @include govuk-font($size: 19); 41 | } 42 | 43 | .app-example__new-window { 44 | @include govuk-font($size: 14); 45 | } 46 | 47 | .app-example__copy-code-button { 48 | font-family: arial, sans-serif; 49 | z-index: 1; 50 | min-width: 110px; 51 | padding: 3px 10px; 52 | margin-right: 0; 53 | margin-left: auto; 54 | display: block; 55 | border: 1px solid #00823b; 56 | color: #00823b; 57 | box-shadow: 0 2px 0 0 govuk-colour("green"); 58 | text-align: center; 59 | text-decoration: none; 60 | cursor: pointer; 61 | font-size: 1rem; 62 | line-height: 1.25; 63 | background-color: govuk-colour("white"); 64 | 65 | &:active, 66 | &:focus { 67 | padding: 2px 10px; 68 | border: 2px solid govuk-colour("yellow"); 69 | outline: 2px solid transparent; 70 | box-shadow: none; 71 | } 72 | } 73 | 74 | .app-example__table-col { 75 | width: 33.3%; 76 | } -------------------------------------------------------------------------------- /app/assets/sass/_header.scss: -------------------------------------------------------------------------------- 1 | @include govuk-exports("app-header") { 2 | 3 | // Move the blue border from the container to the header so that it spans 4 | // the full width of the page 5 | .app-header { 6 | border-bottom: 10px solid $dwp-brand-colour; 7 | } 8 | 9 | .app-header__container { 10 | margin-bottom: 0; 11 | border-bottom: 0; 12 | } 13 | 14 | // Override the default 33% width on the logo in GOV.UK Frontend (prevents 15 | // unnecessary wrapping of "GOV.UK Design System" on smaller tablet / desktop 16 | // viewports) 17 | .app-header__logo { 18 | display: inline; 19 | float: left; 20 | 21 | @include govuk-media-query($from: tablet) { 22 | width: 100%; 23 | display: block; 24 | } 25 | } 26 | 27 | .app-header-mobile-nav-toggler-wrapper { 28 | margin-top: -10px; 29 | display: block; 30 | float: right; 31 | } 32 | 33 | .app-header-mobile-nav-toggler { 34 | display: none; 35 | min-height: 40px; // match the height of the search box 36 | margin-top: govuk-spacing(2); 37 | margin-bottom: govuk-spacing(2); 38 | padding-right: govuk-spacing(1); 39 | padding-left: govuk-spacing(1); 40 | border: 1px solid transparent; // Override the button default border, keep this around for when users change their colours 41 | box-shadow: none; // Override the button default box shadow 42 | 43 | &, 44 | &:hover { 45 | background-color: transparent; // Override the button default green 46 | } 47 | 48 | &::after { 49 | @include govuk-shape-arrow($direction: down, $base: 10px, $display: inline-block); 50 | content: ""; 51 | margin-left: govuk-spacing(1); 52 | border-top-color: currentColor; 53 | } 54 | 55 | &--active::after { 56 | @include govuk-shape-arrow($direction: up, $base: 10px, $display: inline-block); 57 | border-bottom-color: currentColor; 58 | } 59 | 60 | .js-enabled & { 61 | @include govuk-media-query($until: tablet) { 62 | display: inline; 63 | } 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /app/assets/sass/_highlight.scss: -------------------------------------------------------------------------------- 1 | /*! 2 | Theme: GitHub 3 | Description: Light theme as seen on github.com 4 | Author: github.com 5 | Maintainer: @Hirse 6 | Updated: 2021-05-15 7 | 8 | Outdated base version: https://github.com/primer/github-syntax-light 9 | Current colors taken from GitHub's CSS 10 | */ 11 | 12 | .hljs { 13 | color: #24292e; 14 | } 15 | 16 | .hljs-doctag, 17 | .hljs-keyword, 18 | .hljs-meta .hljs-keyword, 19 | .hljs-template-tag, 20 | .hljs-template-variable, 21 | .hljs-type, 22 | .hljs-variable.language_ { 23 | /* prettylights-syntax-keyword */ 24 | color: #d73a49; 25 | } 26 | 27 | .hljs-title, 28 | .hljs-title.class_, 29 | .hljs-title.class_.inherited__, 30 | .hljs-title.function_ { 31 | /* prettylights-syntax-entity */ 32 | color: #6f42c1; 33 | } 34 | 35 | .hljs-attr, 36 | .hljs-attribute, 37 | .hljs-literal, 38 | .hljs-meta, 39 | .hljs-number, 40 | .hljs-operator, 41 | .hljs-variable, 42 | .hljs-selector-attr, 43 | .hljs-selector-class, 44 | .hljs-selector-id { 45 | /* prettylights-syntax-constant */ 46 | color: #005cc5; 47 | } 48 | 49 | .hljs-regexp, 50 | .hljs-string, 51 | .hljs-meta .hljs-string { 52 | /* prettylights-syntax-string */ 53 | color: #032f62; 54 | } 55 | 56 | .hljs-built_in, 57 | .hljs-symbol { 58 | /* prettylights-syntax-variable */ 59 | color: #e36209; 60 | } 61 | 62 | .hljs-comment, 63 | .hljs-code, 64 | .hljs-formula { 65 | /* prettylights-syntax-comment */ 66 | color: #6a737d; 67 | } 68 | 69 | .hljs-name, 70 | .hljs-quote, 71 | .hljs-selector-tag, 72 | .hljs-selector-pseudo { 73 | /* prettylights-syntax-entity-tag */ 74 | color: #22863a; 75 | } 76 | 77 | .hljs-subst { 78 | /* prettylights-syntax-storage-modifier-import */ 79 | color: #24292e; 80 | } 81 | 82 | .hljs-section { 83 | /* prettylights-syntax-markup-heading */ 84 | color: #005cc5; 85 | font-weight: bold; 86 | } 87 | 88 | .hljs-bullet { 89 | /* prettylights-syntax-markup-list */ 90 | color: #735c0f; 91 | } 92 | 93 | .hljs-emphasis { 94 | /* prettylights-syntax-markup-italic */ 95 | color: #24292e; 96 | font-style: italic; 97 | } 98 | 99 | .hljs-strong { 100 | /* prettylights-syntax-markup-bold */ 101 | color: #24292e; 102 | font-weight: bold; 103 | } 104 | 105 | .hljs-addition { 106 | /* prettylights-syntax-markup-inserted */ 107 | color: #22863a; 108 | background-color: #f0fff4; 109 | } 110 | 111 | .hljs-deletion { 112 | /* prettylights-syntax-markup-deleted */ 113 | color: #b31d28; 114 | background-color: #ffeef0; 115 | } 116 | -------------------------------------------------------------------------------- /app/assets/sass/_layout.scss: -------------------------------------------------------------------------------- 1 | .ds-grid-row { 2 | padding: 0 15px; 3 | margin-bottom: 30px; 4 | 5 | @include govuk-media-query($from: desktop) { 6 | padding: 0; 7 | margin-bottom: 50px; 8 | } 9 | 10 | &--item { 11 | box-sizing: border-box; 12 | float: left; 13 | width: 100%; 14 | margin: 0; 15 | margin-bottom: 30px; 16 | 17 | &:last-of-type { 18 | margin-right: 0; 19 | } 20 | 21 | @include govuk-media-query($from: desktop) { 22 | width: 30.333%; 23 | margin-left: 1.5%; 24 | margin-right: 1.5%; 25 | margin-bottom: 0; 26 | } 27 | } 28 | } 29 | 30 | @supports (display: grid) { 31 | 32 | .ds-grid-row { 33 | display: grid; 34 | grid-template-columns: 1fr; 35 | grid-gap: 30px; 36 | margin: 0; 37 | padding: 0; 38 | 39 | &--item { 40 | float: none; 41 | width: 100%; 42 | padding: 0; 43 | margin: 0; 44 | } 45 | 46 | @include govuk-media-query($from: desktop) { 47 | grid-template-columns: 1fr 1fr 1fr; 48 | grid-auto-rows: max-content; 49 | 50 | &--item { 51 | margin-bottom: 20px; 52 | } 53 | } 54 | 55 | } 56 | 57 | } -------------------------------------------------------------------------------- /app/assets/sass/_masthead.scss: -------------------------------------------------------------------------------- 1 | /* ========================================================================== 2 | #MASTHEAD 3 | // Ideal line length (https://pearsonified.com/typography) 4 | ========================================================================== */ 5 | 6 | .app-masthead { 7 | @include govuk-responsive-padding(6, "top"); 8 | @include govuk-responsive-padding(6, "bottom"); 9 | background-color: govuk-colour("purple"); 10 | color: govuk-colour("white"); 11 | margin-top: -1px; // Covers the navigation border bottom 12 | } 13 | 14 | 15 | .app-masthead__title { 16 | @include govuk-responsive-margin(6, "bottom"); 17 | color: govuk-colour("white"); 18 | max-width: 1057px; // Desired CPL 50 (headings) chars at a font size of 48px 19 | } 20 | 21 | .app-masthead__description { 22 | @include govuk-font(24); 23 | color: govuk-colour("white"); 24 | margin-bottom: 0; 25 | max-width: 793px; // Desired CPL 75 (paragraphs) chars at a font size of 24px 26 | 27 | @include govuk-media-query($from: mobile, $until: desktop) { 28 | margin-bottom: 20px; 29 | } 30 | 31 | } 32 | 33 | .app-masthead__new { 34 | border: 2px solid govuk-colour("light-purple"); 35 | padding: 15px; 36 | 37 | ul { 38 | @extend %govuk-list; 39 | @extend %govuk-list--bullet; 40 | color: govuk-colour("white"); 41 | } 42 | } -------------------------------------------------------------------------------- /app/assets/sass/_mobile-navigation.scss: -------------------------------------------------------------------------------- 1 | .app-mobile-nav { 2 | display: none; 3 | border-bottom: 1px solid $govuk-border-colour; 4 | } 5 | 6 | .app-mobile-nav--active { 7 | display: block; 8 | 9 | @include govuk-media-query($from: tablet) { 10 | display: none; 11 | } 12 | } 13 | 14 | .no-js .app-mobile-nav { 15 | @include govuk-media-query($until: tablet) { 16 | display: block; 17 | } 18 | } 19 | 20 | .app-mobile-nav__list { 21 | margin: 0; 22 | padding: 0; 23 | list-style: none; 24 | } 25 | 26 | .app-mobile-nav-subnav-toggler { 27 | position: relative; 28 | padding: 16px govuk-spacing(4) 17px govuk-spacing(4); 29 | background-color: govuk-colour("light-grey"); 30 | } 31 | 32 | .app-mobile-nav-subnav-toggler__link { 33 | @include govuk-typography-weight-bold; // Override .govuk-link weight 34 | font-size: 19px; // We do not have a font mixin that produces 19px on mobile 35 | font-size: govuk-px-to-rem(19px); // sass-lint:disable-line no-duplicate-properties 36 | 37 | &:not(:focus):hover { 38 | color: $govuk-link-colour; 39 | } 40 | } 41 | 42 | .app-mobile-nav-subnav-toggler__link, 43 | .app-mobile-nav__link { 44 | text-decoration: none; 45 | 46 | // Expand the touch area of the link to the full menu width 47 | &:after { 48 | content: ""; 49 | position: absolute; 50 | top: 0; 51 | right: 0; 52 | bottom: 0; 53 | left: 0; 54 | } 55 | } 56 | 57 | .app-mobile-nav__subnav { 58 | display: none; 59 | padding-top: govuk-spacing(2); 60 | padding-bottom: govuk-spacing(2); 61 | border-top: 1px solid govuk-colour("light-grey"); 62 | border-bottom: 1px solid govuk-colour("light-grey"); 63 | } 64 | 65 | .js-enabled .app-mobile-nav__subnav--active { 66 | display: block; 67 | } 68 | 69 | .app-mobile-nav__section-item { 70 | position: relative; 71 | } 72 | 73 | .app-mobile-nav__subnav-item { 74 | display: block; 75 | position: relative; 76 | padding: (govuk-spacing(2) + 2px) govuk-spacing(4); 77 | } 78 | 79 | .app-mobile-nav__subnav-item--current { 80 | $_current-indicator-width: 4px; 81 | padding-left: govuk-spacing(4) - $_current-indicator-width; 82 | border-left: $_current-indicator-width solid govuk-colour("purple"); 83 | } 84 | 85 | .app-mobile-nav__theme { 86 | @include govuk-typography-common; 87 | margin: 0; 88 | padding: govuk-spacing(4) govuk-spacing(4) govuk-spacing(1) govuk-spacing(4); 89 | color: govuk-colour("dark-grey"); 90 | // Font is defined as a hard 19px so 91 | // it does not re-size on mobile viewport 92 | font-size: 19px; 93 | font-size: govuk-px-to-rem(19px); // sass-lint:disable-line no-duplicate-properties 94 | font-weight: normal; 95 | } -------------------------------------------------------------------------------- /app/assets/sass/_navigation.scss: -------------------------------------------------------------------------------- 1 | $navigation-height: 50px; 2 | 3 | .app-navigation { 4 | @include govuk-font(19, $weight: bold); 5 | box-sizing: border-box; 6 | width: 100%; 7 | background-color: $app-light-grey; 8 | 9 | @include govuk-media-query($until: tablet) { 10 | display: none; 11 | } 12 | } 13 | 14 | .app-navigation__list { 15 | position: relative; 16 | left: -(govuk-spacing(3)); 17 | margin: 0; 18 | padding: 0; 19 | list-style: none; 20 | } 21 | 22 | .app-navigation__list-item { 23 | box-sizing: border-box; 24 | display: block; 25 | position: relative; 26 | height: $navigation-height; 27 | padding: 0 govuk-spacing(3); 28 | float: left; 29 | line-height: $navigation-height; 30 | } 31 | 32 | .app-navigation__list-item--selected { 33 | border-bottom: 4px solid govuk-colour(purple); 34 | 35 | } 36 | 37 | .app-navigation__list-item--current { 38 | border-bottom: 4px solid govuk-colour(purple); 39 | } 40 | 41 | .app-navigation__link { 42 | // color: govuk-colour(purple) !important; 43 | @include govuk-typography-weight-bold; 44 | text-decoration: none; 45 | 46 | &:not(:focus):hover { 47 | color: govuk-colour(purple); 48 | text-decoration: underline; 49 | } 50 | 51 | // Extend the touch area of the link to the list 52 | &:after { 53 | content: ""; 54 | position: absolute; 55 | top: 0; 56 | right: 0; 57 | bottom: 0; 58 | left: 0; 59 | } 60 | } 61 | 62 | .app-navigation__list-item--current .app-navigation__link:hover { 63 | text-decoration: none; 64 | } 65 | -------------------------------------------------------------------------------- /app/assets/sass/_sub-navigation.scss: -------------------------------------------------------------------------------- 1 | @include govuk-exports("app-subnav") { 2 | 3 | .app-subnav { 4 | // Since the back to top link is outside the flow of the document we need to create a space for it. 5 | // This number is magic and was determined by manually judging the visual spacing. 6 | margin-bottom: 100px; 7 | padding: govuk-spacing(6) govuk-spacing(3) 0 0; 8 | @include govuk-font(16); 9 | } 10 | 11 | .app-subnav__section { 12 | margin: 0 0 govuk-spacing(4); 13 | padding: 0; 14 | list-style-type: none; 15 | } 16 | 17 | .app-subnav__link { 18 | padding: 2px 0; 19 | @include govuk-font(16); 20 | 21 | &:not(:focus):hover { 22 | color: $govuk-link-colour; 23 | } 24 | } 25 | 26 | .app-subnav__section-item { 27 | position: relative; 28 | margin-bottom: govuk-spacing(1); 29 | padding-top: govuk-spacing(1); 30 | padding-bottom: govuk-spacing(1); 31 | } 32 | 33 | .app-subnav__section-item--current { 34 | $_current-indicator-width: 4px; 35 | margin-left: -(govuk-spacing(2) + $_current-indicator-width); 36 | padding-left: govuk-spacing(2); 37 | border-left: $_current-indicator-width solid govuk-colour("purple"); 38 | background-color: $app-light-grey; 39 | } 40 | 41 | .app-subnav__section-item--current .app-subnav__link { 42 | font-weight: bold; 43 | } 44 | 45 | .app-subnav__section-item--top { 46 | .app-subnav__link { 47 | position: relative; 48 | z-index: 2; 49 | } 50 | 51 | &:after { 52 | content: ''; 53 | display: block; 54 | $_current-indicator-width: 4px; 55 | padding-left: govuk-spacing(2); 56 | border-left: $_current-indicator-width solid govuk-colour("purple"); 57 | background-color: $app-light-grey; 58 | position: absolute; 59 | top: 0; 60 | left: -(govuk-spacing(4) + $_current-indicator-width); 61 | width: 100%; 62 | height: 35px; 63 | } 64 | } 65 | 66 | .app-subnav__section-item--bold .app-subnav__link { 67 | font-weight: bold; 68 | position: relative; 69 | z-index: 2; 70 | } 71 | 72 | .app-subnav__section--nested { 73 | margin-top: govuk-spacing(2); 74 | margin-bottom: 0; 75 | padding-left: govuk-spacing(4); 76 | } 77 | 78 | .app-subnav__section--nested .app-subnav__section-item::before { 79 | margin-left: -(govuk-spacing(4)); 80 | color: govuk-colour("dark-grey"); 81 | } 82 | 83 | .app-subnav__section--nested .app-subnav__link { 84 | padding-left: 0; 85 | font-weight: normal; 86 | } 87 | 88 | .app-subnav__theme { 89 | margin: 0; 90 | padding: govuk-spacing(2) govuk-spacing(3) govuk-spacing(2) 0; 91 | color: govuk-colour("dark-grey"); 92 | @include govuk-font(19); 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /app/assets/sass/_tabs.scss: -------------------------------------------------------------------------------- 1 | /* ========================================================================== 2 | #TABS 3 | ========================================================================== */ 4 | 5 | .app-tabs { 6 | background: govuk-colour("white"); 7 | margin-bottom: govuk-spacing(6); 8 | } 9 | 10 | 11 | .app-tabs__list { 12 | border: 1px solid $govuk-border-colour; 13 | list-style: none; 14 | margin: 0; 15 | padding: 0; 16 | font-size: 0; // Remove white space when using display: inline-block 17 | 18 | } 19 | 20 | 21 | .app-tabs__list-item { 22 | display: inline-block; 23 | margin: 0; 24 | margin-bottom: 0; 25 | 26 | } 27 | 28 | 29 | .app-tabs__tab { 30 | @include govuk-font($size: 19, $weight: bold); 31 | background-color: govuk-colour("white"); 32 | color: govuk-colour("purple"); 33 | display: inline-block; 34 | padding: 20px; 35 | position: relative; 36 | border: 0; 37 | cursor: pointer; 38 | text-decoration: underline; 39 | 40 | &:link, 41 | &:active, 42 | &:visited { 43 | background-color: govuk-colour("white"); 44 | color: govuk-colour("purple"); 45 | } 46 | 47 | &:hover { 48 | text-decoration-skip-ink: none; 49 | text-decoration-thickness: 3px; 50 | color: govuk-colour("light-purple"); 51 | } 52 | 53 | &:focus { 54 | z-index: 2; // Focus state must sit above 55 | text-decoration-skip-ink: none; 56 | text-decoration-thickness: 3px; 57 | color: $govuk-focus-text-colour; 58 | background-color: $govuk-focus-colour; 59 | box-shadow: 0 -2px $govuk-focus-colour, 0 4px $govuk-focus-text-colour; 60 | border-color: $govuk-focus-text-colour; 61 | text-decoration: none; 62 | } 63 | 64 | &[aria-expanded=true] { 65 | color: govuk-colour("black"); 66 | margin-bottom: -1px; 67 | padding-bottom: 21px; 68 | border-left: 1px solid $govuk-border-colour; 69 | border-right: 1px solid $govuk-border-colour; 70 | } 71 | 72 | &:first-of-type { 73 | &[aria-expanded=true] { 74 | border-left: 0; 75 | } 76 | } 77 | 78 | } 79 | 80 | 81 | .app-tabs__panel { 82 | @include govuk-font($size: 19); 83 | border: 1px solid $govuk-border-colour; 84 | border-top: 0; 85 | position: relative; 86 | padding: 20px; 87 | 88 | *:last-child { 89 | margin-bottom: 0; // Remove margin bottom from any last element 90 | } 91 | 92 | p { 93 | background-color: govuk-colour("white"); 94 | max-width: 100% !important; 95 | padding: govuk-spacing(2); 96 | } 97 | 98 | &__details { 99 | margin-bottom: 16px; 100 | p { 101 | padding: 0; 102 | } 103 | } 104 | 105 | &__code { 106 | position: relative; 107 | } 108 | } 109 | 110 | // add slight indent to css code snippet 111 | .hljs-attribute { 112 | padding-left: 15px; 113 | } -------------------------------------------------------------------------------- /app/assets/sass/_timeout-warning.scss: -------------------------------------------------------------------------------- 1 | @import "vendor/dialog-polyfill.0.5.0"; 2 | 3 | .govuk-timeout-warning { 4 | display: none; 5 | // @include govuk-responsive-padding(6); 6 | // Setting width allows IE to center dialog vertically 7 | width: 100%; 8 | 9 | // To do: allow this to be customised 10 | max-width: 500px; 11 | 12 | .govuk-button { 13 | margin: 0 govuk-spacing(2) govuk-spacing(3) 0; 14 | @include govuk-media-query($from: tablet) { 15 | margin-bottom: govuk-spacing(0); 16 | } 17 | } 18 | 19 | &[open] { 20 | display: block; 21 | 22 | $backdrop-colour: rgba(0, 0, 0, .8); 23 | 24 | // Backdrop styles for browsers with native support 25 | &+ .backdrop { 26 | background: $backdrop-colour; 27 | } 28 | 29 | // Backdrop styles for browsers using 30 | // Keep these two backdrop styles separate - Safari didn't 31 | // work when combined 32 | &::backdrop { 33 | background: $backdrop-colour; 34 | } 35 | } 36 | } 37 | 38 | // Stop background scrolling while dialog open. 39 | .govuk-timeout-warning-overlay { 40 | overflow: hidden; 41 | } 42 | 43 | .govuk-notification-banner--blue { 44 | background-color: $govuk-blue; 45 | border-color: $govuk-blue; 46 | } 47 | 48 | .js-enabled .dwp-timeout-warning-fallback { 49 | display: none; 50 | } 51 | 52 | -------------------------------------------------------------------------------- /app/assets/sass/_toggle-to-welsh.scss: -------------------------------------------------------------------------------- 1 | .dwp-language-toggle { 2 | font-family: Arial,sans-serif; 3 | font-size: 14px; 4 | } 5 | .dwp-language-toggle__list { 6 | margin-top: 1em; 7 | text-align: right; 8 | } 9 | .dwp-language-toggle__list-item { 10 | display: inline-block; 11 | } 12 | .dwp-language-toggle__list-item:first-child:after { 13 | content: ""; 14 | display: inline-block; 15 | border-right: 1px solid #0b0c0c; 16 | position: relative; 17 | top: .1875em; 18 | height: 1em; 19 | } -------------------------------------------------------------------------------- /app/assets/sass/application-ie8.scss: -------------------------------------------------------------------------------- 1 | // By setting $govuk-is-ie8 to true, we create a version of the stylesheet that 2 | // targets IE8 – e.g. conditionally including or excluding styles, and 3 | // rasterizing media queries. 4 | $govuk-is-ie8: true; 5 | 6 | @import "application"; 7 | -------------------------------------------------------------------------------- /app/assets/sass/vendor/dialog-polyfill.0.5.0.css: -------------------------------------------------------------------------------- 1 | dialog { 2 | position: absolute; 3 | left: 0; right: 0; 4 | width: -moz-fit-content; 5 | width: -webkit-fit-content; 6 | width: fit-content; 7 | height: -moz-fit-content; 8 | height: -webkit-fit-content; 9 | height: fit-content; 10 | margin: auto; 11 | border: solid; 12 | padding: 1em; 13 | background: white; 14 | color: black; 15 | display: block; 16 | } 17 | 18 | dialog:not([open]) { 19 | display: none; 20 | } 21 | 22 | dialog + .backdrop { 23 | position: fixed; 24 | top: 0; right: 0; bottom: 0; left: 0; 25 | background: rgba(0,0,0,0.1); 26 | } 27 | 28 | ._dialog_overlay { 29 | position: fixed; 30 | top: 0; right: 0; bottom: 0; left: 0; 31 | } 32 | 33 | dialog.fixed { 34 | position: fixed; 35 | top: 50%; 36 | transform: translate(0, -50%); 37 | } 38 | -------------------------------------------------------------------------------- /app/middleware/accessibility.js: -------------------------------------------------------------------------------- 1 | const renderA11yStatement = (req, res) => res.render( 2 | '_accessibility.njk', 3 | ); 4 | module.exports = { renderA11yStatement }; -------------------------------------------------------------------------------- /app/middleware/cookies/cookieDetails.js: -------------------------------------------------------------------------------- 1 | const renderCookieDetails = (req, res) => res.render( 2 | '_cookie-details.njk', 3 | ); 4 | module.exports = { renderCookieDetails }; 5 | -------------------------------------------------------------------------------- /app/middleware/cookies/cookiePolicy.js: -------------------------------------------------------------------------------- 1 | const { setCookieChoice } = require('./cookiesConsent'); 2 | 3 | const renderCookiePolicy = (req, res) => { 4 | res.locals.cookieConsent = req.cookies.seen_cookie_message; 5 | res.render( 6 | '_cookie-policy.njk', 7 | ); 8 | }; 9 | 10 | const cookiePolicyPostHandler = (req, res, next) => { 11 | const { cookieChoice } = req.body; 12 | if (!cookieChoice) { 13 | res.locals.validationError = true; 14 | next(); 15 | } else { 16 | setCookieChoice(req, res); 17 | } 18 | }; 19 | 20 | module.exports = { renderCookiePolicy, cookiePolicyPostHandler }; 21 | -------------------------------------------------------------------------------- /app/middleware/cookies/cookiesConsent.js: -------------------------------------------------------------------------------- 1 | const oneYearInMilliseconds = 1000 * 60 * 60 * 24 * 365; 2 | const CONSENT_COOKIE = 'dwp_analytics'; 3 | const COOKIE_DECISION_MADE = 'cookie_decision_made'; 4 | 5 | const consentCookieOptions = (res, cookieChoice) => { 6 | res.cookie(CONSENT_COOKIE, cookieChoice, { 7 | path: '/', 8 | maxAge: oneYearInMilliseconds, 9 | httpOnly: false, 10 | sameSite: true, 11 | secure: false, 12 | }); 13 | }; 14 | 15 | const cookieDecisionMadeOptions = (res, flag) => { 16 | res.cookie(COOKIE_DECISION_MADE, flag, { 17 | path: '/', 18 | maxAge: oneYearInMilliseconds, 19 | httpOnly: false, 20 | sameSite: true, 21 | secure: false, 22 | }); 23 | }; 24 | 25 | const setCookieChoice = (req, res) => { 26 | const { cookieChoice } = req.body; 27 | 28 | if (cookieChoice) { 29 | consentCookieOptions(res, cookieChoice); 30 | cookieDecisionMadeOptions(res, true); 31 | } 32 | if (res.locals.currentUrl === '/cookie-policy') { 33 | res.redirect('/'); 34 | } else { 35 | res.redirect('back'); 36 | } 37 | }; 38 | 39 | const getCookieChoice = (req, res, next) => { 40 | const cookieChoice = req.cookies[CONSENT_COOKIE]; 41 | const cookieDecisionMade = req.cookies[COOKIE_DECISION_MADE]; 42 | 43 | if (cookieDecisionMade || cookieChoice) { 44 | res.locals.cookieChoiceJustMade = cookieDecisionMade; 45 | res.clearCookie(COOKIE_DECISION_MADE); 46 | 47 | if (cookieChoice) { 48 | res.locals.cookieMessage = cookieChoice; 49 | res.locals.currentUrl = req.originalUrl; 50 | } 51 | } 52 | 53 | next(); 54 | }; 55 | 56 | module.exports = { setCookieChoice, getCookieChoice }; 57 | -------------------------------------------------------------------------------- /app/middleware/errorHandler.js: -------------------------------------------------------------------------------- 1 | const errorHandler = (err, req, res, next) => { 2 | console.error('WHAT > > > ', err); 3 | res.status(err.status || 500); 4 | res.render('_page-not-found.njk') 5 | } 6 | 7 | module.exports = { errorHandler }; 8 | -------------------------------------------------------------------------------- /app/middleware/sitemap.js: -------------------------------------------------------------------------------- 1 | const renderSitemap = (req, res) => res.render( 2 | '_sitemap.njk', 3 | ); 4 | module.exports = { renderSitemap }; -------------------------------------------------------------------------------- /app/middleware/urlPartials.js: -------------------------------------------------------------------------------- 1 | const urlPartials = (req, res, next) => { 2 | //store original url as array in locals, removing the first item as it is always an empty string 3 | const urlPartials = req.originalUrl.split('/').slice(1); 4 | res.locals.urlPartials = urlPartials; 5 | next(); 6 | } 7 | 8 | module.exports = { urlPartials }; -------------------------------------------------------------------------------- /app/routes/auto.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const router = express.Router(); 3 | const { navigationDataLoader } = require('../utils/navigation-data-loader'); 4 | const { contentLoader } = require('../utils/content-loader'); 5 | const { dotHtmlMatch, slugMatch } = require('../utils/regexes') 6 | 7 | router.use(navigationDataLoader); 8 | router.use(contentLoader); 9 | 10 | router.get(dotHtmlMatch, function (req, res) { 11 | var path = req.path; 12 | var parts = path.split('.'); 13 | parts.pop(); 14 | path = parts.join('.'); 15 | res.redirect(path); 16 | }); 17 | 18 | router.get(slugMatch, function (req, res) { 19 | const path = req.params[0]; 20 | res.render(`${path}/index`) 21 | }) 22 | 23 | module.exports = router; 24 | -------------------------------------------------------------------------------- /app/routes/index.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | 3 | const router = express.Router(); 4 | const { navigationDataLoader } = require('../utils/navigation-data-loader'); 5 | const { renderCookiePolicy, cookiePolicyPostHandler } = require('../middleware/cookies/cookiePolicy'); 6 | const { renderCookieDetails } = require('../middleware/cookies/cookieDetails'); 7 | const { setCookieChoice, getCookieChoice } = require('../middleware/cookies/cookiesConsent'); 8 | const { renderA11yStatement } = require('../middleware/accessibility') 9 | const { renderSitemap } = require('../middleware/sitemap') 10 | 11 | 12 | const redirects = require('./redirects'); 13 | 14 | router.use(navigationDataLoader, getCookieChoice); 15 | 16 | router.post('/set-cookie-message', setCookieChoice); 17 | router.post('/cookie-policy', cookiePolicyPostHandler, renderCookiePolicy); 18 | 19 | router.get('/', (req, res) => { 20 | res.render('index'); 21 | }); 22 | 23 | // TODO this needs investigating as to why we redirect to /index on live? 24 | router.get('/index', (req, res) => { 25 | res.render('index'); 26 | }); 27 | 28 | router.get('/cookie-policy', renderCookiePolicy); 29 | router.get('/cookie-details', renderCookieDetails); 30 | router.get('/accessibility', renderA11yStatement); 31 | router.get('/sitemap', renderSitemap) 32 | 33 | // redirects 34 | router.use('/', redirects); 35 | 36 | module.exports = router; 37 | -------------------------------------------------------------------------------- /app/routes/redirects.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const router = express.Router(); 3 | 4 | router.get('/patterns/consent-to-cookies', (req, res) => { 5 | res.redirect(301, '/patterns/retired-patterns/consent-to-cookies'); 6 | }) 7 | 8 | module.exports = router; 9 | -------------------------------------------------------------------------------- /app/utils/content-loader.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | contentLoader(req, res, next) { 3 | const { backlogSections } = require('../../config/content/backlog-page.json'); 4 | res.locals.backlogSections = backlogSections; 5 | next(); 6 | }, 7 | }; 8 | -------------------------------------------------------------------------------- /app/utils/file-helper.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const yaml = require('js-yaml'); 3 | const nunjucks = require('nunjucks'); 4 | const matter = require('gray-matter'); 5 | const beautify = require('js-beautify').html; 6 | const { removeWhitespace } = require('../utils/regexes') 7 | 8 | // This helper function gets the params for a components Nunjucks macro 9 | // from the component's .yaml file. 10 | exports.getMacroParams = path => { 11 | const file = fs.readFileSync(path, 'utf8'); 12 | return yaml.load(file).params; 13 | } 14 | 15 | // This helper function takes a path of a file and 16 | // returns the contents as string 17 | exports.getFileContents = (path) => { 18 | let fileContents; 19 | try { 20 | fileContents = fs.readFileSync(path); 21 | } catch (err) { 22 | if (err.code === 'ENOENT') { 23 | console.log(err.message); 24 | } else { 25 | throw err; 26 | } 27 | } 28 | return fileContents.toString(); 29 | }; 30 | 31 | // This helper function takes a path of a *.md.njk file and 32 | // returns the Nunjucks syntax inside that file without markdown data and imports 33 | exports.getNunjucksCode = (path) => { 34 | const fileContents = this.getFileContents(path); 35 | const parsedFile = matter(fileContents); 36 | return parsedFile.content; 37 | }; 38 | 39 | // This helper function takes a path of a *.md.njk file and 40 | // returns the HTML rendered by Nunjucks without markdown data 41 | exports.getHtmlCode = (path) => { 42 | const fileContents = this.getFileContents(path); 43 | const parsedFile = matter(fileContents); 44 | const { content } = parsedFile; 45 | let html; 46 | try { 47 | html = nunjucks.renderString(content); 48 | } catch (err) { 49 | if (err) { 50 | console.log(`Could not get HTML code from ${path}`); 51 | } 52 | } 53 | return beautify(html.replace(removeWhitespace,''), { 54 | end_with_newline: true, 55 | // If there are multiple blank lines, reduce down to one blank new line. 56 | max_preserve_newlines: 1, 57 | }); 58 | }; 59 | 60 | // returns CSS from path provided 61 | exports.getCSSCode = (path) => { 62 | let fileContents; 63 | try { 64 | const file = this.getFileContents(path); 65 | const parsedFile = matter(file); 66 | fileContents = beautify(parsedFile.content); 67 | } catch(err) { 68 | if(err){ 69 | return null; 70 | } 71 | } 72 | return fileContents; 73 | } -------------------------------------------------------------------------------- /app/utils/navigation-data-loader.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | // Load JSON data and expose it to Nunjucks 3 | navigationDataLoader(req, res, next) { 4 | const { navItems } = require('../../config/navigation-data.json'); 5 | res.locals.navItems = navItems; 6 | next(); 7 | }, 8 | }; 9 | -------------------------------------------------------------------------------- /app/utils/regexes.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | dotHtmlMatch: /\.html?$/i, 3 | slugMatch: /^\/([^.]+)$/, 4 | removeWhitespace: /^\s+|\s+$/gm 5 | }; -------------------------------------------------------------------------------- /app/views/_layouts/base.html: -------------------------------------------------------------------------------- 1 | {%- from "_macros/example/macro.njk" import dsExample -%} 2 | {%- from "_macros/mobile-navigation/macro.njk" import appMobileNavigation -%} {# TODO: shorten paths #} 3 | {%- from "_macros/navigation/macro.njk" import appNavigation -%} 4 | {%- from "_macros/sub-navigation/macro.njk" import appSubNavigation -%} 5 | {%- from "tag/macro.njk" import govukTag -%} 6 | {%- from "phase-banner/macro.njk" import govukPhaseBanner -%} 7 | {%- from "skip-link/macro.njk" import govukSkipLink -%} 8 | 9 | 10 | 11 |
12 | 22 | 23 | 24 |This accessibility statement applies to the DWP Design System website at design-system.dwp.gov.uk.
12 |This website is run by the Department for Work and Pensions (DWP). We want as many people as possible to be able to use this website. For example, that means you should be able to:
13 |We’ve also made the website text as simple as possible to understand.
21 |AbilityNet has advice on making your device easier to use if you have a disability.
22 |We have tested the content of this website for accessibility using a range of browsers and technologies including screen readers. It meets the ‘AA’ standard of the Web Content Accessibility Guidelines version 2.1.
24 |We’re always looking to improve the accessibility of this website. If you find any problems or think we’re not meeting accessibility requirements, contact the design system team on dwp-design-system@engineering.digital.dwp.gov.uk
26 |DWP is committed to making its websites accessible, in accordance with the Public Sector Bodies (Websites and Mobile Applications) (No. 2) Accessibility Regulations 2018.
28 |This website is fully compliant with the Web Content Accessibility Guidelines version 2.1 AA standard.
30 |If you need information on this website in a different format, email dwp-design-system@engineering.digital.dwp.gov.uk
32 |The Equality and Human Rights Commission (EHRC) is responsible for enforcing the Public Sector Bodies (Websites and Mobile Applications) (No. 2) Accessibility Regulations 2018 (the ‘accessibility regulations’). If you’re not happy with how we respond to your complaint, contact the Equality Advisory and Support Service (EASS).
34 |This statement was prepared on 23 June 2022. It was last reviewed on 23 June 2022.
36 |This website was last tested on 1 October 2021. The test was carried out by the DWP Accessibility Standards and Strategy Team.
37 |The internal services footer is a simplified standard footer for services used by DWP staff or agents.
6 | 7 |Hint text gives extra information that helps people to answer a question.
12 | 13 |The key details bar groups and highlights the most relevant information on a page so that agents can find it easily.
18 | 19 |Name | 6 |GitHub discussion | 7 |Code example | 8 |
---|---|---|
Internal services footer | 15 |#90 | 16 |Yes | 17 |
Hint text | 24 |#88 | 25 |No | 26 |
Internal services header | 33 |#70 | 34 |Yes | 35 |
Key details bar | 42 |#160 | 43 |Yes | 44 |
Timeline | 51 |#67 | 52 |Yes | 53 |
4 | If you’ve got a question, idea or suggestion email the Design System team on 5 | 6 | dwp-design-system@engineering.digital.dwp.gov.uk 7 |
8 |Contribute ideas and get involved with the DWP Design System.
6 | 7 |See what people are currently working on in the community backlog.
12 | 13 |We're using GitHub Discussions to help the community talk to us about our components and patterns.
18 | 19 |A cookie is a small file which is stored on your device for a short time to make this service work.
35 |We use cookies that are:
36 |We will not:
41 |We use Google Analytics to get information about how you use this service and help us make it better.
50 | 51 | 107 | 108 | 109 |12 | If you typed the web address, check it is correct. 13 |
14 |15 | If you pasted the web address, check you copied the entire address. 16 |
17 |18 | Something broken? Please raise a new issue on GitHub using the ‘Bug report’ template, or email the design system team on dwp-design-system@engineering.digital.dwp.gov.uk. 19 | 20 |
21 |Help users to add more than one thing of the same type.
6 | 7 |This pattern lets the user change the language used in a service from English to Welsh and from Welsh to English.
12 | 13 |Use this pattern to warn users that their session is about to end and explain what has happened after the session has timed out.
18 | 19 |Name | 6 |GitHub discussion | 7 |Code example | 8 |
---|---|---|
Add another thing | 15 |#87 | 16 |Yes | 17 |
Make a declaration | 24 |#69 | 25 |Yes | 26 |
Manage a session timeout | 33 |#66 | 34 |Yes | 35 |
Toggle to Welsh | 42 |#72 | 43 |Yes | 44 |
Things I'm working on this sprint:
17 |See all the components in the backlog
16 | {% endblock %} -------------------------------------------------------------------------------- /app/views/components/internal-services-footer/README.md.njk: -------------------------------------------------------------------------------- 1 | The internal services footer is based on the standard GOV.UK footer component but with the copyright notice and Royal Coat of Arms removed. 2 | 3 | You may also want to read our step-by-step guidance on [adapting the GOV.UK Prototype Kit for use with internal services](https://github.com/dwp/design-system/discussions/347), including changing the default font and removing other branding elements. 4 | 5 | ## When to use this component 6 | Use this footer for internal services not hosted on service.gov.uk domains. Users of these services will normally be DWP staff but may also include staff of other organisations such as local authorities. 7 | 8 | ## When not to use this component 9 | If your service is hosted on a service.gov.uk domain it should use the [GOV.UK Design System footer component](https://design-system.service.gov.uk/components/footer/). 10 | 11 | ## How it works 12 | Like the GOV.UK footer, the internal services footer can be adapted to the needs of your service. When deciding what information to place in the footer, remember that: 13 | - information placed in the footer is sometimes skipped or not noticed 14 | - the grey background lowers the contrast ratio which will limit readability for some people 15 | 16 | ### Footer with links 17 | {{dsExample({ 18 | name: 'internal-services-footer', 19 | example: 'meta-links', 20 | height: 140 21 | })}} 22 | 23 | ### Footer with secondary navigation 24 | {{dsExample({ 25 | name: 'internal-services-footer', 26 | example: 'default', 27 | height: 140 28 | })}} 29 | 30 | ### Footer with links, secondary navigation and plain text 31 | {{dsExample({ 32 | name: 'internal-services-footer', 33 | example: 'nav-and-links', 34 | height: 140 35 | })}} 36 | 37 | ## Research 38 | 39 | ### Have you used this component? 40 | Please let us know what you found so we can make it better for everyone. There is an [open discussion for this component on GitHub](https://github.com/dwp/design-system-community-backlog/discussions/90) where you can share anything you think might be useful. 41 | 42 | [Discuss Internal services footer on GitHub](https://github.com/dwp/design-system-community-backlog/discussions/90) 43 | 44 | -------------------------------------------------------------------------------- /app/views/components/internal-services-footer/examples/default/index.html: -------------------------------------------------------------------------------- 1 | {% extends "code.html" %} 2 | 3 | {% set pageTitle = "Internal Services Footer" %} 4 | 5 | {% block pageContent %} 6 | {% include './template.html' %} 7 | {% endblock %} -------------------------------------------------------------------------------- /app/views/components/internal-services-footer/examples/default/template.html: -------------------------------------------------------------------------------- 1 | {% from "internal-services-footer/macro.njk" import dwpFooter %} 2 | 3 | {{ dwpFooter({ 4 | navigation: [ 5 | { 6 | title: "Two column list", 7 | width: "two-thirds", 8 | columns: 2, 9 | items: [ 10 | { 11 | text: "Item 1", 12 | href: "#1" 13 | }, 14 | { 15 | text: "Item 2", 16 | href: "#2" 17 | }, 18 | { 19 | text: "Item 3", 20 | href: "#3" 21 | }, 22 | { 23 | text: "Item 4", 24 | href: "#4" 25 | }, 26 | { 27 | text: "Item 5", 28 | href: "#5" 29 | }, 30 | { 31 | text: "Item 6", 32 | href: "#6" 33 | } 34 | ] 35 | }, 36 | { 37 | title: "One column list", 38 | width: "one-third", 39 | items: [ 40 | { 41 | text: "Item 1", 42 | href: "#1" 43 | }, 44 | { 45 | text: "Item 2", 46 | href: "#2" 47 | }, 48 | { 49 | text: "Item 3", 50 | href: "#3" 51 | } 52 | ] 53 | } 54 | ] 55 | }) }} 56 | -------------------------------------------------------------------------------- /app/views/components/internal-services-footer/examples/meta-links/index.html: -------------------------------------------------------------------------------- 1 | {% extends "code.html" %} 2 | 3 | {% set pageTitle = "Internal Services Footer" %} 4 | 5 | {% block pageContent %} 6 | {% include './template.html' %} 7 | {% endblock %} -------------------------------------------------------------------------------- /app/views/components/internal-services-footer/examples/meta-links/template.html: -------------------------------------------------------------------------------- 1 | {% from "internal-services-footer/macro.njk" import dwpFooter %} 2 | 3 | {{ dwpFooter({ 4 | meta: { 5 | visuallyHiddenTitle: "Meta links", 6 | items: [ 7 | { 8 | href: "#1", 9 | text: "Item 1" 10 | }, 11 | { 12 | href: "#2", 13 | text: "Item 2" 14 | }, 15 | { 16 | href: "#3", 17 | text: "Item 3" 18 | } 19 | ] 20 | } 21 | }) }} 22 | -------------------------------------------------------------------------------- /app/views/components/internal-services-footer/examples/nav-and-links/index.html: -------------------------------------------------------------------------------- 1 | {% extends "code.html" %} 2 | 3 | {% set pageTitle = "Internal Services Footer" %} 4 | 5 | {% block pageContent %} 6 | {% include './template.html' %} 7 | {% endblock %} -------------------------------------------------------------------------------- /app/views/components/internal-services-footer/examples/nav-and-links/template.html: -------------------------------------------------------------------------------- 1 | {% from "internal-services-footer/macro.njk" import dwpFooter %} 2 | 3 | {{ dwpFooter({ 4 | navigation: [ 5 | { 6 | title: "Two column list", 7 | width: "two-thirds", 8 | columns: 2, 9 | items: [ 10 | { 11 | text: "Item 1", 12 | href: "#1" 13 | }, 14 | { 15 | text: "Item 2", 16 | href: "#2" 17 | }, 18 | { 19 | text: "Item 3", 20 | href: "#3" 21 | }, 22 | { 23 | text: "Item 4", 24 | href: "#4" 25 | }, 26 | { 27 | text: "Item 5", 28 | href: "#5" 29 | }, 30 | { 31 | text: "Item 6", 32 | href: "#6" 33 | } 34 | ] 35 | }, 36 | { 37 | title: "One column list", 38 | width: "one-third", 39 | items: [ 40 | { 41 | text: "Item 1", 42 | href: "#1" 43 | }, 44 | { 45 | text: "Item 2", 46 | href: "#2" 47 | }, 48 | { 49 | text: "Item 3", 50 | href: "#3" 51 | } 52 | ] 53 | } 54 | ], 55 | meta: { 56 | visuallyHiddenTitle: "Meta links", 57 | items: [ 58 | { 59 | href: "#1", 60 | text: "Item 1" 61 | }, 62 | { 63 | href: "#2", 64 | text: "Item 2" 65 | }, 66 | { 67 | href: "#3", 68 | text: "Item 3" 69 | } 70 | ], 71 | text: "Plain text item" 72 | } 73 | }) }} 74 | -------------------------------------------------------------------------------- /app/views/components/internal-services-footer/index.html: -------------------------------------------------------------------------------- 1 | {% extends "sidebar-width.html" %} 2 | 3 | {% set sectionId = "components" %} 4 | {% set pageTitle = "Internal services footer" %} 5 | {% set pageId = "internal-services-footer" %} 6 | 7 | {% block pageContent %} 8 |Use this design system to make your service consistent with DWP services. Learn from the research and experience of other service teams and avoid repeating work that’s already been done.
12 |Components are reusable parts of the user interface that have been made to support a variety of applications.
23 |Patterns are best practice design solutions for specific user-focused tasks and page types.
33 |43 | The DWP Design System is maintained by the DWP Design System team. Anyone can contribute to it by proposing new components or patterns and sharing their research and findings.
44 |See all the patterns in the backlog
17 | {% endblock %} 18 | -------------------------------------------------------------------------------- /app/views/patterns/make-a-declaration/README.md.njk: -------------------------------------------------------------------------------- 1 | Help users to tell you that they have understood or agree to something before they submit an application or an online form. This is known as a ‘declaration’. 2 | 3 | {{dsExample({ 4 | section: 'patterns', 5 | name: 'make-a-declaration', 6 | description: 'Declaration pattern', 7 | example: 'default', 8 | height: 454 9 | })}} 10 | 11 | ## When to use this pattern 12 | 13 | You should use the declaration pattern when you need a user to confirm that they have understood the information they have been given or you need them to agree to something. 14 | 15 | You should use this pattern if there are significant consequences to the user if they provide false information when using your service. 16 | 17 | It should also be used if using your service could alter the user's quality of life. For example, if applying for a benefit might reduce other support they may be receiving. 18 | 19 | 20 | ## When not to use this pattern 21 | 22 | Do not use this pattern to give users complex or complicated information about policy or legislation. 23 | 24 | ## How it works 25 | 26 | The content should be clear and concise. The declaration should be tailored to the service and include information about what will happen if the user makes a false declaration. 27 | 28 | 29 | ## Research on this pattern 30 | This pattern has been used in a number of DWP services. 31 | 32 | The pattern has been amended by some services to: 33 | 34 |6 | By sending the application you agree that the information you have given is complete and correct. 7 | If you deliberately give the wrong or incomplete information, or you do not report any changes, you may: 8 |
9 |We will delete your answers if you do not do anything for 20 minutes and you will have to start again. This is to protect your information.
6 |We have deleted your answers because you did not do anything for 20 minutes. This is to protect your information.
6 |You will need to start again.
7 |You have been signed out and any information you have not saved has been deleted because you did not do anything for 20 minutes. This is to protect your information.
6 |We will delete your answers if you do not continue in the next 2 minutes. This is to protect your information.
10 |We have reset your application because you did not do anything for 30 minutes. We did this to keep your information secure.
18 | 19 |20 | Start application again 21 |
22 |If you don’t want to start again, you can return to GOV.UK.
23 | 24 |Find out if you can apply for a benefit
11 | 12 |This service is also available in Welsh (Cymraeg).
13 | 14 | 15 | Start 16 | 19 | 20 |