diff --git a/CHANGELOG.md b/CHANGELOG.md index 5f5f93d03..442e9ad35 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,18 @@ and this project adheres to [Semantic Versioning](http://semver.org/). For compatibility information see `govukFrontendVersion` and `hmrcFrontendVersion` in [LibDependencies](project/LibDependencies.scala) +## [9.6.0] - 2024-04-10 + +### Changed + +- Release new version of play-frontend-hmrc that includes govuk-frontend 5.3.0 +- Added ADR for [deferring the inclusion of the password field](./docs/maintainers/adr/0021-defer-inclusion-of-password-field.md) from govuk-frontend v5.3.0 + +### Compatible with + +- [hmrc/hmrc-frontend v6.15.0](https://github.com/hmrc/hmrc-frontend/releases/tag/v6.15.0) +- [alphagov/govuk-frontend v5.3.0](https://github.com/alphagov/govuk-frontend/releases/tag/v5.3.0) + ## [9.5.0] - 2024-04-3 ### Changed diff --git a/docs/maintainers/adr/0021-defer-inclusion-of-password-field.md b/docs/maintainers/adr/0021-defer-inclusion-of-password-field.md new file mode 100644 index 000000000..1b58aa20b --- /dev/null +++ b/docs/maintainers/adr/0021-defer-inclusion-of-password-field.md @@ -0,0 +1,50 @@ +# Defer Inclusion of Password Field from govuk-frontend v5.3.0 + +* Status: accepted +* Date: 2024-08-04 + +## Context and Problem Statement + +With the release of govuk-frontend v5.3.0, which includes a password field, we are considering whether to integrate this feature into our frontend library. Given that authentication for most services is handled by a central service (e.g., GG or the upcoming OLFG), the need for a library component for password fields may not be widespread. There are also considerations around the engineering cost of creating and maintaining such a component. + +## Decision Drivers + +* Centralized authentication services reducing the need for a password field component +* Engineering cost of maintenance and development +* Potential future demand for this component + +## Considered Options + +* Immediately include the password field feature from govuk-frontend v5.3.0 +* Defer the inclusion of the password field feature until there is a demonstrated need + +## Decision Outcome + +Chosen option: "Defer the inclusion of the password field feature until there is a demonstrated need", because it allows us to focus on components with a clear demand and reduces the maintenance burden. This decision is reversible, and we remain open to revisiting it should a significant need for this component arise from our services. + +### Positive Consequences + +* Keeps the library focused on widely used components +* Reduces unnecessary maintenance and development work +* Flexible approach that can adapt to future demands + +### Negative Consequences + +* Teams needing the password field immediately may have to implement their own solutions + +## Pros and Cons of the Options + +### Immediately include the password field feature + +* Good, because it provides immediate feature completeness. +* Bad, because it likely adds an unused feature for most teams, increasing maintenance overhead. + +### Defer the inclusion of the password field feature + +* Good, because it aligns our resources with current needs and reduces overhead. +* Good, because it leaves room to adapt based on future demand. +* Bad, because teams with immediate needs must find alternative solutions. + +## Links + +* [govuk-frontend v5.3.0 Release Notes](https://github.com/alphagov/govuk-frontend/releases/tag/v5.3.0) \ No newline at end of file diff --git a/docs/maintainers/adr/index.md b/docs/maintainers/adr/index.md index 3b43dcae9..2e8163565 100644 --- a/docs/maintainers/adr/index.md +++ b/docs/maintainers/adr/index.md @@ -22,6 +22,7 @@ * [ADR-0018](0018-help-teams-implement-new-date-guidance.md) - Help teams implement new date guidance * [ADR-0019](0019-add-welsh-language-support-to-govuk-accessible-autocomplete.md) - Add Welsh language support to the GOVUK accessible autocomplete wrapper * [ADR-0020](0020-reduce-support-for-internet-explorer.md) - Reduce support for Internet Explorer +* [ADR-0021](0021-defer-inclusion-of-password-field.md) - Defer Inclusion of Password Field from govuk-frontend v5.3.0 diff --git a/play-frontend-hmrc-play-30/src/main/scala/uk/gov/hmrc/govukfrontend/views/Aliases.scala b/play-frontend-hmrc-play-30/src/main/scala/uk/gov/hmrc/govukfrontend/views/Aliases.scala index 0adf9c0a5..f6e76d41a 100644 --- a/play-frontend-hmrc-play-30/src/main/scala/uk/gov/hmrc/govukfrontend/views/Aliases.scala +++ b/play-frontend-hmrc-play-30/src/main/scala/uk/gov/hmrc/govukfrontend/views/Aliases.scala @@ -214,6 +214,12 @@ trait Aliases { type CookieBanner = viewmodels.cookiebanner.CookieBanner val CookieBanner = viewmodels.cookiebanner.CookieBanner + type Message = viewmodels.cookiebanner.Message + val Message = viewmodels.cookiebanner.Message + + type Action = viewmodels.cookiebanner.Action + val Action = viewmodels.cookiebanner.Action + type PageLayout = viewmodels.pagelayout.PageLayout val PageLayout = viewmodels.pagelayout.PageLayout diff --git a/play-frontend-hmrc-play-30/src/main/scala/uk/gov/hmrc/govukfrontend/views/Utils.scala b/play-frontend-hmrc-play-30/src/main/scala/uk/gov/hmrc/govukfrontend/views/Utils.scala index aeec0ba85..068225567 100644 --- a/play-frontend-hmrc-play-30/src/main/scala/uk/gov/hmrc/govukfrontend/views/Utils.scala +++ b/play-frontend-hmrc-play-30/src/main/scala/uk/gov/hmrc/govukfrontend/views/Utils.scala @@ -33,13 +33,6 @@ trait Utils extends UtilsSupport { .map(p => s"$p/$file") .getOrElse(uk.gov.hmrc.hmrcfrontend.controllers.routes.Assets.at(s"govuk/$file").url) - private[views] def govukPluralisedI18nAttributes( - translationKey: String, - pluralForms: Option[Map[String, String]] - ): immutable.Iterable[Html] = - pluralForms.getOrElse(Map.empty).map { case (k, v) => - Html(s"""data-i18n.$translationKey.${HtmlFormat.escape(k)}="${HtmlFormat.escape(v)}" """) - } } object Utils extends Utils diff --git a/play-frontend-hmrc-play-30/src/main/scala/uk/gov/hmrc/govukfrontend/views/viewmodels/FormGroup.scala b/play-frontend-hmrc-play-30/src/main/scala/uk/gov/hmrc/govukfrontend/views/viewmodels/FormGroup.scala index 8daffb37a..ebbaa2638 100644 --- a/play-frontend-hmrc-play-30/src/main/scala/uk/gov/hmrc/govukfrontend/views/viewmodels/FormGroup.scala +++ b/play-frontend-hmrc-play-30/src/main/scala/uk/gov/hmrc/govukfrontend/views/viewmodels/FormGroup.scala @@ -18,10 +18,12 @@ package uk.gov.hmrc.govukfrontend.views.viewmodels import play.api.libs.functional.syntax._ import play.api.libs.json._ +import uk.gov.hmrc.govukfrontend.views.viewmodels.content.Content case class FormGroup( classes: Option[String] = None, - attributes: Map[String, String] = Map.empty + attributes: Map[String, String] = Map.empty, + afterInput: Option[Content] = None ) object FormGroup { @@ -31,13 +33,15 @@ object FormGroup { implicit def jsonReads: Reads[FormGroup] = ( (__ \ "classes").readNullable[String] and - (__ \ "attributes").readWithDefault[Map[String, String]](Map.empty) + (__ \ "attributes").readWithDefault[Map[String, String]](Map.empty) and + (__ \ "afterInput").readNullable[Content] )(FormGroup.apply _) implicit def jsonWrites: OWrites[FormGroup] = ( (__ \ "classes").writeNullable[String] and - (__ \ "attributes").write[Map[String, String]] + (__ \ "attributes").write[Map[String, String]] and + (__ \ "afterInput").writeNullable[Content] )(unlift(FormGroup.unapply)) } diff --git a/play-frontend-hmrc-play-30/src/main/scala/uk/gov/hmrc/govukfrontend/views/viewmodels/input/Input.scala b/play-frontend-hmrc-play-30/src/main/scala/uk/gov/hmrc/govukfrontend/views/viewmodels/input/Input.scala index c1a3a3b01..d07485020 100644 --- a/play-frontend-hmrc-play-30/src/main/scala/uk/gov/hmrc/govukfrontend/views/viewmodels/input/Input.scala +++ b/play-frontend-hmrc-play-30/src/main/scala/uk/gov/hmrc/govukfrontend/views/viewmodels/input/Input.scala @@ -43,6 +43,8 @@ import uk.gov.hmrc.govukfrontend.views.viewmodels.label.Label * @param prefix optional content to display immediately before the `input` * @param suffix optional content to display immediately after the `input` * @param disabled optional `disabled` attribute for the `input` + * @param autocapitalize optional `autocapitalize` attribute for the `input` + * @param inputWrapper additional CSS classes/attributes to apply to the input wrapper */ case class Input( id: String = "", @@ -62,7 +64,9 @@ case class Input( spellcheck: Option[Boolean] = None, prefix: Option[PrefixOrSuffix] = None, suffix: Option[PrefixOrSuffix] = None, - disabled: Option[Boolean] = None + disabled: Option[Boolean] = None, + autocapitalize: Option[String] = None, + inputWrapper: InputWrapper = InputWrapper.empty ) object Input { @@ -88,7 +92,9 @@ object Input { (__ \ "spellcheck").readNullable[Boolean] and (__ \ "prefix").readNullable[PrefixOrSuffix] and (__ \ "suffix").readNullable[PrefixOrSuffix] and - (__ \ "disabled").readNullable[Boolean] + (__ \ "disabled").readNullable[Boolean] and + (__ \ "autocapitalize").readNullable[String] and + (__ \ "inputWrapper").readWithDefault[InputWrapper](defaultObject.inputWrapper) )(Input.apply _) implicit def jsonWrites: OWrites[Input] = @@ -110,7 +116,9 @@ object Input { (__ \ "spellcheck").writeNullable[Boolean] and (__ \ "prefix").writeNullable[PrefixOrSuffix] and (__ \ "suffix").writeNullable[PrefixOrSuffix] and - (__ \ "disabled").writeNullable[Boolean] + (__ \ "disabled").writeNullable[Boolean] and + (__ \ "autocapitalize").writeNullable[String] and + (__ \ "inputWrapper").write[InputWrapper] )(unlift(Input.unapply)) } diff --git a/play-frontend-hmrc-play-30/src/main/scala/uk/gov/hmrc/govukfrontend/views/viewmodels/input/InputWrapper.scala b/play-frontend-hmrc-play-30/src/main/scala/uk/gov/hmrc/govukfrontend/views/viewmodels/input/InputWrapper.scala new file mode 100644 index 000000000..770e6da0c --- /dev/null +++ b/play-frontend-hmrc-play-30/src/main/scala/uk/gov/hmrc/govukfrontend/views/viewmodels/input/InputWrapper.scala @@ -0,0 +1,43 @@ +/* + * Copyright 2024 HM Revenue & Customs + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package uk.gov.hmrc.govukfrontend.views.viewmodels.input + +import play.api.libs.functional.syntax._ +import play.api.libs.json._ + +case class InputWrapper( + classes: Option[String] = None, + attributes: Map[String, String] = Map.empty +) + +object InputWrapper { + + val empty: InputWrapper = InputWrapper() + + implicit def jsonReads: Reads[InputWrapper] = + ( + (__ \ "classes").readNullable[String] and + (__ \ "attributes").readWithDefault[Map[String, String]](Map.empty) + )(InputWrapper.apply _) + + implicit def jsonWrites: OWrites[InputWrapper] = + ( + (__ \ "classes").writeNullable[String] and + (__ \ "attributes").write[Map[String, String]] + )(unlift(InputWrapper.unapply)) + +} diff --git a/play-frontend-hmrc-play-30/src/main/twirl/uk/gov/hmrc/govukfrontend/views/components/FixedWidthPageLayout.scala.html b/play-frontend-hmrc-play-30/src/main/twirl/uk/gov/hmrc/govukfrontend/views/components/FixedWidthPageLayout.scala.html index 642127167..63f438a85 100644 --- a/play-frontend-hmrc-play-30/src/main/twirl/uk/gov/hmrc/govukfrontend/views/components/FixedWidthPageLayout.scala.html +++ b/play-frontend-hmrc-play-30/src/main/twirl/uk/gov/hmrc/govukfrontend/views/components/FixedWidthPageLayout.scala.html @@ -24,7 +24,7 @@
@beforeContentBlock -
lang="@mainLang"}> +
lang="@mainLang"}> @contentBlock
\ No newline at end of file diff --git a/play-frontend-hmrc-play-30/src/main/twirl/uk/gov/hmrc/govukfrontend/views/components/GovukCharacterCount.scala.html b/play-frontend-hmrc-play-30/src/main/twirl/uk/gov/hmrc/govukfrontend/views/components/GovukCharacterCount.scala.html index c3369d62d..e4825a26b 100644 --- a/play-frontend-hmrc-play-30/src/main/twirl/uk/gov/hmrc/govukfrontend/views/components/GovukCharacterCount.scala.html +++ b/play-frontend-hmrc-play-30/src/main/twirl/uk/gov/hmrc/govukfrontend/views/components/GovukCharacterCount.scala.html @@ -15,38 +15,36 @@ *@ @import uk.gov.hmrc.govukfrontend.views.html.components._ +@import scala.collection.immutable.ListMap @this(govukTextarea: GovukTextarea, govukHint: GovukHint) + @(params: CharacterCount) @import params._ @require(name.nonEmpty && id.nonEmpty, "name and id should be non-empty") -@attrs = { - @maxLength.filter(_ > 0).map {value => data-maxlength="@value"} - @threshold.filter(_ > 0).map {value => data-threshold="@value"} - @maxWords.filter(_ > 0).map {value => data-maxwords="@value"} - - @govukPluralisedI18nAttributes("characters-under-limit", charactersUnderLimitText) - @charactersAtLimitText match { - case Some(v) => { data-i18n.characters-at-limit="@{v}" } - case None => {} - } - @govukPluralisedI18nAttributes("characters-over-limit", charactersOverLimitText) - @govukPluralisedI18nAttributes("words-under-limit", wordsUnderLimitText) - @wordsAtLimitText match { - case Some(v) => { data-i18n.words-at-limit="@{v}" } - case None => {} - } - @govukPluralisedI18nAttributes("words-over-limit", wordsOverLimitText) +@govukPluralisedI18nAttributes(translationKey: String, pluralForms: Option[Map[String, String]]) = @{ + pluralForms.getOrElse(Map.empty).map { case (key, value) => + s"data-i18n.$translationKey.$key" -> value + } +} - @if(maxLength.isEmpty && maxWords.isEmpty) { - @textareaDescriptionText match { - case Some(v) => { data-i18n.textarea-description.other="@{v}" } - case None => {} - } - } +@dataAttributes = @{ + val maybeDataAttributes = ListMap( + "data-module" -> "govuk-character-count", + "data-maxlength" -> maxLength.filter(_ > 0).map(_.toString).getOrElse(""), + "data-threshold" -> threshold.filter(_ > 0).map(_.toString).getOrElse(""), + "data-maxwords" -> maxWords.filter(_ > 0).map(_.toString).getOrElse(""), + ) ++ govukPluralisedI18nAttributes("characters-under-limit", charactersUnderLimitText) ++ Map( + "data-i18n.characters-at-limit" -> charactersAtLimitText.getOrElse("") + ) ++ govukPluralisedI18nAttributes("characters-over-limit", charactersOverLimitText) ++ govukPluralisedI18nAttributes("words-under-limit", wordsUnderLimitText) ++ Map( + "data-i18n.words-at-limit" -> wordsAtLimitText.getOrElse("") + ) ++ govukPluralisedI18nAttributes("words-over-limit", wordsOverLimitText) ++ Map( + "data-i18n.textarea-description.other" -> textareaDescriptionText.filter(_ => maxLength.isEmpty && maxWords.isEmpty).getOrElse("") + ) + maybeDataAttributes.filter { case (_, value) => value.nonEmpty } } @customTextArea = @{ @@ -61,8 +59,19 @@ } } -
- @govukTextarea(Textarea( +@characterCountMessage = { + @govukHint(Hint(id=Some(id+"-info"), + classes = toClasses("govuk-character-count__message", if (countMessageClasses.isEmpty) "" else s" $countMessageClasses"), + content = customTextArea + )) +} + +@characterCountMessagePlusOptionalAfterInput = { + @characterCountMessage + @formGroup.afterInput.map(_.asHtml) +} + +@govukTextarea(Textarea( id = id, name = name, describedBy = Some(s"${id}-info"), @@ -71,12 +80,11 @@ label = label.copy(forAttr = Some(id)), hint = hint, errorMessage = errorMessage, - formGroup = formGroup, - classes = toClasses("govuk-js-character-count", if (classes.isEmpty) "" else s" ${classes}"), + formGroup = formGroup.copy( + classes = Some(toClasses("govuk-character-count", formGroup.classes.getOrElse(""))), + attributes = dataAttributes ++ formGroup.attributes, + afterInput = Some(HtmlContent(characterCountMessagePlusOptionalAfterInput)) + ), + classes = toClasses("govuk-js-character-count", if (classes.isEmpty) "" else s" $classes"), attributes = attributes - )) - @govukHint(Hint(id=Some(id+"-info"), - classes = toClasses("govuk-character-count__message", if (countMessageClasses.isEmpty) "" else s" $countMessageClasses"), - content = customTextArea - )) -
+)) diff --git a/play-frontend-hmrc-play-30/src/main/twirl/uk/gov/hmrc/govukfrontend/views/components/GovukFooter.scala.html b/play-frontend-hmrc-play-30/src/main/twirl/uk/gov/hmrc/govukfrontend/views/components/GovukFooter.scala.html index 0f8ef3156..f3c3958e3 100644 --- a/play-frontend-hmrc-play-30/src/main/twirl/uk/gov/hmrc/govukfrontend/views/components/GovukFooter.scala.html +++ b/play-frontend-hmrc-play-30/src/main/twirl/uk/gov/hmrc/govukfrontend/views/components/GovukFooter.scala.html @@ -20,7 +20,7 @@ @(params: Footer = Footer()) @import params._ -