@@ -15,15 +17,21 @@ otherwise, see [sbb-teaser-product](/docs/elements-sbb-teaser-sbb-teaser-product
## Slots
-Use the `image` slot to pass a `sbb-image` or an `img` that will be used as a background,
-and use the optional `footnote` slot to add a text anchored to the bottom-end of the component.
+Use the `image` slot to pass a `figure` containing an `sbb-image | img` that will be used as background.
+Optionally, you can add an overlapping `sbb-chip-label` to the slotted `figure`.
+
+Use the optional `footnote` slot to add a text anchored to the bottom-end of the component.
The default slot is reserved for the main content: it could be a simple text or a text combined with more elements,
like a `sbb-title` or some interactive elements, like buttons or links within the `sbb-action-group` component.
```html
-
+
+
+ Chip label
+
+
Content ...
```
@@ -33,7 +41,9 @@ to display the components with the correct spacings.
```html
-
+
+
+
Benefit from up to 70% discount
diff --git a/src/elements/teaser-product/teaser-product-static/teaser-product-static.snapshot.spec.ts b/src/elements/teaser-product/teaser-product-static/teaser-product-static.snapshot.spec.ts
index 546242e430..92b50b86ea 100644
--- a/src/elements/teaser-product/teaser-product-static/teaser-product-static.snapshot.spec.ts
+++ b/src/elements/teaser-product/teaser-product-static/teaser-product-static.snapshot.spec.ts
@@ -16,7 +16,9 @@ describe(`sbb-teaser-product-static`, () => {
beforeEach(async () => {
element = await fixture(html`
-
+
+
+
diff --git a/src/elements/teaser-product/teaser-product/readme.md b/src/elements/teaser-product/teaser-product/readme.md
index 6166250124..194a0c85ca 100644
--- a/src/elements/teaser-product/teaser-product/readme.md
+++ b/src/elements/teaser-product/teaser-product/readme.md
@@ -6,7 +6,9 @@ If it has to include more than one interactive element, use the [sbb-teaser-prod
```html
-
+
+
+
Content ...
@@ -16,15 +18,21 @@ If it has to include more than one interactive element, use the [sbb-teaser-prod
## Slots
-Use the `image` slot to pass a `sbb-image` or an `img` that will be used as a background,
-and use the optional `footnote` slot to add a text anchored to the bottom-end of the component.
+Use the `image` slot to pass a `figure` containing an `sbb-image | img` that will be used as background.
+Optionally, you can add an overlapping `sbb-chip-label` to the slotted `figure`.
+
+Use the optional `footnote` slot to add a text anchored to the bottom-end of the component.
The default slot is reserved for the main content: it could be a simple text or a text combined with more elements,
like the `sbb-title` or an interactive element, like a button or a link (needs to be in static variant!).
```html
-
+
+
+ Chip label
+
+
diff --git a/src/elements/teaser-product/teaser-product/teaser-product.stories.ts b/src/elements/teaser-product/teaser-product/teaser-product.stories.ts
index b17659f9c1..caa4070992 100644
--- a/src/elements/teaser-product/teaser-product/teaser-product.stories.ts
+++ b/src/elements/teaser-product/teaser-product/teaser-product.stories.ts
@@ -17,6 +17,7 @@ import sampleImages from '../../core/images.js';
import readme from './readme.md?raw';
import './teaser-product.js';
import '../../button/button-static.js';
+import '../../chip.js';
import '../../image.js';
import '../../title.js';
@@ -39,6 +40,12 @@ const withFooter: InputType = {
},
};
+const withChip: InputType = {
+ control: {
+ type: 'boolean',
+ },
+};
+
const slottedImg: InputType = {
control: {
type: 'boolean',
@@ -67,6 +74,7 @@ const defaultArgTypes: ArgTypes = {
'image-alignment': imageAlignment,
negative,
withFooter,
+ withChip,
slottedImg,
href,
'accessibility-label': accessibilityLabel,
@@ -76,6 +84,7 @@ const defaultArgs: Args = {
'image-alignment': imageAlignment.options![0],
negative: false,
withFooter: true,
+ withChip: false,
slottedImg: false,
href: 'https://www.sbb.ch',
'accessibility-label': undefined,
@@ -102,11 +111,16 @@ const footer = (): TemplateResult => html`
`;
-const Template = ({ withFooter, slottedImg, ...args }: Args): TemplateResult => html`
+const Template = ({ withChip, withFooter, slottedImg, ...args }: Args): TemplateResult => html`
- ${slottedImg
- ? html``
- : html``}
+
+ ${slottedImg
+ ? html``
+ : html``}
+ ${withChip
+ ? html`AI generated`
+ : nothing}
+
${content()} ${withFooter ? footer() : nothing}
`;
@@ -141,6 +155,12 @@ export const SlottedImg: StoryObj = {
args: { ...defaultArgs, slottedImg: true },
};
+export const WithChip: StoryObj = {
+ render: Template,
+ argTypes: defaultArgTypes,
+ args: { ...defaultArgs, withChip: true },
+};
+
const meta: Meta = {
decorators: [withActions as Decorator],
parameters: {
diff --git a/src/elements/teaser-product/teaser-product/teaser-product.visual.spec.ts b/src/elements/teaser-product/teaser-product/teaser-product.visual.spec.ts
index 5484b3501e..66e1966381 100644
--- a/src/elements/teaser-product/teaser-product/teaser-product.visual.spec.ts
+++ b/src/elements/teaser-product/teaser-product/teaser-product.visual.spec.ts
@@ -11,6 +11,7 @@ import { waitForImageReady } from '../../core/testing/wait-for-image-ready.js';
import './teaser-product.js';
import '../../button/button-static.js';
+import '../../chip.js';
import '../../image.js';
import '../../title.js';
@@ -46,17 +47,24 @@ const template = ({
showFooter,
slottedImg,
longContent,
+ withChip,
}: {
negative?: boolean;
imageAlignment?: string;
showFooter?: boolean;
slottedImg?: boolean;
longContent?: boolean;
+ withChip?: boolean;
} = {}): TemplateResult => html`
- ${slottedImg
- ? html``
- : html``}
+
+ ${slottedImg
+ ? html``
+ : html``}
+ ${withChip
+ ? html`Label`
+ : nothing}
+
${content(longContent)} ${showFooter ? footer() : nothing}
`;
@@ -79,6 +87,21 @@ describe('sbb-teaser-product', () => {
);
}),
);
+
+ it(
+ `withChip_${visualState.name}`,
+ visualState.with(async (setup) => {
+ await setup.withFixture(
+ template({ negative, showFooter: true, slottedImg, withChip: true }),
+ {
+ backgroundColor: negative ? 'var(--sbb-color-black)' : undefined,
+ },
+ );
+ await waitForImageReady(
+ setup.snapshotElement.querySelector(slottedImg ? 'img' : 'sbb-image')!,
+ );
+ }),
+ );
}
});
}
From a4ba48185f90068d17760d3f94803c92a684f404 Mon Sep 17 00:00:00 2001
From: Tommmaso Menga
Date: Wed, 6 Nov 2024 14:41:22 +0100
Subject: [PATCH 04/47] refactor(sbb-teaser): adapt sbb-image usages
---
src/elements/core/styles/core.scss | 22 ++++++++++++
.../teaser.snapshot.spec.snap.js | 10 ++++--
src/elements/teaser/readme.md | 12 +++++--
src/elements/teaser/teaser.scss | 35 ++++++-------------
src/elements/teaser/teaser.snapshot.spec.ts | 4 ++-
src/elements/teaser/teaser.stories.ts | 32 +++++++++--------
src/elements/teaser/teaser.visual.spec.ts | 28 ++++++++++++---
7 files changed, 93 insertions(+), 50 deletions(-)
diff --git a/src/elements/core/styles/core.scss b/src/elements/core/styles/core.scss
index 5107ddbec6..bc7ecc0016 100644
--- a/src/elements/core/styles/core.scss
+++ b/src/elements/core/styles/core.scss
@@ -167,6 +167,7 @@ input[data-sbb-time-input] {
}
}
+// TODO Move back to the teaser components when the global css refactoring happens
:is(sbb-teaser-product, sbb-teaser-product-static) {
// Reset sbb-image border radius in order to control it from teaser product.
sbb-image {
@@ -180,3 +181,24 @@ input[data-sbb-time-input] {
aspect-ratio: 16 / 9;
}
}
+
+// TODO Move back to the teaser components when the global css refactoring happens
+:is(sbb-teaser) {
+ & [slot='image']:is(sbb-image, img),
+ & [slot='image'] :is(sbb-image, img) {
+ transition-property: filter, transform;
+ will-change: filter, transform;
+ transform: scale(var(--sbb-teaser-scale, 1));
+ }
+
+ // TODO create and use utility classes
+ sbb-image {
+ --sbb-image-aspect-ratio: 4 / 3;
+ }
+
+ // TODO create and use utility classes
+ img {
+ object-fit: cover;
+ aspect-ratio: 4/3;
+ }
+}
diff --git a/src/elements/teaser/__snapshots__/teaser.snapshot.spec.snap.js b/src/elements/teaser/__snapshots__/teaser.snapshot.spec.snap.js
index 7afc024946..eacc5aa08f 100644
--- a/src/elements/teaser/__snapshots__/teaser.snapshot.spec.snap.js
+++ b/src/elements/teaser/__snapshots__/teaser.snapshot.spec.snap.js
@@ -115,11 +115,15 @@ snapshots["sbb-teaser renders below with projected content DOM"] =
data-slot-names="chip image title unnamed"
href="https://github.com/sbb-design-systems/lyne-components"
>
-
+
+
Chip
diff --git a/src/elements/teaser/readme.md b/src/elements/teaser/readme.md
index 77e213e210..c18ffed67b 100644
--- a/src/elements/teaser/readme.md
+++ b/src/elements/teaser/readme.md
@@ -9,7 +9,9 @@ Simple teaser example:
title-content="Title"
chip-content="Chip label"
>
-
+
+
+
A brief description.
```
@@ -19,9 +21,15 @@ Simple teaser example:
The default slot is reserved for the description. The component displays the `image` and the `title` with the self-named slots.
It's also possible to display a [sbb-chip-label](/docs/elements-sbb-chip-label--docs) using the `chip` slot.
+Use the `image` slot to pass a `figure` containing an `sbb-image | img` that will be used as background.
+Optionally, you can add an overlapping `sbb-chip-label` to the slotted `figure`.
+
```html
-
+
+
+ AI Generated
+ Chip labelTitle
A brief description.
diff --git a/src/elements/teaser/teaser.scss b/src/elements/teaser/teaser.scss
index 1af507f64b..274e33e9c7 100644
--- a/src/elements/teaser/teaser.scss
+++ b/src/elements/teaser/teaser.scss
@@ -17,11 +17,12 @@
--sbb-teaser-gap: var(--sbb-spacing-fixed-4x);
--sbb-teaser-width: fit-content;
--sbb-teaser-border-radius: var(--sbb-border-radius-4x);
- --sbb-teaser-brightness-hover: var(--sbb-hover-image-brightness);
- --sbb-teaser-animation-duration: var(
- --sbb-disable-animation-zero-duration,
+ --sbb-teaser-image-brightness-hover: var(--sbb-hover-image-brightness);
+ --sbb-teaser-image-animation-duration: var(
+ --sbb-disable-animation-zero-time,
var(--sbb-animation-duration-4x)
);
+ --sbb-teaser-image-animation-easing: var(--sbb-animation-easing);
}
:host([alignment='after']) {
@@ -35,6 +36,13 @@
--sbb-teaser-width: 100%;
}
+@include sbb.hover-mq($hover: true) {
+ :host(:hover) {
+ --sbb-teaser-image-brightness: var(--sbb-teaser-image-brightness-hover);
+ --sbb-teaser-scale: var(--sbb-teaser-scale-hover);
+ }
+}
+
.sbb-teaser {
display: flex;
text-decoration: none;
@@ -75,27 +83,6 @@
::slotted([slot='image']) {
width: #{sbb.px-to-rem-build(300)};
- will-change: transform;
- display: block;
- filter: brightness(var(--sbb-teaser-brightness, 1));
- transition: var(--sbb-teaser-animation-duration) var(--sbb-animation-easing);
-
- @include sbb.hover-mq($hover: true) {
- .sbb-teaser:hover & {
- transform: scale(var(--sbb-teaser-scale-hover));
-
- --sbb-teaser-brightness: var(--sbb-teaser-brightness-hover);
- }
- }
-}
-
-::slotted(sbb-image[slot='image']) {
- --sbb-image-aspect-ratio: 4 / 3;
-}
-
-::slotted(img[slot='image']) {
- aspect-ratio: 4/3;
- object-fit: cover;
}
.sbb-teaser__image-wrapper {
diff --git a/src/elements/teaser/teaser.snapshot.spec.ts b/src/elements/teaser/teaser.snapshot.spec.ts
index 9ed4f1c472..696efb458b 100644
--- a/src/elements/teaser/teaser.snapshot.spec.ts
+++ b/src/elements/teaser/teaser.snapshot.spec.ts
@@ -62,7 +62,9 @@ describe(`sbb-teaser`, () => {
accessibility-label="SBB teaser"
alignment="below"
>
-
+
+
+ ChipTITLE
description
diff --git a/src/elements/teaser/teaser.stories.ts b/src/elements/teaser/teaser.stories.ts
index fec1a00ad2..107e77dd28 100644
--- a/src/elements/teaser/teaser.stories.ts
+++ b/src/elements/teaser/teaser.stories.ts
@@ -10,6 +10,7 @@ import images from '../core/images.js';
import placeholderImage from './assets/placeholder.png';
import readme from './readme.md?raw';
+import '../chip-label.js';
import '../image.js';
import './teaser.js';
@@ -89,7 +90,10 @@ const defaultArgs: Args = {
const TemplateDefault = ({ description, ...remainingArgs }: Args): TemplateResult => {
return html`
-
+
+
+ AI Generated
+
${description}
`;
@@ -98,7 +102,9 @@ const TemplateDefault = ({ description, ...remainingArgs }: Args): TemplateResul
const TemplateDefaultFixedWidth = ({ description, ...remainingArgs }: Args): TemplateResult => {
return html`
-
+
+
+
${description}
`;
@@ -107,12 +113,9 @@ const TemplateDefaultFixedWidth = ({ description, ...remainingArgs }: Args): Tem
const TemplateCustom = ({ description, ...remainingArgs }: Args): TemplateResult => {
return html`
-
+
+
+
${description}
`;
@@ -126,7 +129,9 @@ const TemplateSlots = ({
}: Args): TemplateResult => {
return html`
-
+
+
+ ${chipContent}${titleContent}
${description}
@@ -149,12 +154,9 @@ const TemplateGrid = ({ description, ...remainingArgs }: Args): TemplateResult =
new Array(4),
() => html`
-
+
+
+
${description}
`,
diff --git a/src/elements/teaser/teaser.visual.spec.ts b/src/elements/teaser/teaser.visual.spec.ts
index 34101c0059..fa4747506e 100644
--- a/src/elements/teaser/teaser.visual.spec.ts
+++ b/src/elements/teaser/teaser.visual.spec.ts
@@ -52,7 +52,9 @@ describe(`sbb-teaser`, () => {
await setup.withFixture(
html`
-
+
+
+
This is a paragraph
`,
@@ -75,7 +77,14 @@ describe(`sbb-teaser`, () => {
alignment=${alignment}
chip-content=${hasChip ? 'This is a chip.' : nothing}
>
-
+
+
+ ${hasChip
+ ? html`AI chip`
+ : nothing}
+
${withLongContent ? loremIpsum : 'This is a paragraph'}
`,
@@ -98,7 +107,9 @@ describe(`sbb-teaser`, () => {
alignment=${alignment}
chip-content=${longChip}
>
-
+
+
+
This is a paragraph
`,
@@ -123,7 +134,9 @@ describe(`sbb-teaser`, () => {
href="#"
alignment=${alignment}
>
-
+
+
+
This is the paragraph n.${i + 1}
@@ -155,7 +168,12 @@ describe(`sbb-teaser`, () => {
alignment="below"
style="--sbb-teaser-align-items: stretch;"
>
-
+
+
+ AI chip
+
This is a paragraph
`,
From 4f1fcba3f5e1740ca9c986cc088fa19c2ef47f57 Mon Sep 17 00:00:00 2001
From: Tommmaso Menga
Date: Wed, 6 Nov 2024 17:36:02 +0100
Subject: [PATCH 05/47] refactor(sbb-image): convert 'aspect-ratio' and
'border-radius' to classes
---
src/elements/core/styles/image.scss | 50 +++++++++++++++
src/elements/image/image.scss | 54 +---------------
src/elements/image/image.stories.ts | 55 ++++++++++++-----
src/elements/image/image.ts | 35 +----------
src/elements/image/image.visual.spec.ts | 82 +++++++++++++++----------
src/elements/image/readme.md | 62 +++++++++++++------
6 files changed, 184 insertions(+), 154 deletions(-)
diff --git a/src/elements/core/styles/image.scss b/src/elements/core/styles/image.scss
index bd0a8d650e..41d14c82e5 100644
--- a/src/elements/core/styles/image.scss
+++ b/src/elements/core/styles/image.scss
@@ -15,6 +15,7 @@
@include image.figure-caption;
}
+ // Utility classes for placing elements over an image (eg. 'sbb-figure-overlap-start-start')
$alignments: start, center, end;
@each $row-alignment in $alignments {
@each $column-alignment in $alignments {
@@ -24,3 +25,52 @@
}
}
}
+
+// Utility classes for the aspect ratio (eg. 'sbb-image-16-9')
+$aspects-ratio: (
+ 'free': 'auto',
+ '1-1': '1 / 1',
+ '1-2': '1 / 2',
+ '2-1': '2 / 1',
+ '2-3': '2 / 3',
+ '3-2': '3 / 2',
+ '3-4': '3 / 4',
+ '4-3': '4 / 3',
+ '4-5': '4 / 5',
+ '5-4': '5 / 4',
+ '9-16': '9 / 16',
+ '16-9': '16 / 9',
+);
+@each $name, $ratio in $aspects-ratio {
+ sbb-image {
+ &.sbb-image-#{$name} {
+ --sbb-image-aspect-ratio: #{$ratio};
+ }
+ }
+
+ img {
+ &.sbb-image-#{$name} {
+ aspect-ratio: #{$ratio};
+ }
+ }
+}
+
+// Utility classes for the border radius (eg. 'sbb-image-border-radius-none')
+$border-radius: (
+ 'default': 'var(--sbb-border-radius-4x)',
+ 'none': '0',
+ 'round': 'var(--sbb-border-radius-infinity)',
+);
+@each $name, $radius in $border-radius {
+ sbb-image {
+ &.sbb-image-border-radius-#{$name} {
+ --sbb-image-border-radius: #{$radius};
+ }
+ }
+
+ img {
+ &.sbb-image-border-radius-#{$name} {
+ border-radius: #{$radius};
+ }
+ }
+}
diff --git a/src/elements/image/image.scss b/src/elements/image/image.scss
index b517431e21..c85948e4e3 100644
--- a/src/elements/image/image.scss
+++ b/src/elements/image/image.scss
@@ -5,7 +5,7 @@
:host {
--sbb-image-border-radius: var(--sbb-border-radius-4x);
- --sbb-image-aspect-ratio: auto;
+ --sbb-image-aspect-ratio: 16 / 9;
--sbb-image-animation-duration: var(
--sbb-disable-animation-zero-duration,
var(--sbb-animation-duration-4x)
@@ -15,50 +15,6 @@
display: block;
}
-:host([aspect-ratio='1-1']) {
- --sbb-image-aspect-ratio: 1 / 1;
-}
-
-:host([aspect-ratio='1-2']) {
- --sbb-image-aspect-ratio: 1 / 2;
-}
-
-:host([aspect-ratio='2-1']) {
- --sbb-image-aspect-ratio: 2 / 1;
-}
-
-:host([aspect-ratio='2-3']) {
- --sbb-image-aspect-ratio: 2 / 3;
-}
-
-:host([aspect-ratio='3-2']) {
- --sbb-image-aspect-ratio: 3 / 2;
-}
-
-:host([aspect-ratio='3-4']) {
- --sbb-image-aspect-ratio: 3 / 4;
-}
-
-:host([aspect-ratio='4-3']) {
- --sbb-image-aspect-ratio: 4 / 3;
-}
-
-:host([aspect-ratio='4-5']) {
- --sbb-image-aspect-ratio: 4 / 5;
-}
-
-:host([aspect-ratio='5-4']) {
- --sbb-image-aspect-ratio: 5 / 4;
-}
-
-:host([aspect-ratio='16-9']) {
- --sbb-image-aspect-ratio: 16 / 9;
-}
-
-:host([aspect-ratio='9-16']) {
- --sbb-image-aspect-ratio: 9 / 16;
-}
-
// Variant: Hero Teaser and Paid Teaser
:host([data-teaser]) {
--sbb-image-aspect-ratio: 1 / 1;
@@ -68,14 +24,6 @@
}
}
-:host(:is([border-radius='none'], [data-teaser])) {
- --sbb-image-border-radius: 0;
-}
-
-:host([border-radius='round']:not([data-teaser])) {
- --sbb-image-border-radius: var(--sbb-border-radius-infinity);
-}
-
.sbb-image__img {
opacity: 0.000001;
diff --git a/src/elements/image/image.stories.ts b/src/elements/image/image.stories.ts
index 709ceddc07..c3621d7576 100644
--- a/src/elements/image/image.stories.ts
+++ b/src/elements/image/image.stories.ts
@@ -3,6 +3,7 @@ import type { InputType } from '@storybook/types';
import type { Args, ArgTypes, Decorator, Meta, StoryObj } from '@storybook/web-components';
import type { TemplateResult } from 'lit';
import { html } from 'lit';
+import { classMap } from 'lit/directives/class-map.js';
import { sbbSpread } from '../../storybook/helpers/spread.js';
import images from '../core/images.js';
@@ -11,9 +12,20 @@ import { SbbImageElement } from './image.js';
import readme from './readme.md?raw';
import '../chip-label.js';
+const imageTemplate = ({ aspectRatio, borderRadius, ...args }: Args): TemplateResult => html`
+
+
+`;
+
const WithCaptionTemplate = (args: Args): TemplateResult => html`
-
+ ${imageTemplate(args)}
With the
html`
`;
const Template = (args: Args): TemplateResult => html`
-
-
-
+ ${imageTemplate(args)}
`;
-const WithChipTemplate = (args: Args): TemplateResult => html`
+const WithChipTemplate = ({ chipPosition, ...args }: Args): TemplateResult => html`
-
- AI generated
+ ${imageTemplate(args)}
+ AI generated
`;
@@ -51,11 +61,25 @@ const borderRadius: InputType = {
type: 'select',
},
options: ['default', 'none', 'round'],
+ table: {
+ category: 'Utility classes',
+ },
};
const aspectRatio: InputType = {
control: { type: 'select' },
options: ['free', '1-1', '1-2', '2-1', '2-3', '3-2', '3-4', '4-3', '4-5', '5-4', '9-16', '16-9'],
+ table: {
+ category: 'Utility classes',
+ },
+};
+
+const chipPosition: InputType = {
+ control: { type: 'select' },
+ options: ['start-start', 'start-end', 'end-start', 'end-end'],
+ table: {
+ category: 'Utility classes',
+ },
};
const alt: InputType = {
@@ -130,8 +154,9 @@ const performanceMark: InputType = {
const defaultArgTypes: ArgTypes = {
alt,
- 'border-radius': borderRadius,
- 'aspect-ratio': aspectRatio,
+ borderRadius,
+ aspectRatio,
+ chipPosition,
'custom-focal-point': customFocalPoint,
'focal-point-debug': focalPointDebug,
'focal-point-x': focalPointX,
@@ -144,9 +169,9 @@ const defaultArgTypes: ArgTypes = {
const defaultArgs: Args = {
alt: '',
- // we need a string and not boolean, otherwise storybook add/remove the attribute but don't write the value
- 'border-radius': 'default',
- 'aspect-ratio': aspectRatio.options![0],
+ borderRadius: borderRadius.options![0],
+ aspectRatio: aspectRatio.options![0],
+ chipPosition: chipPosition.options![0],
'custom-focal-point': false,
'focal-point-debug': false,
'focal-point-x': '',
@@ -177,7 +202,7 @@ export const NoCaptionNoRadius: StoryObj = {
argTypes: defaultArgTypes,
args: {
...defaultArgs,
- 'border-radius': 'none',
+ borderRadius: 'none',
},
};
@@ -186,8 +211,8 @@ export const RoundBorderRadius: StoryObj = {
argTypes: defaultArgTypes,
args: {
...defaultArgs,
- 'border-radius': 'round',
- 'aspect-ratio': '1-1',
+ borderRadius: 'round',
+ aspectRatio: '1-1',
},
};
diff --git a/src/elements/image/image.ts b/src/elements/image/image.ts
index d544d75999..229f0209c6 100644
--- a/src/elements/image/image.ts
+++ b/src/elements/image/image.ts
@@ -364,34 +364,6 @@ class SbbImageElement extends LitElement {
@property({ attribute: 'picture-sizes-config' })
public accessor pictureSizesConfig: string = '';
- /**
- * Border radius of the image. Choose between a default radius, no radius and a completely round image.
- */
- @property({ attribute: 'border-radius', reflect: true }) public accessor borderRadius:
- | 'default'
- | 'none'
- | 'round' = 'default';
-
- /**
- * Set an aspect ratio
- * default is '16-9' (16/9)
- * other values: 'free', '1-1', '1-2', '2-1', '2-3', '3-2', '3-4', '4-3', '4-5', '5-4', '9-16'
- */
- @property({ attribute: 'aspect-ratio', reflect: true })
- public accessor aspectRatio:
- | 'free'
- | '1-1'
- | '1-2'
- | '2-1'
- | '2-3'
- | '3-2'
- | '3-4'
- | '4-3'
- | '4-5'
- | '5-4'
- | '9-16'
- | '16-9' = '16-9';
-
/** Whether the image is finished loading or failed to load. */
public get complete(): boolean {
return this.shadowRoot?.querySelector?.('.sbb-image__img')?.complete ?? false;
@@ -399,11 +371,8 @@ class SbbImageElement extends LitElement {
public override connectedCallback(): void {
super.connectedCallback();
- // Check if the current element is nested in an `` element on in an `` element.
- this.toggleAttribute(
- 'data-teaser',
- !!hostContext('sbb-teaser-hero', this) || !!this.closest('sbb-teaser-paid'),
- );
+ // Check if the current element is nested in an `` element.
+ this.toggleAttribute('data-teaser', !!hostContext('sbb-teaser-hero', this));
}
protected override updated(changedProperties: PropertyValues): void {
diff --git a/src/elements/image/image.visual.spec.ts b/src/elements/image/image.visual.spec.ts
index b69f110c20..50652e0d47 100644
--- a/src/elements/image/image.visual.spec.ts
+++ b/src/elements/image/image.visual.spec.ts
@@ -9,6 +9,7 @@ import './image.js';
const imageUrl = import.meta.resolve('../core/testing/assets/placeholder-image.png');
const aspectRatios = [
+ 'free',
'1-1',
'1-2',
'2-1',
@@ -29,7 +30,9 @@ describe(`sbb-image`, () => {
`aspect-ratio=${aspectRatio}`,
visualDiffDefault.with(async (setup) => {
await setup.withFixture(
- html``,
+ html`
+
+ `,
);
await waitForImageReady(setup.snapshotElement.querySelector('sbb-image')!);
@@ -41,27 +44,30 @@ describe(`sbb-image`, () => {
`aspect-ratio=free`,
visualDiffDefault.with(async (setup) => {
await setup.withFixture(
- html``,
+ html`
+
+ `,
);
await waitForImageReady(setup.snapshotElement.querySelector('sbb-image')!);
}),
);
- for (const borderRadius of ['none', 'round']) {
+ for (const borderRadius of ['none', 'round', 'default']) {
it(
`border-radius=${borderRadius}`,
visualDiffDefault.with(async (setup) => {
await setup.withFixture(
- html``,
+ html`
+
+ `,
);
await waitForImageReady(setup.snapshotElement.querySelector('sbb-image')!);
@@ -73,11 +79,16 @@ describe(`sbb-image`, () => {
'with caption',
visualDiffDefault.with(async (setup) => {
await setup.withFixture(
- html`Gleis 7. After the link there is more text.`}
- >`,
+ html`
+
+
+ A long text which takes several lines and contains a link
+ Gleis 7. After the link there is more text.
+
+ `,
);
await waitForImageReady(setup.snapshotElement.querySelector('sbb-image')!);
@@ -87,7 +98,11 @@ describe(`sbb-image`, () => {
it(
'transparent image from img cdn',
visualDiffDefault.with(async (setup) => {
- await setup.withFixture(html``);
+ await setup.withFixture(
+ html`
+
+ `,
+ );
await waitForImageReady(setup.snapshotElement.querySelector('sbb-image')!);
}),
@@ -97,7 +112,9 @@ describe(`sbb-image`, () => {
'cropped',
visualDiffDefault.with(async (setup) => {
await setup.withFixture(
- html``,
+ html`
+
+ `,
);
await waitForImageReady(setup.snapshotElement.querySelector('sbb-image')!);
@@ -108,11 +125,10 @@ describe(`sbb-image`, () => {
'cropped with caption',
visualDiffDefault.with(async (setup) => {
await setup.withFixture(
- html``,
+ html`
+
+ I am a caption below
+ `,
);
await waitForImageReady(setup.snapshotElement.querySelector('sbb-image')!);
@@ -123,10 +139,9 @@ describe(`sbb-image`, () => {
'cropped with object-position',
visualDiffDefault.with(async (setup) => {
await setup.withFixture(
- html``,
+ html`
+
+ `,
);
await waitForImageReady(setup.snapshotElement.querySelector('sbb-image')!);
@@ -137,10 +152,9 @@ describe(`sbb-image`, () => {
'cropped with object-fit',
visualDiffDefault.with(async (setup) => {
await setup.withFixture(
- html``,
+ html`
+
+ `,
);
await waitForImageReady(setup.snapshotElement.querySelector('sbb-image')!);
@@ -151,7 +165,9 @@ describe(`sbb-image`, () => {
'skipLqip=true',
visualDiffDefault.with(async (setup) => {
await setup.withFixture(
- html``,
+ html`
+
+ `,
);
await waitForImageReady(setup.snapshotElement.querySelector('sbb-image')!);
diff --git a/src/elements/image/readme.md b/src/elements/image/readme.md
index 984d2bc8d6..42eb103ad8 100644
--- a/src/elements/image/readme.md
+++ b/src/elements/image/readme.md
@@ -5,16 +5,20 @@ The size can be set with `pictureSizesConfig`.
## Usage
-It is possible to add a caption and/or the copyright by wrapping everything in a `figure` tag.
+In general, it is strongly recommended to wrap an `sbb-image` and all its related elements in a `figure` tag.
+
+It is possible to add a caption and/or the copyright using the `figcaption`.
```html
- or or <... class="sbb-image" />
+ or
Caption / Copyright
```
-Also, you can place overlapping content by using the `sbb-figure-overlap-${horizontal-alignment}-${vertical-alignment}` utility classes.
+### Utility classes
+
+You can place overlapping content by using the `sbb-figure-overlap-${horizontal-alignment}-${vertical-alignment}` utility classes.
```html
@@ -23,27 +27,45 @@ Also, you can place overlapping content by using the `sbb-figure-overlap-${horiz
```
+Use the `sbb-image-border-radius-${value}` utility classes to set the image border radius. Available values: `default`, `none` and `round`
+
+```html
+
+
+
+
+
+```
+
+Use the `sbb-image-${value}` utility classes to set the image aspect ratio. Available values: `free`, `1-1`, `2-3`, `3-2` ... `9-16`, `16-9`
+
+```html
+
+
+
+
+
+```
+
## Properties
-| Name | Attribute | Privacy | Type | Default | Description |
-| -------------------- | ---------------------- | ------- | ------------------------------------------------------------------------------------------------------------- | ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
-| `alt` | `alt` | public | `string` | `''` | An alt text is not always necessary (e.g. in teaser cards when additional link text is provided). In this case we can leave the value of the alt attribute blank, but the attribute itself still needs to be present. That way we can signal assistive technology, that they can skip the image. |
-| `aspectRatio` | `aspect-ratio` | public | `'free' \| '1-1' \| '1-2' \| '2-1' \| '2-3' \| '3-2' \| '3-4' \| '4-3' \| '4-5' \| '5-4' \| '9-16' \| '16-9'` | `'16-9'` | Set an aspect ratio default is '16-9' (16/9) other values: 'free', '1-1', '1-2', '2-1', '2-3', '3-2', '3-4', '4-3', '4-5', '5-4', '9-16' |
-| `borderRadius` | `border-radius` | public | `'default' \| 'none' \| 'round'` | `'default'` | Border radius of the image. Choose between a default radius, no radius and a completely round image. |
-| `complete` | - | public | `boolean` | | Whether the image is finished loading or failed to load. |
-| `customFocalPoint` | `custom-focal-point` | public | `boolean` | `false` | Set this to true, if you want to pass a custom focal point for the image. See full documentation here: https://docs.imgix.com/apis/rendering/focalpoint-crop |
-| `decoding` | `decoding` | public | `'sync' \| 'async' \| 'auto'` | `'auto'` | If the lazy property is set to true, the module will automatically change the decoding to async, otherwise the decoding is set to auto which leaves the handling up to the browser. Read more about the decoding attribute here: https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/decoding |
-| `focalPointDebug` | `focal-point-debug` | public | `boolean` | `false` | Set this to true, to receive visual guidance where the custom focal point is currently set. |
-| `focalPointX` | `focal-point-x` | public | `number` | `1` | Pass in a floating number between 0 (left) and 1 (right). |
-| `focalPointY` | `focal-point-y` | public | `number` | `1` | Pass in a floating number between 0 (top) and 1 (bottom). |
-| `imageSrc` | `image-src` | public | `string` | `''` | Right now the module is heavily coupled with the image delivery service imgix and depends on the original files being stored inside AEM. You can pass in any https://cdn.img.sbb.ch img src address you find on sbb.ch to play around with it. Just strip the url parameters and paste in the plain file address. If you want to know how to best work with this module with images coming from a different source, please contact the LYNE Core Team. |
-| `importance` | `importance` | public | `'auto' \| 'high' \| 'low'` | `'high'` | The importance attribute is fairly new attribute which should help the browser decide which resources it should prioritise during page load. We will set the attribute value based on the value, we receive in the loading attribute. 'eager', which we use for the largest image within the initial viewport, will set the attribute value to 'high'. 'lazy', which we use for images below the fold, will set the attribute value to 'low'. |
-| `loading` | `loading` | public | `'eager' \| 'lazy'` | `'eager'` | With the support of native image lazy loading, we can now decide whether we want to load the image immediately or only once it is close to the visible viewport. The value eager is best used for images within the initial viewport. We want to load these images as fast as possible to improve the Core Web Vitals values. lazy on the other hand works best for images which are further down the page or invisible during the loading of the initial viewport. |
-| `performanceMark` | `performance-mark` | public | `string` | `''` | With performance.mark you can log a timestamp associated with the name you define in performanceMark when a certain event is happening. In our case we will log the performance.mark into the PerformanceEntry API once the image is fully loaded. Performance monitoring tools like SpeedCurve or Lighthouse are then able to grab these entries from the PerformanceEntry API and give us additional information and insights about our page loading behaviour. We are then also able to monitor these values over a long period to see if our performance increases or decreases over time. Best to use lowercase strings here, separate words with underscores or dashes. |
-| `pictureSizesConfig` | `picture-sizes-config` | public | `string` | `''` | With the pictureSizesConfig object, you can pass in information into image about what kind of source elements should get rendered. mediaQueries accepts multiple Media Query entries which can get combined by defining a conditionOperator. Type is: stringified InterfaceImageAttributesSizesConfig-Object An example could look like this: { "breakpoints": \[ { "image": { "height": "675", "width": "1200" }, "mediaQueries": \[ { "conditionFeature": "min-width", "conditionFeatureValue": { "lyneDesignToken": true, "value": "sbb-breakpoint-large-min" }, "conditionOperator": false } ] }, { "image": { "height": "549", "width": "976" }, "mediaQueries": \[ { "conditionFeature": "min-width", "conditionFeatureValue": { "lyneDesignToken": true, "value": "sbb-breakpoint-small-min" }, "conditionOperator": false } ] }, { "image": { "height": "180", "width": "320" }, "mediaQueries": \[ { "conditionFeature": "max-width", "conditionFeatureValue": { "lyneDesignToken": true, "value": "sbb-breakpoint-micro-max" }, "conditionOperator": "and" }, { "conditionFeature": "orientation", "conditionFeatureValue": { "lyneDesignToken": false, "value": "landscape" }, "conditionOperator": false } ] } ] } |
-| `skipLqip` | `skip-lqip` | public | `boolean` | `false` | If set to false, we show a blurred version of the image as placeholder before the actual image shows up. This will help to improve the perceived loading performance. Read more about the idea of lqip here: https://medium.com/@imgix/lqip-your-images-for-fast-loading-2523d9ee4a62 |
+| Name | Attribute | Privacy | Type | Default | Description |
+| -------------------- | ---------------------- | ------- | ----------------------------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
+| `alt` | `alt` | public | `string` | `''` | An alt text is not always necessary (e.g. in teaser cards when additional link text is provided). In this case we can leave the value of the alt attribute blank, but the attribute itself still needs to be present. That way we can signal assistive technology, that they can skip the image. |
+| `complete` | - | public | `boolean` | | Whether the image is finished loading or failed to load. |
+| `customFocalPoint` | `custom-focal-point` | public | `boolean` | `false` | Set this to true, if you want to pass a custom focal point for the image. See full documentation here: https://docs.imgix.com/apis/rendering/focalpoint-crop |
+| `decoding` | `decoding` | public | `'sync' \| 'async' \| 'auto'` | `'auto'` | If the lazy property is set to true, the module will automatically change the decoding to async, otherwise the decoding is set to auto which leaves the handling up to the browser. Read more about the decoding attribute here: https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/decoding |
+| `focalPointDebug` | `focal-point-debug` | public | `boolean` | `false` | Set this to true, to receive visual guidance where the custom focal point is currently set. |
+| `focalPointX` | `focal-point-x` | public | `number` | `1` | Pass in a floating number between 0 (left) and 1 (right). |
+| `focalPointY` | `focal-point-y` | public | `number` | `1` | Pass in a floating number between 0 (top) and 1 (bottom). |
+| `imageSrc` | `image-src` | public | `string` | `''` | Right now the module is heavily coupled with the image delivery service imgix and depends on the original files being stored inside AEM. You can pass in any https://cdn.img.sbb.ch img src address you find on sbb.ch to play around with it. Just strip the url parameters and paste in the plain file address. If you want to know how to best work with this module with images coming from a different source, please contact the LYNE Core Team. |
+| `importance` | `importance` | public | `'auto' \| 'high' \| 'low'` | `'high'` | The importance attribute is fairly new attribute which should help the browser decide which resources it should prioritise during page load. We will set the attribute value based on the value, we receive in the loading attribute. 'eager', which we use for the largest image within the initial viewport, will set the attribute value to 'high'. 'lazy', which we use for images below the fold, will set the attribute value to 'low'. |
+| `loading` | `loading` | public | `'eager' \| 'lazy'` | `'eager'` | With the support of native image lazy loading, we can now decide whether we want to load the image immediately or only once it is close to the visible viewport. The value eager is best used for images within the initial viewport. We want to load these images as fast as possible to improve the Core Web Vitals values. lazy on the other hand works best for images which are further down the page or invisible during the loading of the initial viewport. |
+| `performanceMark` | `performance-mark` | public | `string` | `''` | With performance.mark you can log a timestamp associated with the name you define in performanceMark when a certain event is happening. In our case we will log the performance.mark into the PerformanceEntry API once the image is fully loaded. Performance monitoring tools like SpeedCurve or Lighthouse are then able to grab these entries from the PerformanceEntry API and give us additional information and insights about our page loading behaviour. We are then also able to monitor these values over a long period to see if our performance increases or decreases over time. Best to use lowercase strings here, separate words with underscores or dashes. |
+| `pictureSizesConfig` | `picture-sizes-config` | public | `string` | `''` | With the pictureSizesConfig object, you can pass in information into image about what kind of source elements should get rendered. mediaQueries accepts multiple Media Query entries which can get combined by defining a conditionOperator. Type is: stringified InterfaceImageAttributesSizesConfig-Object An example could look like this: { "breakpoints": \[ { "image": { "height": "675", "width": "1200" }, "mediaQueries": \[ { "conditionFeature": "min-width", "conditionFeatureValue": { "lyneDesignToken": true, "value": "sbb-breakpoint-large-min" }, "conditionOperator": false } ] }, { "image": { "height": "549", "width": "976" }, "mediaQueries": \[ { "conditionFeature": "min-width", "conditionFeatureValue": { "lyneDesignToken": true, "value": "sbb-breakpoint-small-min" }, "conditionOperator": false } ] }, { "image": { "height": "180", "width": "320" }, "mediaQueries": \[ { "conditionFeature": "max-width", "conditionFeatureValue": { "lyneDesignToken": true, "value": "sbb-breakpoint-micro-max" }, "conditionOperator": "and" }, { "conditionFeature": "orientation", "conditionFeatureValue": { "lyneDesignToken": false, "value": "landscape" }, "conditionOperator": false } ] } ] } |
+| `skipLqip` | `skip-lqip` | public | `boolean` | `false` | If set to false, we show a blurred version of the image as placeholder before the actual image shows up. This will help to improve the perceived loading performance. Read more about the idea of lqip here: https://medium.com/@imgix/lqip-your-images-for-fast-loading-2523d9ee4a62 |
## Events
From 838819aa3a2806d5574ea28288011f7239a02a30 Mon Sep 17 00:00:00 2001
From: Tommmaso Menga
Date: Thu, 7 Nov 2024 10:09:22 +0100
Subject: [PATCH 06/47] refactor(sbb-image): update tests
---
.../__snapshots__/image.snapshot.spec.snap.js | 58 +++++++++----------
.../lead-container.snapshot.spec.snap.js | 2 -
.../message.snapshot.spec.snap.js | 2 -
.../teaser-hero.snapshot.spec.snap.js | 2 -
src/elements/teaser-hero/teaser-hero.spec.ts | 2 +-
...easer-product-static.snapshot.spec.snap.js | 5 +-
.../teaser-product.snapshot.spec.snap.js | 5 +-
src/elements/teaser/teaser.stories.ts | 4 +-
8 files changed, 31 insertions(+), 49 deletions(-)
diff --git a/src/elements/image/__snapshots__/image.snapshot.spec.snap.js b/src/elements/image/__snapshots__/image.snapshot.spec.snap.js
index b4bb7b14df..a2ed420dcf 100644
--- a/src/elements/image/__snapshots__/image.snapshot.spec.snap.js
+++ b/src/elements/image/__snapshots__/image.snapshot.spec.snap.js
@@ -2,50 +2,44 @@
export const snapshots = {};
snapshots["sbb-image should render DOM"] =
-`
+`
`;
/* end snapshot sbb-image should render DOM */
snapshots["sbb-image should render Shadow DOM"] =
-`
-
diff --git a/src/elements/image/image.scss b/src/elements/image/image.scss
index 8f86fa3fcf..47c6f8825c 100644
--- a/src/elements/image/image.scss
+++ b/src/elements/image/image.scss
@@ -4,7 +4,6 @@
@include sbb.box-sizing;
:host {
- --sbb-image-border-radius: var(--sbb-border-radius-4x);
--sbb-image-aspect-ratio: 16 / 9;
--sbb-image-animation-duration: var(
--sbb-disable-animation-zero-duration,
@@ -13,6 +12,8 @@
--sbb-image-object-fit: cover;
display: block;
+ border-radius: var(--sbb-border-radius-4x);
+ overflow: hidden;
}
.sbb-image__img {
@@ -53,9 +54,7 @@ picture {
.sbb-image__wrapper {
display: flex;
position: relative;
- overflow: hidden;
width: 100%;
height: 100%;
aspect-ratio: var(--sbb-image-aspect-ratio);
- border-radius: var(--sbb-image-border-radius);
}
diff --git a/src/elements/image/image.ts b/src/elements/image/image.ts
index 34a479bbcc..6f764f9b61 100644
--- a/src/elements/image/image.ts
+++ b/src/elements/image/image.ts
@@ -152,8 +152,6 @@ const breakpointMap: Record = {
* @cssprop [--sbb-image-aspect-ratio=auto] - Can be used to override `aspectRatio` property.
* This way we can have, for example, an image component with an aspect
* ratio of 4/3 in smaller viewports and 16/9 in larger viewports.
- * @cssprop [--sbb-image-border-radius=var(--sbb-border-radius-4x)] - Can be used to override the
- * `borderRadius` property in case of different values for different viewports.
* @cssprop [--sbb-image-object-position] - Can be used to set the object-position css property of the image itself if the image itself is cropped.
* @cssprop [--sbb-image-object-fit=cover] - Can be used to set the object-fit css property of the image itself if the image itself is cropped.
*/
diff --git a/src/elements/image/readme.md b/src/elements/image/readme.md
index 455be69359..c84d324f5e 100644
--- a/src/elements/image/readme.md
+++ b/src/elements/image/readme.md
@@ -75,9 +75,8 @@ Use the `sbb-image-${value}` utility classes to set the image aspect ratio. Avai
## CSS Properties
-| Name | Default | Description |
-| ----------------------------- | ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
-| `--sbb-image-aspect-ratio` | `auto` | Can be used to override `aspectRatio` property. This way we can have, for example, an image component with an aspect ratio of 4/3 in smaller viewports and 16/9 in larger viewports. |
-| `--sbb-image-border-radius` | `var(--sbb-border-radius-4x)` | Can be used to override the `borderRadius` property in case of different values for different viewports. |
-| `--sbb-image-object-fit` | `cover` | Can be used to set the object-fit css property of the image itself if the image itself is cropped. |
-| `--sbb-image-object-position` | | Can be used to set the object-position css property of the image itself if the image itself is cropped. |
+| Name | Default | Description |
+| ----------------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
+| `--sbb-image-aspect-ratio` | `auto` | Can be used to override `aspectRatio` property. This way we can have, for example, an image component with an aspect ratio of 4/3 in smaller viewports and 16/9 in larger viewports. |
+| `--sbb-image-object-fit` | `cover` | Can be used to set the object-fit css property of the image itself if the image itself is cropped. |
+| `--sbb-image-object-position` | | Can be used to set the object-position css property of the image itself if the image itself is cropped. |
diff --git a/src/elements/lead-container/lead-container.scss b/src/elements/lead-container/lead-container.scss
index b08d33c3e0..91d99393d4 100644
--- a/src/elements/lead-container/lead-container.scss
+++ b/src/elements/lead-container/lead-container.scss
@@ -29,7 +29,8 @@
::slotted(sbb-image[slot='image']) {
--sbb-image-aspect-ratio: var(--sbb-lead-container-image-ratio);
- --sbb-image-border-radius: var(--sbb-lead-container-image-border-radius);
+
+ border-radius: var(--sbb-lead-container-image-border-radius);
}
::slotted(:is(img[slot='image'], picture[slot='image'])) {
From bdc88bbedd5625c167fbe9acaa4db71a83fbf597 Mon Sep 17 00:00:00 2001
From: Tommmaso Menga
Date: Wed, 4 Dec 2024 15:56:10 +0100
Subject: [PATCH 33/47] docs(sbb-image): update readme
---
src/elements/image/readme.md | 32 ++++++++++++++++++++++++++++++--
1 file changed, 30 insertions(+), 2 deletions(-)
diff --git a/src/elements/image/readme.md b/src/elements/image/readme.md
index c84d324f5e..264f2a7d4f 100644
--- a/src/elements/image/readme.md
+++ b/src/elements/image/readme.md
@@ -21,6 +21,13 @@ E.g. `` or ``.
You can place overlapping content by using the `sbb-figure-overlap-${horizontal-alignment}-${vertical-alignment}` utility classes.
+| Position | CSS class |
+| -------------- | -------------------------------- |
+| `top-left` | `sbb-figure-overlap-start-start` |
+| `top-right` | `sbb-figure-overlap-start-end` |
+| `bottom-left` | `sbb-figure-overlap-end-start` |
+| `bottom-right` | `sbb-figure-overlap-end-end` |
+
```html
@@ -30,7 +37,13 @@ You can place overlapping content by using the `sbb-figure-overlap-${horizontal-
### Utility classes
-Use the `sbb-image-border-radius-${value}` utility classes to set the image border radius. Available values: `default`, `none` and `round`
+Use the `sbb-image-border-radius-${value}` utility classes to set the image border radius.
+
+| Border Radius | CSS class |
+| ------------- | ------------------- |
+| `default` | `sbb-image-default` |
+| `none` | `sbb-image-none` |
+| `round` | `sbb-image-round` |
```html
@@ -38,7 +51,22 @@ Use the `sbb-image-border-radius-${value}` utility classes to set the image bord
```
-Use the `sbb-image-${value}` utility classes to set the image aspect ratio. Available values: `free`, `1-1`, `2-3`, `3-2` ... `9-16`, `16-9`
+Use the `sbb-image-${ratio}` utility classes to set the image aspect ratio.
+
+| Aspect Ratio | CSS class |
+| ------------ | ---------------- |
+| `free` | `sbb-image-free` |
+| `1-1` | `sbb-image-1-1` |
+| `1-2` | `sbb-image-1-2` |
+| `2-1` | `sbb-image-2-1` |
+| `2-3` | `sbb-image-2-3` |
+| `3-2` | `sbb-image-3-2` |
+| `3-4` | `sbb-image-3-4` |
+| `4-3` | `sbb-image-4-3` |
+| `4-5` | `sbb-image-4-5` |
+| `5-4` | `sbb-image-5-4` |
+| `9-16` | `sbb-image-9-16` |
+| `16-9` | `sbb-image-16-9` |
```html
From 2c92877c6d359353f16c4abbd3604c97bc45ba4c Mon Sep 17 00:00:00 2001
From: Tommmaso Menga
Date: Wed, 4 Dec 2024 16:10:06 +0100
Subject: [PATCH 34/47] fix: pr feedbacks pt.8
---
src/elements/core/styles/core.scss | 14 +++++---------
src/elements/teaser-hero/teaser-hero.stories.ts | 8 --------
2 files changed, 5 insertions(+), 17 deletions(-)
diff --git a/src/elements/core/styles/core.scss b/src/elements/core/styles/core.scss
index 9be4442122..5e61509db8 100644
--- a/src/elements/core/styles/core.scss
+++ b/src/elements/core/styles/core.scss
@@ -215,26 +215,22 @@ input[data-sbb-time-input] {
// TODO: Move back to the teaser-hero components when the global css refactoring happens
:is(sbb-teaser-hero) {
- sbb-image {
+ :is(sbb-image, img) {
--sbb-image-aspect-ratio: 1 / 1;
- border-radius: 0;
-
@include mediaqueries.mq($from: small) {
--sbb-image-aspect-ratio: 16 / 9;
}
}
- img {
- --sbb-image-aspect-ratio: 1 / 1;
+ sbb-image {
+ border-radius: 0;
+ }
+ img {
width: 100%;
display: block;
aspect-ratio: var(--sbb-image-aspect-ratio);
-
- @include mediaqueries.mq($from: small) {
- --sbb-image-aspect-ratio: 16 / 9;
- }
}
}
diff --git a/src/elements/teaser-hero/teaser-hero.stories.ts b/src/elements/teaser-hero/teaser-hero.stories.ts
index 08b574d245..25d6d64fa9 100644
--- a/src/elements/teaser-hero/teaser-hero.stories.ts
+++ b/src/elements/teaser-hero/teaser-hero.stories.ts
@@ -164,14 +164,6 @@ export const chipOnly: StoryObj = {
},
};
-export const withSlots: StoryObj = {
- render: Template,
- argTypes: defaultArgTypes,
- args: {
- ...defaultArgs,
- },
-};
-
const meta: Meta = {
decorators: [withActions as Decorator],
parameters: {
From 2b6341db799dd52de76a20a84d57ee2eb6dfa8f5 Mon Sep 17 00:00:00 2001
From: Tommmaso Menga
Date: Wed, 4 Dec 2024 16:46:14 +0100
Subject: [PATCH 35/47] fix: pr feedbacks pt.8
---
src/elements/image/__snapshots__/image.snapshot.spec.snap.js | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/src/elements/image/__snapshots__/image.snapshot.spec.snap.js b/src/elements/image/__snapshots__/image.snapshot.spec.snap.js
index e5e10acbaf..a2ed420dcf 100644
--- a/src/elements/image/__snapshots__/image.snapshot.spec.snap.js
+++ b/src/elements/image/__snapshots__/image.snapshot.spec.snap.js
@@ -13,7 +13,9 @@ snapshots["sbb-image should render Shadow DOM"] =
alt=""
class="sbb-image__blurred"
decoding="auto"
+ height="562"
loading="eager"
+ width="1000"
>
From 7e651a8b7aedd311313fb360045a5724a96865d9 Mon Sep 17 00:00:00 2001
From: Jeremias Peier
Date: Thu, 5 Dec 2024 08:12:53 +0100
Subject: [PATCH 36/47] docs: improve teaser-hero docs
---
src/elements/teaser-hero/readme.md | 6 +++++-
src/elements/teaser-hero/teaser-hero.stories.ts | 4 +++-
src/elements/teaser-hero/teaser-hero.visual.spec.ts | 4 +++-
3 files changed, 11 insertions(+), 3 deletions(-)
diff --git a/src/elements/teaser-hero/readme.md b/src/elements/teaser-hero/readme.md
index 56cee4aff1..278fd46827 100644
--- a/src/elements/teaser-hero/readme.md
+++ b/src/elements/teaser-hero/readme.md
@@ -17,6 +17,8 @@ Use the `image` slot to pass an `sbb-image` or an `img` that will be used as bac
```
Optionally, you can add an overlapping `sbb-chip-label` by wrapping the `sbb-image` in a `figure` tag (see [sbb-image doc](/docs/elements-sbb-image--docs#utility%classes)).
+If the `sbb-chip-label` should appear on top of the red panel (e.g. on small screens), you need to set a `z-index` on the `sbb-chip-label`.
+Otherwise, it stays behind the red panel.
```html
@@ -24,7 +26,9 @@ Optionally, you can add an overlapping `sbb-chip-label` by wrapping the `sbb-ima
Find out more
- Chip label
+
+ Chip label
+
```
diff --git a/src/elements/teaser-hero/teaser-hero.stories.ts b/src/elements/teaser-hero/teaser-hero.stories.ts
index 25d6d64fa9..3e7c23dc37 100644
--- a/src/elements/teaser-hero/teaser-hero.stories.ts
+++ b/src/elements/teaser-hero/teaser-hero.stories.ts
@@ -120,7 +120,9 @@ const Template = ({
: html`
- ${chipLabel}
+
+ ${chipLabel}
+
`}
diff --git a/src/elements/teaser-hero/teaser-hero.visual.spec.ts b/src/elements/teaser-hero/teaser-hero.visual.spec.ts
index 75995fe282..5423b4eeee 100644
--- a/src/elements/teaser-hero/teaser-hero.visual.spec.ts
+++ b/src/elements/teaser-hero/teaser-hero.visual.spec.ts
@@ -27,7 +27,9 @@ describe(`sbb-teaser-hero`, () => {
- Label
+
+ Label
+
`);
From 3ec88276840714f57309d0e78cce19bfcfc3efd1 Mon Sep 17 00:00:00 2001
From: Jeremias Peier
Date: Thu, 5 Dec 2024 09:00:45 +0100
Subject: [PATCH 37/47] fix: fix teaser product height styling
---
src/elements/core/styles/mixins/image.scss | 1 -
src/elements/teaser-product/common/teaser-product-common.scss | 3 ++-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/elements/core/styles/mixins/image.scss b/src/elements/core/styles/mixins/image.scss
index b3ccd25b3e..8124911314 100644
--- a/src/elements/core/styles/mixins/image.scss
+++ b/src/elements/core/styles/mixins/image.scss
@@ -6,7 +6,6 @@
grid-template-columns: 100%;
grid-auto-rows: auto;
margin: 0;
- height: 100%;
}
@mixin figure-image {
diff --git a/src/elements/teaser-product/common/teaser-product-common.scss b/src/elements/teaser-product/common/teaser-product-common.scss
index a2955bb60d..cb9c0caec8 100644
--- a/src/elements/teaser-product/common/teaser-product-common.scss
+++ b/src/elements/teaser-product/common/teaser-product-common.scss
@@ -64,7 +64,8 @@
}
::slotted([slot='image']) {
- display: block;
+ display: flex;
+ width: 100%;
height: 100%;
}
From 61a3a7f24577033ee0de3511d33d9eb55016c4e3 Mon Sep 17 00:00:00 2001
From: Tommmaso Menga
Date: Thu, 5 Dec 2024 11:47:26 +0100
Subject: [PATCH 38/47] style(img): use generic variables for ratio, fit and
position
---
.../container/container/container.scss | 3 +-
src/elements/core/styles/core.scss | 31 +++++++++----------
src/elements/core/styles/image.scss | 12 ++-----
.../flip-card-summary/flip-card-summary.scss | 2 +-
4 files changed, 20 insertions(+), 28 deletions(-)
diff --git a/src/elements/container/container/container.scss b/src/elements/container/container/container.scss
index 3b2a499f35..1b3a25217d 100644
--- a/src/elements/container/container/container.scss
+++ b/src/elements/container/container/container.scss
@@ -74,7 +74,8 @@
}
::slotted(img[slot='image']) {
- object-fit: cover;
+ --sbb-image-object-fit: cover;
+
height: 100%;
width: 100%;
}
diff --git a/src/elements/core/styles/core.scss b/src/elements/core/styles/core.scss
index 5e61509db8..8b05b843c0 100644
--- a/src/elements/core/styles/core.scss
+++ b/src/elements/core/styles/core.scss
@@ -154,6 +154,12 @@ input[data-sbb-time-input] {
}
}
+img {
+ aspect-ratio: var(--sbb-image-aspect-ratio);
+ object-fit: var(--sbb-image-object-fit);
+ object-position: var(--sbb-image-object-position);
+}
+
// Target the slotted `sbb-image` which are generally wrapped by a (therefore are not reachable with the :slotted)
// Apply the brightness effect on mouse hover
// TODO: Move back to the teaser components when the global css refactoring happens
@@ -182,15 +188,15 @@ input[data-sbb-time-input] {
// TODO: Move back to the teaser components when the global css refactoring happens
:is(sbb-teaser-product, sbb-teaser-product-static) {
- // Reset sbb-image border radius in order to control it from teaser product.
- sbb-image {
- border-radius: 0;
+ :is(sbb-image, img) {
+ border-radius: 0; // Reset sbb-image border radius in order to control it from teaser product.
+
+ --sbb-image-object-fit: cover;
+ --sbb-image-aspect-ratio: 16 / 9;
}
img {
place-self: stretch;
- object-fit: cover;
- aspect-ratio: 16 / 9;
}
}
@@ -203,14 +209,10 @@ input[data-sbb-time-input] {
scale: var(--sbb-teaser-scale, 1);
}
- sbb-image {
+ :is(sbb-image, img) {
+ --sbb-image-object-fit: cover;
--sbb-image-aspect-ratio: 4 / 3;
}
-
- img {
- object-fit: cover;
- aspect-ratio: 4/3;
- }
}
// TODO: Move back to the teaser-hero components when the global css refactoring happens
@@ -218,19 +220,16 @@ input[data-sbb-time-input] {
:is(sbb-image, img) {
--sbb-image-aspect-ratio: 1 / 1;
+ border-radius: 0;
+
@include mediaqueries.mq($from: small) {
--sbb-image-aspect-ratio: 16 / 9;
}
}
- sbb-image {
- border-radius: 0;
- }
-
img {
width: 100%;
display: block;
- aspect-ratio: var(--sbb-image-aspect-ratio);
}
}
diff --git a/src/elements/core/styles/image.scss b/src/elements/core/styles/image.scss
index 6e241fa2db..2d4f29b98b 100644
--- a/src/elements/core/styles/image.scss
+++ b/src/elements/core/styles/image.scss
@@ -48,16 +48,8 @@ $aspects-ratio: (
'16-9': '16 / 9',
);
@each $name, $ratio in $aspects-ratio {
- sbb-image {
- &.sbb-image-#{$name} {
- --sbb-image-aspect-ratio: #{$ratio};
- }
- }
-
- img {
- &.sbb-image-#{$name} {
- aspect-ratio: #{$ratio};
- }
+ :is(sbb-image, img).sbb-image-#{$name} {
+ --sbb-image-aspect-ratio: #{$ratio};
}
}
diff --git a/src/elements/flip-card/flip-card-summary/flip-card-summary.scss b/src/elements/flip-card/flip-card-summary/flip-card-summary.scss
index 8c44281a11..911a5f89ce 100644
--- a/src/elements/flip-card/flip-card-summary/flip-card-summary.scss
+++ b/src/elements/flip-card/flip-card-summary/flip-card-summary.scss
@@ -81,7 +81,7 @@
}
::slotted(img) {
- object-fit: cover;
+ --sbb-image-object-fit: cover;
}
::slotted(sbb-image) {
From 31fb1473ac1e0bb181e0414f5f4fb743630bf6af Mon Sep 17 00:00:00 2001
From: Tommmaso Menga
Date: Thu, 5 Dec 2024 14:56:38 +0100
Subject: [PATCH 39/47] feat(sbb-container): support the use of `figure` as bg
image
---
.../container/container/container.scss | 20 +++-----
.../container/container.visual.spec.ts | 51 ++++++++++++-------
src/elements/core/styles/core.scss | 20 ++++++--
3 files changed, 58 insertions(+), 33 deletions(-)
diff --git a/src/elements/container/container/container.scss b/src/elements/container/container/container.scss
index 1b3a25217d..0950dc6905 100644
--- a/src/elements/container/container/container.scss
+++ b/src/elements/container/container/container.scss
@@ -4,6 +4,8 @@
@include sbb.box-sizing;
:host {
+ --sbb-container-background-border-radius: 0;
+
display: block;
}
@@ -28,6 +30,12 @@
position: relative;
}
+:host(:not([expanded], [background-expanded])) {
+ @include sbb.mq($from: ultra) {
+ --sbb-container-background-border-radius: var(--sbb-border-radius-4x);
+ }
+}
+
.sbb-container {
background-color: var(--sbb-container-background-color);
padding: var(--sbb-container-padding);
@@ -62,20 +70,8 @@
}
::slotted([slot='image']) {
- border-radius: 0;
position: absolute;
inset: 0;
-
- :host(:not([expanded], [background-expanded])) & {
- @include sbb.mq($from: ultra) {
- border-radius: var(--sbb-border-radius-4x);
- }
- }
-}
-
-::slotted(img[slot='image']) {
- --sbb-image-object-fit: cover;
-
height: 100%;
width: 100%;
}
diff --git a/src/elements/container/container/container.visual.spec.ts b/src/elements/container/container/container.visual.spec.ts
index d95e6344d7..a94864a87b 100644
--- a/src/elements/container/container/container.visual.spec.ts
+++ b/src/elements/container/container/container.visual.spec.ts
@@ -25,10 +25,19 @@ describe(`sbb-container`, () => {
const images = [
{
+ name: 'sbb-image',
selector: 'sbb-image',
image: html``,
},
{
+ name: 'figure-sbb-image',
+ selector: 'sbb-image',
+ image: html`
+
+ `,
+ },
+ {
+ name: 'img',
selector: 'img',
image: html` {
alt=''
>`,
},
+ {
+ name: 'figure-img',
+ selector: 'img',
+ image: html`
+
+ `,
+ },
];
const containerContent = (): TemplateResult => html`
@@ -88,7 +104,7 @@ describe(`sbb-container`, () => {
describe(`expanded=${expanded}`, () => {
for (const image of images) {
it(
- `slotted=${image.selector}`,
+ `slotted=${image.name}`,
visualDiffDefault.with(async (setup) => {
await setup.withFixture(
html`
@@ -146,23 +162,24 @@ describe(`sbb-container`, () => {
}),
);
- it(
- `background-image`,
- visualDiffDefault.with(async (setup) => {
- await setup.withFixture(
- html`
-
- ${backgroundImageContent}
-
-
- `,
- wrapperStyles,
- );
+ for (const image of images) {
+ it(
+ `background-image slotted=${image.name}`,
+ visualDiffDefault.with(async (setup) => {
+ await setup.withFixture(
+ html`
+
+ ${backgroundImageContent} ${image.image}
+
+ `,
+ wrapperStyles,
+ );
- await setViewport(viewport);
- await waitForImageReady(setup.snapshotElement.querySelector('sbb-image')!);
- }),
- );
+ await setViewport(viewport);
+ await waitForImageReady(setup.snapshotElement.querySelector(image.selector)!);
+ }),
+ );
+ }
});
}
});
diff --git a/src/elements/core/styles/core.scss b/src/elements/core/styles/core.scss
index 8b05b843c0..f7c15dd3b4 100644
--- a/src/elements/core/styles/core.scss
+++ b/src/elements/core/styles/core.scss
@@ -160,6 +160,18 @@ img {
object-position: var(--sbb-image-object-position);
}
+// TODO: Move back to the sbb-container components when the global css refactoring happens
+sbb-container {
+ [slot='image']:is(sbb-image, img),
+ [slot='image'] :is(sbb-image, img) {
+ --sbb-image-object-fit: cover;
+
+ border-radius: var(--sbb-container-background-border-radius);
+ height: 100%;
+ position: absolute;
+ }
+}
+
// Target the slotted `sbb-image` which are generally wrapped by a (therefore are not reachable with the :slotted)
// Apply the brightness effect on mouse hover
// TODO: Move back to the teaser components when the global css refactoring happens
@@ -177,8 +189,8 @@ img {
}
}
- & [slot='image']:is(sbb-image, img),
- & [slot='image'] :is(sbb-image, img) {
+ [slot='image']:is(sbb-image, img),
+ [slot='image'] :is(sbb-image, img) {
will-change: filter;
filter: brightness(var(--sbb-teaser-image-brightness, 1));
transition: filter var(--sbb-teaser-image-animation-duration)
@@ -202,8 +214,8 @@ img {
// TODO: Move back to the teaser components when the global css refactoring happens
:is(sbb-teaser) {
- & [slot='image']:is(sbb-image, img),
- & [slot='image'] :is(sbb-image, img) {
+ [slot='image']:is(sbb-image, img),
+ [slot='image'] :is(sbb-image, img) {
transition-property: filter, scale;
will-change: filter, scale;
scale: var(--sbb-teaser-scale, 1);
From 385cfcdfb8b4a1d1b2581ccc1f26bc3f660ebe7e Mon Sep 17 00:00:00 2001
From: Tommmaso Menga
Date: Mon, 9 Dec 2024 09:36:00 +0100
Subject: [PATCH 40/47] feat(sbb-lead-container): support the use of `figure`
as lead image
---
src/elements/core/styles/core.scss | 14 ++-
.../lead-container/lead-container.scss | 11 +-
.../lead-container/lead-container.stories.ts | 114 +++++++++++-------
.../lead-container.visual.spec.ts | 93 +++++++++-----
4 files changed, 143 insertions(+), 89 deletions(-)
diff --git a/src/elements/core/styles/core.scss b/src/elements/core/styles/core.scss
index f7c15dd3b4..c4a6564a1c 100644
--- a/src/elements/core/styles/core.scss
+++ b/src/elements/core/styles/core.scss
@@ -154,7 +154,8 @@ input[data-sbb-time-input] {
}
}
-img {
+img,
+picture {
aspect-ratio: var(--sbb-image-aspect-ratio);
object-fit: var(--sbb-image-object-fit);
object-position: var(--sbb-image-object-position);
@@ -172,6 +173,17 @@ sbb-container {
}
}
+// TODO: Move back to the sbb-lead-container components when the global css refactoring happens
+sbb-lead-container {
+ [slot='image']:is(sbb-image, img, picture),
+ [slot='image'] :is(sbb-image, img, picture) {
+ --sbb-image-aspect-ratio: var(--sbb-lead-container-image-ratio);
+ --sbb-image-object-fit: cover;
+
+ border-radius: var(--sbb-lead-container-image-border-radius);
+ }
+}
+
// Target the slotted `sbb-image` which are generally wrapped by a (therefore are not reachable with the :slotted)
// Apply the brightness effect on mouse hover
// TODO: Move back to the teaser components when the global css refactoring happens
diff --git a/src/elements/lead-container/lead-container.scss b/src/elements/lead-container/lead-container.scss
index 91d99393d4..69f997a787 100644
--- a/src/elements/lead-container/lead-container.scss
+++ b/src/elements/lead-container/lead-container.scss
@@ -27,18 +27,9 @@
padding-block-end: var(--sbb-spacing-responsive-l);
}
-::slotted(sbb-image[slot='image']) {
- --sbb-image-aspect-ratio: var(--sbb-lead-container-image-ratio);
-
- border-radius: var(--sbb-lead-container-image-border-radius);
-}
-
-::slotted(:is(img[slot='image'], picture[slot='image'])) {
+::slotted([slot='image']) {
display: block;
width: 100%;
- object-fit: cover;
- aspect-ratio: var(--sbb-lead-container-image-ratio);
- border-radius: var(--sbb-lead-container-image-border-radius);
}
::slotted(:is(sbb-breadcrumb-group, sbb-block-link).sbb-lead-container-spacing) {
diff --git a/src/elements/lead-container/lead-container.stories.ts b/src/elements/lead-container/lead-container.stories.ts
index 15fc4a0f52..e99960e47c 100644
--- a/src/elements/lead-container/lead-container.stories.ts
+++ b/src/elements/lead-container/lead-container.stories.ts
@@ -3,6 +3,7 @@ import { html, type TemplateResult } from 'lit';
import '../alert.js';
import '../breadcrumb.js';
+import '../chip-label.js';
import '../image.js';
import '../link/block-link/block-link.js';
import '../notification.js';
@@ -13,60 +14,77 @@ import images from '../core/images.js';
import readme from './readme.md?raw';
+const content = (): TemplateResult => html`
+
+
+
+ The rail traffic between Allaman and Morges is interrupted. All trains are cancelled.
+
+
+
+
+ Level 1
+ Level 2
+ Level 3
+ Level 4
+
+
+ Link
+
+ Title
+
+ Lead text. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer enim elit, ultricies
+ in tincidunt quis, mattis eu quam. Nulla sit amet lorem fermentum, molestie nunc ut, hendrerit
+ risus.
+
+
+ Vestibulum rutrum elit et lacus sollicitudin, quis malesuada lorem vehicula. Suspendisse at
+ augue quis tellus vulputate tempor. Vivamus urna velit, varius nec est ac, mollis efficitur
+ lorem. Quisque non nisl eget massa interdum tempus. Praesent vel feugiat metus.
+
+
+ Other content. Vestibulum rutrum elit et lacus sollicitudin, quis malesuada lorem vehicula.
+ Suspendisse at augue quis tellus vulputate tempor. Vivamus urna velit, varius nec est ac, mollis
+ efficitur lorem. Quisque non nisl eget massa interdum tempus. Praesent vel feugiat metus.
+
+`;
+
const DefaultTemplate = (): TemplateResult => html`
-
+ ${content()};
-
-
+`;
+
+const WithChipTemplate = (): TemplateResult => html`
+
+ ${content()};
+
+
+
+
+ AI generated
- The rail traffic between Allaman and Morges is interrupted. All trains are cancelled.
-
-
-
-
- Level 1
- Level 2
- Level 3
- Level 4
-
-
- Link
-
- Title
-
- Lead text. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer enim elit,
- ultricies in tincidunt quis, mattis eu quam. Nulla sit amet lorem fermentum, molestie nunc ut,
- hendrerit risus.
-
-
- Vestibulum rutrum elit et lacus sollicitudin, quis malesuada lorem vehicula. Suspendisse at
- augue quis tellus vulputate tempor. Vivamus urna velit, varius nec est ac, mollis efficitur
- lorem. Quisque non nisl eget massa interdum tempus. Praesent vel feugiat metus.
-
-
- Other content. Vestibulum rutrum elit et lacus sollicitudin, quis malesuada lorem vehicula.
- Suspendisse at augue quis tellus vulputate tempor. Vivamus urna velit, varius nec est ac,
- mollis efficitur lorem. Quisque non nisl eget massa interdum tempus. Praesent vel feugiat
- metus.
-
+
`;
@@ -74,6 +92,10 @@ export const Default: StoryObj = {
render: DefaultTemplate,
};
+export const WithChip: StoryObj = {
+ render: WithChipTemplate,
+};
+
const meta: Meta = {
parameters: {
docs: {
diff --git a/src/elements/lead-container/lead-container.visual.spec.ts b/src/elements/lead-container/lead-container.visual.spec.ts
index 638ce85452..07128a9d96 100644
--- a/src/elements/lead-container/lead-container.visual.spec.ts
+++ b/src/elements/lead-container/lead-container.visual.spec.ts
@@ -10,6 +10,7 @@ import { waitForImageReady } from '../core/testing.js';
import '../alert.js';
import '../breadcrumb.js';
+import '../chip-label.js';
import '../image.js';
import '../link/block-link/block-link.js';
import '../notification.js';
@@ -22,14 +23,63 @@ const leadImageBase64 = await loadAssetAsBase64(leadImageUrl);
describe(`sbb-lead-container`, () => {
const wrapperStyles = { backgroundColor: `var(--sbb-color-milk)`, padding: '0' };
- const leadContainerTemplate = (image: TemplateResult): TemplateResult => html`
+ const testCases = [
+ {
+ title: 'with sbb-image',
+ imgSelector: 'sbb-image',
+ imgTemplate: () => html``,
+ },
+ {
+ title: 'with img tag',
+ imgSelector: 'img',
+ imgTemplate: () => html``,
+ },
+ {
+ title: 'with figure_sbb-image',
+ imgSelector: 'sbb-image',
+ imgTemplate: () =>
+ html`
+
+ AI generated
+ `,
+ },
+ {
+ title: 'with figure_img',
+ imgSelector: 'img',
+ imgTemplate: () =>
+ html`
+
+ AI generated
+ `,
+ },
+ {
+ title: 'with picture_sbb-image',
+ imgSelector: 'sbb-image',
+ imgTemplate: () =>
+ html`
+
+ AI generated
+ `,
+ },
+ {
+ title: 'with picture_img',
+ imgSelector: 'img',
+ imgTemplate: () =>
+ html`
+
+ AI generated
+ `,
+ },
+ ];
+
+ const leadContainerTemplate = (image: () => TemplateResult): TemplateResult => html`
- ${image}
+ ${image()}
{
`;
describeViewports(() => {
- it(
- 'with sbb-image',
- visualDiffDefault.with(async (setup) => {
- await setup.withFixture(
- leadContainerTemplate(
- html``,
- ),
- wrapperStyles,
- );
-
- await waitForImageReady(setup.snapshotElement.querySelector('sbb-image')!);
- }),
- );
-
- it(
- 'with img tag',
- visualDiffDefault.with(async (setup) => {
- await setup.withFixture(
- leadContainerTemplate(
- html``,
- ),
- wrapperStyles,
- );
+ for (const testCase of testCases) {
+ it(
+ testCase.title,
+ visualDiffDefault.with(async (setup) => {
+ await setup.withFixture(leadContainerTemplate(testCase.imgTemplate), wrapperStyles);
- await waitForImageReady(setup.snapshotElement.querySelector('img')!);
- }),
- );
+ await waitForImageReady(setup.snapshotElement.querySelector(testCase.imgSelector)!);
+ }),
+ );
+ }
});
});
From 1f875efa821d5e4bbed85a5b2648897d71c89fe6 Mon Sep 17 00:00:00 2001
From: Tommmaso Menga
Date: Mon, 9 Dec 2024 10:20:39 +0100
Subject: [PATCH 41/47] feat(sbb-flip-card): support the use of `figure` as
image
---
src/elements/core/styles/core.scss | 12 +++
.../flip-card-summary/flip-card-summary.scss | 11 +--
.../flip-card/flip-card/flip-card.stories.ts | 42 ++++++---
.../flip-card/flip-card.visual.spec.ts | 86 +++++++++++++++----
4 files changed, 114 insertions(+), 37 deletions(-)
diff --git a/src/elements/core/styles/core.scss b/src/elements/core/styles/core.scss
index c4a6564a1c..f17a517503 100644
--- a/src/elements/core/styles/core.scss
+++ b/src/elements/core/styles/core.scss
@@ -173,6 +173,18 @@ sbb-container {
}
}
+// TODO: Move back to the sbb-flip-card-summary components when the global css refactoring happens
+sbb-flip-card-summary {
+ [slot='image']:is(sbb-image, img),
+ [slot='image'] :is(sbb-image, img) {
+ --sbb-image-aspect-ratio: auto;
+ --sbb-image-object-fit: cover;
+
+ border-radius: 0;
+ height: 100%;
+ }
+}
+
// TODO: Move back to the sbb-lead-container components when the global css refactoring happens
sbb-lead-container {
[slot='image']:is(sbb-image, img, picture),
diff --git a/src/elements/flip-card/flip-card-summary/flip-card-summary.scss b/src/elements/flip-card/flip-card-summary/flip-card-summary.scss
index 911a5f89ce..8c4e74c294 100644
--- a/src/elements/flip-card/flip-card-summary/flip-card-summary.scss
+++ b/src/elements/flip-card/flip-card-summary/flip-card-summary.scss
@@ -74,16 +74,7 @@
}
}
-::slotted(:is(img, sbb-image)) {
- border-radius: 0;
+::slotted([slot='image']) {
width: 100%;
height: 100%;
}
-
-::slotted(img) {
- --sbb-image-object-fit: cover;
-}
-
-::slotted(sbb-image) {
- --sbb-image-aspect-ratio: auto;
-}
diff --git a/src/elements/flip-card/flip-card/flip-card.stories.ts b/src/elements/flip-card/flip-card/flip-card.stories.ts
index 101635a45f..6e97581f49 100644
--- a/src/elements/flip-card/flip-card/flip-card.stories.ts
+++ b/src/elements/flip-card/flip-card/flip-card.stories.ts
@@ -10,9 +10,10 @@ import sampleImages from '../../core/images.js';
import { SbbFlipCardElement } from './flip-card.js';
import readme from './readme.md?raw';
-import '../../image/image.js';
-import '../../link/link/link.js';
-import '../../title/title.js';
+import '../../chip-label.js';
+import '../../image.js';
+import '../../link/link.js';
+import '../../title.js';
import '../flip-card-details.js';
import '../flip-card-summary.js';
@@ -53,20 +54,30 @@ const defaultArgs: Args = {
'accessibility-label': undefined,
};
+const imgTemplate = (): TemplateResult => html`
+
+`;
+
+const imgWithChipTemplate = (): TemplateResult => html`
+
+
+ AI generated
+
+`;
+
const cardSummary = (
label: string,
imageAlignment: any,
showImage: boolean,
+ showChip?: boolean,
): TemplateResult => html`
${label}
- ${showImage
- ? html``
- : nothing}
+ ${showImage ? (showChip ? imgWithChipTemplate() : imgTemplate()) : nothing}
`;
@@ -84,6 +95,11 @@ const DefaultTemplate = (args: Args): TemplateResult =>
${cardSummary(args.label, args.imageAlignment, true)} ${cardDetails()}
`;
+const WithChipTemplate = (args: Args): TemplateResult =>
+ html`
+ ${cardSummary(args.label, args.imageAlignment, true, true)} ${cardDetails()}
+ `;
+
const NoImageTemplate = (args: Args): TemplateResult =>
html`
${cardSummary(args.label, args.imageAlignment, false)} ${cardDetails()}
@@ -153,6 +169,12 @@ export const ImageBelow: StoryObj = {
args: { ...defaultArgs, imageAlignment: imageAlignment.options![1] },
};
+export const WithChipOnImage: StoryObj = {
+ render: WithChipTemplate,
+ argTypes: defaultArgTypes,
+ args: { ...defaultArgs },
+};
+
export const NoImage: StoryObj = {
render: NoImageTemplate,
argTypes: defaultArgTypes,
diff --git a/src/elements/flip-card/flip-card/flip-card.visual.spec.ts b/src/elements/flip-card/flip-card/flip-card.visual.spec.ts
index 7ed3c32148..f7a619267b 100644
--- a/src/elements/flip-card/flip-card/flip-card.visual.spec.ts
+++ b/src/elements/flip-card/flip-card/flip-card.visual.spec.ts
@@ -15,9 +15,10 @@ import type { SbbFlipCardElement } from './flip-card.js';
import './flip-card.js';
import '../flip-card-summary.js';
import '../flip-card-details.js';
-import '../../title.js';
-import '../../link.js';
+import '../../chip-label.js';
import '../../image.js';
+import '../../link.js';
+import '../../title.js';
const imageUrl = import.meta.resolve('../../core/testing/assets/placeholder-image.png');
@@ -25,10 +26,13 @@ const content = (
title: string = 'Summary',
imageAlignment: SbbFlipCardImageAlignment = 'after',
longContent: boolean = false,
+ imgTemplate?: () => TemplateResult,
): TemplateResult =>
html`${title}
-
+ ${imgTemplate
+ ? imgTemplate()
+ : html``}
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam luctus ornare condimentum.
@@ -45,6 +49,37 @@ const content = (
Link`;
+const imgTestCases = [
+ {
+ title: 'with sbb-image',
+ imgSelector: 'sbb-image',
+ imgTemplate: () => html``,
+ },
+ {
+ title: 'with img tag',
+ imgSelector: 'img',
+ imgTemplate: () => html``,
+ },
+ {
+ title: 'with figure_sbb-image',
+ imgSelector: 'sbb-image',
+ imgTemplate: () =>
+ html`
+
+ AI generated
+ `,
+ },
+ {
+ title: 'with figure_img',
+ imgSelector: 'img',
+ imgTemplate: () =>
+ html`
+
+ AI generated
+ `,
+ },
+];
+
describe(`sbb-flip-card`, () => {
describeViewports({ viewports: ['zero', 'medium'] }, () => {
for (const imageAlignment of ['after', 'below']) {
@@ -95,20 +130,6 @@ describe(`sbb-flip-card`, () => {
}),
);
- for (const imageAlignment of ['after', 'below']) {
- it(
- `long content image-alignment=${imageAlignment}`,
- visualDiffDefault.with(async (setup) => {
- await setup.withFixture(
- html`
- ${content('Summary', imageAlignment as SbbFlipCardImageAlignment, true)}
- `,
- );
- await waitForImageReady(setup.snapshotElement.querySelector('sbb-image')!);
- }),
- );
- }
-
for (const imageAlignment of ['after', 'below']) {
describe(`imageAlignment=${imageAlignment}`, () => {
it(
@@ -146,6 +167,37 @@ describe(`sbb-flip-card`, () => {
await waitForImageReady(setup.snapshotElement.querySelector('sbb-image')!);
}),
);
+
+ it(
+ `long content`,
+ visualDiffDefault.with(async (setup) => {
+ await setup.withFixture(
+ html`
+ ${content('Summary', imageAlignment as SbbFlipCardImageAlignment, true)}
+ `,
+ );
+ await waitForImageReady(setup.snapshotElement.querySelector('sbb-image')!);
+ }),
+ );
+
+ for (const testCase of imgTestCases) {
+ it(
+ testCase.title,
+ visualDiffDefault.with(async (setup) => {
+ await setup.withFixture(
+ html`
+ ${content(
+ 'Summary',
+ imageAlignment as SbbFlipCardImageAlignment,
+ false,
+ testCase.imgTemplate,
+ )}
+ `,
+ );
+ await waitForImageReady(setup.snapshotElement.querySelector(testCase.imgSelector)!);
+ }),
+ );
+ }
});
}
From ab9cb93659b1637a534419b81bd45dcd436c852d Mon Sep 17 00:00:00 2001
From: Tommmaso Menga
Date: Mon, 9 Dec 2024 10:24:18 +0100
Subject: [PATCH 42/47] feat(sbb-container): support the use of `figure` as bg
image pt.2
---
src/elements/container/container/container.visual.spec.ts | 3 +++
1 file changed, 3 insertions(+)
diff --git a/src/elements/container/container/container.visual.spec.ts b/src/elements/container/container/container.visual.spec.ts
index a94864a87b..da75e666c8 100644
--- a/src/elements/container/container/container.visual.spec.ts
+++ b/src/elements/container/container/container.visual.spec.ts
@@ -11,6 +11,7 @@ import { waitForImageReady } from '../../core/testing.js';
import '../../button.js';
import '../../card.js';
+import '../../chip-label.js';
import '../../image.js';
import '../../title.js';
import './container.js';
@@ -34,6 +35,7 @@ describe(`sbb-container`, () => {
selector: 'sbb-image',
image: html`
+ AI generated`,
},
{
@@ -50,6 +52,7 @@ describe(`sbb-container`, () => {
selector: 'img',
image: html`
+ AI generated`,
},
];
From 1696197ec31778366f1021bd4555b51964814f87 Mon Sep 17 00:00:00 2001
From: Tommmaso Menga
Date: Mon, 9 Dec 2024 10:29:50 +0100
Subject: [PATCH 43/47] feat(sbb-lead-container): support the use of `figure`
as bg image pt.2
---
src/elements/lead-container/lead-container.stories.ts | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/elements/lead-container/lead-container.stories.ts b/src/elements/lead-container/lead-container.stories.ts
index 9ffeb925f8..10da1282f1 100644
--- a/src/elements/lead-container/lead-container.stories.ts
+++ b/src/elements/lead-container/lead-container.stories.ts
@@ -76,13 +76,13 @@ const WithChipTemplate = (): TemplateResult => html`
${content()};
-
+ AI generated
-
+
`;
From 87aacf7f6f78a4ec77eb82a5b17d96866a8bc6b8 Mon Sep 17 00:00:00 2001
From: Tommmaso Menga
Date: Mon, 9 Dec 2024 12:19:42 +0100
Subject: [PATCH 44/47] feat: support the use of `figure` as image pt.2
---
src/elements/core/styles/core.scss | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/src/elements/core/styles/core.scss b/src/elements/core/styles/core.scss
index f17a517503..f751792787 100644
--- a/src/elements/core/styles/core.scss
+++ b/src/elements/core/styles/core.scss
@@ -154,8 +154,7 @@ input[data-sbb-time-input] {
}
}
-img,
-picture {
+img {
aspect-ratio: var(--sbb-image-aspect-ratio);
object-fit: var(--sbb-image-object-fit);
object-position: var(--sbb-image-object-position);
From 9feca0dff2b8d2000e86d8b18935334c72f79e63 Mon Sep 17 00:00:00 2001
From: Tommmaso Menga
Date: Tue, 10 Dec 2024 12:52:13 +0100
Subject: [PATCH 45/47] feat(sbb-flip-card): support the use of `figure` as
image pt.2
---
src/elements/core/styles/core.scss | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/elements/core/styles/core.scss b/src/elements/core/styles/core.scss
index f751792787..1da26d7abc 100644
--- a/src/elements/core/styles/core.scss
+++ b/src/elements/core/styles/core.scss
@@ -180,6 +180,7 @@ sbb-flip-card-summary {
--sbb-image-object-fit: cover;
border-radius: 0;
+ display: block;
height: 100%;
}
}
From 155767d7ac26690b86ec554746f714cfdfb22143 Mon Sep 17 00:00:00 2001
From: Tommmaso Menga
Date: Wed, 11 Dec 2024 08:54:56 +0100
Subject: [PATCH 46/47] docs: add overlap chip doc
---
src/elements/container/container/readme.md | 15 +++++++++++++++
.../flip-card/flip-card-summary/readme.md | 19 ++++++++++++++++++-
src/elements/lead-container/readme.md | 15 +++++++++++++++
3 files changed, 48 insertions(+), 1 deletion(-)
diff --git a/src/elements/container/container/readme.md b/src/elements/container/container/readme.md
index e5a7cc9f83..3bb1543a81 100644
--- a/src/elements/container/container/readme.md
+++ b/src/elements/container/container/readme.md
@@ -19,6 +19,21 @@ use CSS object-position for slotted `img`, or `--sbb-image-object-position` vari
If an image is present, the container receives a pre-defined padding.
It's possible to override the padding by using the CSS variable `--sbb-container-padding`.
+Optionally, you can add an overlapping `sbb-chip-label` by wrapping the `sbb-image` in a `figure` tag (see [sbb-image doc](/docs/elements-sbb-image--docs#utility%classes)).
+
+```html
+
+
+
+ ...
+
+ ...
+
+```
+
## Style
By default `sbb-container` uses the `page spacing` defined in the [layout documentation](/docs/styles-layout--docs). Optionally the user can use the `expanded` property (default: `false`) to switch to the `page spacing expanded` layout.
diff --git a/src/elements/flip-card/flip-card-summary/readme.md b/src/elements/flip-card/flip-card-summary/readme.md
index 9063e233e4..c2cb95dd87 100644
--- a/src/elements/flip-card/flip-card-summary/readme.md
+++ b/src/elements/flip-card/flip-card-summary/readme.md
@@ -12,7 +12,24 @@ The component's slot is implicitly set to `"summary"`.
## Slots
-Use the unnamed slot of `sbb-flip-card-summary` to provide a title and, optionally, the `image` slot to provide an image (via either `sbb-image` or `img`).
+Use the unnamed slot to provide a title and the `image` slot to provide an image (via either `sbb-image` or `img`).
+
+Optionally, you can add an overlapping `sbb-chip-label` by wrapping the `sbb-image` in a `figure` tag (see [sbb-image doc](/docs/elements-sbb-image--docs#utility%classes)).
+
+```html
+
+
+ ...
+
+
+ ...
+
+
+
+```
diff --git a/src/elements/lead-container/readme.md b/src/elements/lead-container/readme.md
index 22291b3951..c675c422fc 100644
--- a/src/elements/lead-container/readme.md
+++ b/src/elements/lead-container/readme.md
@@ -67,6 +67,21 @@ Full example with applied spacings (CSS classes) in content:
```
+Optionally, you can add an overlapping `sbb-chip-label` by wrapping the `sbb-image` in a `figure` tag (see [sbb-image doc](/docs/elements-sbb-image--docs#utility%classes)).
+
+```html
+
+
+
+ ...
+
+ ...
+
+```
+
## Accessibility
Please either define the `alt` attribute of your image or set `aria-hidden="true"` to the image
From fcd0dc171bc84dc317960c8ef26db4a8e4c016df Mon Sep 17 00:00:00 2001
From: Tommmaso Menga
Date: Wed, 11 Dec 2024 08:57:36 +0100
Subject: [PATCH 47/47] fix: post-merge fix
---
src/elements/core/styles/core.scss | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/elements/core/styles/core.scss b/src/elements/core/styles/core.scss
index 1da26d7abc..220a7f68e3 100644
--- a/src/elements/core/styles/core.scss
+++ b/src/elements/core/styles/core.scss
@@ -202,7 +202,7 @@ sbb-lead-container {
:is(sbb-teaser, sbb-teaser-hero, sbb-teaser-product) {
--sbb-teaser-image-brightness-hover: var(--sbb-hover-image-brightness);
--sbb-teaser-image-animation-duration: var(
- --sbb-disable-animation-zero-duration,
+ --sbb-disable-animation-duration,
var(--sbb-animation-duration-4x)
);
--sbb-teaser-image-animation-easing: var(--sbb-animation-easing);