Skip to content

Commit

Permalink
feat(sbb-timetable-row): provide a11y footpaths (#3048)
Browse files Browse the repository at this point in the history
---------

Co-authored-by: Osman Minaz <[email protected]>
Co-authored-by: Robert Fuhrmann <[email protected]>
Co-authored-by: Jeri Peier <[email protected]>
  • Loading branch information
4 people committed Sep 12, 2024
1 parent 9701f84 commit cf9e70f
Show file tree
Hide file tree
Showing 15 changed files with 239 additions and 39 deletions.
54 changes: 54 additions & 0 deletions src/elements-experimental/core/timetable/access-leg-helper.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { expect } from '@open-wc/testing';

import {
connectionTrip,
defaultTrip,
extendedEnterTimeTrip,
} from '../../timetable-row/timetable-row.sample-data.js';
Expand Down Expand Up @@ -39,6 +40,43 @@ describe('getDepartureArrivalTimeAttribute', () => {
});
});

it('should return correct a11y time attributes', () => {
const { departureTimeAttribute, arrivalTimeAttribute } = getDepartureArrivalTimeAttribute(
defaultTrip.legs as Leg[],
10,
10,
'en',
true,
);

expect(departureTimeAttribute).to.be.deep.equal({
duration: 10,
icon: 'wheelchair-small',
text: 'minutes of walking time before departure:',
});
expect(arrivalTimeAttribute).to.be.deep.equal({
duration: 10,
icon: 'wheelchair-small',
text: 'minutes of walking time after arrival:',
});
});

it('should return correct time attribute for connection-leg', () => {
const { departureTimeAttribute } = getDepartureArrivalTimeAttribute(
connectionTrip.legs as Leg[],
10,
0,
'en',
true,
);

expect(departureTimeAttribute).to.be.deep.equal({
duration: 30,
icon: 'walk-small',
text: 'Zu Fuss',
});
});

it('should returns extended departure time attribute', () => {
const { departureTimeAttribute } = getDepartureArrivalTimeAttribute(
extendedEnterTimeTrip.legs as Leg[],
Expand Down Expand Up @@ -68,4 +106,20 @@ describe('getDepartureArrivalTimeAttribute', () => {
text: 'Extended boarding time ',
});
});

it('should return correct a11y time attribute with extended departure time', () => {
const { departureTimeAttribute } = getDepartureArrivalTimeAttribute(
extendedEnterTimeTrip.legs as Leg[],
0,
0,
'en',
true,
);

expect(departureTimeAttribute).to.be.deep.equal({
duration: 45,
icon: 'wheelchair-small',
text: 'minutes of walking time before departure:',
});
});
});
114 changes: 84 additions & 30 deletions src/elements-experimental/core/timetable/access-leg-helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ function getPTConnectionAttribute(
function getFirstExtendedLegAttribute(
leg: PtRideLeg | PtConnectionLeg,
departureWalk: number,
a11yFootpath: boolean | undefined,
currentLanguage: string,
): IAccessAttribute | null {
// Extended enter
const extendedFirstLeg = isRideLeg(leg)
Expand All @@ -64,16 +66,23 @@ function getFirstExtendedLegAttribute(
return extendedFirstLeg
? {
duration: (extractTimeAndString?.duration || 0) + (departureWalk || 0),
text: extractTimeAndString?.text || '',
icon: `sa-${extendedFirstLeg?.name?.toLowerCase()}`,
text: a11yFootpath
? i18nWalkingDistanceDeparture[currentLanguage]
: extractTimeAndString?.text || '',
icon: a11yFootpath ? 'wheelchair-small' : `sa-${extendedFirstLeg?.name?.toLowerCase()}`,
}
: null;
}

/**
* @returns the extended exit attribute of the PTRideLeg
*/
function getLastExtendedLegAttribute(leg: Leg, arrivalWalk: number): IAccessAttribute | null {
function getLastExtendedLegAttribute(
leg: Leg,
arrivalWalk: number,
a11yFootpath: boolean | undefined,
currentLanguage: string,
): IAccessAttribute | null {
// Extended exit
const extendedLastLeg = isRideLeg(leg)
? (leg as PtRideLeg)?.serviceJourney?.notices?.filter((notice) =>
Expand All @@ -87,8 +96,10 @@ function getLastExtendedLegAttribute(leg: Leg, arrivalWalk: number): IAccessAttr
return extendedLastLeg
? {
duration: (extractTimeAndString?.duration || 0) + (arrivalWalk || 0),
text: extractTimeAndString?.text || '',
icon: `sa-${extendedLastLeg?.name?.toLowerCase()}`,
text: a11yFootpath
? i18nWalkingDistanceArrival[currentLanguage]
: extractTimeAndString?.text || '',
icon: a11yFootpath ? 'wheelchair-small' : `sa-${extendedLastLeg?.name?.toLowerCase()}`,
}
: null;
}
Expand All @@ -104,7 +115,7 @@ function renderTransferTime(
type?: 'departure' | 'arrival',
): TemplateResult {
return html`
<span class="sbb-pearl-chain__time-transfer sbb-pearl-chain__time-transfer--${type}">
<span class="sbb-pearl-chain__time-transfer sbb-pearl-chain__time-transfer--${icon}-${type}">
<sbb-icon name=${icon}></sbb-icon>
<time datetime=${duration + 'M'}>
<span class="sbb-screen-reader-only">
Expand All @@ -130,10 +141,11 @@ function renderWalkTime(
duration: number | string,
label: string,
variant: 'left' | 'right',
icon: string,
): TemplateResult {
return html`
<span class="sbb-pearl-chain__time-walktime sbb-pearl-chain__time-walktime--${variant}">
<sbb-icon name="walk-small"></sbb-icon>
<span class="sbb-pearl-chain__time-walktime sbb-pearl-chain__time-walktime--${icon}-${variant}">
<sbb-icon name=${icon}></sbb-icon>
<time datetime=${duration + 'M'}>
<span class="sbb-screen-reader-only">${label}</span>
${duration}
Expand All @@ -148,6 +160,7 @@ function renderWalkTime(
* @param departureWalk: The walking distance in minutes from the departure point to the first leg.
* @param arrivalWalk: The walking distance in minutes from the last leg to the arrival point.
* @param currentLanguage: The current language for localization.
* @param a11yFootpath: Whether the a11y-icon should be shown.
* @returns renderDepartureTimeAttribute: A function that renders the element for the departure time attribute.
* @returns renderArrivalTimeAttribute: A function that renders the element for the arrival time attribute.
* @returns arrivalTimeAttribute: The access attribute for the arrival time.
Expand All @@ -158,6 +171,7 @@ export function getDepartureArrivalTimeAttribute(
departureWalk: number,
arrivalWalk: number,
currentLanguage: string,
a11yFootpath?: boolean,
): {
renderDepartureTimeAttribute: () => TemplateResult;
renderArrivalTimeAttribute: () => TemplateResult;
Expand All @@ -173,12 +187,17 @@ export function getDepartureArrivalTimeAttribute(
const connectionLegNotice = ['YM', 'YB', 'Y', 'YT'];

const connectionFirstLeg = getPTConnectionAttribute(connectionRideLeg, connectionLegNotice);
const extendedFirstLeg = getFirstExtendedLegAttribute(connectionRideLeg, departureWalk);
const extendedFirstLeg = getFirstExtendedLegAttribute(
connectionRideLeg,
departureWalk,
a11yFootpath,
currentLanguage,
);
const departureWalkAttribute = departureWalk
? {
text: i18nWalkingDistanceDeparture[currentLanguage],
duration: departureWalk,
icon: 'walk-small',
icon: a11yFootpath ? 'wheelchair-small' : 'walk-small',
}
: null;

Expand All @@ -197,19 +216,36 @@ export function getDepartureArrivalTimeAttribute(
function renderDepartureTimeAttribute(): TemplateResult {
return html`
${connectionFirstLeg
? renderWalkTime(connectionFirstLeg.duration, connectionFirstLeg.text, 'left')
? renderWalkTime(
connectionFirstLeg.duration,
connectionFirstLeg.text,
'left',
connectionFirstLeg.icon,
)
: nothing}
${departureWalkAttribute && !extendedFirstLeg && !connectionFirstLeg
? renderWalkTime(departureWalkAttribute.duration, departureWalkAttribute.text, 'left')
? renderWalkTime(
departureWalkAttribute.duration,
departureWalkAttribute.text,
'left',
departureWalkAttribute.icon,
)
: nothing}
${extendedFirstLeg
? renderTransferTime(
extendedFirstLeg.duration,
extendedFirstLeg.icon,
currentLanguage,
extendedFirstLeg.text,
'departure',
)
? a11yFootpath
? renderWalkTime(
extendedFirstLeg.duration,
extendedFirstLeg.text,
'left',
extendedFirstLeg.icon,
)
: renderTransferTime(
extendedFirstLeg.duration,
extendedFirstLeg.icon,
currentLanguage,
extendedFirstLeg.text,
'departure',
)
: nothing}
`;
}
Expand All @@ -221,12 +257,13 @@ export function getDepartureArrivalTimeAttribute(
const connectionLastLeg =
lastConnectionRideLeg && getPTConnectionAttribute(lastConnectionRideLeg, connectionLegNotice);
const extendedLastLeg =
lastConnectionRideLeg && getLastExtendedLegAttribute(lastConnectionRideLeg, arrivalWalk);
lastConnectionRideLeg &&
getLastExtendedLegAttribute(lastConnectionRideLeg, arrivalWalk, a11yFootpath, currentLanguage);
const arrivalWalkAttribute = arrivalWalk
? {
text: i18nWalkingDistanceArrival[currentLanguage],
duration: arrivalWalk,
icon: 'walk-small',
icon: a11yFootpath ? 'wheelchair-small' : 'walk-small',
}
: null;

Expand All @@ -245,19 +282,36 @@ export function getDepartureArrivalTimeAttribute(
function renderArrivalTimeAttribute(): TemplateResult {
return html`
${connectionLastLeg
? renderWalkTime(connectionLastLeg.duration, connectionLastLeg.text, 'right')
? renderWalkTime(
connectionLastLeg.duration,
connectionLastLeg.text,
'right',
connectionLastLeg.icon,
)
: nothing}
${arrivalWalkAttribute && !extendedLastLeg && !connectionLastLeg
? renderWalkTime(arrivalWalkAttribute.duration, arrivalWalkAttribute.text, 'right')
? renderWalkTime(
arrivalWalkAttribute.duration,
arrivalWalkAttribute.text,
'right',
arrivalWalkAttribute.icon,
)
: nothing}
${extendedLastLeg
? renderTransferTime(
extendedLastLeg.duration,
extendedLastLeg.icon,
currentLanguage,
extendedLastLeg.text,
'arrival',
)
? a11yFootpath
? renderWalkTime(
extendedLastLeg.duration,
extendedLastLeg.text,
'right',
extendedLastLeg.icon,
)
: renderTransferTime(
extendedLastLeg.duration,
extendedLastLeg.icon,
currentLanguage,
extendedLastLeg.text,
'arrival',
)
: nothing}
`;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ snapshots["sbb-pearl-chain-time renders with departure walk DOM"] =

snapshots["sbb-pearl-chain-time renders with departure walk Shadow DOM"] =
`<div class="sbb-pearl-chain__time">
<span class="sbb-pearl-chain__time-walktime sbb-pearl-chain__time-walktime--left">
<span class="sbb-pearl-chain__time-walktime sbb-pearl-chain__time-walktime--walk-small-left">
<sbb-icon
aria-hidden="true"
data-namespace="default"
Expand Down Expand Up @@ -125,7 +125,7 @@ snapshots["sbb-pearl-chain-time renders with arrival walk Shadow DOM"] =
</span>
15:00
</time>
<span class="sbb-pearl-chain__time-walktime sbb-pearl-chain__time-walktime--right">
<span class="sbb-pearl-chain__time-walktime sbb-pearl-chain__time-walktime--walk-small-right">
<sbb-icon
aria-hidden="true"
data-namespace="default"
Expand Down Expand Up @@ -163,7 +163,7 @@ snapshots["sbb-pearl-chain-time renders with departure and arrival walk DOM"] =

snapshots["sbb-pearl-chain-time renders with departure and arrival walk Shadow DOM"] =
`<div class="sbb-pearl-chain__time">
<span class="sbb-pearl-chain__time-walktime sbb-pearl-chain__time-walktime--left">
<span class="sbb-pearl-chain__time-walktime sbb-pearl-chain__time-walktime--walk-small-left">
<sbb-icon
aria-hidden="true"
data-namespace="default"
Expand Down Expand Up @@ -204,7 +204,7 @@ snapshots["sbb-pearl-chain-time renders with departure and arrival walk Shadow D
</span>
15:00
</time>
<span class="sbb-pearl-chain__time-walktime sbb-pearl-chain__time-walktime--right">
<span class="sbb-pearl-chain__time-walktime sbb-pearl-chain__time-walktime--walk-small-right">
<sbb-icon
aria-hidden="true"
data-namespace="default"
Expand Down
17 changes: 13 additions & 4 deletions src/elements-experimental/pearl-chain-time/pearl-chain-time.scss
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,21 @@
align-items: center;
}

.sbb-pearl-chain__time-walktime--left {
.sbb-pearl-chain__time-walktime--walk-small-left {
transform: translateX(sbb.px-to-rem-build(-7));
margin-inline-end: calc(var(--sbb-spacing-fixed-2x) - #{sbb.px-to-rem-build(7)});
}

.sbb-pearl-chain__time-walktime--right {
.sbb-pearl-chain__time-walktime--walk-small-right {
margin-inline-start: calc(var(--sbb-spacing-fixed-2x) - #{sbb.px-to-rem-build(4)});
}

.sbb-pearl-chain__time-walktime--wheelchair-small-left {
transform: translateX(sbb.px-to-rem-build(-6));
margin-inline-end: calc(var(--sbb-spacing-fixed-2x) - #{sbb.px-to-rem-build(7)});
}

.sbb-pearl-chain__time-walktime--wheelchair-small-right {
margin-inline-start: calc(var(--sbb-spacing-fixed-2x) - #{sbb.px-to-rem-build(4)});
}

Expand All @@ -50,11 +59,11 @@
gap: var(--sbb-spacing-fixed-1x);
}

.sbb-pearl-chain__time-transfer--departure {
.sbb-pearl-chain__time-transfer--sa-ci-departure {
margin-inline-end: var(--sbb-spacing-fixed-2x);
}

.sbb-pearl-chain__time-transfer--arrival {
.sbb-pearl-chain__time-transfer--sa-ci-arrival {
margin-inline-start: calc(var(--sbb-spacing-fixed-2x) - #{sbb.px-to-rem-build(4)});
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ export class SbbPearlChainTimeElement extends LitElement {
*/
@property({ attribute: 'disable-animation', type: Boolean }) public disableAnimation?: boolean;

/** Optional prop to render wheelchair-small instead of walk-small */
@property({ attribute: 'a11y-footpath', type: Boolean }) public a11yFootpath?: boolean;

/** A configured date which acts as the current date instead of the real current date. Recommended for testing purposes. */
@property()
public set now(value: SbbDateLike | undefined) {
Expand All @@ -80,6 +83,7 @@ export class SbbPearlChainTimeElement extends LitElement {
this.departureWalk || 0,
this.arrivalWalk || 0,
this._language.current,
this.a11yFootpath,
);

const rideLegs = this.legs?.filter((leg) => isRideLeg(leg));
Expand Down
1 change: 1 addition & 0 deletions src/elements-experimental/pearl-chain-time/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ This is helpful if you need a specific state of the component.

| Name | Attribute | Privacy | Type | Default | Description |
| ------------------ | ------------------- | ------- | ---------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `a11yFootpath` | `a11y-footpath` | public | `boolean \| undefined` | | Optional prop to render wheelchair-small instead of walk-small |
| `arrivalTime` | `arrival-time` | public | `string \| undefined` | | Prop to render the arrival time - will be formatted as "H:mm" |
| `arrivalWalk` | `arrival-walk` | public | `number \| undefined` | | Optional prop to render the walk time (in minutes) after arrival |
| `departureTime` | `departure-time` | public | `string \| undefined` | | Prop to render the departure time - will be formatted as "H:mm" |
Expand Down
Loading

0 comments on commit cf9e70f

Please sign in to comment.