Skip to content

Commit

Permalink
Add password input component
Browse files Browse the repository at this point in the history
  • Loading branch information
AshGDS committed Sep 4, 2024
1 parent a6258f1 commit abece9f
Show file tree
Hide file tree
Showing 9 changed files with 185 additions and 1 deletion.
1 change: 1 addition & 0 deletions app/assets/javascripts/component_guide/application.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@
//= require ../govuk_publishing_components/dependencies
//= require ../govuk_publishing_components/components/accordion
//= require ../govuk_publishing_components/components/intervention
//= require ../govuk_publishing_components/components/password-input
//= require ../govuk_publishing_components/components/tabs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// This component relies on JavaScript from GOV.UK Frontend
// = require govuk/components/password-input/password-input.bundle.js
window.GOVUK = window.GOVUK || {}
window.GOVUK.Modules = window.GOVUK.Modules || {}
window.GOVUK.Modules.GovukPasswordInput = window.GOVUKFrontend.PasswordInput
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
@import "components/option-select";
@import "components/organisation-logo";
@import "components/panel";
@import "components/password-input";
@import "components/phase-banner";
@import "components/previous-and-next-navigation";
@import "components/print-link";
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
@import "govuk_publishing_components/individual_component_support";
@import "govuk/components/password-input/password-input";
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
<%
add_gem_component_stylesheet("password-input")

label_text ||= t("components.password_input.label")

error_text ||= nil
error_text_prefix ||= t("components.password_input.error_text_prefix")

shared_helper = GovukPublishingComponents::Presenters::SharedHelper.new(local_assigns)
component_helper = GovukPublishingComponents::Presenters::ComponentWrapperHelper.new(local_assigns)
component_helper.add_data_attribute({ module: "govuk-password-input" })
component_helper.add_class('govuk-form-group')
component_helper.add_class('govuk-form-group--error') if error_text
component_helper.add_class('govuk-password-input')
component_helper.add_class('gem-c-password-input')
component_helper.add_class(shared_helper.get_margin_bottom)

uid = SecureRandom.hex(4)

label_for = uid + '-password-input'

input_name = 'password'
input_id = uid + '-password-input'

aria_controls = uid + '-password-input'

input_classes = %w(govuk-input govuk-password-input__input govuk-js-password-input-input)

if error_text
label_for << '-with-error-message'
input_id << '-with-error-message'
input_name << '-input-with-error-message'
input_classes << 'govuk-input--error'
aria_controls << '-with-error-message'
paragraph_id = uid + '-password-input-with-error-message-error'
end

%>
<%= tag.div(**component_helper.all_attributes) do %>
<%= render "govuk_publishing_components/components/label", {
text: label_text,
html_for: label_for
} %>
<% if error_text %>
<p id="<%= paragraph_id %>" class="govuk-error-message">
<span class="govuk-visually-hidden"><%= error_text_prefix %>:</span> <%= error_text %>
</p>
<% end %>

<div class="govuk-input__wrapper govuk-password-input__wrapper">
<%= tag.input(
name: input_name,
type: "password",
class: input_classes,
id: input_id,
spellcheck: false,
autocomplete: "current-password",
autocapitalize: "none",
aria: {
describedby: paragraph_id
}) %>
<%= tag.button(
type: "button",
class: "govuk-button govuk-button--secondary govuk-password-input__toggle govuk-js-password-input-toggle",
data: {
module: "govuk-button"
},
hidden: true,
aria: {
controls: aria_controls,
label: t("components.password_input.button_aria_label")
}) do %>
<%= t("components.password_input.button") %>
<% end %>
</div>
<% end %>
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
name: Password input
description: The password input component helps users to create and enter passwords.
govuk_frontend_components:
- password-input

accessibility_criteria: |
The password input component must:
* accept focus
* be focusable with a keyboard
* be usable with a keyboard
* be usable with touch
* indicate when they have focus
* be recognisable as form input elements
* have correctly associated labels
* have the appropriate type of 'password'
* have an appropriate validation message if there was an error
* allow users to interact with any 'show password' button
* allow users to use `autocomplete` to securely create and enter passwords
* allow users to copy and paste into the password input
When CSS and / or JavaScript is unavailable, the component must:
* fallback to a regular input element, with the show/hide button hidden
uses_component_wrapper_helper: true

examples:
default:
data:
with_error:
description: If there is a validation error, passing error text will style the password input component with error styles, and semantically state that there was a validation error.
data:
error_text: Enter a password
with_custom_label_and_error_text:
description: For translations or other purposes, the text presented to the user in this component can be changed. Note that the error text prefix is hidden visually and used by assistive tools when there is an error. By default, the prefix is "Error".
data:
label_text: Secret number
error_text_prefix: Incompatible
error_text: 6 is scared of 7, so they can't be next to each other.
with_margin_bottom:
description: |
The component accepts a number for margin bottom from `0` to `9` (`0px` to `60px`) using the [GOV.UK Frontend spacing scale](https://design-system.service.gov.uk/styles/spacing/#the-responsive-spacing-scale). It defaults to having a margin bottom of `30px`.
data:
margin_bottom: 5
5 changes: 5 additions & 0 deletions config/locales/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,11 @@ en:
selected: selected
organisation_schema:
all_content_search_description: Find all content from %{organisation}
password_input:
label: "Password"
button: "Show"
button_aria_label: "Show password"
error_text_prefix: "Error"
previous_and_next_navigation:
next: Next
pagination: Pagination
Expand Down
47 changes: 47 additions & 0 deletions spec/components/password_input_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
require "rails_helper"

describe "Password Input", type: :view do
def component_name
"password_input"
end

before { allow(SecureRandom).to receive(:hex).and_return("1234") }

it "renders a password input component correctly by default" do
render_component({})
assert_select 'div.govuk-password-input[class~="govuk-form-group govuk-password-input gem-c-password-input govuk-!-margin-bottom-3"]'
assert_select "div.govuk-password-input[data-module=govuk-password-input]"
assert_select "div.govuk-password-input input.govuk-input.govuk-password-input__input.govuk-js-password-input-input"
assert_select "div.govuk-password-input input[name=password][type=password][autocomplete=current-password][autocapitalize=none][spellcheck=false][id='1234-password-input']"
assert_select "div.govuk-password-input label[for='1234-password-input']", "Password"
assert_select "div.govuk-password-input button[aria-controls='1234-password-input']", "Show"
assert_select "p#1234-password-input-with-error-message-error", false
assert_select "div.govuk-password-input input.govuk-input--error", false
assert_select "div.govuk-form-group--error", false
end

it "renders a password input with extra classes and a paragraph when error_text is passed" do
render_component({ error_text: "Password must contain at least 8 characters" })
assert_select "div.govuk-form-group--error"
assert_select "div.govuk-password-input label[for='1234-password-input-with-error-message']", "Password"
assert_select "div.govuk-password-input input.govuk-input--error[name=password-input-with-error-message]"
assert_select "div.govuk-password-input input.govuk-input--error[aria-describedby='1234-password-input-with-error-message-error']"
assert_select "div.govuk-password-input button[aria-controls='1234-password-input-with-error-message']", "Show"
assert_select "p#1234-password-input-with-error-message-error", "Error: Password must contain at least 8 characters"
end

it "renders a password input with custom text" do
render_component({
label_text: "Secret number",
error_text_prefix: "Incompatible",
error_text: "6 is scared of 7, so they can't be next to each other.",
})
assert_select "div.govuk-password-input label", "Secret number"
assert_select "p#1234-password-input-with-error-message-error", "Incompatible: 6 is scared of 7, so they can't be next to each other."
end

it "accepts margin_bottom values" do
render_component({ margin_bottom: 9 })
assert_select 'div.govuk-password-input[class~="govuk-form-group govuk-password-input gem-c-password-input govuk-!-margin-bottom-9"]'
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ def request
end

it "detect the total number of stylesheet paths" do
expect(get_component_css_paths.count).to eql(75)
expect(get_component_css_paths.count).to eql(76)
end

it "initialize empty asset helper" do
Expand Down

0 comments on commit abece9f

Please sign in to comment.