
Design System
Latest projects All projects →
Brand Centre All brands →
Shipping log
Everything that merged, shipped or opened — newest first. Every row links to the project page with its options and decision.
Colour
Two layers: primitives named by what they are, semantic tokens named by role. Components consume only semantic tokens; the brand mode swaps what they resolve to. Brand values are the Colour Alignment set (post-KM review, Aug 26).
Brand-resolved roles live — switch brand in the sidebar
surface/actionPrimary action fillsurface/action-hoverAction hoversurface/action-pressedTouch-down statetext/on-actionLabel on action fillsurface/accentAccent fills — badges, highlightsbrand/light-1Tinted surfaces, badgesbrand/light-3 · surface/accent-subtleWash backgroundssurface/pagePage backgroundtext/link · border/focusLinks, focus rings — follow the action colourSemantic — text mode-invariant unless marked
Body text floor is Grey 5. Grey 4 and below never carry body text — they fail AA contrast.
#0F0F0F#6B6B6B · floor#B5B5B5#FFFFFF#D33F3F#1F7A25#7A5800Semantic — surface
#FAFAFA#FFF + border#0F0F0F#000 @ 60%#E7E7E7#FFF2F2#EAF6EA#FFFBE6Semantic — border & icon
#E7E7E7 · dividers#D6D6D6#767676#0F0F0F#767676 · grey 4 okNeutrals shared by every fascia
#FFFFFF#FAFAFA#F2F2F2#E7E7E7#D6D6D6#B5B5B5#767676#6B6B6B · text floor#323232#0F0F0F#000000Status never colour alone — always paired with icon or text
#D33F3F#FFF2F2#FFD600#FFFBE6#70C474#EAF6EAPrimitives — Debenhams Aqua family locked · names preserved from the DS file
#E6FFFC#D6FFF9#E8F4F2#B8FDF4#9DEDE2#7BE7D8#76DECF#70BEB3#529C92#00787D#00565A#1E6F63Primitives — boohoo Pink family 12 slots · same structure every fascia
#FFE9F0#FEE0EA#F1DCE3#FCD3E1#FBC7D8#F8B5CC#EEA5BE#EA92B0#DD789B#BB305F#A82A55#CB4870boohooMAN, PLT and Karen Millen carry their colour-alignment CTA set (rendered above when switched); their remaining primitive slots land as each fascia is audited. Removed from the primitive layer: KM mode overrides (re-mapped fresh via semantic layer) and Rewards colours (project dead).
Typography
One role set, every fascia. Sizes are identical across brands — only font family and weight change with the mode. Fixed per-breakpoint sizes (no fluid clamp for v1), line-height mirrors Figma AUTO, letter-spacing defaults to 0.
display-lg · 48Wardrobe iconsheading-xl · 28New season editheading-sm · 16Delivery & returnsbody-md · 14Free returns within 28 days. Star buys are final sale — check the label before you commit.caption · 12Selected lines only. T&Cs apply.Roles mobile / desktop px · same for every fascia
display-lg32 / 48 · strongHero, marketing pagesdisplay-md28 / 40 · strongSection openersdisplay-sm24 / 32 · strongEditorial leadsheading-xl20 / 28 · strongPage titlesheading-lg18 / 24 · strongSection titlesheading-md16 / 20 · strongSubsection titlesheading-sm16 / 16 · strongCard titles — matches existing "Header 1"heading-xs14 / 14 · strongInline section labels — matches "Header 2"body-lg16 / 16 · regularLong-form bodybody-md14 / 14 · regularDefault body — matches "Body M"body-md-strong14 / 14 · strongEmphasisbody-sm12 / 12 · regularCompact bodycaption12 / 12 · regularCaptions, T&Cs, legalmicro10 / 10 · regularSmallest legal labelsSize primitives
10 · 12 · 14 · 16 · 20 · 24 · 28 · 32 · 36 · 40 · 48
Per-fascia resolution colour alignment, Aug 26
debenhamsGeologica300 Light600 SemiBoldsentenceboohooMontserrat500 Medium700 BoldsentenceboohoomanMontserrat500 Medium700 BoldsentencepltRoboto400 Regular700 BoldUPPERCASEkarenmillenJost400 Regular600 SemiBoldsentenceEvery brand font is a Google Font with the full weight range available. Fonts for the other 11 fascias are captured as each is audited. If a fascia's font ever demands a size shift, it becomes a brand-mode override at the role layer — the default is consistency.
Spacing
We measure spacing in gaps. 1 gap = 4px, so gap N = N × 4px. It is the same unit as Tailwind's spacing scale (1 = 0.25rem = 4px at a 16px root), so gap N is Tailwind N: gap 4 = 16px = p-4 / gap-4 / m-4. Every spacing value is quoted in both: gap 4 (16px).
The scale gap · px · Tailwind · token
gap 0.52pxp-0.5 · gap-0.5 · m-0.5--gap-0_5Hairline nudges — rating stars, countdown under its textgap 14pxp-1 · gap-1 · m-1--gap-1Tight inline gaps — icon + label · USP bar top/bottomgap 1.56pxp-1.5 · gap-1.5 · m-1.5--gap-1_5Desktop USP bar top/bottomgap 28pxp-2 · gap-2 · m-2--gap-2Tight component padding · card actions inset · promo field gapgap 312pxp-3 · gap-3 · m-3--gap-3Standard inline gapgap 416pxp-4 · gap-4 · m-4--gap-4Default component padding · mobile page margingap 520pxp-5 · gap-5 · m-5--gap-5Modal padding · medium paddinggap 624pxp-6 · gap-6 · m-6--gap-6Default desktop margin (small) · section separationgap 832pxp-8 · gap-8 · m-8--gap-8Section breaksgap 1040pxp-10 · gap-10 · m-10--gap-10Large section spacinggap 1248pxp-12 · gap-12 · m-12--gap-12Layout-level spacinggap 1664pxp-16 · gap-16 · m-16--gap-16Hero / page-level spacinggap 2080pxp-20 · gap-20 · m-20--gap-20Page-level spacinggap 2496pxp-24 · gap-24 · m-24--gap-24Desktop side gutter at 1440+ — content scales insidegap 32128pxp-32 · gap-32 · m-32--gap-32Largest layout spacingIn Tailwind assets/ds/tailwind.preset.js
Add the preset to the front end's config — presets:[require('./assets/ds/tailwind.preset.js')] — and load tokens.css. It maps every DS step to its --gap-* token, so p-4 resolves to var(--gap-4) (16px). It extends Tailwind rather than replacing it, so existing classes keep compiling.
Off the DS scale in today's front-end build (from the dev Storybook's compiled CSS): 2.5 (10px) · 3.5 (14px) · 7 (28px) · 9 (36px) · 11 (44px) · 14 (56px). They still work; each should move to the nearest DS step when that component is next touched.
Writing it down: designs, specs, the catalogue and Storybook quote spacing as gap N (Npx). Sizes (a 50px field, a 24px icon) and type (12/15) stay in px — they aren't spacing.
Icon sizes
All icons draw at a 1pt stroke. Buttons use 16 / 20 / 24; 32 and 48 are for hero and decorative use.
Z-index layer scale
z-base / z-raised0 / 10Page flow, raised cardsz-dropdown / z-sticky100 / 200Menus, sticky headersz-banner / z-overlay300 / 400Banners, scrimsz-modal / z-popover500 / 600Dialogs, popoversz-toast / z-tooltip700 / 800Toasts, tooltips — always on topBreakpoints deferred — deliberate
The live estate applies breakpoints inconsistently per component; the new system exists partly to fix that. Designers work at 390 and 1440. Components are specced fluid-first; the named breakpoint set gets locked once the component audit reveals real reflow needs.
Radius
4pt corners by default. Square is a brand-mode option, not a fork — PLT and The Brand Room opt in today; any fascia can, by swapping one token mapping.
Semantic mapping
radius/defaultradius-4radius-0radius/lgradius-8radius-0radius/pillradius-fullradius-0current brand resolves radius/default →
Borders
Everything draws at 1pt — borders, dividers, line icons. 2pt is reserved for focus rings and selected states. No shadow scale: the system is flat, hierarchy comes from borders and surface tones.
border-width/default1ptBorders, dividers, iconsborder-width/emphasis2ptSelected statesborder-width/focus2ptFocus ringsColour conventions
border/subtle#E7E7E7Default divider · PDP box bordersborder/default#D6D6D6Inputs, cardsborder/strong#767676Emphasised bordersborder/action · border/focusSecondary buttons, focused inputs, focus ringsborder/error#D33F3FError input bordersBorders aren't subject to text contrast rules, so every grey is available — the Grey 5 floor applies to text only.
Motion
Conservative by default. Three durations, two curves, and a global collapse to instant under prefers-reduced-motion — built into the token layer, no per-component work.
motion-duration-fast100msMicro — button pressmotion-duration-base200msDefault — hover, fade, modal openmotion-duration-slow300msLarger transitions — drawer slidemotion-easing-standardcubic-bezier(.2, 0, 0, 1)Defaultmotion-easing-emphasisedcubic-bezier(.3, 0, .8, .15)Attention-pullingNo shadows
Deliberately flat. If a future component genuinely needs elevation (a floating popover, say), an elevation token gets proposed then — not pre-emptively.
Accessibility
Every component targets WCAG 2.1 AA. Non-negotiable: anything that doesn't meet the bar doesn't ship, and a component spec without an Accessibility section isn't finished.
contrast · body4.5 : 1Floor is Grey 5 #6B6B6B — Grey 4 and below never carry body textcontrast · large/UI3 : 118pt+ text and UI componentsfocusalways visible2pt ring in the brand action colour · full keyboard operationtouch targets44 × 44Minimum on mobile — inline body links exempt where naturalmotionreduced-motionAll animation collapses to instant · nothing auto-plays without opt-outmeaningnever colour aloneStatus pairs colour with icon and text · icon-only buttons carry aria-labelExemptions
The Grey 5 floor applies to text only. Borders, dividers, icons and decorative elements may use any grey — Grey 2 is the typical divider, Grey 4 the standard secondary icon.
Using the system
Brand sites install two packages: the tokens and the components. Set one attribute on the root element and every semantic token resolves to that fascia.
Wire in the tokens
Set the brand mode
Use a component
The rules that keep it working
semantic tokens onlycomponents never touch primitivesBrand colours appear only in the token layer — this is what keeps multi-brand workingone mechanismdata-brand attributeNo per-brand CSS files, no component forksdocs page = specthey ship togetherA component without a docs page doesn't existEscape hatch
Components are intentionally constrained. If one genuinely doesn't fit, the source is visible on its page — copy and modify, or raise a request to extend the official component.
Components
The library index. Brand chips show themed coverage; status is live in production or in build.
Button
Four states, one component, every fascia. Switch the demo brand in the top bar — colour, type, radius and case all follow the tokens.
Props ButtonProps
variantprimary · secondary · tertiaryOne primary per view · default primarysizesm · md · lgDefault md · sm needs touch-target reviewdisabledbooleanPrevents interactionloadingbooleanPrevents interaction · sets aria-busy · spinnerbrandinherited from modeNever set per-instanceUsage
Secondary carries the CTA colour as a keyline, never a second fill. PLT renders square with uppercase labels; every other fascia 4px radius, sentence case — that difference is brand config, not a component fork.
Accessibility
keyboardnativeRenders a native button element — focusable and operable by defaultfocus ring2ptborder/focus — brand action colour, 2px offsetloadingaria-busyBoth disabled and loading prevent interactiontouch target44 × 44Met at md and above · sm under review for mobileStill to specify after the Figma node audit
Full variant set (Pill, Icon Only, Roundel, Navigation, Payment, Dropdown, Quantity Selector, App Store badges) · icon slot handling (boolean + size, not encoded as states) · loading visuals · pressed-vs-hover naming unification · disabled colour reconciliation (golden truth label #767676 vs token text/disabled Grey 3) · focus ring exact width and offset per size.
Source
packages/react/src/components/button · Figma: DS file → BUTTONS (new) · 9144-1807
Product card
The hero asset — built exactly from the Figma component, used across every PLP and carousel. Every optional element is a variable layer: turn it on per fascia, never fork the card.
Formats: standard, and .pc--compact — the shorter PLT / Brand Room format (caps brand 11px, 12px name, tighter gaps) that the alignment rolls out to every fascia. Wishlist variants: heart-in-circle (Debenhams, boohoo, Warehouse today) · bookmark-in-square (boohooMAN, KM, Brand Room) · plain heart (PLT). Image corners are square — matching live and Figma.
Variable layers booleans on one component — the Figma model, kept verbatim
wishlistButton32px circle · heartIcon swaps per fascia: heart or bookmark (KM, boohooMAN, Brand Room, Warehouse) — nested atomic iconquickAddicon · button · noneCircle icon (Debenhams) or full-width Add button (boohooMAN)productTagbadge, bottom-leftPlus / Petite / Tall — see C-07 Badges for stackingtaggstarsocial-proof barGrey 1 chip, no icon · PLP "Selling Fast! 79 Sold" · PDP two-line card with close · bag linesponsoredtext rowFigma uses Grey 4 — lifted to Grey 5 here for the AA text floorcolourSwatches20px swatch rowSwatch shape is a nested atomic component — restyle per brand without touching the cardshowReviewStarsstars + count12px stars, 2px gapshowBrandbrand lineHidden on PLT + Warehouse per the Sep briefAnatomy values
Image 2:3 on surface/media · card gap 12 · info gap 8 · title gap 4 · text 14px — brand w-strong, name w-regular 2-line clamp, was-price w-mid strikethrough · sale price + percent in status red · actions 32px circles, top 8 right 8, gap 8.
Source
assets/ds/components.css → .pc · Figma: DS file → Product Card · 5992-10841 · variable layers on · 12999-146812
Sort & filter
The combined pattern from the A/B/C tests: desktop gets a dropdown row with sort on the right; mobile gets Next Day Delivery + a single Sort & Filter entry opening a full sheet with drill-in panels and a pinned CTA.
Desktop is a strip under the category links: optional NDD toggle, dropdown boxes, "Show more filters", sort right. Mobile (live platform) is the split Filters | Relevance bar; mobile (new format) is the floating pill row — white radius-42 chips with soft shadow, NDD toggle inline, chips open the combined sheet (Brand Room Figma 739-92223).
Source
assets/ds/components.css → .sf · Figma: Sort & Filter combined · 1783-11572 — A/B/C variants live in the same file for the test readout.
Badges
Image-overlay tags (Plus, Petite, Sale, Sponsored) and the AI-generated banner. Badges stack bottom-left, newest on top; the AI banner is a full-width strip pinned to the image foot and is mandatory whenever the imagery is AI-generated.
Rules
ai bannermandatoryFull-width black strip at image foot whenever product imagery is AI-generated — uppercase, 10px, whitestackingbottom-left columnBadges lift 32px when the AI banner is present (.has-ai) · gap 4themingtokens onlyRadius, font, case follow the brand mode — square on PLT/Brand Room automaticallySource
assets/ds/components.css → .badge · Figma: AI watermark + stacking · 25-11775 · live demo: ai-generated-badge
Icons
The canonical icon set, pulled from the DS Figma Iconography page. Rules: 1pt stroke everywhere regardless of scale, aspect ratio always locked (render in a fixed square box, object-fit contain — never stretch), default colour icon/primary. PLT runs its own lighter 16px set for header and card chrome.
Core set 136 icons
360appleauthenticityduplicategeolocateararrow-increaseboohooman-premierbookmarkplane48hr-refundaccountaccount-balanceaccount-overviewacornaddadd-photoaddressesaialertappassemblybagbirthdaycalendarcameracardcash-backcelebratecheckoutclearclosecollapsecompensationcompletion-timecontact-prefscopycountry-settingscovercross-circlecruelty-freedeletedeliverydelivery-fastdelivery-insurancedowndown-arrowdresseditemailexpandexpand-filledfilterflamefoundation-findergiftgift-cardgridhairadvisorhamburger-menuhangerhideimageinfoleafleftlight-bulblinklinked-accountlocationlocklock-fillmakeup-advisormeasureandroid-menuminusmirrormorenotificationoffersorderparabenpauseplaceholderplay-controlplay-thumbplt-royaltyprice-promisepromo-codequestionquick-addreplayresalereturnreturn-to-paymentrightright-arrowroomsavesearchsettingsshareshare-androidshowsign-outsizeskinadvisorspinnerstaff-areastar-fillstar-halfstar-outlinesubscribe-and-savesuggested-searchsupportticktick-circle-filltick-circle-outlinetiletimetrophyuniversityunlimitedunlimited-infinityunlimited-plusupuploadveganvisually-similarwishlistxmasxmas-treepalettequantityshopzoomSocial
facebookinstagrampintresttik-tokxyou-tubePayment badges
Figma aIHmkCaTy9c5EWOxAGw0So · node 669-2707 (Payment Icons). Raster exports at 3x in assets/ds/icons/pay/, shown at 30px tall in the footer band (C-08) in live order. iDEAL-Wero and Tink exist in Figma but aren't used on boohooMAN.
visamastercardamexmaestrovisa-electronapple-paypaypluspaypalklarnaclearpaygoogle-payCountry flags 202 · 24 × 17
Figma aIHmkCaTy9c5EWOxAGw0So · node 5353-2781 (Country Flags, component set Flags). Flat SVGs in assets/ds/icons/flags/, one per country, named by slug (united-kingdom.svg). Globe and EU first, then A–Z. Square, country-selector and PLT header variants in the same frame are built from these.
GlobeEuropean UnionAfghanistanAlbaniaAlgeriaAndorraAngolaAntigua and BarbudaArgentinaArmeniaArubaAustraliaAustriaAzerbaijanBahamasBahrainBangladeshBarbadosBelarusBelgiumBelizeBeninBhutanBoliviaBosnia and HerzegovinaBotswanaBouvet IslandBrazilBruneiBulgariaBurkina FasoBurundiCambodiaCameroonCanadaCape VerdeCentral African RepublicChadChileChinaColombiaComorosCongoCosta RicaCroatiaCubaCuracaoCyprusCzechiaDR CongoDenmarkDjiboutiDominicaDominican RepublicEcuadorEgyptEl SalvadorEquatorial GuineaEritreaEstoniaEswatiniEthiopiaFijiFinlandFranceGabonGambiaGeorgiaGermanyGhanaGreeceGrenadaGuatemalaGuineaGuinea-BissauGuyanaHaitiHoly SeeHondurasHong KongHungaryIcelandIndiaIndonesiaIranIraqIrelandIsraelItalyIvory CoastJamaicaJapanJordanKazakhstanKenyaKiribatiKuwaitKyrgyzstanLaosLatviaLebanonLesothoLiberiaLibyaLiechtensteinLithuaniaLuxembourgMadagascarMalawiMalaysiaMaldivesMaliMaltaMarshall IslandsMauritaniaMauritiusMexicoMicronesiaMoldovaMonacoMongoliaMontenegroMoroccoMozambiqueMyanmarNamibiaNauruNepalNetherlandsNew ZealandNicaraguaNigerNigeriaNorth KoreaNorth MacedoniaNorwayOmanPakistanPalauPalestinePanamaPapua New GuineaParaguayPeruPhilippinesPolandPortugalQatarRomaniaRussiaRwandaSaint LuciaSaint Vincent and the GrenadinesSamoaSan MarinoSao Tome and PrincipeSaudi ArabiaSenegalSerbiaSeychellesSierra LeoneSingaporeSint MaartenSlovakiaSloveniaSolomon IslandsSomaliaSouth AfricaSouth KoreaSouth SudanSpainSri LankaSudanSurinameSwedenSwitzerlandSyriaTajikistanTanzaniaThailandTimor-LesteTogoTongaTrinidad and TobagoTunisiaTurkeyTurkmenistanTuvaluUgandaUkraineUnited Arab EmiratesUnited KingdomUnited StatesUruguayUzbekistanVanuatuVenezuelaVietnamVirgin IslandsYemenZambiaZimbabweUsage
aspect lockedalwaysFixed square box + object-fit contain — a squished icon is a bug1pt strokeall scalesDrawn at 1pt on the 24 grid; don't scale below 16px (stroke thins) — flagged: source stroke-based SVGs for true non-scaling 1ptsizes16 · 20 · 24UI chrome 24 · card chrome 16 · PLT set 16 with 12px glyphsmulti-part10 flaggedzoom, cross-circle, support, resale + 6 more export as layered vectors — re-export flat when neededSource
assets/ds/icons/lib/ · Figma: Iconography · 470-887
Extended library
Every component harvested from the estate on 08 Sep 2026 — ten repos read end to end (.context/18-component-inventory.md). Colour truth is the colour-alignment set; slot architecture follows Group-Design-System. Switch fascia with the brand button to see each skin. Nothing below carries a hardcoded brand colour.
C-09 · Button system .bd
Five types from the golden matrix (Buy It Now is off on every fascia for now): primary, secondary (white + brand outline), tertiary (Neutral fill, 40px), tertiary XS, text only. States: pressed, disabled (grey on every brand for tertiary), spinner — per Figma 12533:14818 the label gives way to a 24px arc and the fill drops to Neutral. Sizes .sm 6/12 · .md 8/16. Icon slot 20px (.ic24 / .ic16). .pay is the fixed-navy checkout Pay CTA, 8px radius.
C-10 · Payment buttons .pay
Scheme colours are fixed and never brand tokens (DS 9144-1931): PayPal #FFC439 (KM runs PayPal on #EEEEEE via --paypal), Apple Pay black, Google Pay white with #3C4043 border, Klarna #0B051D, Clearpay #B2FCE4. .pay--mini 114px, .pay--glass 25px radius + blur for floating chrome. Artwork is the frame's own exports in assets/ds/icons/payments/.
C-11 · Form controls
Floating-label field (default / focus / filled / error — label shrinks 14→12 and the input grows in), select driven by a real native <select>, 24px checkbox filled with --icon-action, 26px radio, toggle, 28px quantity stepper (minus becomes remove at 1), promo field + 95px Apply, and the PSP static field set — fixed navy / #EFEFF1 / 8px radius on every fascia, because the payment provider renders it.
C-12 · Messaging
Banner: 4px status bar + 20px icon + text, optional inline action and dismiss; success / neutral (never dismissible — it's a readout) / error. Toast: bottom black snackbar (1.8s) or top light actionable (6s, "View"). Stock alert and empty state round it out.
Your bag is empty
C-13 · PDP kit
Price block (now / was / save badge — PLT's is transparent with #C90000 / promo line / OOS label), size selector 60×50 with three OOS treatments (greyed, strike, notify bell), 60×89 colour image swatches with the black-plus-white-keyline selection, accordion, section header + rail, USP box (DS 3619-10541), BNPL (DS 2969-10048), free-delivery threshold (BBz64OeCbe5TBmYKbCxvCp), Deliver+ banner and bag module skinned per fascia (SEEL 2026), at-a-glance list.
- +14-day return extension
- £5/day late delivery compensation
- Full order coverage with instant payout
- ✓Regular fit
- ✓Machine washable
- ✓Recycled polyester
C-14 · Overlays & bag
One sheet shell: scrim 40%, white panel with 4px top radius to 100% − 56px on mobile, a centred 480px card from 768px; .sheet--auto hugs content (Added to bag), .sheet--dark is the VTO gradient variant with a 12px radius and safe-area padding. .modal is the centred card that scales in from 0.96. Bag line item is the 99×148 grid; order summary sits on Grey 05.

C-15 · Chips & pills
C-16 · Account
Balance card fills per fascia (--card-bg: Debenhams aqua gradient, boohoo/MAN black, PLT garnet, KM orange), 62.5px numeral with tight tracking, loyalty label in caps (Royalty / Unlimited / Premier). Rows are white panels on --page-bg with a 24px icon, status text and an 8px status dot.
C-17 · AI Generated strip — the rules
From the AI-generated-badge proposal (EU AI Act Article 50(4), live 02.08.26; ASA covers the UK). The strip is live text, never a rasterised layer (screen readers, the 10px legal floor, localisation, badge shifting); it owns the bottom edge of the image at every size; every other badge shifts up by exactly --ai-h; wishlist and quick add stay top-right; Sponsored stays below the image except in PLP grid view where it becomes a badge and no other badge shows. Placement is driven by an image-level AI flag everywhere before add-to-bag; hidden in bag / mini bag / checkout — legal sign-off required. Alt text appends "AI generated image". See C-07 for the strip itself.
C-18 · Square tile rail .tile-rail
Source
assets/ds/components.css → EXTENDED LIBRARY · assets/ds/tokens.css → EXTENDED COMPONENT TOKENS · Inventory: .context/18-component-inventory.md (+ four full repo reads in .context/inventory/) · Backlog not yet ported: PDP gallery, Shop The Look + bundle family, notify-me form, VTO flow, Brand Room nav/drawer/hero family, checkout saved-card rows, glass nav chrome (app), request-form kit.
Component library
Every component in the system, live, in the brand you have selected. Open one for what it is, when to use it and how it is built. The same catalogue generates our Storybook for the dev team.
Dev alignment
The front-end team's Storybook has 79 components across 178 stories, themed for 21 fascias. This is how it overlays with ours — component by component, token by token — and what the shared build should become.
How the devs build React · Tailwind · per-fascia CSS variables
Components are React with Tailwind utility classes. A variant prop selects a class string (Button has 19). Theming is a flat list of ~25–67 CSS variables per fascia — RGB triplets like --color-primary: 123 231 216 — read by utilities such as bg-primary, font-cta and rounded (which resolves --default-rounding: 0 on PLT and Brand Room — exactly our square modes). Greys are fixed utilities on the same Grey 1–6 ramp we use. Fonts per fascia match ours except Karen Millen (dev runs Work Sans for CTA and headings) and Warehouse (Roboto). A fascia toolbar global switches the theme; our Storybook exposes the same global mapped onto data-brand.
The plan: our catalogue is the visual target. Where a dev component matches, the dev build adopts our tokens and states; where it is partial, the Docs note says what to add on which side; where we have no counterpart it is a new component for us to spec; where they have no counterpart it is a new component for them to build from our story.
Component overlay dev → ours
Token map dev theme variables → our semantic tokens
Source
.context/inventory/05-dev-storybook.md — the full ingest: every component with its props, per-fascia theme variables, 1440 + 390 renders of all 178 stories. DG Group Design System Storybook ↗ — generated from the same catalogue (storybook/).
Changelog
What was added, changed and fixed in the design system in each iteration, newest first, and which project drove it. Projects build only from these components: a wrong one is fixed here and pushed back, a missing one is added here first.
Foundations
The general rules every component is built from — colour, typography, spacing, radius, borders, motion, accessibility, and how to use the system. One page; jump with the chips.
Projects
Every project in the estate, one click away. Prototypes open in a new tab; the repo link is the record (brief, options, decisions).
The record briefs · options · chosen routes
Every brief as a record: what was explored, what won, and where it lives now. Delivered work merges to the master prototype.
PLP Redesign
Align boohoo, boohooMAN, PLT, Warehouse and The Brand Room onto one core PLP template. Differences become configuration, not forks. PLT is the reference implementation.
Options
All five run PLT's exact card and grid; only tokens differ.
PLT base; brand label, was-price, badges and grid density per fascia.
B plus a compact / comfortable density switch per market.
Requirements from the brief
imageFullWidthBHW · WarehouseMatch PLT full-width imageryfontScale → pltBHW · WarehouseSite-wide reduction to PLT sizescolumnsDesktop 5→4WarehouseMatch other brandsshowBrand → falseWarehouseLike PLTfavouriteIcon → kmWarehouseAdopt KM heartCTA Colour Alignment
Final styling per fascia across five core screens, plus the golden-truth button state matrix. The Colour page renders this project's output.
Routes explored
Side-by-side with live colour picker for review sessions.
Picker and Before states removed post-review; deep-linkable per brand.
Rejected — breaks the token model.
New Checkout
One smart field between donation and payment that accepts a promo code or a gift card number and works out which it's been given. Single self-contained prototype.
All brands
Every fascia in the group. Pick one for its own page: logo downloads in black or white as SVG or PNG, brand guidelines, colour and type. Opening a brand also previews it across the system.
Modes data-brand — the only theming mechanism
One attribute on the root element themes everything: colours, font, weights, radius, case. No per-brand CSS files, no component forks. All 17 fascias are modes today.
debenhamsGeologicaColour set from the colour-alignment prototype (Aug 26)boohooMontserratColour set from the colour-alignment prototype (Aug 26)boohoomanMontserratColour set from the colour-alignment prototype (Aug 26)pltRobotoColour set from the colour-alignment prototype (Aug 26)karenmillenJostColour set from the colour-alignment prototype (Aug 26)warehouseHelvetica NeueColour set from the colour-alignment prototype (Aug 26)brandroomArchivoColour set from the colour-alignment prototype (Aug 26)debenhamsoutletGeologicaNo aqua: black buttons + outlines like boohoo (12 Oct)wallisUrbanistColour set mapped from the front-end theme (primary / CTA / nav / footer band)burtonMontserratType + buttons = boohoo / MAN (Jake, 12 Oct)principlesLatoColour set mapped from the front-end theme (primary / CTA / nav / footer band)coastRobotoColour set mapped from the front-end theme (primary / CTA / nav / footer band)oasisGeologicaColour set mapped from the front-end theme (primary / CTA / nav / footer band)dorothyperkinsPublicSansColour set mapped from the front-end theme (primary / CTA / nav / footer band)misspapMontserratboohoo / MAN in #101820, grey secondary outline, inverted header (12 Oct)dsgnstudioHanken GroteskColour set mapped from the front-end theme (primary / CTA / nav / footer band)trainingdeptHanken GroteskBlack like boohoo, DSGN Studio font, black logo bar (12 Oct)

