Search by

kommandhub / base-theme-sw

kommandhub

Modern, premium base theme for Shopware 6.7: neutral monochrome UI with colour reserved for meaning, design tokens, dark mode, accessible navigation and refined checkout.

Package info

github.com/KommandHub-Org/base-theme-sw

Documentation

Language:SCSS

Type:shopware-platform-plugin

pkg:composer/kommandhub/base-theme-sw

Statistics

Installs: 7

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

1.0.0 2026-10-16 23:19 UTC

This package is auto-updated.

Last update: 2026-10-16 23:30:38 UTC


README

Kommandhub Logo

Packagist version Packagist downloads CI Shopware 6.7 PHP 8.2+ License: Apache 2.0

Base Theme for Shopware 6

A modern, premium base theme for Shopware 6.7 in a contemporary product-UI style (think Linear / Vercel / Stripe) — a reusable foundation for storefront projects, not a single-store skin. The interface is neutral monochrome: hierarchy and interaction come from tone, typography, spacing and hairline borders. Hue is reserved for meaning — status (success / warning / danger / info) and rating stars — so the few coloured things carry information.

Developed by Kommandhub. Light and dark mode, desktop and phone, WCAG AA text contrast — covered by a Playwright suite.

Contents

Requirements

  • Shopware 6.7 (shopware/core and shopware/storefront ~6.7.0)
  • PHP 8.2 or newer

Installation

Composer (recommended)

The theme is published on Packagist:

composer require kommandhub/base-theme-sw
bin/console plugin:refresh
bin/console plugin:install --activate KmhBaseTheme
bin/console theme:change --all KmhBaseTheme   # or pick it per sales channel
bin/console cache:clear

Zip upload

Download the release zip from GitHub Releases and upload it under Extensions → My extensions → Upload extension, or extract it to custom/plugins/KmhBaseTheme and run the plugin: commands above.

Assign the theme

In the Administration open Sales Channels → (your storefront) → Theme and choose KmhBaseTheme, or use theme:change as above. After changing theme settings or updating the theme, recompile with bin/console theme:compile.

Update

composer update kommandhub/base-theme-sw
bin/console plugin:update KmhBaseTheme
bin/console theme:compile
bin/console cache:clear

See CHANGELOG.md for what changed in each release.

Design system

All visual decisions flow from one token layer, so brands customise through theme config / SCSS variables rather than editing components. Bootstrap stays the foundation; its variables and --bs-* custom properties are re-pointed at the tokens instead of being fought with per-selector overrides.

app/storefront/src/scss/
  overrides.scss          ← loads BEFORE @Storefront: Bootstrap & Shopware
                            !default variables (type scale, control sizes,
                            radii, surfaces) → tokens
  base.scss               ← loads AFTER @Storefront: token CSS vars + layers
  abstract/
    _palette.scss         ← neutral scale (mono-0…mono-1000), semantic aliases,
                            status hues (+ derived -text / -bg / -border)
    _config.scss          ← theme.json config → radius scale, widths, spacing
    _tokens-css.scss      ← ALL tokens as :root custom properties + dark mode
    _mixins.scss          ← focus-ring, elevation, motion-safe helpers
  base/                   ← reboot/typography & links, focus, buttons, forms,
                            core-colour bridge (dark mode)
  component/              ← cards/lists/tables, overlays (dropdown, modal,
                            tooltip), alerts & badges, listing, product card
  layout/                 ← header & nav, off-canvas, footer, chrome, container
  page/                   ← PDP, checkout, account

Tokens (_tokens-css.scss)

Group Tokens
Colour --color-text-*, --color-bg-*, --color-surface, --color-border(-subtle/-strong/-input), --color-action*, --color-disabled-*, --color-focus-ring
Status --color-{success,warning,danger,info} + -text (AA), -bg (tint), -border
Type --font-size-2xs … 3xl (11 → 34px fluid), --font-weight-*, --line-height-*, --tracking-*
Space --space-1 … 16 (4px grid)
Controls --control-height-sm/-/-lg (32 / 40 / 46px)
Radius --radius-sm (chips, menu rows) · --radius (controls, 8px) · --radius-lg (cards, 12px) · --radius-xl (dialogs, 16px) · --radius-full
Elevation --shadow-xs/sm/md/lg, --focus-halo
Motion --ease-standard, --transition-fast/base

Dark mode is the same names re-valued under [data-theme="dark"].

Principles

  • Typography — Inter (self-hosted by core). Semibold headings with tight tracking; 16px/1.6 body; 14px medium for labels, nav and controls; muted text stays ≥ 4.5:1.
  • Links — no default underline. Chrome links (nav, footer, cards, breadcrumbs) read by position. Links inside running text keep a hairline underline because they share the text colour (WCAG 1.4.1). .btn-link looks like a link.
  • Navigation — muted at rest → ink on hover with a tinted pill; the active section (and the one whose flyout is open) gets a 2px ink indicator on the bar's hairline. Account, category and drawer navs use the same inset rounded-row idiom.
  • Buttons — primary (ink), secondary (surface + hairline), outline, ghost (.btn-light), link, destructive (.btn-danger, .btn-outline-danger); disabled via tokens (not opacity); loading keeps the button's look and shows core's spinner in currentColor.
  • Forms — 40px, 16px text (no iOS zoom), borders kept at 3:1 (WCAG 1.4.11), ink border + soft halo on focus, status-red invalid state + message.
  • Breadcrumb → page header → content — 13px muted trail with / separators (current page in ink, plain text, aria-current; on product pages the product is the current crumb), 12px to a semibold title, 8px to an optional description, 32px to content. Phones collapse the trail to … / parent / current. Reuse the .page-header component (component/_page-header.scss documents the markup: title, description, meta badges, actions, tabs, toolbar); core headers are mapped onto the same mixins.
  • Surfaces — hairline border + xs shadow for cards; lg shadow for anything floating (dropdowns, modals, search suggest, flyout).
  • Focus — one solid 2px ring, :focus-visible only, never suppressed.
  • Reduced motion — global prefers-reduced-motion safety net.
  • Ratings — --color-rating (amber, theme config Rating stars).

Theme configuration

Beyond the standard Shopware colour/logo/typography fields (neutral defaults; Status colours drive the status system), two extra blocks expose base-theme controls:

  • Layout — container width (fixed/fluid), content max-width, section spacing, sticky header, top bar, breadcrumb visibility, navigation style, footer columns.
  • Components — corner radius, primary button style, card style, product image ratio, product-grid columns per breakpoint, dark-mode toggle.

Dark mode

Dark mode toggle (on by default) adds a moon button next to the account and cart icons, at every breakpoint. It's implemented inline (a no-flash <head> script + a small wiring script, both gated on the setting) — no webpack build required. The visitor's choice is stored in localStorage and the whole palette flips via [data-theme="dark"] on <html>. Turn the setting off to ship zero extra markup/script.

Core Shopware bakes some colours in at compile time; base/_core-colors.scss re-points those elements at the tokens so they follow the flip too. When a new core element shows up dark-on-dark, add it there.

Config fields are consumed in SCSS ($kmh-*); the sticky-header, top-bar, breadcrumb and dark-mode switches also gate markup in Twig via theme_config('kmh-...'). The Commerce block adds the rating-star colour.

Branding assets

Master artwork lives in src/Resources/config/ (plugin.png = icon only, kommandhub.png = logo + wordmark). Derived, web-optimised copies are generated into src/Resources/app/storefront/src/assets/:

Asset Source Used for Size
config/plugin.png — Plugin-manager icon (composer.json → extra.plugin-icon) 256²
.../logo/favicon.png plugin.png Favicon (sw-logo-favicon) 96²
.../logo/kommandhub-logo.png kommandhub.png Storefront logo — desktop/tablet/mobile + share (one shared file) 600×144
.../preview.png kommandhub.png Theme preview card (theme.json → previewMedia) 1530×1000

The logo is monochrome (pure black), so dark mode inverts it via CSS ([data-theme="dark"] .header-logo-main-img) rather than shipping a second file. Merchants override any of these through the theme settings.

Fonts

Performance/privacy first: no Google Fonts CDN. Uses the Inter variable font that Shopware core already self-hosts (@Storefront assets), falling back to the system stack. To use another font, add an @font-face in base.scss and point sw-font-family-base / sw-font-family-headline at it.

Kommandhub plugin skins (optional)

The theme styles the storefront UI of the Kommandhub plugins so they match the design system — and depends on none of them. Every rule in scss/plugins/ targets the plugin's own markup, so with a plugin absent nothing matches; no Twig of the theme references a plugin.

Plugin What the theme adjusts
KmhClickAndPickSW pickup labels and selects at checkout; the pickup card's inline styles (gradient, fixed colours, Segoe UI) replaced with tokens — light + dark
KmhPaystackSW / KmhFlutterwaveSW bank details as label/value pairs; with both active, the two account-overview cards sit side by side
KmhSmsSW dial-code + number field keeps its rounded outer corners
KmhAfricaCommerceCoreSW none needed — its address fields use core form markup

Generic fix that also serves plugins: any <select class="form-control"> gets the same chevron as .form-select. tests/e2e/plugins.spec.ts checks each skin and skips itself when the plugin isn't on the shop.

Shopping Experiences (CMS)

Every core CMS block is styled on the design system (component/_cms.scss): text typography and .lead, rounded images, sliders and galleries, circular bubbles, hairline image-text cards, equal-height product boxes (also in product sliders), a scrim + light text on Text on image, and a themed consent card for YouTube/Vimeo. Core's baked white frames and backdrops follow dark mode.

What an editor sets in the Administration keeps working: block and section margins, background colours and media, sizing mode and alignment are never overridden. On top of that, three opt-in looks go into a block's CSS class field (Layout → block → Advanced):

Class Look
kmh-cms-surface tinted panel with hairline border and padding
kmh-cms-cards each column of the block becomes a card
kmh-cms-center centred text in every column

Rich-text elements can use <p class="kmh-eyebrow"> (small label above a heading), <p class="lead"> and btn btn-primary / btn btn-outline-secondary links.

tests/e2e/fixtures/seed-cms-home.mjs builds a homepage that uses every block that works outside a product or listing page (32 blocks, including a sidebar section) and assigns it to a sales channel's root category. It is idempotent (fixed layout id) and leaves the previous homepage layout in place — assign it back in the Administration to roll back. Run it with make e2e-cms on the theme stack, or against any shop with an integration's credentials:

SW_URL=http://localhost SW_CLIENT_ID=… SW_CLIENT_SECRET=… SW_SALES_CHANNEL=Storefront \
  node tests/e2e/fixtures/seed-cms-home.mjs

Images come from product covers; on a shop without product media it uploads neutral SVG placeholders.

End-to-end tests

A Playwright suite in tests/e2e/ drives a live storefront that has the theme assigned — desktop (1440×900) and phone (Pixel 7) — and checks behaviour the theme is responsible for:

Spec Covers
header.spec.ts header icons share one centre/size, no sideways scroll, one-row phone header, full-bleed 32px top bar, active nav indicator, dark-mode toggle (switch, persist, revert); breadcrumb semantics (current page is text + aria-current, product crumb on PDP, single-item trail hidden, phone collapse, keyboard focus ring); page titles share one style
listing.spec.ts horizontal filter row (even 40px row, 24px under title), boolean filter ring + active chip, phone filter sheet stacks full width; sidebar active category, card rows align, pagination
wishlist.spec.ts red heart when saved, header counter fully visible, wishlist page header + no empty toolbar
checkout.spec.ts cart drawer + success tint, cart page title/counter, register-form validation colour; logged-in customer places an order → finish page → order history with status chip; account pages share the page-header pattern
theme.spec.ts WCAG AA text contrast (4.5:1 / 3:1 large) on guest and customer pages and the open account menu, light and dark
address.spec.ts address manager (6.7): rounded address cards, neutral default chip, search row on phones, new-address page spacing; checkout address modal title, segmented shipping/billing switch and contrast, light and dark
sliders.spec.ts every visible slider arrow is a round 40px button with a centred icon, inside the slider's clip (home, PDP gallery, cross-selling); cross-selling cards not clipped; room for the card hover lift; currency menu opens above the header
product-tabs.spec.ts PDP description (measure, unstriped properties) and reviews (score, aligned distribution bars, date beside stars, reply panel, CTA toggles the form) + contrast, light and dark
cms.spec.ts Shopping Experiences homepage: no sideways scroll, circular bubbles, highlight-row elevation, equal product cards, text-on-image scrim, themed video consent, opt-in classes
plugins.spec.ts optional plugin skins (pickup controls + contrast, bank details layout, dial-code field); each skips when its plugin is absent

Run it against the plugin's own stack (recommended — see Development):

make up            # once: build + start the stack, composer-install theme + demo data
make e2e-setup     # activate, seed demo catalogue + CMS homepage, map domains to :8100, assign theme
make e2e-install   # once, on the host: npm deps + Chromium
make e2e           # run the suite; `make e2e-report` opens the HTML report

…or against any storefront that has the theme assigned:

E2E_BASE_URL=https://staging.example.com npx playwright test

Notes:

  • Page paths default to the KmhDemoDataSW catalogue; override with E2E_SIDEBAR_CATEGORY, E2E_TOOLBAR_CATEGORY, E2E_SEARCH. The product the suite opens is the first one listed in the sidebar category, unless E2E_PRODUCT and E2E_PRODUCT_NAME are both set (see tests/e2e/support.ts).
  • Each run registers one throwaway customer (kmh-e2e-…@example.com) and places one real order (cash on delivery) — run it against dev/staging, not production. Its session and credentials stay in the git-ignored tests/e2e/.auth/.
  • Cookie consent is pre-set, so the banner never covers controls.
  • make e2e-cms creates a new admin integration (kmh-e2e-cms) on each run; delete old ones under Settings → Integrations if they pile up.
  • The contrast probe skips text over CMS background images (no single background colour to measure); cms.spec.ts checks the scrim instead.
  • Order- and wishlist-changing tests run on the desktop project only (both projects share the run's customer); skipped tests are these plus device-specific checks.

Development

The theme carries its own dockware stack (Shopware 6.7.8 + shopware-cli), published on http://localhost:8100 so it can run beside other shops.

Command What it does
make up / make down start (and composer-install the theme + KmhDemoDataSW) / tear down
make check php-cs-fixer dry-run + PHPStan + PHPUnit
make test · make analyse · make cs-fix the individual steps
make e2e-setup · make e2e prepare the storefront and run Playwright
make validate-plugin shopware-cli store-compliance check
make shell shell in the container (bin/console theme:compile after SCSS edits)

CI (.github/workflows/php.yml) runs the PHP checks with coverage, then the Playwright suite in the same stack.

Releasing

  1. Bump version in composer.json and add the entry to CHANGELOG.md and CHANGELOG_de-DE.md.
  2. make check, make e2e and make validate-plugin must pass.
  3. make zip writes the store-ready archive to build/.
  4. Tag the commit (git tag 1.2.0) and push the tag; Packagist picks up the new version from the tag, and the zip goes on the GitHub release.

Coverage

The storefront is styled end-to-end. All work is token-driven SCSS; the Twig overrides are small and block-preserving (sticky-header wrapper, header actions for the theme toggle, dark logo, top-bar gate, breadcrumb (setting gate, non-link current crumb, product crumb) and the PDP breadcrumb include).

Area Files
Design system, base layer abstract/*, base/*
Header, nav, search, actions layout/_header.scss, views/…/header.html.twig, header/header.html.twig, header/logo.html.twig, top-bar.html.twig
Listing + product cards component/_product-card.scss
Product detail (PDP) page/_product-detail.scss, page/_product-tabs.scss, views/…/component/review/review-widget.html.twig
Shopping Experiences (CMS blocks) component/_cms.scss
Sliders: arrows, dots, product-slider track and clipping component/_slider.scss
Breadcrumb + page headers component/_page-header.scss, views/…/breadcrumb.html.twig, views/…/page/content/product-detail.html.twig
Filters, pagination, category nav component/_listing.scss
Off-canvas nav + cart, line items layout/_offcanvas.scss, component/_line-item.scss
Checkout (cart/confirm/finish/register) page/_checkout.scss
Alerts, badges, order status component/_alert.scss
Dropdowns, modals, tooltips, popovers component/_modal.scss
Footer + global switches layout/_footer.scss, layout/_container.scss, base/_buttons.scss
Cards, list groups, tables, account, address manager + modal component/_card.scss, page/_account.scss
Dark-mode bridge for core's baked colours base/_core-colors.scss

State signalling — where it lives

  • Alerts & badges — status tint + border + AA text shade, plus the per-type icon core renders (colour is never the only cue).
  • Order status — open/in progress = info, completed = success, cancelled/failed = danger chips.
  • Selection (payment/shipping method, address, swatch) — ink ring + the control's own check/radio.
  • Navigation & lists — tinted row + ink + semibold for the current item; 2px indicator on the main nav.
  • Pagination — current page in solid ink.

CMS text/HTML blocks and CMS forms inherit the base typography and form styles — no dedicated overrides needed.

Support

Contributing

Contributions are welcome — see CONTRIBUTING.md and the Code of Conduct.

Security

Please report vulnerabilities privately as described in SECURITY.md, never in a public issue.

License

The source code is licensed under the Apache License 2.0; keep the NOTICE file in redistributions. The Kommandhub name and logo are not covered by the code licence — forks must be rebranded, see TRADEMARKS.md. "Shopware" is a registered trademark of shopware AG.