[SPIKE] Link variants through custom properties (selectors in govuk-link-style-*)#7247
Draft
romaricpascal wants to merge 3 commits into
Conversation
Makes link variants override `--govuk-link-colour`, `--govuk-link-hover-colour` and `--govuk-link-active-colour`, as well as include `govuk-link-style-no-visited-state` instead of redefining selectors. This not only avoids having each variant create selectors for each of the state, but removes the need to duplicate the `:focus` in each of them too, only switching the colours that need switching. It also allows to better define the relationships between the colours, explicitely saying that the active state is the same as the link colour, rather than duplicating the colours.
If the `govuk-link-style-<STYLE_NAME>` mixins only set the custom properties, the link style doesn't change in classes set on elements that are not also `.govuk-link`. For example, the Header's link, or the Error Summary's links would not have the correct styles. This is because, previously, the `govuk-link-style-<STYLE_NAME>` mixins were creating selectors for each of the link's state. To avoid a breaking change, we need to restore that, which we can do by applying `govuk-link-style-default` in all mixins. To avoid doubling the markup in a future PR, we separate: - applying the styles in `govuk-link-style...`, meant for use on link elements - themeing the links by applying custom properties, in a new `govuk-link-theme...` mixin
As link states now rely on custom properties, we can use them to adjust the colours of the links in the Service Navigation more easily. When not inverted, we no longer need a compound selector for adjusting the link colour. The `__service-name` element can set up the appropriate custom properties and let them cascade to the `__link` element it contains. When inverted, the Service Navigation itself can set up the right custom properties to style all links as text, configuring in one go: - the link of the Service Name - the links of the navigation itself - any link injected in slots, like links from a Language Switcher Because we need to set the custom properties on a parent, we need to extract a `govuk-link-theme-text` mixin to apply only the custom properties.
Stylesheets changes to npm packagediff --git a/packages/govuk-frontend/dist/govuk/govuk-frontend.min.css b/packages/govuk-frontend/dist/govuk/govuk-frontend.min.css
index ef495c34f..25f88b972 100644
--- a/packages/govuk-frontend/dist/govuk/govuk-frontend.min.css
+++ b/packages/govuk-frontend/dist/govuk/govuk-frontend.min.css
@@ -119,33 +119,81 @@
}
}
-.govuk-link--muted:link,
+.govuk-link--muted {
+ --govuk-link-visited-colour: var(--govuk-link-colour);
+ --govuk-link-colour: var(--govuk-secondary-text-colour, #484949);
+ --govuk-link-hover-colour: var(--govuk-text-colour, #0b0c0c);
+ --govuk-link-active-colour: var(--govuk-link-hover-colour)
+}
+
+.govuk-link--muted:link {
+ color: var(--govuk-link-colour, #1a65a6)
+}
+
.govuk-link--muted:visited {
- color: var(--govuk-secondary-text-colour, #484949)
+ color: var(--govuk-link-visited-colour, #54319f)
}
-.govuk-link--muted:active,
.govuk-link--muted:hover {
- color: var(--govuk-text-colour, #0b0c0c)
+ color: var(--govuk-link-hover-colour, #0f385c)
+}
+
+.govuk-link--muted:active {
+ color: var(--govuk-link-active-colour, #0b0c0c)
}
.govuk-link--muted:focus {
color: var(--govuk-focus-text-colour, #0b0c0c)
}
-.govuk-link--text-colour:active,
-.govuk-link--text-colour:link,
+.govuk-link--text-colour {
+ --govuk-link-visited-colour: var(--govuk-link-colour);
+ --govuk-link-colour: var(--govuk-text-colour, #0b0c0c);
+ --govuk-link-hover-colour: var(--govuk-link-colour);
+ --govuk-link-active-colour: var(--govuk-link-colour)
+}
+
+.govuk-link--text-colour:link {
+ color: var(--govuk-link-colour, #1a65a6)
+}
+
.govuk-link--text-colour:visited {
- color: var(--govuk-text-colour, #0b0c0c)
+ color: var(--govuk-link-visited-colour, #54319f)
+}
+
+.govuk-link--text-colour:hover {
+ color: var(--govuk-link-hover-colour, #0f385c)
+}
+
+.govuk-link--text-colour:active {
+ color: var(--govuk-link-active-colour, #0b0c0c)
}
.govuk-link--text-colour:focus {
color: var(--govuk-focus-text-colour, #0b0c0c)
}
-.govuk-link--inverse:link,
+.govuk-link--inverse {
+ --govuk-link-visited-colour: var(--govuk-link-colour);
+ --govuk-link-colour: var(--govuk-inverse-text-colour, #fff);
+ --govuk-link-hover-colour: var(--govuk-link-colour);
+ --govuk-link-active-colour: var(--govuk-link-colour)
+}
+
+.govuk-link--inverse:link {
+ color: var(--govuk-link-colour, #1a65a6)
+}
+
.govuk-link--inverse:visited {
- color: var(--govuk-inverse-text-colour, #fff)
+ color: var(--govuk-link-visited-colour, #54319f)
+}
+
+.govuk-link--inverse:hover {
+ color: var(--govuk-link-hover-colour, #0f385c)
+}
+
+.govuk-link--inverse:active {
+ color: var(--govuk-link-active-colour, #0b0c0c)
}
.govuk-link--inverse:focus {
@@ -156,11 +204,18 @@
text-decoration: none
}
-.govuk-link--no-visited-state:link,
-.govuk-link--no-visited-state:visited {
+.govuk-link--no-visited-state {
+ --govuk-link-visited-colour: var(--govuk-link-colour)
+}
+
+.govuk-link--no-visited-state:link {
color: var(--govuk-link-colour, #1a65a6)
}
+.govuk-link--no-visited-state:visited {
+ color: var(--govuk-link-visited-colour, #54319f)
+}
+
.govuk-link--no-visited-state:hover {
color: var(--govuk-link-hover-colour, #0f385c)
}
@@ -1423,6 +1478,10 @@
text-decoration: underline;
text-decoration-thickness: max(1px, .0625rem);
text-underline-offset: .1578em;
+ --govuk-link-visited-colour: var(--govuk-link-colour);
+ --govuk-link-colour: var(--govuk-text-colour, #0b0c0c);
+ --govuk-link-hover-colour: var(--govuk-link-colour);
+ --govuk-link-active-colour: var(--govuk-link-colour);
display: inline-block;
position: relative;
margin-top: 15px;
@@ -1460,10 +1519,20 @@
}
}
-.govuk-back-link:active,
-.govuk-back-link:link,
+.govuk-back-link:link {
+ color: var(--govuk-link-colour, #1a65a6)
+}
+
.govuk-back-link:visited {
- color: var(--govuk-text-colour, #0b0c0c)
+ color: var(--govuk-link-visited-colour, #54319f)
+}
+
+.govuk-back-link:hover {
+ color: var(--govuk-link-hover-colour, #0f385c)
+}
+
+.govuk-back-link:active {
+ color: var(--govuk-link-active-colour, #0b0c0c)
}
.govuk-back-link:focus {
@@ -1506,9 +1575,27 @@
left: 0
}
-.govuk-back-link--inverse:link,
+.govuk-back-link--inverse {
+ --govuk-link-visited-colour: var(--govuk-link-colour);
+ --govuk-link-colour: var(--govuk-inverse-text-colour, #fff);
+ --govuk-link-hover-colour: var(--govuk-link-colour);
+ --govuk-link-active-colour: var(--govuk-link-colour)
+}
+
+.govuk-back-link--inverse:link {
+ color: var(--govuk-link-colour, #1a65a6)
+}
+
.govuk-back-link--inverse:visited {
- color: var(--govuk-inverse-text-colour, #fff)
+ color: var(--govuk-link-visited-colour, #54319f)
+}
+
+.govuk-back-link--inverse:hover {
+ color: var(--govuk-link-hover-colour, #0f385c)
+}
+
+.govuk-back-link--inverse:active {
+ color: var(--govuk-link-active-colour, #0b0c0c)
}
.govuk-back-link--inverse:focus {
@@ -1599,7 +1686,11 @@
-moz-osx-font-smoothing: grayscale;
text-decoration: underline;
text-decoration-thickness: max(1px, .0625rem);
- text-underline-offset: .1578em
+ text-underline-offset: .1578em;
+ --govuk-link-visited-colour: var(--govuk-link-colour);
+ --govuk-link-colour: var(--govuk-text-colour, #0b0c0c);
+ --govuk-link-hover-colour: var(--govuk-link-colour);
+ --govuk-link-active-colour: var(--govuk-link-colour)
}
@media print {
@@ -1630,10 +1721,20 @@
}
}
-.govuk-breadcrumbs__link:active,
-.govuk-breadcrumbs__link:link,
+.govuk-breadcrumbs__link:link {
+ color: var(--govuk-link-colour, #1a65a6)
+}
+
.govuk-breadcrumbs__link:visited {
- color: var(--govuk-text-colour, #0b0c0c)
+ color: var(--govuk-link-visited-colour, #54319f)
+}
+
+.govuk-breadcrumbs__link:hover {
+ color: var(--govuk-link-hover-colour, #0f385c)
+}
+
+.govuk-breadcrumbs__link:active {
+ color: var(--govuk-link-active-colour, #0b0c0c)
}
.govuk-breadcrumbs__link:focus {
@@ -2918,7 +3019,11 @@ screen and (forced-colors:active) {
-moz-osx-font-smoothing: grayscale;
text-decoration: underline;
text-decoration-thickness: max(1px, .0625rem);
- text-underline-offset: .1578em
+ text-underline-offset: .1578em;
+ --govuk-link-visited-colour: var(--govuk-link-colour);
+ --govuk-link-colour: var(--govuk-error-colour, #ca3535);
+ --govuk-link-hover-colour: #651b1b;
+ --govuk-link-active-colour: var(--govuk-link-colour)
}
@media print {
@@ -2949,17 +3054,20 @@ screen and (forced-colors:active) {
}
}
-.govuk-error-summary__list a:link,
+.govuk-error-summary__list a:link {
+ color: var(--govuk-link-colour, #1a65a6)
+}
+
.govuk-error-summary__list a:visited {
- color: var(--govuk-error-colour, #ca3535)
+ color: var(--govuk-link-visited-colour, #54319f)
}
.govuk-error-summary__list a:hover {
- color: #651b1b
+ color: var(--govuk-link-hover-colour, #0f385c)
}
.govuk-error-summary__list a:active {
- color: var(--govuk-error-colour, #ca3535)
+ color: var(--govuk-link-active-colour, #0b0c0c)
}
.govuk-error-summary__list a:focus {
@@ -3384,10 +3492,27 @@ screen and (forced-colors:active) {
text-wrap: balance
}
-.govuk-footer__copyright-logo:active,
-.govuk-footer__copyright-logo:link,
+.govuk-footer__copyright-logo {
+ --govuk-link-visited-colour: var(--govuk-link-colour);
+ --govuk-link-colour: var(--govuk-text-colour, #0b0c0c);
+ --govuk-link-hover-colour: var(--govuk-link-colour);
+ --govuk-link-active-colour: var(--govuk-link-colour)
+}
+
+.govuk-footer__copyright-logo:link {
+ color: var(--govuk-link-colour, #1a65a6)
+}
+
.govuk-footer__copyright-logo:visited {
- color: var(--govuk-text-colour, #0b0c0c)
+ color: var(--govuk-link-visited-colour, #54319f)
+}
+
+.govuk-footer__copyright-logo:hover {
+ color: var(--govuk-link-hover-colour, #0f385c)
+}
+
+.govuk-footer__copyright-logo:active {
+ color: var(--govuk-link-active-colour, #0b0c0c)
}
.govuk-footer__copyright-logo:focus {
@@ -3548,13 +3673,27 @@ screen and (forced-colors:active) {
display: inline;
margin-right: 10px;
font-size: 30px;
- text-decoration: none
+ text-decoration: none;
+ --govuk-link-visited-colour: var(--govuk-link-colour);
+ --govuk-link-colour: var(--govuk-text-colour, #0b0c0c);
+ --govuk-link-hover-colour: var(--govuk-link-colour);
+ --govuk-link-active-colour: var(--govuk-link-colour)
+}
+
+.govuk-generic-header__homepage-link:link {
+ color: var(--govuk-link-colour, #1a65a6)
}
-.govuk-generic-header__homepage-link:active,
-.govuk-generic-header__homepage-link:link,
.govuk-generic-header__homepage-link:visited {
- color: var(--govuk-text-colour, #0b0c0c)
+ color: var(--govuk-link-visited-colour, #54319f)
+}
+
+.govuk-generic-header__homepage-link:hover {
+ color: var(--govuk-link-hover-colour, #0f385c)
+}
+
+.govuk-generic-header__homepage-link:active {
+ color: var(--govuk-link-active-colour, #0b0c0c)
}
.govuk-generic-header__homepage-link:link,
@@ -3639,13 +3778,27 @@ screen and (forced-colors:active) {
margin-right: 10px;
font-size: 30px;
text-decoration: none;
+ --govuk-link-visited-colour: var(--govuk-link-colour);
+ --govuk-link-colour: var(--govuk-text-colour, #0b0c0c);
+ --govuk-link-hover-colour: var(--govuk-link-colour);
+ --govuk-link-active-colour: var(--govuk-link-colour);
word-spacing: -.375rem
}
-.govuk-header__homepage-link:active,
-.govuk-header__homepage-link:link,
+.govuk-header__homepage-link:link {
+ color: var(--govuk-link-colour, #1a65a6)
+}
+
.govuk-header__homepage-link:visited {
- color: var(--govuk-text-colour, #0b0c0c)
+ color: var(--govuk-link-visited-colour, #54319f)
+}
+
+.govuk-header__homepage-link:hover {
+ color: var(--govuk-link-hover-colour, #0f385c)
+}
+
+.govuk-header__homepage-link:active {
+ color: var(--govuk-link-active-colour, #0b0c0c)
}
.govuk-header__homepage-link:link,
@@ -4008,7 +4161,8 @@ screen and (forced-colors:active) {
-moz-osx-font-smoothing: grayscale;
text-decoration: underline;
text-decoration-thickness: max(1px, .0625rem);
- text-underline-offset: .1578em
+ text-underline-offset: .1578em;
+ --govuk-link-visited-colour: var(--govuk-link-colour)
}
@media print {
@@ -4039,11 +4193,14 @@ screen and (forced-colors:active) {
}
}
-.govuk-notification-banner__link:link,
-.govuk-notification-banner__link:visited {
+.govuk-notification-banner__link:link {
color: var(--govuk-link-colour, #1a65a6)
}
+.govuk-notification-banner__link:visited {
+ color: var(--govuk-link-visited-colour, #54319f)
+}
+
.govuk-notification-banner__link:hover {
color: var(--govuk-link-hover-colour, #0f385c)
}
@@ -4060,17 +4217,27 @@ screen and (forced-colors:active) {
--_govuk-notification-banner-colour: var(--govuk-success-colour, #0f7a52)
}
-.govuk-notification-banner--success .govuk-notification-banner__link:link,
+.govuk-notification-banner--success .govuk-notification-banner__link {
+ --govuk-link-visited-colour: var(--govuk-link-colour);
+ --govuk-link-colour: var(--govuk-success-colour, #0f7a52);
+ --govuk-link-hover-colour: #083d29;
+ --govuk-link-active-colour: var(--govuk-link-colour)
+}
+
+.govuk-notification-banner--success .govuk-notification-banner__link:link {
+ color: var(--govuk-link-colour, #1a65a6)
+}
+
.govuk-notification-banner--success .govuk-notification-banner__link:visited {
- color: var(--govuk-success-colour, #0f7a52)
+ color: var(--govuk-link-visited-colour, #54319f)
}
.govuk-notification-banner--success .govuk-notification-banner__link:hover {
- color: #083d29
+ color: var(--govuk-link-hover-colour, #0f385c)
}
.govuk-notification-banner--success .govuk-notification-banner__link:active {
- color: var(--govuk-success-colour, #0f7a52)
+ color: var(--govuk-link-active-colour, #0b0c0c)
}
.govuk-notification-banner--success .govuk-notification-banner__link:focus {
@@ -4180,9 +4347,27 @@ screen and (forced-colors:active) {
background-color: var(--govuk-link-colour, #1a65a6)
}
-.govuk-pagination__item--current .govuk-pagination__link:link,
+.govuk-pagination__item--current .govuk-pagination__link {
+ --govuk-link-visited-colour: var(--govuk-link-colour);
+ --govuk-link-colour: var(--govuk-inverse-text-colour, #fff);
+ --govuk-link-hover-colour: var(--govuk-link-colour);
+ --govuk-link-active-colour: var(--govuk-link-colour)
+}
+
+.govuk-pagination__item--current .govuk-pagination__link:link {
+ color: var(--govuk-link-colour, #1a65a6)
+}
+
.govuk-pagination__item--current .govuk-pagination__link:visited {
- color: var(--govuk-inverse-text-colour, #fff)
+ color: var(--govuk-link-visited-colour, #54319f)
+}
+
+.govuk-pagination__item--current .govuk-pagination__link:hover {
+ color: var(--govuk-link-hover-colour, #0f385c)
+}
+
+.govuk-pagination__item--current .govuk-pagination__link:active {
+ color: var(--govuk-link-active-colour, #0b0c0c)
}
.govuk-pagination__item--current .govuk-pagination__link:focus {
@@ -4922,7 +5107,8 @@ screen and (forced-colors:active) {
-moz-osx-font-smoothing: grayscale;
text-decoration: underline;
text-decoration-thickness: max(1px, .0625rem);
- text-underline-offset: .1578em
+ text-underline-offset: .1578em;
+ --govuk-link-visited-colour: var(--govuk-link-colour)
}
@media print {
@@ -4957,11 +5143,14 @@ screen and (forced-colors:active) {
text-decoration: none
}
-.govuk-service-navigation__link:link,
-.govuk-service-navigation__link:visited {
+.govuk-service-navigation__link:link {
color: var(--govuk-link-colour, #1a65a6)
}
+.govuk-service-navigation__link:visited {
+ color: var(--govuk-link-visited-colour, #54319f)
+}
+
.govuk-service-navigation__link:hover {
color: var(--govuk-link-hover-colour, #0f385c)
}
@@ -4975,17 +5164,11 @@ screen and (forced-colors:active) {
}
.govuk-service-navigation__service-name {
- font-weight: 700
-}
-
-.govuk-service-navigation__service-name .govuk-service-navigation__link:active,
-.govuk-service-navigation__service-name .govuk-service-navigation__link:link,
-.govuk-service-navigation__service-name .govuk-service-navigation__link:visited {
- color: var(--govuk-text-colour, #0b0c0c)
-}
-
-.govuk-service-navigation__service-name .govuk-service-navigation__link:focus {
- color: var(--govuk-focus-text-colour, #0b0c0c)
+ font-weight: 700;
+ --govuk-link-visited-colour: var(--govuk-link-colour);
+ --govuk-link-colour: var(--govuk-text-colour, #0b0c0c);
+ --govuk-link-hover-colour: var(--govuk-link-colour);
+ --govuk-link-active-colour: var(--govuk-link-colour)
}
.govuk-service-navigation__wrapper {
@@ -5110,7 +5293,12 @@ screen and (forced-colors:active) {
.govuk-service-navigation--inverse {
border-bottom: none;
--govuk-text-colour: var(--govuk-inverse-text-colour, #fff);
- background-color: var(--govuk-brand-colour, #1d70b8)
+ background-color: var(--govuk-brand-colour, #1d70b8);
+ --govuk-link-visited-colour: var(--govuk-link-colour);
+ --govuk-link-colour: var(--govuk-text-colour, #0b0c0c);
+ --govuk-link-hover-colour: var(--govuk-link-colour);
+ --govuk-link-active-colour: var(--govuk-link-colour);
+ --govuk-secondary-text-colour: currentcolor
}
.govuk-service-navigation--inverse .govuk-width-container {
@@ -5128,16 +5316,6 @@ screen and (forced-colors:active) {
border-color: currentcolor
}
-.govuk-service-navigation--inverse .govuk-service-navigation__link:active,
-.govuk-service-navigation--inverse .govuk-service-navigation__link:link,
-.govuk-service-navigation--inverse .govuk-service-navigation__link:visited {
- color: var(--govuk-text-colour, #0b0c0c)
-}
-
-.govuk-service-navigation--inverse .govuk-service-navigation__link:focus {
- color: var(--govuk-focus-text-colour, #0b0c0c)
-}
-
.govuk-service-navigation--inverse .govuk-service-navigation__toggle:not(:focus) {
color: currentcolor
}
@@ -5146,6 +5324,10 @@ screen and (forced-colors:active) {
text-decoration: underline;
text-decoration-thickness: max(1px, .0625rem);
text-underline-offset: .1578em;
+ --govuk-link-visited-colour: var(--govuk-link-colour);
+ --govuk-link-colour: var(--govuk-text-colour, #0b0c0c);
+ --govuk-link-hover-colour: var(--govuk-link-colour);
+ --govuk-link-active-colour: var(--govuk-link-colour);
font-family: GDS Transport, arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
@@ -5173,10 +5355,20 @@ screen and (forced-colors:active) {
user-select: none
}
-.govuk-skip-link:active,
-.govuk-skip-link:link,
+.govuk-skip-link:link {
+ color: var(--govuk-link-colour, #1a65a6)
+}
+
.govuk-skip-link:visited {
- color: var(--govuk-text-colour, #0b0c0c)
+ color: var(--govuk-link-visited-colour, #54319f)
+}
+
+.govuk-skip-link:hover {
+ color: var(--govuk-link-hover-colour, #0f385c)
+}
+
+.govuk-skip-link:active {
+ color: var(--govuk-link-active-colour, #0b0c0c)
}
.govuk-skip-link:focus {
@@ -5843,13 +6035,27 @@ screen and (-ms-high-contrast:active) {
}
.govuk-frontend-supported .govuk-tabs__tab {
+ --govuk-link-visited-colour: var(--govuk-link-colour);
+ --govuk-link-colour: var(--govuk-text-colour, #0b0c0c);
+ --govuk-link-hover-colour: var(--govuk-link-colour);
+ --govuk-link-active-colour: var(--govuk-link-colour);
margin-bottom: 0
}
- .govuk-frontend-supported .govuk-tabs__tab:active,
- .govuk-frontend-supported .govuk-tabs__tab:link,
+ .govuk-frontend-supported .govuk-tabs__tab:link {
+ color: var(--govuk-link-colour, #1a65a6)
+ }
+
.govuk-frontend-supported .govuk-tabs__tab:visited {
- color: var(--govuk-text-colour, #0b0c0c)
+ color: var(--govuk-link-visited-colour, #54319f)
+ }
+
+ .govuk-frontend-supported .govuk-tabs__tab:hover {
+ color: var(--govuk-link-hover-colour, #0f385c)
+ }
+
+ .govuk-frontend-supported .govuk-tabs__tab:active {
+ color: var(--govuk-link-active-colour, #0b0c0c)
}
.govuk-frontend-supported .govuk-tabs__tab:focus {
Action run for fce53c6 |
Rendered HTML changes to npm packagediff --git a/packages/govuk-frontend/dist/govuk/components/service-navigation/template-with-language-switcher-inverse.html b/packages/govuk-frontend/dist/govuk/components/service-navigation/template-with-language-switcher-inverse.html
new file mode 100644
index 000000000..60c0fe057
--- /dev/null
+++ b/packages/govuk-frontend/dist/govuk/components/service-navigation/template-with-language-switcher-inverse.html
@@ -0,0 +1,66 @@
+
+ <section aria-label="Service information" class="govuk-service-navigation govuk-service-navigation--inverse"
+data-module="govuk-service-navigation"
+>
+ <div class="govuk-width-container">
+
+ <div class="govuk-service-navigation__container">
+
+ <span class="govuk-service-navigation__service-name">
+ <a href="#/" class="govuk-service-navigation__link">
+ Service name
+ </a>
+ </span>
+
+
+ <nav aria-label="Menu" class="govuk-service-navigation__wrapper">
+ <button type="button" class="govuk-service-navigation__toggle govuk-js-service-navigation-toggle" aria-controls="navigation" hidden aria-hidden="true">
+ Menu
+ </button>
+
+ <ul class="govuk-service-navigation__list" id="navigation" >
+
+
+
+ <li class="govuk-service-navigation__item govuk-service-navigation__item--active">
+ <a class="govuk-service-navigation__link" href="#/1" aria-current="true">
+
+ <strong class="govuk-service-navigation__active-fallback">Navigation item 1</strong>
+
+ </a>
+ </li>
+
+
+ <li class="govuk-service-navigation__item">
+ <a class="govuk-service-navigation__link" href="#/2">
+
+Navigation item 2
+ </a>
+ </li>
+
+
+ <li class="govuk-service-navigation__item">
+ <a class="govuk-service-navigation__link" href="#/3">
+
+Navigation item 3
+ </a>
+ </li>
+
+ </ul>
+ </nav>
+
+
+ </div>
+
+ <nav class="govuk-language-switcher" aria-label="Language switcher">
+ <ul class="govuk-language-switcher__list">
+ <li class="govuk-language-switcher__list-item">
+ <span class="govuk-language-switcher__text" lang="en" aria-current="true">English</span>
+ </li>
+ <li class="govuk-language-switcher__list-item">
+ <a class="govuk-language-switcher__link" href="#/cy" lang="cy" hreflang="cy" rel="alternate">Cymraeg</a>
+ </li>
+ </ul>
+</nav></div>
+
+ </section>
Action run for fce53c6 |
Other changes to npm packagediff --git a/packages/govuk-frontend/dist/govuk/components/service-navigation/_mixin.scss b/packages/govuk-frontend/dist/govuk/components/service-navigation/_mixin.scss
index 65007adb1..685a94638 100644
--- a/packages/govuk-frontend/dist/govuk/components/service-navigation/_mixin.scss
+++ b/packages/govuk-frontend/dist/govuk/components/service-navigation/_mixin.scss
@@ -106,12 +106,7 @@
.govuk-service-navigation__service-name {
@include base.govuk-typography-weight-bold;
- }
-
- // Annoyingly this requires a compound selector in order to overcome the
- // specificity of the other link colour override we're doing
- .govuk-service-navigation__service-name .govuk-service-navigation__link {
- @include base.govuk-link-style-text;
+ @include base.govuk-link-theme-text;
}
// Allow navigation section to always take up maximum available space,
@@ -226,6 +221,11 @@
--govuk-text-colour: #{base.govuk-functional-colour(inverse-text)};
background-color: base.govuk-functional-colour(brand);
+ // Avoid defining specific link styles when inverted and just use the text colours
+ @include base.govuk-link-theme-text;
+
+ // Similarly to the Breadcrumbs, switch the secondary text colour to `currentcolor`
+ --govuk-secondary-text-colour: currentcolor;
.govuk-width-container {
border-width: 1px 0;
@@ -244,11 +244,6 @@
border-color: currentcolor;
}
- // Override link styles
- .govuk-service-navigation__link {
- @include base.govuk-link-style-text;
- }
-
// Override mobile menu toggle colour when not focused
.govuk-service-navigation__toggle:not(:focus) {
color: currentcolor;
diff --git a/packages/govuk-frontend/dist/govuk/components/service-navigation/fixtures.json b/packages/govuk-frontend/dist/govuk/components/service-navigation/fixtures.json
index cdf49259c..2bf0a5855 100644
--- a/packages/govuk-frontend/dist/govuk/components/service-navigation/fixtures.json
+++ b/packages/govuk-frontend/dist/govuk/components/service-navigation/fixtures.json
@@ -694,6 +694,39 @@
"screenshot": false,
"html": "<section aria-label=\"Service information\" class=\"govuk-service-navigation\"\ndata-module=\"govuk-service-navigation\"\n>\n <div class=\"govuk-width-container\">\n\n <div class=\"govuk-service-navigation__container\">\n \n <span class=\"govuk-service-navigation__service-name\">\n <span class=\"govuk-service-navigation__text\">Service name</span>\n </span>\n\n \n <nav aria-label=\"Menu\" class=\"govuk-service-navigation__wrapper\">\n <button type=\"button\" class=\"govuk-service-navigation__toggle govuk-js-service-navigation-toggle\" aria-controls=\"navigation\" hidden aria-hidden=\"true\">\n Menu\n </button>\n\n <ul class=\"govuk-service-navigation__list\" id=\"navigation\" >\n\n \n \n <li class=\"govuk-service-navigation__item govuk-service-navigation__item--active\">\n <a class=\"govuk-service-navigation__link\" href=\"#/1\" aria-current=\"true\">\n \n <strong class=\"govuk-service-navigation__active-fallback\">Navigation item 1</strong>\n\n </a>\n </li>\n\n \n <li class=\"govuk-service-navigation__item\">\n <a class=\"govuk-service-navigation__link\" href=\"#/2\">\n \nNavigation item 2\n </a>\n </li>\n\n \n <li class=\"govuk-service-navigation__item\">\n <a class=\"govuk-service-navigation__link\" href=\"#/3\">\n \nNavigation item 3\n </a>\n </li>\n\n </ul>\n </nav>\n\n \n <div class=\"govuk-service-navigation__end\">\n <nav class=\"govuk-language-switcher\" aria-label=\"Language switcher\">\n <ul class=\"govuk-language-switcher__list\">\n <li class=\"govuk-language-switcher__list-item\">\n <span class=\"govuk-language-switcher__text\" lang=\"en\" aria-current=\"true\">English</span>\n </li>\n <li class=\"govuk-language-switcher__list-item\">\n <a class=\"govuk-language-switcher__link\" href=\"#/cy\" lang=\"cy\" hreflang=\"cy\" rel=\"alternate\">Cymraeg</a>\n </li>\n </ul>\n</nav>\n </div>\n </div>\n\n </div>\n\n </section>"
},
+ {
+ "name": "with language switcher, inverse",
+ "options": {
+ "classes": "govuk-service-navigation--inverse",
+ "serviceName": "Service name",
+ "serviceUrl": "#/",
+ "navigation": [
+ {
+ "href": "#/1",
+ "text": "Navigation item 1",
+ "active": true
+ },
+ {
+ "href": "#/2",
+ "text": "Navigation item 2"
+ },
+ {
+ "href": "#/3",
+ "text": "Navigation item 3"
+ }
+ ],
+ "slots": {
+ "end": "<nav class=\"govuk-language-switcher\" aria-label=\"Language switcher\">\n <ul class=\"govuk-language-switcher__list\">\n <li class=\"govuk-language-switcher__list-item\">\n <span class=\"govuk-language-switcher__text\" lang=\"en\" aria-current=\"true\">English</span>\n </li>\n <li class=\"govuk-language-switcher__list-item\">\n <a class=\"govuk-language-switcher__link\" href=\"#/cy\" lang=\"cy\" hreflang=\"cy\" rel=\"alternate\">Cymraeg</a>\n </li>\n </ul>\n</nav>"
+ }
+ },
+ "hidden": false,
+ "description": "HTML rendered by the language switcher component can be injected into the `end` slot of the service header.",
+ "pageTemplateOptions": {
+ "bodyClasses": "app-template__body--inverse"
+ },
+ "screenshot": false,
+ "html": "<section aria-label=\"Service information\" class=\"govuk-service-navigation govuk-service-navigation--inverse\"\ndata-module=\"govuk-service-navigation\"\n>\n <div class=\"govuk-width-container\">\n\n <div class=\"govuk-service-navigation__container\">\n \n <span class=\"govuk-service-navigation__service-name\">\n <a href=\"#/\" class=\"govuk-service-navigation__link\">\n Service name\n </a>\n </span>\n\n \n <nav aria-label=\"Menu\" class=\"govuk-service-navigation__wrapper\">\n <button type=\"button\" class=\"govuk-service-navigation__toggle govuk-js-service-navigation-toggle\" aria-controls=\"navigation\" hidden aria-hidden=\"true\">\n Menu\n </button>\n\n <ul class=\"govuk-service-navigation__list\" id=\"navigation\" >\n\n \n \n <li class=\"govuk-service-navigation__item govuk-service-navigation__item--active\">\n <a class=\"govuk-service-navigation__link\" href=\"#/1\" aria-current=\"true\">\n \n <strong class=\"govuk-service-navigation__active-fallback\">Navigation item 1</strong>\n\n </a>\n </li>\n\n \n <li class=\"govuk-service-navigation__item\">\n <a class=\"govuk-service-navigation__link\" href=\"#/2\">\n \nNavigation item 2\n </a>\n </li>\n\n \n <li class=\"govuk-service-navigation__item\">\n <a class=\"govuk-service-navigation__link\" href=\"#/3\">\n \nNavigation item 3\n </a>\n </li>\n\n </ul>\n </nav>\n\n \n </div>\n\n <nav class=\"govuk-language-switcher\" aria-label=\"Language switcher\">\n <ul class=\"govuk-language-switcher__list\">\n <li class=\"govuk-language-switcher__list-item\">\n <span class=\"govuk-language-switcher__text\" lang=\"en\" aria-current=\"true\">English</span>\n </li>\n <li class=\"govuk-language-switcher__list-item\">\n <a class=\"govuk-language-switcher__link\" href=\"#/cy\" lang=\"cy\" hreflang=\"cy\" rel=\"alternate\">Cymraeg</a>\n </li>\n </ul>\n</nav></div>\n\n </section>"
+ },
{
"name": "with slotted content",
"options": {
diff --git a/packages/govuk-frontend/dist/govuk/helpers/_links.scss b/packages/govuk-frontend/dist/govuk/helpers/_links.scss
index 2cc324f91..4cc56e74a 100644
--- a/packages/govuk-frontend/dist/govuk/helpers/_links.scss
+++ b/packages/govuk-frontend/dist/govuk/helpers/_links.scss
@@ -121,24 +121,11 @@
/// @access public
@mixin govuk-link-style-error {
- &:link,
- &:visited {
- color: govuk-functional-colour(error);
- }
-
- &:hover {
- color: govuk-colour("red", $variant: "shade-50");
- }
+ @include govuk-link-style-no-visited-state;
- &:active {
- color: govuk-functional-colour(error);
- }
-
- // When focussed, the text colour needs to be darker to ensure that colour
- // contrast is still acceptable
- &:focus {
- color: govuk-functional-colour(focus-text);
- }
+ --govuk-link-colour: #{govuk-functional-colour(error)};
+ --govuk-link-hover-colour: #{govuk-colour("red", $variant: "shade-50")};
+ --govuk-link-active-colour: var(--govuk-link-colour);
}
/// Success link styles
@@ -158,24 +145,15 @@
/// @access public
@mixin govuk-link-style-success {
- &:link,
- &:visited {
- color: govuk-functional-colour(success);
- }
-
- &:hover {
- color: govuk-colour("green", $variant: "shade-50");
- }
-
- &:active {
- color: govuk-functional-colour(success);
- }
-
- // When focussed, the text colour needs to be darker to ensure that colour
- // contrast is still acceptable
- &:focus {
- color: govuk-functional-colour(focus-text);
- }
+ // In order to avoid a breaking change, we need the selectors
+ // to be output by the mixin, as sometimes the mixins are used on their own
+ // and not all instances use `govuk-link-common`
+ @include govuk-link-style-default;
+ @include govuk-link-theme-no-visited-state;
+
+ --govuk-link-colour: #{govuk-functional-colour(success)};
+ --govuk-link-hover-colour: #{govuk-colour("green", $variant: "shade-50")};
+ --govuk-link-active-colour: var(--govuk-link-colour);
}
/// Muted link styles
@@ -195,21 +173,15 @@
/// @access public
@mixin govuk-link-style-muted {
- &:link,
- &:visited {
- color: govuk-functional-colour(secondary-text);
- }
-
- &:hover,
- &:active {
- color: govuk-functional-colour(text);
- }
-
- // When focussed, the text colour needs to be darker to ensure that colour
- // contrast is still acceptable
- &:focus {
- color: govuk-functional-colour(focus-text);
- }
+ // In order to avoid a breaking change, we need the selectors
+ // to be output by the mixin, as sometimes the mixins are used on their own
+ // and not all instances use `govuk-link-common`
+ @include govuk-link-style-default;
+ @include govuk-link-theme-no-visited-state;
+
+ --govuk-link-colour: #{govuk-functional-colour(secondary-text)};
+ --govuk-link-hover-colour: #{govuk-functional-colour(text)};
+ --govuk-link-active-colour: var(--govuk-link-hover-colour);
}
/// Text link styles
@@ -229,15 +201,26 @@
/// @access public
@mixin govuk-link-style-text {
- &:link,
- &:visited,
- &:active {
- color: govuk-functional-colour(text);
- }
+ // In order to avoid a breaking change, we need the selectors
+ // to be output by the mixin, as sometimes the mixins are used on their own
+ // and not all instances use `govuk-link-common`
+ @include govuk-link-style-default;
+ @include govuk-link-theme-text;
+}
- &:focus {
- color: govuk-functional-colour(focus-text);
- }
+/// Themes links to look like the text
+///
+/// Applies the appropriate `--govuk-link-...` custom properties
+/// so that the styled element or links inside the style elements
+/// look like the text
+///
+/// @access private
+@mixin govuk-link-theme-text {
+ @include govuk-link-theme-no-visited-state;
+
+ --govuk-link-colour: #{govuk-functional-colour(text)};
+ --govuk-link-hover-colour: var(--govuk-link-colour);
+ --govuk-link-active-colour: var(--govuk-link-colour);
}
/// Inverse link styles
@@ -257,14 +240,15 @@
/// @access public
@mixin govuk-link-style-inverse {
- &:link,
- &:visited {
- color: govuk-functional-colour(inverse-text);
- }
-
- &:focus {
- color: govuk-functional-colour(focus-text);
- }
+ // In order to avoid a breaking change, we need the selectors
+ // to be output by the mixin, as sometimes the mixins are used on their own
+ // and not all instances use `govuk-link-common`
+ @include govuk-link-style-default;
+ @include govuk-link-theme-no-visited-state;
+
+ --govuk-link-colour: #{govuk-functional-colour(inverse-text)};
+ --govuk-link-hover-colour: var(--govuk-link-colour);
+ --govuk-link-active-colour: var(--govuk-link-colour);
}
/// Default link styles, without a visited state
@@ -288,27 +272,23 @@
/// @access public
@mixin govuk-link-style-no-visited-state {
- &:link {
- color: govuk-functional-colour(link);
- }
+ // In order to avoid a breaking change, we need the selectors
+ // to be output by the mixin, as sometimes the mixins are used on their own
+ // and not all instances use `govuk-link-common`
+ @include govuk-link-style-default;
- &:visited {
- color: govuk-functional-colour(link);
- }
-
- &:hover {
- color: govuk-functional-colour(link-hover);
- }
-
- &:active {
- color: govuk-functional-colour(link-active);
- }
+ @include govuk-link-theme-no-visited-state;
+}
- // When focussed, the text colour needs to be darker to ensure that colour
- // contrast is still acceptable
- &:focus {
- color: govuk-functional-colour(focus-text);
- }
+/// Themes links to have no visited states
+///
+/// Applies the appropriate `--govuk-link-...` custom properties
+/// so that the styled element or links inside the style elements
+/// have no visited states
+///
+/// @access private
+@mixin govuk-link-theme-no-visited-state {
+ --govuk-link-visited-colour: var(--govuk-link-colour);
}
/// Remove underline from links
Action run for fce53c6 |
📋 StatsFile sizes
No changes to module sizes. Action run for fce53c6 |
2 tasks
2 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This spike is one of two exploring the use of custom properties to change the colours of the link variants, particularly to allow a parent element to configure the colours of all the links inside it, which is useful for the Service Navigation.
Ideally, links across the markup would use
.govuk-linkand the variants would only have to set the relevant--govuk-link(-<STATE>)-colourcustom properties (see first commit). This is great, but only affects markup actually using.govuk-link.In the couple of instances where links are styles using mixins attached to a completely different class (for example the header's homepage link or the error summary). These instances need both:
--govuk-link(-<STATE>)-colour--govuk-link-<STATE>-colourto the:<STATE>selectorOtherwise the
<a>element get the browser's default styles:To avoid breaking changes, the simplest route is to keep our
govuk-link-style-<STYLE>mixins output both selectors and changes of custom properties. To facilitate reuse of which variables need changing for a given style, we can extract the variable changes in their owngovuk-link-theme-<STYLE>mixin, starting with the-no-visited-stateone that all the other styles use. (see second commit).This reduces the gains in CSS output, but still opens the path to parents styling links through case. By extracting a theme for text links, the Service Navigation is able to style the links in its inverse variant from the
.govuk-service-navigation--inverseselector, reducing the need for extra selectors to affect:.govuk-linkor class usinggovuk-link-style-defaultinjected in its slot.See third commit.
Thoughts
Moving to custom properties enables to let the link styles cascade to descendants of components, which facilitate creating
--inversevariants.Keeping selectors output by each of the
--govuk-link-style-<STYLE>mixins to avoid a breaking change is a bit sad, as we don't get as much gain on the CSS output. Down the line, I'd be keen to rework our components to use.govuk-linkwhenever they need a link, which would allow the custom classes to only set custom properties to change the colour of the link.Having the output of selectors in each
--govuk-link-style-<STYLE>mixin also requires us to have separate--govuk-link-theme-<STYLE>mixins for components to set the colours. This doubles the number of mixins to manage, and creates a nuance between 'style' and 'theme' which may be tricky to grasp.