Skip to content

Commit

Permalink
feat(sbb-teaser-paid): first implementation (#2434)
Browse files Browse the repository at this point in the history
  • Loading branch information
MarioCastigliano committed Feb 28, 2024
1 parent f1be6bf commit 68f807a
Show file tree
Hide file tree
Showing 10 changed files with 435 additions and 11 deletions.
4 changes: 2 additions & 2 deletions src/components/image/image.scss
Original file line number Diff line number Diff line change
Expand Up @@ -115,8 +115,8 @@
border-radius: var(--sbb-border-radius-infinity);
}

// Variant: Hero Teaser
.image__figure--teaser-hero .image__wrapper {
// Variant: Hero Teaser and Paid Teaser
.image__figure--teaser .image__wrapper {
aspect-ratio: 1 / 1;

@include sbb.mq($from: small) {
Expand Down
13 changes: 7 additions & 6 deletions src/components/image/image.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ export class SbbImageElement extends LitElement {
nonRetinaQuality: '45',
retinaQuality: '20',
};
private _variantTeaserHero = false;
private _variantTeaser = false;

@state() private _loaded = false;

Expand Down Expand Up @@ -426,8 +426,9 @@ export class SbbImageElement extends LitElement {

public override connectedCallback(): void {
super.connectedCallback();
// Check if the current element is nested in an `<sbb-teaser-hero>` element.
this._variantTeaserHero = !!hostContext('sbb-teaser-hero', this);
// Check if the current element is nested in an `<sbb-teaser-hero>` element on in an `<sbb-teaser-paid>` element.
this._variantTeaser =
!!hostContext('sbb-teaser-hero', this) || !!this.closest('sbb-teaser-paid');
}

protected override render(): TemplateResult {
Expand Down Expand Up @@ -465,9 +466,9 @@ export class SbbImageElement extends LitElement {
<figure
class=${classMap({
image__figure: true,
[`image__figure--teaser-hero`]: this._variantTeaserHero,
[`image__figure--no-radius`]: this.borderRadius === 'none' || this._variantTeaserHero,
[`image__figure--round`]: this.borderRadius === 'round' && !this._variantTeaserHero,
[`image__figure--teaser`]: this._variantTeaser,
[`image__figure--no-radius`]: this.borderRadius === 'none' || this._variantTeaser,
[`image__figure--round`]: this.borderRadius === 'round' && !this._variantTeaser,
[`image__figure--ratio-${this.aspectRatio}`]: true,
[`image__figure--loaded`]: this._loaded,
})}
Expand Down
5 changes: 2 additions & 3 deletions src/components/teaser-hero/teaser-hero.stories.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ const href: InputType = {
},
},
table: {
category: 'Link',
category: 'link',
},
};

Expand Down Expand Up @@ -147,7 +147,7 @@ export const withSlots: StoryObj = {

const meta: Meta = {
decorators: [
(story) => html` <div style="padding: 1em;">${story()}</div> `,
(story) => html` <div style="padding: 2rem;">${story()}</div> `,
withActions as Decorator,
],
parameters: {
Expand All @@ -158,7 +158,6 @@ const meta: Meta = {
docs: {
extractComponentDescription: () => readme,
},
layout: 'fullscreen',
},
title: 'components/sbb-teaser/sbb-teaser-hero',
};
Expand Down
114 changes: 114 additions & 0 deletions src/components/teaser-paid/__snapshots__/teaser-paid.spec.snap.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
/* @web/test-runner snapshot v1 */
export const snapshots = {};

snapshots["sbb-teaser-paid Dom"] =
`<sbb-teaser-paid
aria-label="label"
dir="ltr"
href="https://www.sbb.ch"
rel="external"
role="link"
tabindex="0"
target="_blank"
>
</sbb-teaser-paid>
`;
/* end snapshot sbb-teaser-paid Dom */

snapshots["sbb-teaser-paid ShadowDom"] =
`<a
class="sbb-teaser-paid"
href="https://www.sbb.ch"
rel="external"
role="presentation"
tabindex="-1"
target="_blank"
>
<slot name="chip">
</slot>
<slot name="image">
</slot>
<sbb-screenreader-only>
. Link target opens in a new window.
</sbb-screenreader-only>
</a>
`;
/* end snapshot sbb-teaser-paid ShadowDom */

snapshots["sbb-teaser-paid A11y tree Chrome"] =
`<p>
{
"role": "WebArea",
"name": "",
"children": [
{
"role": "link",
"name": "label",
"children": [
{
"role": "link",
"name": ". Link target opens in a new window."
}
]
}
]
}
</p>
`;
/* end snapshot sbb-teaser-paid A11y tree Chrome */

snapshots["sbb-teaser-paid A11y tree Firefox"] =
`<p>
{
"role": "document",
"name": "",
"children": [
{
"role": "link",
"name": "label",
"children": [
{
"role": "link",
"name": ". Link target opens in a new window.",
"value": "https://www.sbb.ch/"
}
]
}
]
}
</p>
`;
/* end snapshot sbb-teaser-paid A11y tree Firefox */

snapshots["sbb-teaser-paid A11y tree Safari"] =
`<p>
{
"role": "WebArea",
"name": "",
"children": [
{
"role": "link",
"name": "label",
"children": [
{
"role": "link",
"name": ". Link target opens in a new window.",
"children": [
{
"role": "text",
"name": ". "
},
{
"role": "text",
"name": "Link target opens in a new window."
}
]
}
]
}
]
}
</p>
`;
/* end snapshot sbb-teaser-paid A11y tree Safari */

30 changes: 30 additions & 0 deletions src/components/teaser-paid/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
The `sbb-teaser-paid` is a component with a background image and a chip with a text.

```html
<sbb-teaser-paid>
<sbb-chip slot="chip">Label</sbb-chip>
<sbb-image slot="image" image-src="https://path-to-source" alt="SBB CFF FFS Employee"></sbb-image>
</sbb-teaser-paid>
```

## Slots

The `sbb-teaser-paid` component has two slots: the `image` slot, used to slot an `sbb-image` and the `chip` slot, used to slot an `sbb-chip`.

<!-- Auto Generated Below -->

## Properties

| Name | Attribute | Privacy | Type | Default | Description |
| ---------- | ---------- | ------- | --------------------------------------- | ------- | ----------------------------------------------------------------- |
| `href` | `href` | public | `string \| undefined` | | The href value you want to link to. |
| `target` | `target` | public | `LinkTargetType \| string \| undefined` | | Where to display the linked URL. |
| `rel` | `rel` | public | `string \| undefined` | | The relationship of the linked URL as space-separated link types. |
| `download` | `download` | public | `boolean \| undefined` | | Whether the browser will show the download dialog on click. |

## Slots

| Name | Description |
| ------- | ---------------------------------------------- |
| `chip` | Link content of the panel |
| `image` | The background image that can be a `sbb-image` |
38 changes: 38 additions & 0 deletions src/components/teaser-paid/teaser-paid.e2e.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { assert, expect, fixture } from '@open-wc/testing';
import { html } from 'lit/static-html.js';

import type { SbbChipElement } from '../chip';
import type { SbbImageElement } from '../image';

import { SbbTeaserPaidElement } from './teaser-paid';

import '../chip';
import '../image';

describe('sbb-teaser-paid', () => {
let element: SbbTeaserPaidElement;

beforeEach(async () => {
element = await fixture(html`
<sbb-teaser-paid>
<sbb-chip slot="chip">Label</sbb-chip>
<sbb-image slot="image"></sbb-image>
</sbb-teaser-paid>
`);
});

it('renders', async () => {
assert.instanceOf(element, SbbTeaserPaidElement);
});

it('styles slotted components', async () => {
const chip = element.querySelector<SbbChipElement>('sbb-chip')!;
const figure = element
.querySelector<SbbImageElement>('sbb-image')!
.shadowRoot?.querySelector('figure');

expect(chip).to.have.attribute('color', 'charcoal');
expect(figure).to.have.class('image__figure--no-radius');
expect(figure).to.have.class('image__figure--teaser');
});
});
46 changes: 46 additions & 0 deletions src/components/teaser-paid/teaser-paid.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
@use '../core/styles' as sbb;

// Default component properties, defined for :host. Properties which can not
// travel the shadow boundary are defined through this mixin
@include sbb.host-component-properties;

:host {
// Use !important here to not interfere with Firefox focus ring definition
// which appears in normalize css of several frameworks.
outline: none !important;

--sbb-teaser-paid-chip-inset: var(--sbb-spacing-responsive-xxxs) auto auto
var(--sbb-spacing-responsive-xxxs);
--sbb-teaser-paid-brightness-hover: 1.075;
--sbb-teaser-paid-animation-duration: var(--sbb-animation-duration-4x);
--sbb-teaser-paid-animation-easing: var(--sbb-animation-easing);
}

@include sbb.hover-mq($hover: true) {
:host(:hover) {
--sbb-teaser-paid-brightness: var(--sbb-teaser-paid-brightness-hover);
}
}

.sbb-teaser-paid {
position: relative;
display: block;

// Hide focus outline when focus origin is mouse or touch. This is being used as a workaround in various components.
:host(:focus-visible:not([data-focus-origin='mouse'], [data-focus-origin='touch'])) & {
@include sbb.focus-outline;
}
}

::slotted([slot='chip']) {
position: absolute;
inset: var(--sbb-teaser-paid-chip-inset);
z-index: 1;
}

::slotted([slot='image']) {
will-change: filter;
filter: brightness(var(--sbb-teaser-paid-brightness, 1));
transition: filter var(--sbb-teaser-paid-animation-duration)
var(--sbb-teaser-paid-animation-easing);
}
32 changes: 32 additions & 0 deletions src/components/teaser-paid/teaser-paid.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { expect, fixture } from '@open-wc/testing';
import { html } from 'lit/static-html.js';

import { testA11yTreeSnapshot } from '../core/testing/a11y-tree-snapshot';

import './teaser-paid';
import type { SbbTeaserPaidElement } from './teaser-paid';

describe('sbb-teaser-paid', () => {
let element: SbbTeaserPaidElement;

beforeEach(async () => {
element = await fixture(
html`<sbb-teaser-paid
aria-label="label"
href="https://www.sbb.ch"
rel="external"
target="_blank"
></sbb-teaser-paid>`,
);
});

it('Dom', async () => {
await expect(element).dom.to.be.equalSnapshot();
});

it('ShadowDom', async () => {
await expect(element).shadowDom.to.be.equalSnapshot();
});

testA11yTreeSnapshot();
});
Loading

0 comments on commit 68f807a

Please sign in to comment.