Skip to content

@gluonjs/core / packages/organisms/src / productCardStyles

Variable: productCardStyles ​

const productCardStyles: CSSStyleSheet

Example ​

Adopt the exact constructable ProductCard stylesheet and its CSS-variable hooks:

ts
import { html } from '@gluonjs/core';
import { AdminShell, AppShell, AsyncState, ConfirmationDialog, MegaMenu, PageLayout, ProductCard, ProductGallery, ProductGrid, SiteFooter, SiteHeader, SplitPane, WorkflowTimeline, adminShellStyles, asyncStateStyles, confirmationDialogStyles, createConfirmationDialogController, megaMenuStyles, organismManifest, organismStyles, pageLayoutStyles, productCardStyles, productGalleryStyles, productGridStyles, siteFooterStyles, siteHeaderStyles, splitPaneStyles, workflowTimelineStyles, type AdminShellAttributes, type AdminShellNavigationAttributes, type AdminShellProps, type AdminShellRegionAttributes, type AppShellProps, type AsyncStateAttributes, type AsyncStateHeadingLevel, type AsyncStateMessages, type AsyncStateProps, type AsyncStateStatus, type ConfirmationDialogAttributes, type ConfirmationDialogController, type ConfirmationDialogControllerOptions, type ConfirmationDialogInitialFocus, type ConfirmationDialogProps, type MegaMenuAttributes, type MegaMenuGroup, type MegaMenuLink, type MegaMenuLinkAttributes, type MegaMenuOpenChangeEvent, type MegaMenuProps, type MegaMenuTriggerAttributes, type PageLayoutAttributes, type PageLayoutHeadingLevel, type PageLayoutProps, type PageLayoutRegionAttributes, type ProductCardAttributes, type ProductCardProduct, type ProductCardProps, type ProductGalleryAttributes, type ProductGalleryImage, type ProductGalleryImageAttributes, type ProductGalleryProps, type ProductGridAttributes, type ProductGridColumns, type ProductGridProps, type SiteFooterAttributes, type SiteFooterNavigationAttributes, type SiteFooterProps, type SiteFooterRegionAttributes, type SiteHeaderAttributes, type SiteHeaderNavigationAttributes, type SiteHeaderOpenChangeEvent, type SiteHeaderProps, type SiteHeaderRegionAttributes, type SiteHeaderTriggerAttributes, type SplitPaneAttributes, type SplitPaneOpenChangeEvent, type SplitPaneOrientation, type SplitPaneProps, type SplitPaneRegionAttributes, type WorkflowTimelineProps, type WorkflowTimelineStatus, type WorkflowTimelineOverallState, type WorkflowTimelineAttributes, type WorkflowTimelineStep, type WorkflowTimelineMessages } from '@gluonjs/organisms';

const shell = {
  header: html`<strong>GLUON GOODS</strong>`,
  navigation: html`<a href="/shop">Shop</a><a href="/bag">Bag</a>`,
  children: html`<h1>New arrivals</h1>`,
  footer: html`<small>Free shipping over €100</small>`,
} satisfies AppShellProps;
const adminAttributes: AdminShellAttributes = { class: 'catalog-admin-shell' };
const adminRegionAttributes: AdminShellRegionAttributes = { class: 'catalog-admin-region' };
const adminNavigationAttributes: AdminShellNavigationAttributes = { class: 'catalog-admin-navigation' };
const adminShell: AdminShellProps = { id: 'catalog-admin', header: html`<strong>Back office</strong>`, sidebar: html`<a href='/overview'>Overview</a><a href='/settings'>Settings</a>`, main: html`<h1>Workspace</h1>`, footer: html`<small>Tenant: Gluon Goods</small>`, attributes: adminAttributes, headerAttributes: adminRegionAttributes, sidebarAttributes: adminRegionAttributes, navigationAttributes: adminNavigationAttributes, mainAttributes: adminRegionAttributes, footerAttributes: adminRegionAttributes, sidebarLabel: 'Back office navigation' };
const asyncStatus: AsyncStateStatus = 'partial';
const asyncAttributes: AsyncStateAttributes = { class: 'recommendations-state' };
const asyncMessages: AsyncStateMessages = { partial: 'Recommendations are partially loaded.' };
const asyncState: AsyncStateProps = { id: 'recommendations', status: asyncStatus, heading: 'Recommendations', headingLevel: 2 satisfies AsyncStateHeadingLevel, partialContent: html`<p>Profile data is ready while recommendations refresh.</p>`, actions: html`<button type="button">Retry</button>`, messages: asyncMessages, attributes: asyncAttributes };
const product: ProductCardProduct = { id: 'orbit-lamp', title: 'Orbit lamp', description: 'Adjustable light for focused work.' };
const productCardAttributes: ProductCardAttributes = { class: 'catalog-product-card' };
const productCard: ProductCardProps = { product, href: '/products/orbit-lamp', media: html`<img src="/assets/orbit-lamp.webp" alt="" />`, price: '€128', availability: 'In stock', actions: html`<button type="button">Add to bag</button>`, attributes: productCardAttributes };
const productColumns: ProductGridColumns = 3;
const productGridAttributes: ProductGridAttributes = { class: 'catalog-product-grid' };
const productGrid: ProductGridProps = { items: [product], columns: productColumns, renderCard: (item) => ProductCard({ product: item, price: '€128' }), emptyContent: 'No products found.', attributes: productGridAttributes };
const galleryImage: ProductGalleryImage = { id: 'orbit-primary', src: '/assets/orbit-lamp.webp', alt: 'Orbit lamp', primary: true };
const galleryImageAttributes: ProductGalleryImageAttributes = { class: 'catalog-gallery-image', loading: 'lazy' };
const galleryAttributes: ProductGalleryAttributes = { class: 'catalog-product-gallery', style: { '--gluon-product-gallery-gap': '1rem' } };
const productGallery: ProductGalleryProps = { id: 'catalog-gallery', label: 'Orbit lamp gallery', images: [{ ...galleryImage, attributes: galleryImageAttributes }, { id: 'orbit-detail', src: '/assets/orbit-lamp.webp', alt: '' }], attributes: galleryAttributes };
const initialFocus: ConfirmationDialogInitialFocus = '[data-confirm-primary]';
const confirmationOptions = { initialFocus } satisfies ConfirmationDialogControllerOptions;
const confirmationController: ConfirmationDialogController = createConfirmationDialogController(confirmationOptions);
const confirmationAttributes = { '@close': () => console.log('closed') } satisfies ConfirmationDialogAttributes;
const confirmation = { id: 'archive-confirmation', title: 'Archive order?', description: 'The caller owns the archive mutation.', safeAction: 'Cancel', primaryAction: html`<button data-confirm-primary>Archive</button>`, dismissOnBackdrop: false, controller: confirmationController, attributes: confirmationAttributes } satisfies ConfirmationDialogProps;
const workflowStep: WorkflowTimelineStep = { id: 'review', label: 'Review', status: 'current' satisfies WorkflowTimelineStatus, role: 'Reviewer', evidence: 'Ticket 42' };
const workflowState: WorkflowTimelineOverallState = 'degraded';
const workflowAttributes: WorkflowTimelineAttributes = { 'aria-label': 'Order workflow' };
const workflowMessages: WorkflowTimelineMessages = { timeline: 'Ablauf', status: (status) => `Status: ${status}`, step: (position, total) => `${position} von ${total}`, evidence: 'Nachweis' };
const workflow: WorkflowTimelineProps = { id: 'order-workflow', steps: [workflowStep], state: workflowState, messages: workflowMessages, role: 'Operations', evidence: 'Import log 42', attributes: workflowAttributes };
const megaLink: MegaMenuLink = { id: 'orbit-lamp', label: 'Orbit lamp', href: '/products/orbit-lamp', description: 'Adjustable light for focused work.' };
const megaGroup: MegaMenuGroup = { id: 'lighting', label: 'Lighting', links: [megaLink] };
const megaAttributes: MegaMenuAttributes = { class: 'catalog-mega-menu' };
const megaTriggerAttributes: MegaMenuTriggerAttributes = { class: 'catalog-mega-trigger' };
const megaLinkAttributes: MegaMenuLinkAttributes = { class: 'catalog-mega-link' };
const megaOpenChangeEvent: MegaMenuOpenChangeEvent = new MouseEvent('open-change');
const megaMenu: MegaMenuProps = { id: 'shop-menu', label: 'Shop navigation', trigger: 'Shop', groups: [megaGroup], open: true, attributes: megaAttributes, triggerAttributes: megaTriggerAttributes, onOpenChange: (open, event) => console.log('shop menu', open, event.type) };
const headerAttributes: SiteHeaderAttributes = { class: 'catalog-site-header' };
const headerNavigationAttributes: SiteHeaderNavigationAttributes = { 'aria-label': 'Catalog navigation' };
const headerRegionAttributes: SiteHeaderRegionAttributes = { class: 'catalog-header-region' };
const headerTriggerAttributes: SiteHeaderTriggerAttributes = { class: 'catalog-header-trigger' };
const headerOpenChangeEvent: SiteHeaderOpenChangeEvent = new MouseEvent('mobile-open-change');
const header: SiteHeaderProps = { id: 'catalog-header', brand: html`<a href='/'>GLUON GOODS</a>`, navigation: html`<a href='/shop'>Shop</a>`, actions: html`<button type='button'>Search</button>`, mobileNavigation: html`<a href='/shop'>Shop</a>`, attributes: headerAttributes, navigationAttributes: headerNavigationAttributes, brandAttributes: headerRegionAttributes, triggerAttributes: headerTriggerAttributes, onMobileOpenChange: (open, event) => console.log('mobile header', open, event.type) };
const footerAttributes: SiteFooterAttributes = { class: 'catalog-site-footer' };
const footerNavigationAttributes: SiteFooterNavigationAttributes = { 'aria-label': 'Catalog footer navigation' };
const footerRegionAttributes: SiteFooterRegionAttributes = { class: 'catalog-footer-region' };
const footer: SiteFooterProps = { id: 'catalog-footer', brand: html`<a href='/'>GLUON GOODS</a>`, navigation: html`<a href='/shop'>Shop</a><a href='/journal'>Journal</a>`, legal: html`<a href='/privacy'>Privacy</a>`, meta: html`<small>© 2026 Gluon Goods</small>`, attributes: footerAttributes, navigationAttributes: footerNavigationAttributes, brandAttributes: footerRegionAttributes, legalAttributes: footerRegionAttributes, metaAttributes: footerRegionAttributes };
const pageLayoutAttributes: PageLayoutAttributes = { class: 'catalog-page-layout' };
const pageLayoutHeadingLevel: PageLayoutHeadingLevel = 1;
const pageLayout: PageLayoutProps = { id: 'catalog-page', title: 'Catalog', headingLevel: pageLayoutHeadingLevel, breadcrumbs: html`<a href='/'>Home</a> / Catalog`, actions: html`<button type='button'>Create</button>`, children: html`<p>Caller-owned page content.</p>`, aside: html`<p>Related filters.</p>`, footer: html`<small>Tenant-owned metadata.</small>`, attributes: pageLayoutAttributes };
const splitPaneAttributes: SplitPaneAttributes = { class: 'catalog-split-pane' };
const splitPaneOrientation: SplitPaneOrientation = 'horizontal';
const splitPaneOpenChangeEvent: SplitPaneOpenChangeEvent = new MouseEvent('collapse-change');
const splitPane: SplitPaneProps = { id: 'catalog-workspace', primary: html`<p>Caller-owned workspace.</p>`, secondary: html`<p>Caller-owned inspector.</p>`, orientation: splitPaneOrientation, secondaryLabel: 'Inspector', attributes: splitPaneAttributes, onSecondaryCollapsedChange: (collapsed, event) => console.log('inspector', collapsed, event.type) };
console.log(AdminShell(adminShell), AppShell(shell), AsyncState(asyncState), MegaMenu(megaMenu), PageLayout(pageLayout), ProductCard(productCard), ProductGallery(productGallery), ProductGrid(productGrid), SiteFooter(footer), SiteHeader(header), SplitPane(splitPane), ConfirmationDialog(confirmation), WorkflowTimeline(workflow), adminShellStyles, asyncStateStyles, confirmationDialogStyles, megaMenuStyles, organismStyles, pageLayoutStyles, productCardStyles, productGalleryStyles, productGridStyles, siteFooterStyles, splitPaneStyles, siteHeaderStyles, workflowTimelineStyles, organismManifest.entries, megaOpenChangeEvent, headerOpenChangeEvent, splitPaneOpenChangeEvent);

Version-matched documentation. Examples are checked against the public package contracts.