Skip to content

Commit

Permalink
chore(links): update visited links colors w/ a11y considerations (#1740)
Browse files Browse the repository at this point in the history
* chore(links): update visited links colors and application (#1735)

* fix(links): make visited dark mode links purple-500

* Update color for .s-link__visited

* Fix link visited selector, anchor visited selector

* minor formatting fix

* Prevent changes from impacting input messages

I'd like to punt on implementing visited styles for links within `.s-input-message` since the link colors do not follow our standard 400/500/600 pattern for default/hover/visited. @CGuindon thoughts?

* Implement style for hover + visited links

* formatting

* Use purple-600 for visited+hover

* exclude all `.s-*` elements from default visited styles (with exception)

* fix typo

* Revert unneeded breadcrumb visited override

* whitespace fix

* Add an underline to .s-link elements within p tag

* Add visual test for s-link within paragraph

* Implement similar link underline for docs pages

* Add comment for visited class targeting

Addresses #1740 (comment)
  • Loading branch information
dancormier authored Aug 1, 2024
1 parent b29aef4 commit 4db47a6
Show file tree
Hide file tree
Showing 179 changed files with 643 additions and 61 deletions.
11 changes: 10 additions & 1 deletion docs/assets/less/stacks-documentation.less
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,11 @@
strong {
color: var(--fc-dark);
}

a:not([class]),
.s-link {
text-decoration: underline;
}
}

.stacks-copy__lg {
Expand Down Expand Up @@ -239,6 +244,11 @@
font-size: var(--fs-body3);
line-height: var(--lh-lg);
color: var(--fc-medium);

a:not([class]),
.s-link {
text-decoration: underline;
}
}


Expand Down Expand Up @@ -348,7 +358,6 @@
}

max-height: var(--_tb-searchbar-popover-content-mxh);

}

.ds-dropdown-menu {
Expand Down
12 changes: 6 additions & 6 deletions docs/product/components/inputs.html
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ <h1 class="fs-headline1 fw-normal mb16">
<input class="s-input" id="example-warning" type="text" placeholder="" aria-describedby="example-warning-desc" />
@Svg.Alert.With("s-input-icon")
</div>
<p id="example-warning-desc" class="flex--item s-input-message mb0">Caps lock is on! <a>Having trouble entering your username?</a></p>
<p id="example-warning-desc" class="flex--item s-input-message mb0">Caps lock is on! <a href="#">Having trouble entering your username?</a></p>
</div>
{% endhighlight %}
<div class="stacks-preview--example">
Expand All @@ -207,7 +207,7 @@ <h1 class="fs-headline1 fw-normal mb16">
<input class="s-input" id="example-warning" type="text" value="AA" aria-describedby="example-warning-desc" />
{% icon "Alert", "s-input-icon" %}
</div>
<p id="example-warning-desc" class="flex--item s-input-message mb0">Caps lock is on! <a>Having trouble entering your username?</a></p>
<p id="example-warning-desc" class="flex--item s-input-message mb0">Caps lock is on! <a href="#">Having trouble entering your username?</a></p>
</div>
</div>
</div>
Expand All @@ -226,7 +226,7 @@ <h1 class="fs-headline1 fw-normal mb16">
<input class="s-input" id="example-error" type="text" placeholder="e.g. johndoe111" aria-describedby="example-error-desc" aria-invalid="true" />
@Svg.AlertCircle.With("s-input-icon")
</div>
<p id="example-error-desc" class="flex--item s-input-message mb0">You must provide a username. <a>Forgot your username?</a></p>
<p id="example-error-desc" class="flex--item s-input-message mb0">You must provide a username. <a href="#">Forgot your username?</a></p>
</div>
{% endhighlight %}
<div class="stacks-preview--example">
Expand All @@ -237,7 +237,7 @@ <h1 class="fs-headline1 fw-normal mb16">
<input class="s-input" id="example-error" type="text" aria-describedby="example-error-desc" />
{% icon "AlertCircle", "s-input-icon" %}
</div>
<p id="example-error-desc" class="flex--item s-input-message mb0">You must provide a username. <a>Forgot your username?</a></p>
<p id="example-error-desc" class="flex--item s-input-message mb0">You must provide a username. <a href="#">Forgot your username?</a></p>
</div>
</div>
</div>
Expand All @@ -252,7 +252,7 @@ <h1 class="fs-headline1 fw-normal mb16">
<input class="s-input" id="example-success" type="text" aria-describedby="example-success-desc" />
@Svg.Checkmark.With("s-input-icon")
</div>
<p id="example-success-desc" class="flex--item s-input-message mb0">That name is available! <a>Why do we require a username?</a></p>
<p id="example-success-desc" class="flex--item s-input-message mb0">That name is available! <a href="#">Why do we require a username?</a></p>
</div>
{% endhighlight %}
<div class="stacks-preview--example">
Expand All @@ -263,7 +263,7 @@ <h1 class="fs-headline1 fw-normal mb16">
<input class="s-input" id="example-success" type="text" value="aaronshekey" aria-describedby="example-success-desc" />
{% icon "Checkmark", "s-input-icon" %}
</div>
<p id="example-success-desc" class="flex--item s-input-message mb0">That name is available! <a>Why do we require a username?</a></p>
<p id="example-success-desc" class="flex--item s-input-message mb0">That name is available! <a href="#">Why do we require a username?</a></p>
</div>
</div>
</div>
Expand Down
5 changes: 5 additions & 0 deletions docs/product/components/links.html
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,11 @@
</div>
</div>
</div>

{% header "h3", "Accessibility" %}

<p class="stacks-copy">Any link with adjacent static text cannot use color alone to differentiate it as a link. If a link is next to static text and the only visual indication that it’s a link is the color of the text (often <code class="stacks-code">blue-400</code>), it will require an underline in addition to the color. Reference <a href="https://www.w3.org/WAI/WCAG22/Techniques/failures/F73">WCAG SC 1.4.1</a> for more details.</p>

</section>

<section class="stacks-section">
Expand Down
32 changes: 21 additions & 11 deletions lib/components/anchor/anchor.less
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
// CUSTOM PROPERTIED DEFINED WITHIN VARIANTS
// --_an-a-fc
// --_an-a-fc-hover
--_an-a-fc-visited: var(--_an-a-fc);
// --_an-a-fc-visited
// --_an-a-fc-hover-visited

// MODIFIERS
&&__underlined {
Expand All @@ -13,6 +14,13 @@
}

// VARIANTS
&&__danger,
&&__grayscale,
&&__inherit,
&&__muted {
--_an-a-fc-hover-visited: var(--_an-a-fc-hover);
}

&&__danger {
--_an-a-fc: var(--red-400);
--_an-a-fc-hover: var(--red-500);
Expand All @@ -22,7 +30,8 @@
&&__default {
--_an-a-fc: var(--theme-link-color, var(--theme-secondary-400));
--_an-a-fc-hover: var(--theme-link-color-hover, var(--theme-secondary-500));
--_an-a-fc-visited: var(--theme-link-color-visited, var(--theme-secondary-600));
--_an-a-fc-visited: var(--theme-link-color-visited, var(--purple-500));
--_an-a-fc-hover-visited: var(--theme-link-color-hover, var(--purple-600));
}

&&__grayscale {
Expand Down Expand Up @@ -50,19 +59,20 @@
&&__muted {
a:not(.s-link),
.s-btn.s-btn__link {
&:active,
&:hover {
color: var(--_an-a-fc-hover);
}

color: var(--_an-a-fc, inherit);
}

&:hover,
&:active {
&,
&:visited {
color: var(--_an-a-fc-hover);
}
a:not(.s-link):visited {
&:hover {
color: var(--_an-a-fc-hover-visited, inherit);
}

&:visited {
color: var(--_an-a-fc-visited, inherit);
}
color: var(--_an-a-fc-visited, inherit);
}
}
}
2 changes: 1 addition & 1 deletion lib/components/button/button.less
Original file line number Diff line number Diff line change
Expand Up @@ -412,7 +412,7 @@
border-color: var(--_bu-bc-hover);
}

&:visited:not(:hover):not(:focus) {
&:visited:not(:active):not(:focus) {
&.s-btn__filled {
background-color: var(--_bu-filled-bg);
border-color: var(--_bu-filled-bc);
Expand Down
11 changes: 7 additions & 4 deletions lib/components/input-message/input-message.a11y.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,22 @@ const states = [
{
class: "",
children:
'This is a stateless input message. <a href="">Learn more</a>.',
'This is a stateless input message. <a href="/404-unvisited">Learn more</a>.',
},
{
class: "has-error",
children: 'This is an error input message. <a href="">Learn more</a>.',
children:
'This is an error input message. <a href="/404-unvisited">Learn more</a>.',
},
{
class: "has-success",
children: 'This is a success input message. <a href="">Learn more</a>.',
children:
'This is a success input message. <a href="/404-unvisited">Learn more</a>.',
},
{
class: "has-warning",
children: 'This is a warning input message. <a href="">Learn more</a>.',
children:
'This is a warning input message. <a href="/404-unvisited">Learn more</a>.',
},
{
class: "disabled",
Expand Down
4 changes: 2 additions & 2 deletions lib/components/input-message/input-message.less
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,10 @@
// CHILD ELEMENTS
a {
&:hover {
color: var(--_im-a-fc-hover);
color: var(--_im-a-fc-hover) !important;
}

color: var(--_im-a-fc);
color: var(--_im-a-fc) !important;
}

color: var(--_im-fc);
Expand Down
22 changes: 11 additions & 11 deletions lib/components/link-preview/link-preview.less
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,10 @@
& &--details,
& &--footer {
a {
&:visited {
color: var(--black-500);
}
&:hover,
&:active,
&:focus {
&:focus,
&:visited {
color: var(--black-500);
}

Expand Down Expand Up @@ -106,11 +104,8 @@

& a&--title {
&:active,
&:hover{
&,
&.s-link__visited {
color: var(--theme-link-color-hover, var(--theme-secondary-500));
}
&:hover {
color: var(--theme-link-color-hover, var(--theme-secondary-500));
}

&:active,
Expand All @@ -125,8 +120,13 @@
text-decoration: none;
}

&.s-link__visited:visited {
color: var(--theme-link-color, var(--theme-secondary-600));
&:visited,
&.s-link__visited {
&:hover {
color: var(--theme-link-color, var(--purple-600));
}

color: var(--theme-link-color, var(--purple-500));
}

color: var(--theme-link-color, var(--theme-secondary-400));
Expand Down
55 changes: 35 additions & 20 deletions lib/components/link/link.less
Original file line number Diff line number Diff line change
@@ -1,10 +1,28 @@
// TODO we *really* shouldn't be apply styles directly onto `<a>` like this, but
// it's tech debt that'll take some doing in consumer's code to pay down.
a {
&:visited {
// We're target these specific selectors to avoid affecting the visited state of stacks components
// not specified here. See for https://github.com/StackExchange/Stacks/pull/1740#discussion_r1698389312
&:not([class*="s-"]),
&.s-link,
&.s-sidebarwidget--action,
&.s-user-card--link {
&:hover {
color: var(--_li-fc-hover-visited);
}

color: var(--_li-fc-visited);
}
}
}

a,
.s-link {
--_li-fc: var(--theme-link-color, var(--theme-secondary-400));
--_li-fc-hover: var(--theme-link-color-hover, var(--theme-secondary-500));
--_li-fc-visited: var(--theme-link-color-visited, var(--theme-secondary-600));
--_li-fc-visited: var(--theme-link-color-visited, var(--purple-500));
--_li-fc-hover-visited: var(--theme-link-color-visited, var(--purple-600));

// CONTEXTUAL STYLES
.highcontrast-mode({
Expand All @@ -13,21 +31,6 @@ a,

// STATES
&.s-link {
&__danger,
&__grayscale,
&__inherit,
&__muted,
&__visited {
&:visited {
&:active,
&:hover {
color: var(--_li-fc-hover);
}

color: var(--_li-fc-visited);
}
}

// MODIFIERS
&__dropdown {
&:after {
Expand All @@ -53,12 +56,20 @@ a,
}

&__visited { // TODO can we get rid of this? It's only in 3 places in Core and seems to me it doesn't even serve a purpose.
--_li-fc: var(--theme-link-color-visited, var(--theme-secondary-500));
--_li-fc-hover: var(--theme-link-color-hover, var(--theme-secondary-400));
--_li-fc-visited: var(--theme-link-color-visited, var(--theme-secondary-500));
--_li-fc: var(--theme-link-color-visited, var(--purple-500));
--_li-fc-hover: var(--theme-link-color-hover, var(--purple-600));
--_li-fc-visited: var(--theme-link-color-visited, var(--purple-500));
--_li-fc-hover-visited: var(--theme-link-color-visited, var(--purple-600));
}

// VARIANTS
&__danger,
&__grayscale,
&__inherit,
&__muted {
--_li-fc-hover-visited: var(--_li-fc-hover);
}

&__danger {
--_li-fc: var(--red-400);
--_li-fc-hover: var(--red-500);
Expand Down Expand Up @@ -94,7 +105,7 @@ a,
// INTERACTION
&:active,
&:hover {
color: var(--_li-fc-hover);
--_li-fc: var(--_li-fc-hover);
}

color: var(--_li-fc);
Expand All @@ -117,4 +128,8 @@ a,
padding: 0;
user-select: auto;
}

p & {
text-decoration: underline;
}
}
26 changes: 26 additions & 0 deletions lib/components/link/link.visual.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,30 @@ describe("link", () => {
<div data-testid="${testid}" class="p4 ws1">${component}</div>
`,
});

// Visual tests for link nested within a paragraph
runVisualTests({
baseClass: "s-link",
modifiers: {
primary: [
"grayscale",
"muted",
"danger",
"inherit",
"underlined",
"visited",
],
secondary: ["dropdown"],
},
children: {
p: "s-link",
},
tag: "a",
attributes: {
href: "#",
},
template: ({ component, testid }) => html`
<p data-testid="${testid}" class="p4 ws1">${component}</p>
`,
});
});
Loading

0 comments on commit 4db47a6

Please sign in to comment.