New addition
Yup, I think I’m addicted.
Helpful toggle — default (left) and active (right). Order per design 10: name + badge above the stars.
Component Library
A reference for the rebranded ecommerce components and their interaction states.
The tokens every component below is built from — colour, type, spacing and corner radii, as declared in config/tailwind/preset/. Flat system: structure comes from 1px hairlines, never shadows or gradients.
Colour · ink (text)
ink
#1B1C1C
ink-muted
#5E5E5B
ink-faint
#999999
ink-faint
#BBBBBB
ink-inverse
#FFFFFF
Colour · hairlines & surfaces
line
#E8E2D9
line-warm
#F2EBE1
line-blue
#D4E2EE
surface
#F9F7F2 · page canvas
surface-card
#FBF9F8
surface-card-warm
#FDFCF9
surface-raised
#FFFFFF
surface-blue
#F1F8FF · input focus
Colour · brand fills
ivory
#F9F7F2
sand
#E8E2D9
powder-blue
#D4E2EE
dusty-pink
#EAD7D7
pale-green
#DDE3D5
charcoal
#333333
Colour · functional accents (text) & semantic aliases
sage
#617558 · savings / success
sage-soft
#7A8F6C
blue
#3F7AA6 · info
rose
#A67E7E · errors
primary
#1B1C1C · alias of ink
primary-80
ink @ 80%
primary-40
ink @ 40%
accent
#5E5E5B · alias of ink-muted
Back-compat tokens also live in the preset (black, black-60, black-25, white, pink / message-error, danger, success, primary-110, accent-80, accent-30, surface-80, surface-110). They are outside the Try Lux palette — prefer the tokens above.
Type · families
font-sans
Geist — smoother energy, no jitters
font-mono
Geist Mono — LABELS & PRICES
font-display is declared in the preset but must never be used in Try Lux markup — src/entrypoints/main.css forces font-black uppercase on it. Use font-sans font-light for headings instead.
Type · scale
Display sizes — same scale, rendered at hero/marquee scale only: text-75 · text-105 · text-120 · text-150 · text-170 · text-180 · text-220. Every size is max(Npx, N/16rem) with a per-size line-height; there is no text-64 or text-65.
Spacing scale
Every integer 0–299 exists (0–3 in px, 4 and up as N/16rem), plus 115 · 145 · 250 · 300 · 350 · 400 · 416 · 600 · 700 · 1400. Nothing else — and the same scale backs max-w-* and min-h-*, so max-w-700 exists but max-w-760 does not.
Corner radii
rounded-button
12px
rounded-input
14px · inputs, swatches
rounded-card
16px
rounded-shell
24px · cards, drawer
rounded-full
pills, qty, icon buttons
Generic rounded-sm (4) · rounded-md (8) · rounded-lg (12) · rounded-xl (16) are also defined — prefer the semantic names above in Try Lux markup.
Primary — states
Secondary · Outline · Text · Icon
Full-width mobile CTA
Please enter a valid email address.
Pick a demo product in this section’s settings to preview the product card, flavor selector, purchase options and the sticky add-to-cart bar.
Known gap — the snippet has no max/ceiling prop: only the − button carries a :disabled binding (quantity ≤ 1), so the “max reached” specimen caps the count in its stub scope but the + button still looks enabled. The design’s dimmed + needs a max prop on snippets/quantity-selector.liquid.
Attribute pills
Merchandising · states
Specimens the homepage slice-reviews section deliberately leaves out: the rating summary with a sort control, a single review row with its helpful toggle, and the empty state.
Rating summary + sort
Based on 30 reviews
product-rating · documented modes
Review item
Yup, I think I’m addicted.
Helpful toggle — default (left) and active (right). Order per design 10: name + badge above the stars.
No reviews yet — be the first to share your experience.
Empty review placeholder
Known gap — product-rating always prints the numeric score next to the star scale unless with_total is set, so the stars-only rows above hide it with class_text: 'hidden'. A stars_only prop would express design 10 directly.
Static specimens only. The real drawer is sections/minicart.liquid, mounted globally via minicart-group.json — open it from the header cart icon. The shells below reuse the drawer's own classes and render its real pieces (line-item, minicart-progress, button) so styling drift shows up here.
Your Cart (0)
Your cart is empty
Add LUX gummies to start your smoother energy routine.
Subtext and the secondary link are Minicart section settings — they render nothing until a merchant fills them in.
Empty cart. line-item needs a real cart line (it reads prices, discount allocations, selling-plan allocations and posts its quantity input to the minicart-form), so it cannot be faked here — add a one-time item and a subscription item to the cart and reload to populate states B and C.
Updating cart…
Updating cart…
Your Cart (0)
Cart-level banner. The per-line variant is the empty data-ajax-cart-errors box inside line-item — only liquid-ajax-cart fills it, so it stays collapsed here.
Empty
Filled
Error
Code not valid.
Applied
The field is gated behind the Minicart section's “Show discount code field” setting; the applied banner is built from cart.cart_level_discount_applications, so it is live data in production.
No placeholder swaps: content never blanks to report that it is changing. The drawer-wide signal is the bar below; everything else is scoped to the row you acted on. The two row states are live in the real drawer — the collapse runs from cartLine, the settle from .is-cart-settling in main.css.
Updating cart…
The quantity readout is optimistic, so figures the server owns fade up when its numbers land ~1s later.
Pick a demo product in this section’s settings to preview the sticky add-to-cart bar.
Design 11 · 12 — the header, navigation and footer are the live global sections on this page: resize below 900px to test the mobile header and the accordion footer. Design 13 · 16 have static specimens above; their live counterparts are the globally mounted cart drawer (open it from the header cart icon) and the PDP sticky bar (fixed and lg:hidden — resize below 1024px on a product page to see it in place).