Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create password input component #4442

Merged
merged 46 commits into from
Mar 15, 2024
Merged
Show file tree
Hide file tree
Changes from 33 commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
35225f1
Prototype password input component
querkmachine Aug 30, 2023
ef6b1cf
Rename translation strings, implement data attribute config
querkmachine Nov 7, 2023
ea53ddd
Style refinements
querkmachine Jan 12, 2024
33a48cb
Resolve Typescript complaints
querkmachine Jan 12, 2024
38f8834
Hide user agent password reveal function in Microsoft Edge
querkmachine Feb 1, 2024
14a1b4a
Rework password input to use new beforeInput/afterInput govukInput op…
querkmachine Feb 9, 2024
335926a
Reset component state on pageshow event
querkmachine Feb 12, 2024
0f77224
Add Nunjucks documentation
querkmachine Feb 12, 2024
1f9d107
Minor attribute fixes
querkmachine Feb 12, 2024
dc89d72
Author template tests for new and updated functionality
querkmachine Feb 12, 2024
8524793
Match `attributesHtml` formatting to character count
colinrotherham Feb 13, 2024
436a555
Ensure user `formGroup` params are preserved
colinrotherham Feb 13, 2024
85f7e76
Indent HTML for Password input
colinrotherham Feb 13, 2024
e9c64cf
Fix param `disableFormSubmitCheck: false` setting true
colinrotherham Feb 13, 2024
da49337
Only assign to `this.$xxx` after instanceof checks
colinrotherham Feb 13, 2024
5915a66
Remove conditional checks from elements that always exist
colinrotherham Feb 13, 2024
2a056a4
Refactor code that creates and inserts screen reader status
querkmachine Feb 15, 2024
028a282
Assume Password input `$module` might be null
colinrotherham Feb 29, 2024
7a47001
Remove unused Password input schema
colinrotherham Feb 29, 2024
022b000
Add missing param description
colinrotherham Feb 29, 2024
b223bfd
Assign screen reader status after setup
colinrotherham Feb 29, 2024
800447d
Skip initial status text update yet let `hide()` do it
colinrotherham Feb 29, 2024
e858b43
Consolidate setup code
colinrotherham Feb 29, 2024
baf4927
Ignore repetitive state changes unless changed
colinrotherham Feb 29, 2024
3e9792f
Hide the password if the page is restored from cache
querkmachine Mar 1, 2024
f28aa29
Remove disableFormSubmitCheck option
querkmachine Mar 4, 2024
b48f702
Update review app example to use password input component
querkmachine Mar 4, 2024
77f00c3
Fix failing test around hidden attribute
querkmachine Mar 4, 2024
d0f5c45
Add "sign in" full-page example to review app
querkmachine Mar 7, 2024
9b716c5
Fix incorrect translation key being created
querkmachine Mar 8, 2024
ca304eb
Add i18n data-attributes test
querkmachine Mar 8, 2024
c902abc
Make status announcement assertive
querkmachine Mar 11, 2024
fb86ccb
Updates to account for changes to main
querkmachine Mar 12, 2024
d3d2215
Add Puppeteer tests for Password input
querkmachine Feb 13, 2024
5aca96f
Add test for insertion of `aria-live="assertive"` on status element
querkmachine Mar 11, 2024
b1cfb89
Change toEqual -> toBe
querkmachine Mar 11, 2024
770a13c
Update selector variable names
querkmachine Mar 14, 2024
8f349d7
Add additional type checks on the input and button
querkmachine Mar 14, 2024
bf8d6c8
Refactor tests to use $eval
querkmachine Mar 14, 2024
6601ebe
Condense multiple toggle tests together
querkmachine Mar 14, 2024
80d33b4
Set aria-live on component initialisation
querkmachine Mar 14, 2024
5ee9365
Add tests for translations
querkmachine Mar 14, 2024
5cd0c05
Update aria-live tests to account for upstream updates
querkmachine Mar 14, 2024
812387f
Merge pull request #4763 from alphagov/show-hide-password-component-p…
querkmachine Mar 15, 2024
07d5621
Reorder tests
querkmachine Mar 15, 2024
2b5d976
Add changelog entry
querkmachine Mar 15, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ describe('Full page examples (with form submit)', () => {
title: 'Passport details',
path: '/full-page-examples/passport-details'
},
{
title: 'Sign in to a service',
path: '/full-page-examples/sign-in'
},
{
title: 'Update your account details',
path: '/full-page-examples/update-your-account-details'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export { default as haveYouChangedYourName } from './have-you-changed-your-name/
export { default as feedback } from './feedback/index.mjs'
export { default as howDoYouWantToSignIn } from './how-do-you-want-to-sign-in/index.mjs'
export { default as search } from './search/index.mjs'
export { default as signIn } from './sign-in/index.mjs'
export { default as passportDetails } from './passport-details/index.mjs'
export { default as updateYourAccountDetails } from './update-your-account-details/index.mjs'
export { default as uploadYourPhoto } from './upload-your-photo/index.mjs'
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{% extends "layouts/full-page-example.njk" %}

{% from "govuk/components/panel/macro.njk" import govukPanel %}

{% set pageTitle = "Logged in successfully" %}
{% block pageTitle %}{{ pageTitle }} - GOV.UK{% endblock %}

{% block content %}
<div class="govuk-grid-row">
<div class="govuk-grid-column-two-thirds">
{{ govukPanel({
titleText: pageTitle
}) }}
</div>
</div>
{% endblock %}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import express from 'express'
import { body, matchedData, validationResult } from 'express-validator'

import { formatValidationErrors } from '../../../utils.mjs'

const router = express.Router()

router.post(
'/sign-in',

body('email')
.notEmpty()
.withMessage('Enter your email address')
.isEmail()
.withMessage(
'Enter an email address in the correct format, like name@example.com'
),

body('password').notEmpty().withMessage('Enter your password'),

(req, res) => {
const { example } = res.locals

const viewPath = `./full-page-examples/${example.path}`
const errors = formatValidationErrors(validationResult(req))

if (!errors) {
return res.redirect(303, `./${example.path}/confirm`)
}

res.render(`${viewPath}/index`, {
errors,
errorSummary: Object.values(errors),
values: matchedData(req, { onlyValidData: false }) // In production this should sanitized.
})
}
)

export default router
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
---
title: Sign in to a service
name: Sign in to a service
scenario: |
As part of an online service, you have to sign in before accessing it.

Things to try:

1. Intentionally avoid answering the questions before continuing to the next page.
---

{% extends "layouts/full-page-example.njk" %}

{% from "govuk/components/back-link/macro.njk" import govukBackLink %}
{% from "govuk/components/error-summary/macro.njk" import govukErrorSummary %}
{% from "govuk/components/input/macro.njk" import govukInput %}
{% from "govuk/components/password-input/macro.njk" import govukPasswordInput %}
{% from "govuk/components/checkboxes/macro.njk" import govukCheckboxes %}
{% from "govuk/components/button/macro.njk" import govukButton %}

{% set pageTitle = example.title %}
{% block pageTitle %}{{ "Error: " if errorSummary | length }}{{ pageTitle }} - GOV.UK{% endblock %}

{% block beforeContent %}
{{ govukBackLink({
text: "Back"
}) }}
{% endblock %}

{% block content %}
<div class="govuk-grid-row">
<div class="govuk-grid-column-two-thirds">
{% if errorSummary | length %}
{{ govukErrorSummary({
titleText: "There is a problem",
errorList: errorSummary
}) }}
{% endif %}

<h1 class="govuk-heading-xl">{{ pageTitle }}</h1>

<p class="govuk-body">You'll first need to <a class="govuk-link" href="#">create an account</a> if you haven't already. You can also <a class="govuk-link" href="#">reset your password</a> if you can't remember it.</p>

<form method="post" novalidate>

{{ govukInput({
label: {
text: "Email address",
classes: "govuk-label--m"
},
type: "email",
id: "email",
name: "email",
value: values["email"],
errorMessage: errors["email"],
autocomplete: "email",
spellcheck: false
}) }}

{{ govukPasswordInput({
label: {
text: "Password",
classes: "govuk-label--m"
},
id: "password",
name: "password",
value: values["password"],
errorMessage: errors["password"],
autocomplete: "current-password"
}) }}

{{ govukCheckboxes({
name: "remember-me",
classes: "govuk-checkboxes--small",
items: [
{
value: "true",
text: "Keep me signed in on this device"
}
]
}) }}

{{ govukButton({
text: "Sign in"
}) }}

</form>
</div>
</div>
{% endblock %}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ router.post(
'Enter an email address in the correct format, like name@example.com'
),

body('password').notEmpty().withMessage('Enter your password'),
body('password').notEmpty().withMessage('Enter a password'),

(req, res) => {
const { example } = res.locals
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ scenario: |
{% from "govuk/components/back-link/macro.njk" import govukBackLink %}
{% from "govuk/components/error-summary/macro.njk" import govukErrorSummary %}
{% from "govuk/components/input/macro.njk" import govukInput %}
{% from "govuk/components/password-input/macro.njk" import govukPasswordInput %}
{% from "govuk/components/button/macro.njk" import govukButton %}

{% set pageTitle = example.title %}
Expand Down Expand Up @@ -52,18 +53,16 @@ scenario: |
spellcheck: false
}) }}

{{ govukInput({
{{ govukPasswordInput({
label: {
text: "New password",
classes: "govuk-label--m"
},
type: "password",
id: "password",
name: "password",
value: values["password"],
errorMessage: errors["password"],
autocomplete: "new-password",
spellcheck: false
autocomplete: "new-password"
}) }}

{{ govukButton({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,10 @@ describe('GOV.UK Prototype Kit config', () => {
importFrom: 'govuk/components/panel/macro.njk',
macroName: 'govukPanel'
},
{
importFrom: 'govuk/components/password-input/macro.njk',
macroName: 'govukPasswordInput'
},
{
importFrom: 'govuk/components/phase-banner/macro.njk',
macroName: 'govukPhaseBanner'
Expand Down
4 changes: 3 additions & 1 deletion packages/govuk-frontend/src/govuk/all.jsdom.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ jest.mock(`./components/error-summary/error-summary.mjs`)
jest.mock(`./components/exit-this-page/exit-this-page.mjs`)
jest.mock(`./components/header/header.mjs`)
jest.mock(`./components/notification-banner/notification-banner.mjs`)
jest.mock(`./components/password-input/password-input.mjs`)
jest.mock(`./components/radios/radios.mjs`)
jest.mock(`./components/skip-link/skip-link.mjs`)
jest.mock(`./components/tabs/tabs.mjs`)
Expand All @@ -27,7 +28,8 @@ describe('initAll', () => {
'character-count',
'error-summary',
'exit-this-page',
'notification-banner'
'notification-banner',
'password-input'
]

afterEach(() => {
Expand Down
5 changes: 5 additions & 0 deletions packages/govuk-frontend/src/govuk/all.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { ErrorSummary } from './components/error-summary/error-summary.mjs'
import { ExitThisPage } from './components/exit-this-page/exit-this-page.mjs'
import { Header } from './components/header/header.mjs'
import { NotificationBanner } from './components/notification-banner/notification-banner.mjs'
import { PasswordInput } from './components/password-input/password-input.mjs'
import { Radios } from './components/radios/radios.mjs'
import { SkipLink } from './components/skip-link/skip-link.mjs'
import { Tabs } from './components/tabs/tabs.mjs'
Expand Down Expand Up @@ -41,6 +42,7 @@ function initAll(config) {
[ExitThisPage, config.exitThisPage],
[Header],
[NotificationBanner, config.notificationBanner],
[PasswordInput, config.passwordInput],
[Radios],
[SkipLink],
[Tabs]
Expand Down Expand Up @@ -81,6 +83,7 @@ export {
ExitThisPage,
Header,
NotificationBanner,
PasswordInput,
Radios,
SkipLink,
Tabs
Expand All @@ -96,6 +99,7 @@ export {
* @property {ErrorSummaryConfig} [errorSummary] - Error Summary config
* @property {ExitThisPageConfig} [exitThisPage] - Exit This Page config
* @property {NotificationBannerConfig} [notificationBanner] - Notification Banner config
* @property {PasswordInputConfig} [passwordInput] - Password input config
*/

/**
Expand All @@ -110,6 +114,7 @@ export {
* @typedef {import('./components/exit-this-page/exit-this-page.mjs').ExitThisPageConfig} ExitThisPageConfig
* @typedef {import('./components/exit-this-page/exit-this-page.mjs').ExitThisPageTranslations} ExitThisPageTranslations
* @typedef {import('./components/notification-banner/notification-banner.mjs').NotificationBannerConfig} NotificationBannerConfig
* @typedef {import('./components/password-input/password-input.mjs').PasswordInputConfig} PasswordInputConfig
*/

/**
Expand Down
1 change: 1 addition & 0 deletions packages/govuk-frontend/src/govuk/components/_all.scss
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
@import "notification-banner/index";
@import "pagination/index";
@import "panel/index";
@import "password-input/index";
@import "phase-banner/index";
@import "radios/index";
@import "select/index";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ describe('GOV.UK Frontend', () => {
'ExitThisPage',
'Header',
'NotificationBanner',
'PasswordInput',
'Radios',
'SkipLink',
'Tabs'
Expand Down
40 changes: 40 additions & 0 deletions packages/govuk-frontend/src/govuk/components/input/input.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,23 @@ params:
type: boolean
required: false
description: Optional field to enable or disable the `spellcheck` attribute on the input.
- name: autocapitalize
type: string
required: false
description: Optional field to enable or disable autocapitalisation of user input. See [autocapitalization](https://html.spec.whatwg.org/multipage/interaction.html#autocapitalization) for a full list of values that can be used.
- name: inputWrapper
type: object
required: false
description: If any of `prefix`, `suffix`, `formGroup.beforeInput` or `formGroup.afterInput` have a value, a wrapping element is added around the input and inserted content. This object allows you to customise that wrapping element.
params:
- name: classes
type: string
required: false
description: Classes to add to the wrapping element.
- name: attributes
type: object
required: false
description: HTML attributes (for example data attributes) to add to the wrapping element.
- name: attributes
type: object
required: false
Expand Down Expand Up @@ -279,6 +296,14 @@ examples:
name: spellcheck
type: text
spellcheck: false
- name: with autocapitalize turned off
options:
label:
text: Autocapitalize is turned off
id: input-with-autocapitalize-off
name: autocapitalize
type: text
autocapitalize: none

- name: with prefix
options:
Expand Down Expand Up @@ -522,3 +547,18 @@ examples:
html: <span>kg</span>
attributes:
data-attribute: value
- name: with customised input wrapper
hidden: true
options:
label:
text: Cost per item, in pounds
id: input-with-customised-input-wrapper
name: cost
inputWrapper:
classes: app-input-wrapper--custom-modifier
attributes:
data-attribute: value
prefix:
text: £
suffix:
text: per item
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
{%- if params.autocomplete %} autocomplete="{{ params.autocomplete }}"{% endif %}
{%- if params.pattern %} pattern="{{ params.pattern }}"{% endif %}
{%- if params.inputmode %} inputmode="{{ params.inputmode }}"{% endif %}
{%- if params.autocapitalize %} autocapitalize="{{ params.autocapitalize }}"{% endif %}
{{- govukAttributes(params.attributes) }}>
{%- endmacro -%}

Expand Down Expand Up @@ -65,7 +66,8 @@
{% endif %}

{%- if hasPrefix or hasSuffix or hasBeforeInput or hasAfterInput %}
<div class="govuk-input__wrapper">
<div class="govuk-input__wrapper {%- if params.inputWrapper.classes %} {{ params.inputWrapper.classes }}{% endif %}"
{{- govukAttributes(params.inputWrapper.attributes) }}>
{% if hasBeforeInput %}
{{- params.formGroup.beforeInput.html | safe | trim | indent(4, true) if params.formGroup.beforeInput.html else params.formGroup.beforeInput.text }}
{% endif %}
Expand Down