Skip to content

Changelog

UspBanner

Every released version of UspBanner, newest first.

Storefront 4 releases latest 0.1.3RepositoryDocumentation

Fixed

  • Let the benefits slider take all the room next to the language and currency switchers from lg up. The centred middle track sized itself to the slides' content, so the benefits sat cramped in the middle once Splide rendered no loop clones while all benefits fit (GUPPY-329).

Fixed

  • Mount the banner slider with the shared Splide extensions from DmfSplideSlider via the new getSplideExtensions() helper, so dragging and loop clones are disabled while all benefits fit and there is nothing to scroll (GUPPY-329).

  • Read Splide through getSplide(), like DmfCmsBlog and DmfCmsCustomElements. A missing DmfSplideSlider plugin now throws an error instead of silently leaving the banner unmounted (GUPPY-329).

Added

  • Replace the plain URL field for banner links with the link picker Shopware's CMS elements use: an internal category, product or media file, an e-mail address, a phone number or an external URL. Internal targets are resolved per sales channel and language (GUPPY-300).

Fixed

  • Lay out the top bar on three tracks from lg up: an empty one mirroring the language and currency switchers, the banner, and the switchers. The banner now sits on the page's centre and pushes the switchers aside instead of sliding underneath them when it grows (GUPPY-300).

  • Turn the benefits into a slider below 1200 px instead of 1024 px (GUPPY-300).

  • Apply the left link position only to a single text; the benefits slider always stays centred (GUPPY-300).

  • Clip the banner background breakout in the header. The background now paints out to the viewport edges with calc(50% - 50vw) instead of -100vmax, and .header-main trims the scrollbar-width overhang with overflow-x: clip, only while a banner is shown.

Added

  • Add a USP banner to the storefront top bar - the customer benefits a shop wants above its header, such as free shipping over a threshold or a returns period. One banner per sales channel, maintained in the administration under Inhalte, in two layouts: Standard, a single text with an optional link, and Vorteile, up to three benefit texts shown side by side and turned into a slider where they do not fit. A banner renders only when it is switched on, belongs to the current sales channel and carries copy in the current language; anything else produces no markup at all rather than an empty strip (GUPPY-300).

  • Store the banner in its own entity with a translation table (dmf_usp_banner, dmf_usp_banner_translation) rather than in theme configuration, which is where this lived before. Theme configuration is resolved once per theme compile and stored per theme, so every sales channel sharing a theme also shared one set of benefit texts, and there was no language dimension at all - a shop running one channel in two languages could only ever show one of them. Every merchant-entered string is translatable, the link included, because a second language usually points at a different landing page. One row per channel is enforced by a unique index on sales_channel_id and, in the administration, by filtering channels that already have a banner out of the select (GUPPY-300).

  • Give each banner its own background, text and hover colour, replacing the theme-wide guppy-usp-* settings. The background covers the whole strip, the language and currency switchers included, so the banner reads as one component rather than a coloured patch beside the theme's own colours. The hover colour is optional: left empty, everything that hovers keeps the text colour instead of jumping to a default nobody chose (GUPPY-300).

  • Check the text colour against the background in the administration and warn below WCAG 2.1 AA's 4.5:1 (BFSG). The ratio is shown next to the pickers, green above the threshold and red below it, and a banner spells out the failing case in words so the signal is not carried by colour alone. The hover pair is checked as well, but only once a hover colour is set - otherwise it would report the resting pair a second time. Saving is never blocked: the merchant picks the colours and the decision stays theirs (GUPPY-300).

  • Add own ACL privileges under dmf_usp_banner rather than riding on a core content role. A user who may edit categories has no rights on this entity, so gating the interface on content.* would pass every check in the administration and then fail with a 403 from the API (GUPPY-300).

Changed

  • The strip sits inside the header's .container, but its background belongs to the full width of the viewport, so a pseudo-element paints out to both viewport edges and .header-main:has(.usp-banner-bar) carries overflow-x: clip to trim the scrollbar-width overhang that 50vw produces. clip rather than hidden, which would make the header a scroll container and break sticky positioning inside it, and which would also clip the vertical axis the language and currency dropdowns open into. Not clip-path on the strip either: that applies to the whole subtree and cuts those dropdowns off. body carries overflow-x: hidden, but that does not contain the overhang - overflow set on body propagates to the viewport while html is visible, leaving body computing to visible and clipping nothing.

  • The benefits layout has three fixed slots, as the theme configuration did. An empty slot in the middle is closed up rather than rendered as a gap, and the slider counts what is left to decide how many fit per page. Lifting the cap later means a migration.

  • The banner texts that shops hold in guppy-usp-* theme configuration are not migrated. The theme cannot write into a plugin that may not be installed, so a shop that wants to keep its banner re-enters the copy here; the Guppy theme drops those keys in its own 2.8.0.

  • No aria-labelledby on the slider. The template this was extracted from carried aria-labelledby="carousel-heading", pointing at an element that does not exist in it.

Compatibility

  • Requires dmf/sw6-plugin-splide-slider. Three benefits that do not fit have to rotate, and the slider comes from that plugin rather than a second copy of Splide.

  • Render from core's layout_header_top_bar, sharing one row with the language and currency switchers: the banner takes col-lg-9, the switchers col-lg-3, which is the arrangement the Guppy theme used before the extraction. Deliberately the top bar's own template rather than layout_top_bar in the header - that block is where other plugins hang their own full-width strips, and wrapping its parent() pulled the announcement bar into this row. A theme that overrides layout_header_top_bar without calling parent() will drop the banner, which is that theme's call to make.

  • The storefront stylesheet reads no Sass variable or mixin from the theme. It is compiled with whatever theme the shop runs, and a variable only one theme defines breaks the build everywhere else - $focus-outline-* from the original Guppy partial would have done exactly that. Where a theme value is wanted it comes in as the CSS custom property Bootstrap and core already publish (--bs-border-radius, --bs-gray-500, --spacer-sm), with the stock value as a fallback, and Bootstrap's md breakpoint is written out as a plain media query.

  • Colour the language and currency switchers through .usp-banner-bar .top-bar-nav-btn.btn, which redeclares Bootstrap's --bs-btn-color and --bs-btn-hover-color. Bootstrap declares those tokens on .btn itself and an element's own declaration beats anything it would inherit, so setting them on the strip does not reach the buttons: the rule has to match the button. One class deeper than a theme's own .top-bar-nav-btn.btn is enough to win, and it wins on specificity rather than on load order, because a plugin's stylesheet is compiled before the theme's.

  • Both required colours are validated when the banner is read and fall back to the defaults if they are not a plain hex or rgb() value; an invalid optional hover colour is dropped instead. They are written into a style attribute, and Twig's escaping stops the attribute being broken out of but not ; and : - so an unchecked value could append further declarations. The colour pickers run with :alpha="false", because below full opacity they emit #rrggbbaa, which would silently switch the contrast check off and leave the storefront falling back to a colour nobody chose.