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

fix(sbb-teaser, sbb-teaser-product): allow screen readers to navigate the content #3250

Merged
merged 9 commits into from
Dec 2, 2024
6 changes: 5 additions & 1 deletion src/elements/core/base-elements/link-base-element.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,10 @@ abstract class SbbLinkBaseElement extends SbbActionBaseElement {

/** Default render method for link-like components. Can be overridden if the LinkRenderVariables are not needed. */
protected override render(): TemplateResult {
return this.renderLink(this.renderTemplate());
}

protected renderLink(renderContent: TemplateResult): TemplateResult {
return html`
<a
class="sbb-action-base ${this.localName}"
Expand All @@ -84,7 +88,7 @@ abstract class SbbLinkBaseElement extends SbbActionBaseElement {
tabindex=${this.maybeDisabled && !this.maybeDisabledInteractive ? '-1' : nothing}
aria-disabled=${this.maybeDisabled ? 'true' : nothing}
>
${this.renderTemplate()}
${renderContent}
${!!this.href && this.target === '_blank'
? html`<sbb-screen-reader-only
>. ${i18nTargetOpensInNewWindow[this.language.current]}</sbb-screen-reader-only
Expand Down
15 changes: 7 additions & 8 deletions src/elements/teaser-product/common/teaser-product-common.scss
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@
}

.sbb-teaser-product__image-container {
display: block;
overflow: hidden;

// We have to remove the image bottom border-radius when stacked
Expand Down Expand Up @@ -79,11 +78,7 @@
margin-block-start: var(--sbb-spacing-responsive-xxs);
}

.sbb-action-base {
display: block;
position: relative;
text-decoration: none;

.sbb-teaser-product__root {
@include sbb.if-forced-colors {
// Apply a visual border for forced color mode
&::after {
Expand All @@ -98,8 +93,13 @@
}
}

.sbb-teaser-product__container {
.sbb-action-base {
display: block;
position: relative;
text-decoration: none;
}

.sbb-teaser-product__container {
background: var(--sbb-teaser-product-background);
border-radius: 0 0 var(--sbb-teaser-product-border-radius) var(--sbb-teaser-product-border-radius);
padding: var(--sbb-spacing-responsive-s);
Expand Down Expand Up @@ -140,7 +140,6 @@

.sbb-teaser-product__footnote {
grid-area: footnote;
display: block;
padding-block-start: var(--sbb-spacing-responsive-s);
color: var(--sbb-teaser-product-footer-color);

Expand Down
22 changes: 12 additions & 10 deletions src/elements/teaser-product/common/teaser-product-common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ import { property } from 'lit/decorators.js';
import type { SbbActionBaseElement } from '../../core/base-elements.js';
import { slotState } from '../../core/decorators.js';
import {
type AbstractConstructor,
SbbNegativeMixin,
type SbbNegativeMixinType,
type AbstractConstructor,
} from '../../core/mixins.js';

export declare class SbbTeaserProductCommonElementMixinType extends SbbNegativeMixinType {
Expand All @@ -33,15 +33,17 @@ export const SbbTeaserProductCommonElementMixin = <

protected override renderTemplate(): TemplateResult {
return html`
<span class="sbb-teaser-product__image-container"><slot name="image"></slot></span>
<span class="sbb-teaser-product__container">
<span class="sbb-teaser-product__content">
<slot></slot>
</span>
<span class="sbb-teaser-product__footnote">
<slot name="footnote"></slot>
</span>
</span>
<div class="sbb-teaser-product__root">
<div class="sbb-teaser-product__image-container"><slot name="image"></slot></div>
<div class="sbb-teaser-product__container">
<span class="sbb-teaser-product__content">
<slot></slot>
</span>
<div class="sbb-teaser-product__footnote">
<slot name="footnote"></slot>
</div>
</div>
</div>
`;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,20 +28,22 @@ snapshots["sbb-teaser-product-static renders DOM"] =

snapshots["sbb-teaser-product-static renders Shadow DOM"] =
`<span class="sbb-action-base sbb-teaser-product-static">
<span class="sbb-teaser-product__image-container">
<slot name="image">
</slot>
</span>
<span class="sbb-teaser-product__container">
<span class="sbb-teaser-product__content">
<slot>
<div class="sbb-teaser-product__root">
<div class="sbb-teaser-product__image-container">
<slot name="image">
</slot>
</span>
<span class="sbb-teaser-product__footnote">
<slot name="footnote">
</slot>
</span>
</span>
</div>
<div class="sbb-teaser-product__container">
<span class="sbb-teaser-product__content">
<slot>
</slot>
</span>
<div class="sbb-teaser-product__footnote">
<slot name="footnote">
</slot>
</div>
</div>
</div>
</span>
`;
/* end snapshot sbb-teaser-product-static renders Shadow DOM */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,25 +29,31 @@ snapshots["sbb-teaser-product renders DOM"] =
/* end snapshot sbb-teaser-product renders DOM */

snapshots["sbb-teaser-product renders Shadow DOM"] =
`<a
class="sbb-action-base sbb-teaser-product"
href="https://www.sbb.ch"
>
<span class="sbb-teaser-product__image-container">
<slot name="image">
</slot>
</span>
<span class="sbb-teaser-product__container">
<span class="sbb-teaser-product__content">
<slot>
</slot>
</span>
<span class="sbb-teaser-product__footnote">
<slot name="footnote">
`<div class="sbb-teaser-product__wrapper">
<a
class="sbb-action-base sbb-teaser-product"
href="https://www.sbb.ch"
>
<sbb-screen-reader-only>
</sbb-screen-reader-only>
</a>
<div class="sbb-teaser-product__root">
<div class="sbb-teaser-product__image-container">
<slot name="image">
</slot>
</span>
</span>
</a>
</div>
<div class="sbb-teaser-product__container">
<span class="sbb-teaser-product__content">
<slot>
</slot>
</span>
<div class="sbb-teaser-product__footnote">
<slot name="footnote">
</slot>
</div>
</div>
</div>
</div>
`;
/* end snapshot sbb-teaser-product renders Shadow DOM */

Expand All @@ -59,8 +65,16 @@ snapshots["sbb-teaser-product renders A11y tree Firefox"] =
"children": [
{
"role": "link",
"name": "Content Footnote",
"name": "",
"value": "https://www.sbb.ch/"
},
{
"role": "text leaf",
"name": "Content"
},
{
"role": "text leaf",
"name": "Footnote"
}
]
}
Expand All @@ -76,7 +90,15 @@ snapshots["sbb-teaser-product renders A11y tree Chrome"] =
"children": [
{
"role": "link",
"name": "Content Footnote"
"name": ""
},
{
"role": "text",
"name": "Content"
},
{
"role": "text",
"name": "Footnote"
}
]
}
Expand Down
44 changes: 31 additions & 13 deletions src/elements/teaser-product/teaser-product/teaser-product.scss
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,13 @@
);
--sbb-teaser-product-animation-easing: var(--sbb-animation-easing);
--sbb-teaser-product-border-radius: var(--sbb-border-radius-4x);

// Simulate link color optically
@include sbb.if-forced-colors {
--sbb-title-text-color-normal-override: LinkText !important;
--sbb-teaser-product-content-color: LinkText !important;
--sbb-teaser-product-footer-color: LinkText !important;
}
}

:host(:hover) {
Expand All @@ -16,14 +23,20 @@
}
}

.sbb-teaser-product {
&:focus-visible {
:host(:not([data-focus-origin='mouse'], [data-focus-origin='touch'])) & {
@include sbb.focus-outline;
::slotted(:is(img, sbb-image)) {
will-change: filter;
transition-property: filter;
transition-duration: var(--sbb-teaser-product-animation-duration);
transition-timing-function: var(--sbb-animation-easing);
filter: brightness(var(--sbb-teaser-product-brightness, 1));
}

border-radius: var(--sbb-teaser-product-border-radius);
}
}
.sbb-teaser-product__wrapper {
position: relative;
}

.sbb-teaser-product__root {
pointer-events: none;

@include sbb.if-forced-colors {
&::after {
Expand All @@ -34,10 +47,15 @@
}
}

::slotted(:is(img, sbb-image)) {
will-change: filter;
transition-property: filter;
transition-duration: var(--sbb-teaser-product-animation-duration);
transition-timing-function: var(--sbb-animation-easing);
filter: brightness(var(--sbb-teaser-product-brightness, 1));
.sbb-teaser-product {
position: absolute;
inset: 0;

&:focus-visible {
:host(:not([data-focus-origin='mouse'], [data-focus-origin='touch'])) & {
@include sbb.focus-outline;

border-radius: var(--sbb-teaser-product-border-radius);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@ import type {
StoryContext,
StoryObj,
} from '@storybook/web-components';
import { nothing, type TemplateResult } from 'lit';
import { html } from 'lit';
import { html, nothing, type TemplateResult } from 'lit';

import { sbbSpread } from '../../../storybook/helpers/spread.js';
import sampleImages from '../../core/images.js';

import readme from './readme.md?raw';

import './teaser-product.js';
import '../../button/button-static.js';
import '../../image.js';
Expand Down Expand Up @@ -78,7 +78,7 @@ const defaultArgs: Args = {
withFooter: true,
slottedImg: false,
href: 'https://www.sbb.ch',
'accessibility-label': undefined,
'accessibility-label': 'Benefit from up to 70% discount, Follow the link to benefit.',
};

const content = (): TemplateResult => html`
Expand Down
18 changes: 17 additions & 1 deletion src/elements/teaser-product/teaser-product/teaser-product.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
import type { CSSResultGroup } from 'lit';
import type { CSSResultGroup, TemplateResult } from 'lit';
import { customElement } from 'lit/decorators.js';
import { html } from 'lit/static-html.js';

import { SbbLinkBaseElement } from '../../core/base-elements.js';
import { SbbTeaserProductCommonElementMixin, teaserProductCommonStyle } from '../common.js';

import style from './teaser-product.scss?lit&inline';

import '../../screen-reader-only.js';

/**
* Displays a text and a footnote, combined with an image, to tease a product
*
Expand All @@ -19,6 +22,19 @@ export
@customElement('sbb-teaser-product')
class SbbTeaserProductElement extends SbbTeaserProductCommonElementMixin(SbbLinkBaseElement) {
public static override styles: CSSResultGroup = [teaserProductCommonStyle, style];

protected override render(): TemplateResult {
// We render the content outside the anchor tag to allow screen readers to navigate through it
return html`
<div class="sbb-teaser-product__wrapper">
${this.renderLink(
// For SEO we add the accessibility hidden as hidden content of the link
html`<sbb-screen-reader-only>${this.accessibilityLabel}</sbb-screen-reader-only>`,
)}
${this.renderTemplate()}
</div>
`;
}
}

declare global {
Expand Down
Loading
Loading