-
Emit SEO and locale head tags automatically on every page. Each page now renders a self-referential
<link rel="canonical">,<link rel="alternate" hreflang>alternates for every market domain plusx-default,og:locale/og:locale:alternate, and<html lang>— with no per-page or per-layout call required. Alternates are scoped to a page'smarketIds, so a market-restricted page never advertises (or links to a 404 for) markets it does not belong to.MetaPagegains an optionalmarketIdsfield that carries this scope onto the route.Customize the emitted head with one new filter hook, registered in a Nuxt plugin:
frontend-core:page-head:resolve. Itsresult.valuecarries frontend-core's computed head in two slots —seo(title, description, robots, and any og/twitter field) andlocale(canonical, hreflang, og:locale, html lang) — so a handler can add, override, or remove any tag.Breaking: the
useMarketHead()composable is removed. hreflang and canonical links are now emitted automatically, and thefrontend-core:page-head:resolvehook replaces the customization it offered.// Before — manual call, typically in a layout useMarketHead(); // After — nothing to call; to customize, register the hook in a plugin nuxtApp.hook('frontend-core:page-head:resolve', ({ result }) => { result.value.locale.link = result.value.locale.link.filter((l) => l.hreflang !== 'x-default'); });
- Closed-option fields (
select/radio/toggle_button) now clamp a stored value that isn't one of the field's declared options to a valid option when resolving render props, instead of passing it through. Previously a malformed stored value (e.g. a double-encoded select value) could reach a dynamic component tag and throw at render, breaking the page.
-
Breaking:
DescriptionListis renamed toBasicTableandDescriptionListItemtoBasicTableRow— the generic two-column label/value table primitive (outlined/plainvariants). The label column is now overridable via the public--basic-table-label-colcustom property.OpeningHoursWeeklyTablealso moves out ofui-kitinto@laioutr-core/uiasTableOpeningHours.Repoint imports:
-import DescriptionList from '#ui-kit/components/DescriptionList/DescriptionList.vue'; -import DescriptionListItem from '#ui-kit/components/DescriptionList/DescriptionListItem.vue'; +import BasicTable from '#ui-kit/components/BasicTable/BasicTable.vue'; +import BasicTableRow from '#ui-kit/components/BasicTable/BasicTableRow.vue'; -import OpeningHoursWeeklyTable from '#ui-kit/components/OpeningHoursWeeklyTable/OpeningHoursWeeklyTable.vue'; +import TableOpeningHours from '#ui/components/TableOpeningHours/TableOpeningHours.vue';
BasicTablenow renders as a semantic description list (<dl>with<dt>/<dd>rows) instead of presentational<div>s, so label/value pairs are exposed to assistive technology. Grid/subgrid layout and the public CSS surface (.basic-tableroot class, BEM classes,--basic-table-label-col) are unchanged. (DEV-370) -
Editors can now override typography size and colour per heading and subline region in ContentGrid, ContentSlider, CategoryCardGrid, CategoryCardSlider, and EditorialGrid sections — selectable inline next to the existing
Heading as/Subline ascontrols. Leaving the newText SizeatDefaultkeeps the previous rendering. (DEV-31) -
Add
CountdownBoxed, a countdown that renders each unit (days, hours, minutes) as boxed digit tiles with a label, in four painted styles (default/pale/bright/solid). It counts down to anendDate(no start date) and reuses the existinguseCountdownclock. (DEV-47) -
Per-field Body Size + Color Override (DEV-31 C + B Foundation)
@laioutr-core/ui-kit— Card gains four optional props:bodySize?: TextSize(default's') — typography size for the description / body block.captionColor?/headingColor?/sublineColor?/bodyColor?: string— CSS-value colour overrides. When unset (or'initial'), the theme's default colour applies.
All four are pure additions; existing call sites render identically.
@laioutr-app/ui:- New shared field
shared-fields/textColor.ts— exportstextColorField(name'color', type'color',allowCustom: true). Use inline next totextSizeFieldinheadingStyle/sublineStyle/bodyStyle/contentStyledecorators. BlockTextandBlockCardextended end-to-end: schema addstextColornext totextSizein every style decorator, plus a newbodyStyle(on BlockText) / extendedcontentStyle(on BlockCard) that exposes both for the body region. Template forwards viacolorValueToCssto Card's new*Colorprops.
Caption text in CaptionFlag-based banners still has no colour override at the size scale — depends on a separate ui-kit primitive change to CaptionFlag.
-
Breaking — Card: the single
textSizeprop has been split into three per-region props:captionSize,headingSize,sublineSize. The new props accept the full typography scale ('xs' | 's' | 'sm' | 'm' | 'ml' | 'l' | 'xl' | '2xl' | '3xl' | '4xl').Defaults reproduce the previous
textSize='m'behaviour exactly:captionSize='s',headingSize='ml',sublineSize='m'. Existing consumers that did not passtextSizerender identically.Consumers that previously passed
:text-size="'s'"must update to:<Card :caption-size="'xs'" :heading-size="'m'" :subline-size="'sm'" />
:text-size="'l'"maps tocaptionSize='sm', headingSize='l', sublineSize='ml'.The body-text (
description) size is now fixed to's'(the historical default fortextSize=undefined). If a different body size was previously achieved throughtextSize, it is no longer adjustable via Card — wrap the description content in a<Text>element with an explicitsizeinstead.Breaking —
LTextGroup/SwiperChrometext tags: thecaptionTagprop (and theTextGroupCaptionTagtype) are removed — the caption always renders as<span>.headingAs/sublineAsno longer accept'span'; a heading or subline is always block-level (h1–h6/div, andpfor subline). No shipped configuration used either, so no data migration is required.Breaking — shared typography types: the per-component
TextGroupTextSize,TextGroupHeadingAs, andTextGroupSublineAsare replaced byTextSize,HeadingTag, andSublineTag, exported from the new#ui-kit/types/textmodule (consumed byCard,LTextGroup, andSwiperChrome). Update imports:// before import type { TextGroupHeadingAs, TextGroupTextSize } from '#ui-kit/components/TextGroup/TextGroup.vue'; // after import type { HeadingTag, TextSize } from '#ui-kit/types/text';
-
Add an independent tablet aspect-ratio stage to
Sizerand move theresponsive-fixeddesktop switch to the--lgbreakpoint (DEV-341)Sizernow resolves bothresponsive-aspect-ratioandresponsive-fixedagainst one breakpoint scheme, in lockstep with the Columns grid:- mobile (
< --sm, < 600px) — mobile values - tablet (
@media (--sm), 600–1279px) — new aspect-ratio stage, falling back to the mobile ratio when unset - desktop (
@media (--lg), ≥ 1280px) — desktop values
New
Sizing.aspectRatioTabletfield and--sizer-aspect-ratio-tabletcustom property. TheaspectRatioMobile/aspectRatioDesktopkeys are unchanged.Breaking: existing configs render differently across the 600–1279px band.
responsive-aspect-ratioconfigs with only a mobile and desktop ratio now show the mobile ratio from 600–1279px (previously the desktop ratio applied from 800px up). SetaspectRatioTabletto give tablets their own ratio.responsive-fixedconfigs now switch to the desktop height at 1280px instead of 800px, so the mobile height covers 0–1279px.
// responsive-aspect-ratio at a 900px viewport before: desktop ratio after: mobile ratio (or aspectRatioTablet, when set) - mobile (
-
Breaking:
BenefitsBoxnow renders a singlebenefitslist. The dedicated free-delivery row is gone —deliveryBenefitandisFreeDeliverywere removed fromBenefitsBoxProps. Free delivery is now just a regular benefit; add it as an entry inbenefits.// before <BenefitsBox :delivery-benefit="delivery" :is-free-delivery="false" :benefits="benefits" /> // after <BenefitsBox :benefits="[delivery, ...benefits]" />
(DEV-170)
-
Editors can now override typography size (and, where the existing schema didn't already expose one, colour) per heading and subline region in the Brand Hero, Page Hero, Page Not Found, Newsletter Registration, Product Slider, Product Slider Showcase, Logo Slider, and Logo Grid sections — selectable inline next to the existing
Heading as/Subline ascontrols. Leaving the newText SizeatDefaultkeeps the previous rendering. (DEV-31) -
PriceInfo: make the texts below the price configurable. New optional propsstrikethroughPriceLabel,vatInfo,shippingPrefix, andshippingSuffixoverride the respective labels, each falling back to its existingpdp.*locale string when empty. The newvatInfoVisibleprop toggles rendering of the tax/legal note, which previously always rendered. The displayed price values are unchanged. (DEV-329, SUPPORT-11) -
Per-field Text Size — Banner & HeroSlide rollout.
@laioutr-core/ui:BannerBasic,BannerIntegrated,BannerShowcasegain optionalheadingSize(and where applicablesublineSize) props on the full 10-step typography scale. Existing internal size→heading mappings remain as fallback defaults when the override is unset, so existing call sites render identically.HeroSlide:headingSize/sublineSizewidened from's' | 'm' | 'l'to the full 10-step scale. Existing values ('s' | 'm' | 'l') remain valid — pure widening.- Banner, HeroSlide, and the content / product / logo / category sliders and grids now type their
headingAs/sublineAs/ size props with the sharedHeadingTag/SublineTag/TextSizefrom#ui-kit/types/textinstead of per-component unions. Breaking:sublineAsno longer accepts'span'(a subline is always block-level:p/h1–h6/div); no shipped configuration used it.
@laioutr-app/ui:headingStyle/sublineStylestyle decorators inSectionBannerBasic,SectionBannerIntegrated,SectionBannerShowcase,BlockBannerBasic,BlockBannerIntegrated,BlockBannerShowcasenow expose an inlinetextSizeselect. Templates resolve viaresolveOverrideand forward to the underlying ui-component's per-region size prop.BlockHeroSliderSlideis not yet migrated — it already has a legacysizefield (S/M/L) on itsheadingStyle/sublineStylethat conflicts conceptually withtextSize. Unifying the two requires a one-time RcProject migration manifest and is a separate change.
Caption sizing (
captionVariant.textSize) remains out of scope pending CaptionFlag refactor + caption typography tokens beyondxl. -
PopUpPromotioncan now show a countdown instead of a coupon: setcountdownEndDate(and the optionalcountdownVariant) to render aCountdownBoxed. (DEV-47) -
Container: addgapMobile/gapDesktopprops to configure the spacing between child elements per breakpoint.auto(the default) preserves the previous hardcoded gap; an explicit value (none|s|m|l|xl) drives both axes. The gap now also applies at a single column (with two or more children) instead of only when a multi-column grid is active. (DEV-373, SUPPORT-8) -
Add
TableOpeningHours(moved fromui-kit, now built on theBasicTableprimitive) andTableProductSpecifications.TableOpeningHourskeeps its weekday-grouping logic and gains anoutlined/plainvariant;TableProductSpecificationsrenders specification rows overBasicTable, formatting each typed value (string | number | boolean | Measurement | Money) per locale via the newTableProductSpecificationsValuesubcomponent, and grouping rows into sections when asectionNameis present. (DEV-370) -
BannerIntegratedandBannerShowcase: render the caption throughCaptionFlagand accept acaptionVariantprop ({ variant, colorScheme, textShadow }), matchingBannerBasicand the Hero Slider caption. This enables plain/boxed styling, a colour scheme, and a text shadow on the banner caption.Breaking: the
captionColorprop was removed fromBannerIntegratedandBannerShowcase— caption colour is now governed bycaptionVariant.colorScheme(only applied in theboxedvariant). Migrate a freeform caption colour to a boxed caption:<!-- before --> <BannerShowcase caption="Sale" caption-color="#ffffff" /> <!-- after --> <BannerShowcase caption="Sale" :caption-variant="{ variant: 'boxed', colorScheme: 'primary' }" />
The default (plain caption, no shadow) renders via
CaptionFlag; the caption now follows the shared caption-flag typography (uppercase) like the other banners. (DEV-342, SUPPORT-26) -
SectionBannerBasic,SectionBannerIntegrated, andSectionBannerShowcase: expose the caption-styling controls (plain/boxed style, colour scheme, text shadow) at the caption field in Studio, identical to the Hero Slider caption. The colour control is only shown when the style is set to boxed. Existing banners keep their look (default plain, no shadow). (DEV-342, SUPPORT-26) -
Content Slider: added a "Card-Design" panel that lets editors choose the heading element (H1–H6 / DIV) for cards generated from a blog collection (query mode). The section's own styling panel is now labelled "Slider-Design" to distinguish it from the card controls.
-
Per-field Text Size foundation. Editors can now override the typography size for
headingandsublineregions independently of the block-widesize(S / M / L) default, on the full 10-step scale (xs · s · sm · m · ml · l · xl · 2xl · 3xl · 4xl).New shared field:
shared-fields/textSize.ts— exportstextSizeField(select, first option'auto'= inherit) andtextSizeOptions. Use inline as a second field in anyheadingStyle/sublineStylestyle decorator.
New utility:
utils/resolveTextSize.ts—resolveHeadingSize/resolveSublineSize/resolveCaptionSize(map a block's' | 'm' | 'l'+ optional override to a region-specific size) plusresolveOverride(override-or-undefined, for Card-style blocks without a block-level size default).
Migrated to the new pattern in this release:
BlockText— heading + subline both honourheadingStyle.textSize/sublineStyle.textSize.BlockCard— heading honoursheadingStyle.textSize.
Caption (
captionVariant) is intentionally not included yet — CaptionFlag has nosizeprop today and caption tokens stop atxl. Tracking as a follow-up.The remaining sections/blocks that have
headingStyle/sublineStyleare unchanged for now; their schemas will gaintextSizeas their underlying ui-component is widened to accept per-region sizes. -
BlockPopUpPromotionnow offers aPromotion typetoggle to switch between a voucher (discount code) and a countdown. The countdown runs toward a configurable end date and exposes a style selector. (DEV-47) -
SectionContainer: expose Gap (Mobile) and Gap (Desktop) controls in Design → Layout so editors can set the spacing between child elements. Fixes the 0px vertical gap on single-column mobile layouts. (DEV-373, SUPPORT-8) -
Add
SectionPopUp, a modal overlay section, together with three content blocks selectable in its slot:BlockPopUpInfo,BlockPopUpNewsletter, andBlockPopUpPromotion. The section wraps thePopUpcomponent and each block wraps its matchingPopUpInfo/PopUpNewsletter/PopUpPromotioncomponent, exposing their content and layout as Studio fields. The pop-up opens on mount and can be dismissed by the visitor; triggers, scheduling, and frequency capping are not wired yet. (DEV-47) -
Add a Tablet aspect-ratio field to
sizingFieldand clarify the sizing Mode copy (DEV-341, DEV-333)- A
Tabletaspect-ratio field now sits betweenMobileandDesktop, shown when the mode isresponsive-aspect-ratio. It maps toSizer'saspectRatioTabletand falls back to the Mobile ratio when left empty.Mobile/Desktopare unchanged. - The Mode select now describes each mode in plain intent words, with hints for Auto and Fill. No runtime change —
autostill applies no height,fillstill fills the parent's height.
BlockMediaandBlockIframeuse the sharedsizingField, so they pick up the Tablet field automatically. Their prop types are unaffected. - A
-
Add two standalone Studio blocks:
BlockTableOpeningHoursandBlockTableProductSpecifications. Each can be filled either from a query (a Location's opening hours / a Product'sspecifications) or with manually entered rows, switchable via aData Sourcetoggle, and exposes anoutlined/plainstyle toggle.BlockTableProductSpecificationsforwards the product's typed specification values unchanged and supports per-row sections (an optionalSectionfield on manual rows) for grouped output. (DEV-370) -
Hero-slider slides now use the same
Text Sizeselector as every other section and block (the 10-step scalexs · s · sm · m · ml · l · xl · 2xl · 3xl · 4xlplusDefault). The former slide-specificS/M/Lsize selector onBlockHeroSliderSlide'sheadingStyleandsublineStylehas been replaced by the canonicaltextSizeField. Existing slides with a storedsizeof's'/'m'/'l'are rewritten to the newtextSizefield via the migration manifest — the values stay valid on the new scale, so the rendering is unchanged. (DEV-380) -
BlockProductDetailPriceInfo: add Studio fields to configure the texts below the price (strikethrough-price label, tax/legal note with a visibility toggle, and shipping-note prefix/suffix). Empty fields keep the translated defaults. The block now also binds the variant's shipping rate (already fetched viaProductVariantShipping), so the shipping line ("zzgl. 5,95 € Versand") renders on the PDP. All values still come from the product — no query change. (DEV-329, SUPPORT-11) -
Breaking:
BlockProductDetailBenefitsBoxno longer has a separate free-delivery configuration. ThedeliveryBenefitobject field and the forced free-delivery row were removed — the block now exposes only thebenefitslist, with free delivery pre-filled as a normal, removable default benefit. Stored configs lose theirdeliveryBenefit/isFreeDeliveryvalues; re-add free delivery as a benefit entry where needed.(DEV-170)
-
Accordionnow expands and collapses smoothly instead of jolting open. The content animation easing changed fromease-outtoease-in-out(and the duration from0.2sto0.25s), so the content slides rather than shooting out and decelerating. The catch-alltransition: allon the item was also narrowed to the properties that actually change (background-color,outline-color,border-color). -
CaptionFlag: hug the caption text (width: fit-content) instead of stretching to full width when placed as a flex item in a column withalign-items: stretch(e.g. a banner text stack). Center/end alignment from the parent is still honoured. Fixes the boxed caption spanning the full banner width. (DEV-342, SUPPORT-26) -
LinkTileBasicimages now render sharp at any tile width.The
<Media>sizeshint onLinkTileBasicstays at its nominal103pxbut now enablesretina, so a standalone tile is crisp on 2× displays. When the tile is stretched to fill a grid cell,CategoryCardGridprovides a layout-accurate, breakpoint-awaresizesvalue (viaMediaSizesProvider) for every variant and column-count, so<Media>requests an appropriately sized srcset instead of upscaling the 103px image. (DEV-69) -
OptionTileTextandOptionTileImagenow expose their state to assistive technology. The selected option is signalled viaaria-pressed(previously only a CSS class, so screen readers couldn't tell which option was active), unavailable tiles carryaria-disabled="true"and the samearia-pressedstate as available ones, andOptionTileImagebuttons get an accessible name from thelabelprop viaaria-label(it was previously never rendered). Both buttons are also explicitlytype="button". This makes the variant selector composing these tiles (VariantSelectorOptions) announce option state correctly. -
SwiperChrome: bottom-rendered slider navigation now aligns totextAligninstead of always rendering centered. Fixes misaligned buttons in the Logo Slider (and otherSwiperChrome-based sliders) on mobile when the section is set toleftalignment. (DEV-369) -
MobileMenuBasic: the social icon buttons in the footer now use theghost-whitebutton style with a white icon instead ofsecondary-whitewith a dark icon. The variant follows the documented design (ghost buttons on a colored footer background). (DEV-348) -
QuoteCard: das Logo rendert jetzt scharf auf Retina/HiDPI-Displays. Die Media-Komponente bekommt das
retina-Flag, sodass für die fix-breite Anzeige (130×50) zusätzlich eine 2x-Variante imsrcsetausgespielt wird statt nur die 1x-Variante hochzuskalieren. (DEV-379) -
The Basic Header's mobile menu button now adapts to the header's surface tone. Previously the button surface and the menu icon stayed dark regardless of the header configuration, so on a header set to light text on a dark background the button and its icon were invisible. The trigger now switches to the light token set on dark headers, and its icon colour follows the active theme instead of a hardcoded black. (DEV-349)
-
SectionProductSliderShowcase: add an "Image background" colour control for the product tiles and pass it through as the tilefallbackColor, so the tile image background can be set — matching the normal Product Slider. Previously the showcase's tiles had no image-background option (its existing "Image Background" field styles the banner, not the tiles). (DEV-70)