No Preview

Sorry, but you either have no stories or none are selected somehow.

If the problem persists, check the browser console, or the terminal you've run Storybook from.

The component failed to render properly, likely due to a configuration issue in Storybook. Here are some common causes and how you can address them:

  1. Missing Context/Providers: You can use decorators to supply specific contexts or providers, which are sometimes necessary for components to render correctly. For detailed instructions on using decorators, please visit the Decorators documentation.
  2. Misconfigured Webpack or Vite: Verify that Storybook picks up all necessary settings for loaders, plugins, and other relevant parameters. You can find step-by-step guides for configuring Webpack or Vite with Storybook.
  3. Missing Environment Variables: Your Storybook may require specific environment variables to function as intended. You can set up custom environment variables as outlined in the Environment Variables documentation.

Highlight essential product details and provide an entry point to access in-depth information.

<a href="#" class="card product-card"> <div class="card-body product-navigation bg-white"> <h3 class="mb-regular">Produkta</h3> <p class="lead">Ĉi tio estas mallonga priskribo de la produkto.</p> <span class="link-icon"> <post-icon name="3020" aria-hidden="true"></post-icon> <span>Lernu pli</span> </span> </div> </a>
NameDescriptionDefaultControl
General
Title
Defines the text in the heading tag.
string
-
Heading Level
Defines the hierarchical level of the product card title within the heading structure.
string
-
Text
Defines the text displayed under the heading tag.
string
-

Make sure the @swisspost/design-system-styles package is already present in your project or follow the installation guidelines.

To import all Design System styles:

@use '@swisspost/design-system-styles/index.scss';

To import only the styles required for this component:

@use '@swisspost/design-system-styles/basics.scss'; @use '@swisspost/design-system-styles/components/card.scss'; @use '@swisspost/design-system-styles/components/product-card.scss';

For organizing multiple product cards in a group, utilize the grid system. Ensure consistent height by applying the .h-100 class to all product cards.

For presenting a collection of products with comparable features, use cards with multiple sections, as illustrated in the example below.

Note that this layout necessitates JavaScript implementation to ensure consistent section heights across all cards.

Preiswert

Sample Product

Mit SAMPLE PRODUCT kommen Ihre Briefe kostengünstig und zuverlässig ans Ziel.

Sample Product

140 x 90 mm bis B5 (250 x 176 mm)

bis 500 g
1.20
bis 50 g
2.20
Sample Product

140 x 90 mm bis B5 (250 x 176 mm)

so zwischen ca. 5g
bis ungefähr etwa 500 g
1.20
bis 50 g
2.20
bis 100 g
2.90
bis 100 g
2.90
bis 100 g
2.90
bis 100 g
2.90
Sample Product

140 x 90 mm bis B5 (250 x 176 mm)

bis 500 g
1.20
bis 50 g
2.20
bis 100 g
2.90

Schneller

Sample Product

Lorem ipsum aafw ea aewfwe awef awfeaea awefa wawef waf wawefa ea dolor sit amet consectetur adipisicing elit. Iusto nulla laboriosam nesciunt. Unde velit dolores at fugiat dolorum nobis sit.

Sample Product

140 x 90 mm bis B5 (250 x 176 mm)

bis 500 g
1.20
bis 50 g
2.20
bis 100 g
2.90
Sample Product

140 x 90 mm bis B5 (250 x 176 mm)

so zwischen ca. 5g
bis ungefähr etwa 500 g
1.20
bis 50 g
2.20
bis 100 g
2.90
Sample Product

140 x 90 mm bis B5 (250 x 176 mm)

bis 500 g
1.20
bis 50 g
2.20
bis 100 g
2.90
Vanilla JavaScript
function syncHeights() { const nodes = document.querySelectorAll('[data-sync-height-with]'); const heightByGroup = new Map(); nodes.forEach(node => { const group = node.getAttribute('data-sync-height-with'); const groupHeight = heightByGroup.get(group); node.style.height = 'auto'; const nodeHeight = node.offsetHeight; if (!groupHeight || nodeHeight > groupHeight) { heightByGroup.set(group, nodeHeight); } }); heightByGroup.forEach((height, group) => { const groupNodes = document.querySelectorAll( `[data-sync-height-with="${group}"]` ); groupNodes.forEach(node => { node.style.height = `${height}px`; }); }); } let timer; window.addEventListener('resize', () => { if (timer) clearTimeout(timer); timer = setTimeout(() => { syncHeights(); }, 300); }); syncHeights();
Angular Implementation
import { Component, HostListener, OnDestroy, OnInit } from '@angular/core'; import { debounceTime, Subject } from 'rxjs'; @Component({ selector: 'post-product-cards', templateUrl: './post-product-cards.component.html', }) export class PostProductCardsComponent implements OnInit, OnDestroy { resize$ = new Subject<void>(); ngOnInit() { this.resize$ .asObservable() .pipe(debounceTime(300)) .subscribe(() => { this.syncHeight(); }); this.resize$.next(); } ngOnDestroy() { this.resize$.complete(); } syncHeight() { const nodes: NodeListOf<HTMLElement> = document.querySelectorAll('[data-sync-height-with]'); const heightByGroup = new Map<string, number>(); nodes.forEach(node => { const group = node.getAttribute('data-sync-height-with'); const groupHeight = heightByGroup.get(group); const nodeHeight = node.offsetHeight; if (!groupHeight || nodeHeight > groupHeight) { heightByGroup.set(group, nodeHeight); } }); heightByGroup.forEach((height, group) => { const groupNodes: NodeListOf<HTMLElement> = document.querySelectorAll( `[data-sync-height-with="${group}"]`, ); groupNodes.forEach(node => { node.style.height = `${height}px`; }); }); } @HostListener('window:resize') onResize(): void { this.resize$.next(); } }