Wocart

Style and color

A style field does not store CSS. It stores a small set of choices: a spacing step, a width, an alignment. The theme decides what those choices mean in pixels; the SDK writes the classes.

This keeps merchant edits safe. A merchant can make a section wider or add space above it without writing a rule that breaks on mobile. The same idea applies to color: a colorScheme field stores a scheme id, not hex values.

Give the steps a size

The step names and widths are the platform's. A theme maps the ones it offers to pixels:

TypeScriptCode
const theme = defineTheme({ // … style: { spacing: { s0: 0, s2: 8, s4: 16, s6: 32, s8: 64 }, widths: { wide: 1280, content: 960, narrow: 640 }, }, });
ScaleNames
Spacing stepss0 through s12
Widthswide, content, narrow (plus full)

A size the theme does not define has no class. A saved style that names it renders as no style.

Offer a style field

TypeScriptCode
{ key: "style", kind: "style", label: "Style", panels: ["spacing", "size"], default: { spacing: { paddingBlockStart: { base: "s4", lg: "s8" } }, }, }
PanelWhat it controls
spacingpaddingBlockStart, paddingBlockEnd, paddingInline, marginBlockStart, marginBlockEnd, gap
layoutdirection, align, justify, wrap
sizewidth, minHeight

Every property is responsive. A value holds a choice per breakpoint:

BreakpointFrom
baseEvery width
md768 px
lg1024 px

Values are phone-first: a wider breakpoint inherits the narrower one. The SDK uses CSS logical properties, so a right-to-left store mirrors on its own.

A writer refuses a step or width the theme gives no size. A reader renders a saved value as no style and reports it; it never invents a size.

Put the classes on the page

Code
--- import { schemeClass, styleClasses } from "@wocart/theme"; const { style, scheme } = Astro.props; --- <section class={`${schemeClass(scheme)} ${styleClasses(style)}`}> <slot /> </section>

styleClasses returns the classes for the chosen steps and widths (a layout value adds wc-flex). schemeClass(id) returns wc-scheme wc-scheme-<id> for a valid scheme id, or an empty string. The shared wc-scheme class (SCHEME_MARKER_CLASS) lets a theme derive its own tokens once:

CSSCode
:root, .wc-scheme { --button-bg: var(--wc-color-button); --button-fg: var(--wc-color-button-text); }

Every element inside a section that wears a scheme then follows that scheme.

Serve the stylesheet

The SDK can generate one stylesheet with every class the theme's sizes allow.

TypeScriptCode
// src/pages/wocart-styles.css.ts import { themeStylesEndpoint } from "@wocart/theme/astro"; import { theme } from "../theme/theme"; export const prerender = true; export const GET = themeStylesEndpoint(theme);

Then put the link and the store's schemes in the layout's <head>:

Code
--- import ThemeStyles from "@wocart/theme/astro/ThemeStyles.astro"; --- <head> <ThemeStyles schemes={settings.colorSchemes} /> </head>

ThemeStyles defaults to stylesheet on and links /wocart-styles.css. A theme that bundles the classes itself passes stylesheet={false} and generates the same CSS with themeStyleSheet(theme.style). The starter keeps the default and serves the sheet from src/pages/wocart-styles.css.ts.

ThemeStyles also writes the store's color schemes as one small inline sheet. On a page with a Content-Security-Policy, it adds that sheet's hash to the policy, so style-src does not need 'unsafe-inline'.

Color schemes

A color scheme is a named set of colors for every role:

RoleUsed for
backgroundSection background
textBody text
headingHeadings
accentSale and emphasis
buttonButton background
buttonTextButton label
borderBorders

The store's schemes are one colorSchemes theme setting. Each scheme has an id, a translated name and a hex color for every role. A theme may declare at most 24 schemes (COLOR_SCHEMES_MAX); a store keeps the same limit. Ids are lowercase letters, digits and dashes, at most 32 characters; sections store the id, so it must stay stable.

TypeScriptCode
{ key: "colorSchemes", kind: "colorSchemes", label: "Color schemes", default: [ { id: "scheme-1", name: { en: "Light", fr: "Clair" }, colors: { background: "#ffffff", text: "#3b4250", heading: "#0f1626", accent: "#c8102e", button: "#0f1626", buttonText: "#ffffff", border: "#e8e8e5", }, }, ], }

A section picks one with a colorScheme field:

TypeScriptCode
{ key: "scheme", kind: "colorScheme", label: "Colors", default: "scheme-1" }

The page's own scheme is a store setting, not a page-document value. The page document holds only the id, never a color. Changing the scheme's colors changes every section that uses it.

colorSchemeCss(schemes) turns the setting into custom properties such as --wc-color-background and --wc-color-button-text on .wc-scheme-<id>, with the background and text applied. contrastRatio(a, b) gives the WCAG ratio an editor can warn on: below 4.5 for text.

Do not store CSS in a page

A style value is a set of steps and choices. A colorScheme value is an id. Anything else is outside the contract; a theme that accepts raw CSS has given up the guarantees that make saved documents portable across themes.