UI Kit Changelog
All notable changes to Laioutr UI Kit (@laioutr-core/ui-kit, the atomic Vue 3 design-system primitives) are documented here, following Keep a Changelog and Semantic Versioning.
2.3.0
Added
Countdowncomponent (#ui-kit/components/Countdown/Countdown.vue) and auseCountdowncomposable for editorial countdowns. Unit labels come fromIntl.NumberFormat, so they are localized and plural-aware automatically; theunitDisplayprop ('long' | 'short' | 'narrow') sets their verbosity.Countdownalso takes an optional frozennow(for tests/Storybook), and a purecomputeCountdown(endDate, now)helper is exported. Addscountdown.expiredandpromotionBanner.{codeCopiedTitle,codeCopiedSubline,copyCodeAriaLabel}locale entries (EN + DE).useNownow accepts an optional tick interval —useNow(intervalMs = 60_000)— and is seeded viauseState, so the shared clock renders byte-identically across SSR and hydration; consumers no longer needdata-allow-mismatchon time-dependent nodes.target?: stringprop onLinkTile,LinkTileBasic,LinkTileCompact,LinkTileBig, andNavigationMenuTextItem. Forwarded to the underlyingNuxtLink/MaybeLinkto open the link in a new browsing context (_blank), with_selfremaining the default.sectionBrandList.headingandsectionGlossaryList.headingtranslation keys (EN: "Brands"/"Glossary", DE: "Marken"/"Glossar"). These act as the locale-aware fallback heading when an editor leaves the section'sheadingfield empty.rel?: stringprop onButtonandIconButton. Forwarded to the underlyingNuxtLinkonly when the component renders as a link (hrefset), ignored when rendered as a<button>. Accepts any valid HTMLreltoken or space-separated combination — e.g.'prev','next','noopener','noopener noreferrer','external nofollow'.BlockProductDetailEnergyLabelon the Product Detail page. Renders the EU energy efficiency label: an inline energy-class badge (opening the full label in a lightbox) and an optional product data sheet link. Backed by a newProductVariantEnergyLabelcanonical-types entity component and a newEnergyLabelui component. Adds thepdp.energyLabeli18n key (EN + DE), used as the fallback alt text for the energy-label badge image. (Adapter packages still need to implement theProductVariantEnergyLabelresolver before storefronts render data.)
Changed
Mediais now a dispatcher. Images render via the built-in image renderer (unchanged public prop API and DOM/CSS output). Video and audio now render via new built-in native renderers:MediaVideo(native<video>) andMediaAudio(native<audio>with the optionalcovershown above it). AMediavalue of any type renders out of the box with no registration. Playback is controlled by new flat props on<Media>, mirroring the HTML attributes 1:1:controls(defaulttrue),autoplay,muted,loop,playsinline(defaultfalse). These are set by the consuming Block, not carried on theMediavalue. Consumers can override the built-in renderer for a media type (e.g. for HLS/DASH or a custom player):// plugins/media-renderers.ts import { provideMediaRenderers } from '#ui-kit/components/Media/MediaRenderersProvider'; import VidstackMedia from '../components/VidstackMedia.vue'; export default defineNuxtPlugin((nuxtApp) => { provideMediaRenderers(nuxtApp.vueApp, { video: VidstackMedia, audio: VidstackMedia }); });MediaStagenow drives its background<Media>as a decorative loop (autoplay muted loop playsinline,controls={false}); a picked video plays silently and loops behind the foreground content.MediaVideosuppressesautoplaywhen the user prefers reduced motion (prefers-reduced-motion: reduce), settling on theposterframe instead.Paginationnow emits SEO-correct sequence semantics whenhrefTemplateis set: the previous/next anchors carryrel="prev"/rel="next"only on edges where the target page actually exists; on the first page the previous control renders as a<button>(nohref), and on the last page the next control does the same, so crawlers don't follow dead links to page 0 or page N+1.
Removed
- Breaking: the orphaned
brandGrid.titletranslation key — it is no longer referenced anywhere. Consumers that overrode this key in custom locales can delete the override. PromotionBannerhas moved to@laioutr-core/ui(promo-codes are commerce-domain). ui-kit no longer exportsPromotionBanner/types— import from@laioutr-core/uiinstead.
Fixed
- Component props that were silently dropped because they didn't match the target component's API:
FeaturePillListpassedleft-icontoBadge(correct prop isicon-left), so pill icons never rendered;OpeningStatusIndicator,OpeningStatusDetail,LocationCard,LocationFinder, andLocationHeaderpassed a non-existentvarianttoText, sovariant="heading"headings rendered with defaultbodystyling;FilterBarboundv-model:opentoFilterOffCanvas(which exposesv-model:isOpen), so the off-canvas filter panel could not be opened;PromotionBannerpassed an invalidtype="text"toButton.
2.2.3
Added
$unitPricei18n formatter that renders aUnitPriceas a localizedprice / referencestring (e.g.13.99 € / 100 ml), composing the existing$moneyand$measurementformatters. Available as a template global alongside$money/$measurement, and used internally byVariantSelectionCard.
Fixed
.radius-containedcollapsing to square corners on tall elements. Inset banners (BannerBasic,BannerShowcase,BannerIntegrated,BrandHero) now keep their rounded corners regardless of height — previously a banner taller than the viewport width (common at mobile widths) lost its rounding entirely. Full-bleed, edge-to-edge banners still render square. No action required.OpeningStatuscomponents and composables now use the sharednowclock.
2.2.2
Changed
BackgroundAwareButton's adaptive lookup variants are nowadaptive-primary/adaptive-secondary/adaptive-ghost(previouslyprimary/secondary/ghost), so they no longer shadowButton's literalprimary/secondaryvariants. The pass-through variants (tertiary,secondary-white,ghost-*,glass-*,subtle,info,positive,danger,close-*) are unchanged. A newbackgroundAwareButtonFieldsshared field exposes the threeAdaptive *options in Studio alongside the literalButtonVariantoptions, now used by every section and block with a CTA (including header, footer email button, 404 page, and pricing-plan card).
Custom themes that overridebackgroundAwareButtonsindefineTheme/extendThemeneed their map keys renamed accordingly (light:light:primary→light:light:adaptive-primary, same forsecondaryandghostacross alllight|dark×light|dark|brightcombos). Stored Studio CTAs where an editor previously picked "Primary" or "Secondary" will render as the literal Button variant after upgrade — the per-surface remap is no longer applied unless the editor re-selects anAdaptive *option.- Breaking:
Scrollbarnow owns its interaction and sizing logic and takesprogress(0..1) andvisibleRatio(0..1) instead ofthumbSize/thumbPosition(px), and emitsupdate:progressinstead oftrack-click/drag-start. It computes thumb size/position, handles drag and track-click, and hides itself when content fits.<!-- Before --> <Scrollbar :thumb-size="120" :thumb-position="40" @track-click="onClick" @drag-start="onDragStart" /> <!-- After --> <Scrollbar :progress="0.3" :visible-ratio="0.25" @update:progress="(progress, source) => …" />sourceis'drag'(continuous) or'click'(jump-to-position).
Fixed
SwiperScrollbarthumb mis-sizing and mis-positioning underslidesPerView: 'auto': the thumb now reflects true content size (including gaps and uneven slide widths), dragging tracks the cursor, and clicking the track animates to the nearest slide. No API change forSwiperScrollbarconsumers.
2.2.1
Added
- Sizing-system consolidation: a new
Sizerprimitive in ui-kit and matchingsizingFieldshared schema in ui-app. Banner blocks (BlockBannerBasic,BlockBannerIntegrated,BlockBannerShowcase) plusBlockMediaandBlockIframenow route outer-box sizing throughSizerinstead of bespoke per-block fields. Banner blocks also gain vertical content alignment (2D on Basic, vertical-only on Integrated).Placeholderaccepts an optionaltextprop.
Removed
- Breaking:
Iframecomponent removed from@laioutr-core/ui-kit. Inline an<iframe class="…" :src :title />directly and letSizer(in your Block) drive the height. - Breaking:
MediaPreviewno longer acceptsaspectRatio,height, ororientation. Wrap in<Sizer :sizing="…">(or any parent that provides a definite height) and letMediaPreviewfill it. Portrait orientation is now done by typing a portraitaspect-ratiodirectly in the schema (e.g.3/4). - Breaking:
BannerBasic(@laioutr-core/ui) no longer acceptssizing/aspectRatioprops. Wrap in<Sizer>in the consuming Block. - Breaking:
BlockMediadropsaspectRatio,height, andorientationschema fields;BlockIframedropsdesktopHeightandmobileHeight. Existing pages with values stored under these names silently drop them on next save — author the desired height via the newsizingfield in Studio.
Fixed
SwiperChromemobile navigation positioning.
2.2.0
Added
CaptionFlagaccepts an optionaltextShadow?: 'none' | 'soft' | 'strong'prop. When'soft'or'strong', a layered text-shadow improves legibility against busy backgrounds. Defaults to'none', so existing consumers render unchanged. The values resolve from two new global CSS custom properties,--text-shadow-softand--text-shadow-strong, so consumers can override them per theme.HighlightedTextatom — renders a string with substring matches wrapped in<mark>. Diacritic-insensitive (NFD fold + combining-mark strip), highlights all occurrences, accepts ahighlightClassfor per-instance styling. Replaces the inline highlight loop inInputAutocomplete.- Opening-hours primitives in ui-kit:
useOpeningStatus(openingHours, now)composable (reactiveisOpen+ next state-change event across a 30-day horizon, respecting IANA timezone and one-off date exceptions),OpeningStatusIndicator(open/closed pill),OpeningStatusDetail(localized one-liner),OpeningStatus(Indicator + Detail combined), andOpeningHoursWeeklyTable(weekly schedule as aDescriptionList, grouping consecutive same-hours days). AddsopeningStatus.*,openingHoursWeeklyTable.*, andlocationCard.*i18n keys. (LocationCardandPaymentMethodListland in@laioutr-core/ui.) sectionBackground?: BackdropBackgroundprop onBackdrop. When set andcontainerStyle === 'boxed', an outer band element paints edge-to-edge around the constrainedOnSurfaceroot, creating two distinct color zones. Infull-widthmode the band is inert. Accepts the same value space asbackground; defaults to'none', so existing consumers render identically.block?: booleanprop onButton(and through extensionBackgroundAwareButton), defaulting tofalse. Whentrue, the button switches toflex+width: 100%and stretches to its container width. New Storybook story:Block.- An HTML-element selector next to every configurable heading/subline field across sections and blocks, via the existing
as: 'style'decorator popup (no more separate "SEO" panel). Heading optionsH1–H6/DIV; subline optionsP/H1–H6/DIV. Newly available on 13 sections and 7 blocks. Section defaults: heading →h2, subline →div. Block defaults: heading →h3, subline →h4. Components gain additive optionalheadingAs/sublineAsprops;CardgainsheadingAs?/sublineAs?;AlertDialoggainstitleAs/descriptionAs. buttonFieldsexposes a new Size selector per CTA (optionsxs/s/m/l, default'm') across every section and block with a CTA, plus a newbuttonSizeOptionsexport. ui consumers' CTA shapes (HeroSlide,PageNotFound,BannerShowcase,ContentGrid,HeaderBasic.ctaButtons[], slider cta types) accept an optionalsize;PlanCardgainsctaVariant/ctaSize;SwiperChrome.buttons[]acceptssize?: ButtonSize.laioutr:beforeModuleRegisterNuxt hook. Fires before the ui-kit module registers each upstream Nuxt module, with{ name, key, options }. Consumers can mutateoptionsto override defaults applied byregisterModule:// nuxt.config.ts export default defineNuxtConfig({ hooks: { 'laioutr:beforeModuleRegister': ({ name, options }) => { if (name === '@nuxt/image') { options.providers = { ...options.providers, customProvider: { /* … */ } }; } }, }, });
Changed
- Breaking:
TextGroupprop and type renames —headingTag→headingAs,sublineTag→sublineAs;TextGroupHeadingTag→TextGroupHeadingAs,TextGroupSublineTag→TextGroupSublineAs.TextGroupSublineAsis widened to include'h1'.SwiperChromegets the same rename plus an addedsublineAs. External consumers that import the old type names or bind:heading-tag/:subline-tagmust update to the new names. SectionProductSlider/SectionProductSliderShowcaselose their dedicated "SEO" fieldset;headingElementis now stored atheadingStyle.element. Action required: anyone with storedheadingElementvalues on these two sections must re-pick the heading element in Studio once.- The
highlightMatchutility now returns segments withhighlight: boolean(wasmatched: boolean) and finds every occurrence (was only the first).
Removed
- The
strawberry-fieldtheme.
Fixed
Card's body text not visually centering or end-aligning whentextAlignmentis set — the capped-width body box now follows the chosen alignment viaalign-self, matching the caption/heading/subline.
2.1.0
Changed
- Elevation shadows now route through the
--shadow-s/--shadow-m/--shadow-ldesign tokens instead of hardcodedbox-shadowvalues, so themes overriding these tokens take effect on Card, NavigationMenuContent, Select, ContextMenu, DropdownMenu, AlertDialog, Toast, ThemeEditor, the suggest-input dropdown, PlanCard, PersonaQuote, SearchAutoSuggest, and the variant-selector controls. Default-theme rendering is unchanged.
Fixed
NavigationMenuTextItemWrapperrendering white text on a light surface when used inside a topbar (inTopbar+surfaceTone="light"). Items now correctly inherit dark text on a light background. AffectsSectionTopBarwith its defaultcolorMode="grey"and any other consumer combininginTopbarwithsurfaceTone="light". No action required.
2.0.0
A large coordinated refactor across the UI layer (ui-kit, ui, ui-app). Only the @laioutr-core/ui-kit surface is summarized below; cross-package moves and Studio data migrations are noted where they affect ui-kit consumers. Migration code blocks are preserved verbatim at the end of this entry.
Added
- New components:
IconButton(icon-only button; requiredlabelrendered asaria-label, requiredicon),TextGroup(caption + heading + subline molecule),OnSurface(surface-tone context provider, replacesOnBackground),LinkTile(replacesCategoryCard),HighlightToggle(replacesBillingCycleSwitch),StatusMessage(generic icon-led message, replacesLoginReviewPanel),MediaStage(replacesCtaBannerBase),BadgePromotion(replacesSavingsBadge, redesigned),NavLinkItem(replacesMenuLinkItem),NavSectionHeading(replacesMenuSectionTitle/FooterTitle),SwiperChrome,Iframe(sandboxed wrapper), and the reka-ui atomsTabs,Popover,ContextMenu,Listbox,InputSlider,InputAutocomplete,InputCombobox,InputPin. - New
useSwiperEdgeState()anduseFieldContext(props)composables. The Swiper widget family (SwiperBullets,SwiperNumbers,SwiperNavBar,SwiperArrows,SwiperScrollbar,ThumbnailsSlider) andDarkModeSwitch,StockInfoSummary(wasBuyBoxStockInfo),LanguageSwitcher,RatingProgressBarFilter,CommonSwiper, and theswiperBreakpointshelper move into ui-kit. - Many new locale keys (countdown, pagination, social-share, variant-selection, opening-hours, and more). New CSS tokens
--on-light-*,--on-dark-*,--on-bright-*.
Changed
- Breaking —
Buttonrefactor.Button.typeremoved (use the newIconButton). Sizes'small' | 'medium' | 'large'→'xs' | 's' | 'm' | 'l'(default'm').ButtonVariantflattened to a single 14-value union;CtaButtonVariant/IconOnlyButtonVariantremoved.'input-field'→'subtle';'video-control'removed. Legacy alias layer dropped (LegacyButtonVariant,normalizeButtonVariant,VARIANT_ALIASES, …).iconLeft/iconRightnow acceptIconNameprops instead of#iconLeft/#iconRightslots.isLoading→loading; newspinnerType?: 'row' | 'round'.BackgroundAwareButtonVariantrebuilt to mirror the new shape — theme-levelbackgroundAwareButtonsmaps must rewrite their value entries. - Breaking — surface-tone migration.
OnBackgrounddeleted; useOnSurface+useSurfaceTone()(useSurfaceTone(props)resolves explicit prop > nearest ancestor context >'light').BackgroundBrightnesstype removed in favor ofSurfaceTone('light' | 'dark' | 'bright') across the Field, Input, Switch, Select, Checkbox,InputRadio, and Swatch families.colorToBackground→colorToSurfaceTone.Backdrop'scontainerBackgroundandbackgroundBrightnessprops removed — pass:backgrounddirectly.MediaPreview'smodeprop →surfaceTone.provideSurfaceToneContext→ internal_provideSurfaceToneContext(only<OnSurface>may set tone publicly). - Breaking — form prop normalization.
Fielddropserror: string(useerrorMessage+invalid).Input/InputAutocomplete/InputCombobox:isError→invalid.Label:error: boolean→invalid: boolean.SwitchandCheckbox: v-model channelchecked→ defaultmodelValue(v-model:checkedcall sites must becomev-model);Switchsize'small' | 'medium'→'s' | 'm'.Selectsizeprop removed (use:trigger="{ size: 's' }").InputPassword:readOnly→readonly. - Breaking —
is*prefix renames (dropiswhere the component is the subject):Badge.isRounded→rounded,Button.isLoading→loading,Label.isRequired→required,ThumbnailsSlider.isCentered→centered,Toast.isOpen→open,LinkTileBig.isBackgroundDark→backgroundDark,Pagination.isNavigationNumbers→variant: 'arrows' | 'numbers',OptionTileImage/OptionTileTextnotAvailableobject flattened tounavailable?+unavailableTooltip?. - Breaking — other prop / API changes.
Accordion.accordionStyle→variant.LoadingSpinner:type→variant, colorvariant→colorScheme, size'small' | 'large'→'s' | 'l'.IconListsize scale →'xs' | 's' | 'm'.Cardredesigned (size →'m' | 'l', many new props,Card/types.tsdeleted — importCardProps/CardCtafromCard.vue).BadgePromotionprops redesigned (BEM root.badge-promotion).Sheetdropscomponent/customClass. Various banner-refactor changes (variantprop removed from the three banners; border-radius now context-driven via.radius-contained).reka-uibumped^2.3.1→^2.9.6. - Numerous BEM/CSS class renames and the removal of
<style scoped>/:deep()/:global()across many components (full diff preserved below).
Removed
- Breaking:
OnBackground(useOnSurface),BillingCycleSwitch(useHighlightToggle),CategoryCard(useLinkTile),Breadcrumb(moved to ui asBreadcrumbsItem),Menubar,Stepper,HoverCard,DiscountFlag(useBadge),SavingsBadge(useBadgePromotion),SwiperNavigationNumbersWithArrows(useSwiperNavBarwithnavigationStyle="numbers"). - Moved out to
@laioutr-core/ui:LightboxGallery(→MediaGallery),SearchResultHeader(→SearchResultHero),ReviewForm,SocialShare,NavigationNodeButton(→MenuSideBySideNode).
Migration — imports and template tags
- import OnBackground from '#ui-kit/components/OnBackground/OnBackground.vue';
+ import OnSurface from '#ui-kit/components/OnSurface/OnSurface.vue';
- import { colorToBackground } from '#ui-kit/imports/colorToBackground';
+ import { colorToSurfaceTone } from '#ui-kit/imports/colorToSurfaceTone';
- import LightboxGallery from '#ui/components/LightboxGallery/LightboxGallery.vue';
+ import MediaGallery from '#ui/components/MediaGallery/MediaGallery.vue';
- import LoginReviewPanel from '#ui-kit/components/LoginReviewPanel/LoginReviewPanel.vue';
+ import StatusMessage from '#ui-kit/components/StatusMessage/StatusMessage.vue';
- import CategoryCard from '#ui-kit/components/CategoryCard/CategoryCard.vue';
+ import LinkTile from '#ui-kit/components/LinkTile/LinkTile.vue';
- import Card from '#ui/components/Card/Card.vue';
+ import Card from '#ui-kit/components/Card/Card.vue';
- import Iframe from '#ui/components/Iframe/Iframe.vue';
+ import Iframe from '#ui-kit/components/Iframe/Iframe.vue';
- import Media from '#ui/components/Media/Media.vue';
+ import MediaPreview from '#ui-kit/components/MediaPreview/MediaPreview.vue';
- <LuiProductSlider /> <!-- old: ui registered components with the Lui prefix -->
+ <LProductSlider /> <!-- new: ui uses L, matching ui-kit. Applies to every native-ui component. -->
Migration — props and bindings
- <Button type="icon" size="medium" />
+ <IconButton label="..." icon="..." size="m" />
- <Button>
- <template #iconLeft><Icon name="..." /></template>
- </Button>
+ <Button :icon-left="iconName" />
- <Button variant="input-field" />
+ <Button variant="subtle" />
- <Input :is-error="hasError" />
+ <Input :invalid="hasError" />
- <Field :error="errorString" />
+ <Field :error-message="errorString" />
+ <!-- Field auto-derives `invalid` from `errorMessage`. Pass :invalid="…" explicitly only to override. -->
- <Label :error="hasError" />
+ <Label :invalid="hasError" />
- <Select size="small" />
+ <Select :trigger="{ size: 's' }" />
- <Accordion accordion-style="..." />
+ <Accordion variant="..." />
- <SwatchChip color-mode="dark" />
+ <SwatchChip surface-tone="dark" />
- <Badge is-rounded />
+ <Badge rounded />
- <Toast :is-open="open" />
+ <Toast :open="open" />
- <Pagination :is-navigation-numbers="true" />
+ <Pagination variant="numbers" />
- <OptionTileImage :not-available="{ isNotAvailable: true, notAvailableTooltip: '…' }" />
+ <OptionTileImage unavailable unavailable-tooltip="…" />
- <LSwiperCompact />
+ <LSwiperNavBar />
- <LSwiperFadeoutArrows :has-fadeout-background="false" />
+ <LSwiperArrows :fadeout="false" />
- <LSwiperThumbnailsSlider />
+ <LThumbnailsSlider />
- <Switch v-model:checked="open" />
+ <Switch v-model="open" />
- <Checkbox v-model:checked="agreed" />
+ <Checkbox v-model="agreed" />
Migration — CSS class names
- .swatch-chip.is-selected { ... }
+ .swatch-chip--selected { ... }
- .switch--small { ... }
+ .switch--s { ... }
- .round-spinner-s { ... }
+ .round-spinner--s { ... }
- .swiper-chrome__head-top { ... }
+ .swiper-chrome__head--top { ... }
- .user-avatar { ... }
+ .avatar { ... }
- .toast__progress-bar { ... }
+ .toaster-progressbar { ... }
- .login-review-panel { ... }
+ .status-message { ... }
- .swatch-preview { ... }
+ .swatch { ... }
- .swatch-item { ... }
+ .swatch-option { ... }
- .product-tiles-swatches { ... }
+ .swatch-summary { ... }
- .menu-link-item { ... }
+ .nav-link-item { ... }
- .menu-section-title { ... }
+ .nav-section-heading { ... }
- .navigation-node-button { ... }
+ .menu-side-by-side-node { ... }
- .variant-option-selector-button, .variant-option-selector-image
+ .option-tile-text, .option-tile-image
- .zoom-level-mobile, .zoom-level-desktop
+ .zoom-level-segmented, .zoom-level-stepper
- .media-block* { ... }
+ .media-preview* { ... }
Studio data migration required for every renamed or deleted section/block component string, every renamed schema field, and every promoted or demoted section ↔ block. Custom themes that defined
backgroundAwareBackdropwith'default'must rewrite those entries with the equivalentSurfaceTone('default'was a synonym for'light').
1.34.0
Added
- New z-index token scale in ui-kit:
--z-index-sticky(100),--z-index-modal(1400),--z-index-popover(1500),--z-index-tooltip(1600),--z-index-toast(1700). Modal overlays and content share one token so stacked modals layer correctly via DOM order.
Changed
- All portaled components (Dialog, Sheet, AlertDialog, DropdownMenu, Select, Tooltip, MediaLightbox) now set z-index on their content class for reliable stacking. Header sections opt out of section isolation so their sticky/fixed chrome remains visible, and
FilterBarteleports its scroll-triggered fixed bar to<body>to escape section isolation, using an IntersectionObserver instead of hardcoded scroll thresholds.
1.33.0
Added
scrollToTopprop onPagination(defaults totrue), which scrolls the viewport to the top when navigating pages.
Fixed
Buttonnow emitsclickevents on theNuxtLinkbranch and forwards$attrson both root elements, enabling reka-uias-childto work correctly.SectionBlogPostListingnow uses reactive computed properties for client-side pagination.
1.32.5
Fixed
CardRichContent prop (:content→:html), simplifiedSocialSharelayout (removed an unnecessary wrapper div), and wrappedBlogPostDetailcontent in a container div.
1.32.2
Fixed
- CSS-layer order in Studio preview.
1.32.0
Added
$tlVue global for locale translations, plus 13 new message groups, full German translations, and umlaut fixes. Migrated 46 components fromuseLocale().tto$tltemplate calls.
Fixed
- Correct hover font-colors for some elements.
1.31.0
Added
$durationformatter for ISO 8601 duration strings. UsesIntl.DurationFormatwith locale awareness when available, falling back to narrow-style manual formatting (1h 30m 5s). Available as template global and auto-import.
Changed
$moneyand$measurementi18n formatters moved from frontend-core to ui-kit, removing dead code. Template globals and auto-imports work identically — no consumer changes needed.
1.30.0
Added
- An ESLint rule (
laioutr/require-css-layer) that enforces all new component CSS is layered.
Changed
- All component CSS is now wrapped in
@layer lui-components, allowing consumers to override component styles with unlayered CSS without needing!important. Existing@layer lui-overridableblocks (Icon, Text) are preserved.
1.29.3
Fixed
ThemeSwitcherimport andThemeWithMeta.Inputprop fallthrough and theShopHeaderclose-button.
1.29.0
Added
- Theme switcher support.
1.27.0
Fixed
HeroSliderMedia loading eagerness.
1.20.0
Added
SearchOverlayimplemented with actual data.
0.20.0
Fixed
- Minor type fixes.
0.19.11
Fixed
- Worked around a nuxt/image Hygraph provider bug that returned broken image URLs.
0.19.7
Fixed
- Prevent a frontend crash when the
Mediacomponent is not provided amediaprop.
0.19.0
Added
RichContentsupport for anHtmlFragmentprop.
0.18.0
Added
- A basic
strawberry-fieldtheme.
0.17.4
Fixed
- Build issue.
0.16.0
Added
- Detail variant switcher and add-to-cart toast.
0.15.0
Added
- Filter bar implementation and type adjustments.
0.14.3
Fixed
SectionShopHeaderNavigationnow respects menu data; fixedRichContentmargins.
0.14.1
Added
- Studio refresh compatibility.
0.14.0
Changed
- Improved LCP loading strategy.
0.13.0
Changed
- Accessibility improvements for desktop navigation and slider navigation.
0.12.0 – 0.11.0
Fixed
- Missing links; added
robots.txtand page SEO meta.
0.10.4
Changed
- Default color-mode set to
lightinstead ofsystem, since most e-commerce frontends do not provide a dark mode and being greeted with dark mode could confuse users.
0.10.2
Fixed
- Shopify product prices and minor frontend adjustments.
0.10.0
Fixed
- CSS layer order and swiper styles.
0.9.0 – 0.8.0
Added
- Adjusted definition default behaviour; added several sections and blocks to ui-app.
0.7.1
Fixed
- Import paths.
0.6.0
Added
- Section definitions; preparation for the Shopify demo.
0.5.0
Added
- Migrated base components into the UI Kit.