css

package module
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 14, 2026 License: MIT Imports: 1 Imported by: 0

README

tinywasm/css

Typed CSS DSL and design tokens for the tinywasm framework.

This module replaces string-based .css files with a Go-typed DSL. It exposes both RootCSS() and RenderCSS() with strictly separate responsibilities:

  • RootCSS()vocabulary: design token declarations — brand, source tokens, scales.
  • RenderCSS()logic: minimal reset + active-token bindings + @media (prefers-color-scheme).

The DSL ensures that every selector, declaration, and token reference is a Go expression, providing compile-time safety and eliminating hex-fallback drift.

Usage

import . "github.com/tinywasm/css"

func MyComponent() {
    // WASM: Use Class or Token.Var()
    btnClass := Class("btn")
    color := ColorPrimary.Var()
}

// SSR: Use the DSL to generate CSS
func Styles() *Stylesheet {
    return NewStylesheet(
        Rule(".btn",
            BackgroundColor(ColorPrimary),
            Color(Hex("#fff")),
            Padding(Space2, Space4),
            BorderRadius(RadiusMd),
        ),
        Rule(Class("btn").Hover(),
            Opacity(0.8),
        ),
    )
}

SSR contract: RootCSS vs RenderCSS

assetmin recognizes two CSS functions with strictly separate roles:

Function Slot Replacement Content
RootCSS() *Stylesheet open Single-winner — app replaces framework :root {} value declarations (vocabulary)
RenderCSS() *Stylesheet middle Additive — every module's contribution is preserved CSS rules that consume tokens via var() (logic)

The split is the key to safe theming: vocabulary is replaceable so apps can rebrand; logic is additive so dark-mode switching cannot be deleted by accident.

App override pattern
// ssr.go at the app root
import "github.com/tinywasm/css"

func RootCSS() *css.Stylesheet {
    return css.NewStylesheet(
        css.RootCSS(), // inherit framework defaults
        css.Root(
            css.Declare(css.ColorPrimary, "#FF6B35"),
            css.Declare(css.ColorBackgroundLight, "#FAFAFA"),
            css.Declare(css.ColorBackgroundDark, "#121212"),
        ),
    )
}

The app does not need to redeclare the active-layer bindings or the @media rule — those live in RenderCSS() and are always present.


Design Tokens

Tokens are the single source of truth for all design decisions.

Group Purpose
Color — Brand Fixed identity colors
Color — Theme Adaptive light/dark colors
Typography — Size Font-size scale (Major Third ratio)
Typography — Extras Line-height, weight, letter-spacing
Spacing Margin/padding/gap scale (4px grid)
Border-radius Consistent corner rounding
Elevation Box-shadow scale
Motion Animation timing + easing curves
Z-index Stacking contract
Breakpoints Viewport widths (container queries / JS)
Container widths Max-width primitives

Design Philosophy

  • Semantic names over valuesColorOnSurface not #ffffff. Names describe intent; values can change.
  • Scales over magic numbers — typography and spacing follow mathematical ratios so all values are proportional and limited.
  • Two-layer color pattern — separates source values (per mode) from active tokens (used by components). @media (prefers-color-scheme) switches modes without JS.
  • Single override point — apps only need to change source-layer or scale variables; the rest cascades automatically.

DSL Reference

The DSL provides type-safe constructors for CSS properties:

  • BackgroundColor(Value), Color(Value), FontSize(Value), MinWidth(Value), MaxHeight(Value), AlignSelf(Value), Overflow(Value), Visibility(Value), TextAlign(Value), TextTransform(Value), TextDecoration(Value), TextShadow(Value...), UserSelect(Value), TouchAction(Value), ListStyleType(Value), GridArea(Value), GridTemplate(Value), MarginLeft(Value), MarginRight(Value), PaddingBottom(Value), ListStyle(Value), All(Value), OverflowY(Value), GridTemplateRows(Value), GridTemplateColumns(Value), BorderRight(Value...), etc.
  • Padding(Value...), Margin(Value...)
  • Px(int), Rem(float64), Pct(int), Vw(float64), Vh(float64), Calc(string), Hex(string), Str(string)
  • Rule(selector, declarations...)
  • Root(declarations...)
  • Media(query, items...), MediaDesktop(items...)
  • Keyframes(name, At(at, declarations...)...)

Keywords like Auto, None, Block, Flex_, Center, Zero, Fixed, Absolute, Unset, Initial, FlexEnd, SpaceAround, Row, Column, Hidden, Visible, Uppercase, Capitalize, RightText are also provided.

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	// Brand colors
	ColorPrimary     = Token{"--color-primary", "#00ADD8"}
	ColorOnPrimary   = Token{"--color-on-primary", "#1C1C1E"}
	ColorSecondary   = Token{"--color-secondary", "#654FF0"}
	ColorOnSecondary = Token{"--color-on-secondary", "#FFFFFF"}
	ColorSuccess     = Token{"--color-success", "#3FB950"}
	ColorError       = Token{"--color-error", "#E34F26"}

	// Theme — active layer (consumed by components)
	ColorBackground = Token{"--color-background", "#FFFFFF"}
	ColorSurface    = Token{"--color-surface", "#F2F2F7"}
	ColorOnSurface  = Token{"--color-on-surface", "#1C1C1E"}
	ColorMuted      = Token{"--color-muted", "#6E6E73"}
	ColorHover      = Token{"--color-hover", "#B8860B"}

	// Theme — source layer (apps redeclare these for rebrand)
	ColorBackgroundLight = Token{"--color-background-light", "#FFFFFF"}
	ColorBackgroundDark  = Token{"--color-background-dark", "#0D1117"}
	ColorSurfaceLight    = Token{"--color-surface-light", "#F2F2F7"}
	ColorSurfaceDark     = Token{"--color-surface-dark", "#161B22"}
	ColorOnSurfaceLight  = Token{"--color-on-surface-light", "#1C1C1E"}
	ColorOnSurfaceDark   = Token{"--color-on-surface-dark", "#E6EDF3"}
	ColorMutedLight      = Token{"--color-muted-light", "#6E6E73"}
	ColorMutedDark       = Token{"--color-muted-dark", "#8B949E"}
	ColorHoverLight      = Token{"--color-hover-light", "#B8860B"}
	ColorHoverDark       = Token{"--color-hover-dark", "#F7DF1E"}

	// Typography size scale
	TextXs   = Token{"--text-xs", "0.75rem"}
	TextSm   = Token{"--text-sm", "0.875rem"}
	TextBase = Token{"--text-base", "1rem"}
	TextLg   = Token{"--text-lg", "1.25rem"}
	TextXl   = Token{"--text-xl", "1.5rem"}
	Text2xl  = Token{"--text-2xl", "2rem"}

	// Line-height / weight / tracking
	LeadingTight      = Token{"--leading-tight", "1.25"}
	LeadingNormal     = Token{"--leading-normal", "1.5"}
	LeadingRelaxed    = Token{"--leading-relaxed", "1.75"}
	FontWeightRegular = Token{"--font-weight-regular", "400"}
	FontWeightMedium  = Token{"--font-weight-medium", "500"}
	FontWeightBold    = Token{"--font-weight-bold", "700"}
	TrackingTight     = Token{"--tracking-tight", "-0.02em"}
	TrackingNormal    = Token{"--tracking-normal", "0"}
	TrackingWide      = Token{"--tracking-wide", "0.05em"}

	// Spacing (4px grid)
	Space1  = Token{"--space-1", "0.25rem"}
	Space2  = Token{"--space-2", "0.5rem"}
	Space3  = Token{"--space-3", "0.75rem"}
	Space4  = Token{"--space-4", "1rem"}
	Space6  = Token{"--space-6", "1.5rem"}
	Space8  = Token{"--space-8", "2rem"}
	Space12 = Token{"--space-12", "3rem"}

	// Border radius
	RadiusSm   = Token{"--radius-sm", "4px"}
	RadiusMd   = Token{"--radius-md", "8px"}
	RadiusLg   = Token{"--radius-lg", "16px"}
	RadiusFull = Token{"--radius-full", "9999px"}

	// Elevation
	ShadowSm = Token{"--shadow-sm", "0 1px 2px rgba(0,0,0,0.05)"}
	ShadowMd = Token{"--shadow-md", "0 4px 6px rgba(0,0,0,0.1)"}
	ShadowLg = Token{"--shadow-lg", "0 10px 15px rgba(0,0,0,0.1)"}
	ShadowXl = Token{"--shadow-xl", "0 20px 25px rgba(0,0,0,0.15)"}

	// Motion
	DurationFast = Token{"--duration-fast", "150ms"}
	DurationBase = Token{"--duration-base", "250ms"}
	DurationSlow = Token{"--duration-slow", "400ms"}
	EaseIn       = Token{"--ease-in", "cubic-bezier(0.4,0,1,1)"}
	EaseOut      = Token{"--ease-out", "cubic-bezier(0,0,0.2,1)"}
	EaseInOut    = Token{"--ease-in-out", "cubic-bezier(0.4,0,0.2,1)"}

	// Z-index
	ZBase     = Token{"--z-base", "0"}
	ZDropdown = Token{"--z-dropdown", "100"}
	ZSticky   = Token{"--z-sticky", "200"}
	ZModal    = Token{"--z-modal", "300"}
	ZToast    = Token{"--z-toast", "400"}
	ZTooltip  = Token{"--z-tooltip", "500"}

	// Breakpoints
	BpSm = Token{"--bp-sm", "640px"}
	BpMd = Token{"--bp-md", "768px"}
	BpLg = Token{"--bp-lg", "1024px"}
	BpXl = Token{"--bp-xl", "1280px"}

	// Container widths
	MaxWProse   = Token{"--max-w-prose", "65ch"}
	MaxWContent = Token{"--max-w-content", "1200px"}
	MaxWScreen  = Token{"--max-w-screen", "1440px"}
)

Token catalog — every token from the legacy theme.css.

Functions

func Keyframes added in v0.0.3

func Keyframes(name string, steps ...KeyframeStep) item

Keyframes builds an @keyframes at-rule.

func Media added in v0.0.2

func Media(query string, items ...item) item

func MediaDesktop added in v0.0.5

func MediaDesktop(items ...item) item

MediaDesktop wraps the canonical "landscape + hover" media query used by tinywasm layouts to distinguish desktop from mobile. Reference: appears 4 times verbatim in platformd Appendix A.

func MediaPrefersDark added in v0.0.2

func MediaPrefersDark(items ...item) item

func Raw added in v0.0.2

func Raw(css string) item

func RawRule added in v0.0.2

func RawRule(s string) rawRule

RawRule is a transitional escape hatch. New code SHOULD use the typed DSL. Each RawRule call site SHOULD carry a // TODO(css-dsl): add typed X comment naming the missing property, so reviewers can decide whether to extend the DSL or accept the raw use case (vendor-prefixed, exotic property, etc.).

func Root added in v0.0.2

func Root(decls ...Decl) item

func Rule added in v0.0.2

func Rule(sel any, content ...RuleContent) item

Types

type Class added in v0.0.2

type Class string

Class is a CSS class name. Shared by HTML emission (WASM) and CSS emission (SSR). Only the string identity crosses the WASM boundary; pseudo-class helpers (Hover/Focus/Disabled) live in dsl.go (!wasm) because they only feed Rule().

func (Class) AsAttr added in v0.0.4

func (c Class) AsAttr() fmt.KeyValue

AsAttr returns a KeyValue attribute for this class to be used in element construction.

func (Class) Disabled added in v0.0.2

func (c Class) Disabled() Selector

func (Class) Focus added in v0.0.2

func (c Class) Focus() Selector

func (Class) Hover added in v0.0.2

func (c Class) Hover() Selector

Pseudo-class helpers on Class

func (Class) String added in v0.0.2

func (c Class) String() string

type Decl added in v0.0.2

type Decl struct{ Prop, Val string }

func AlignItems added in v0.0.2

func AlignItems(v Value) Decl

func AlignSelf added in v0.0.5

func AlignSelf(v Value) Decl

func All added in v0.1.0

func All(v Value) Decl

func Animation added in v0.0.2

func Animation(v ...Value) Decl

func Background added in v0.0.2

func Background(v Value) Decl

func BackgroundColor added in v0.0.2

func BackgroundColor(v Value) Decl

func BackgroundImage added in v0.0.2

func BackgroundImage(v Value) Decl

func Bind added in v0.0.2

func Bind(active, source Token) Decl

func Border added in v0.0.2

func Border(v ...Value) Decl

func BorderColor added in v0.0.2

func BorderColor(v Value) Decl

func BorderRadius added in v0.0.2

func BorderRadius(v ...Value) Decl

func BorderRight added in v0.1.0

func BorderRight(v ...Value) Decl

func Bottom added in v0.0.2

func Bottom(v Value) Decl

func BoxShadow added in v0.0.2

func BoxShadow(v Value) Decl

func BoxSizing added in v0.0.2

func BoxSizing(v Value) Decl

func Color added in v0.0.2

func Color(v Value) Decl

func Cursor added in v0.0.2

func Cursor(v Value) Decl

func Declare added in v0.0.2

func Declare(t Token, value string) Decl

func Display added in v0.0.2

func Display(v Value) Decl

func Flex added in v0.0.2

func Flex(v ...Value) Decl

func FlexDirection added in v0.0.2

func FlexDirection(v Value) Decl

func FontFamily added in v0.0.2

func FontFamily(v Value) Decl

func FontSize added in v0.0.2

func FontSize(v Value) Decl

func FontWeight added in v0.0.2

func FontWeight(v Value) Decl

func Gap added in v0.0.2

func Gap(v Value) Decl

func GridArea added in v0.0.5

func GridArea(v Value) Decl

func GridTemplate added in v0.0.5

func GridTemplate(v Value) Decl

func GridTemplateColumns added in v0.1.0

func GridTemplateColumns(v Value) Decl

func GridTemplateRows added in v0.1.0

func GridTemplateRows(v Value) Decl

func Height added in v0.0.2

func Height(v Value) Decl

func JustifyContent added in v0.0.2

func JustifyContent(v Value) Decl

func Left added in v0.0.2

func Left(v Value) Decl

func LetterSpacing added in v0.0.2

func LetterSpacing(v Value) Decl

func LineHeight added in v0.0.2

func LineHeight(v Value) Decl

func ListStyle added in v0.1.0

func ListStyle(v Value) Decl

func ListStyleType added in v0.0.5

func ListStyleType(v Value) Decl

func Margin added in v0.0.2

func Margin(v ...Value) Decl

func MarginLeft added in v0.1.0

func MarginLeft(v Value) Decl

func MarginRight added in v0.1.0

func MarginRight(v Value) Decl

func MaxHeight added in v0.0.5

func MaxHeight(v Value) Decl

func MaxWidth added in v0.0.2

func MaxWidth(v Value) Decl

func MinHeight added in v0.0.2

func MinHeight(v Value) Decl

func MinWidth added in v0.0.5

func MinWidth(v Value) Decl

func Opacity added in v0.0.2

func Opacity(v float64) Decl

func Outline added in v0.0.2

func Outline(v Value) Decl

func OutlineOffset added in v0.0.2

func OutlineOffset(v Value) Decl

func Overflow added in v0.0.5

func Overflow(v Value) Decl

func OverflowY added in v0.1.0

func OverflowY(v Value) Decl

func Padding added in v0.0.2

func Padding(v ...Value) Decl

func PaddingBottom added in v0.1.0

func PaddingBottom(v Value) Decl

func PointerEvents added in v0.0.2

func PointerEvents(v Value) Decl

func Position added in v0.0.2

func Position(v Value) Decl
func Right(v Value) Decl

func TextAlign added in v0.0.5

func TextAlign(v Value) Decl

func TextDecoration added in v0.0.5

func TextDecoration(v Value) Decl

func TextShadow added in v0.0.5

func TextShadow(v ...Value) Decl

func TextTransform added in v0.0.5

func TextTransform(v Value) Decl

func Top added in v0.0.2

func Top(v Value) Decl

func TouchAction added in v0.0.5

func TouchAction(v Value) Decl

func Transform added in v0.0.2

func Transform(v Value) Decl

func Transition added in v0.0.2

func Transition(v ...Value) Decl

func UserSelect added in v0.0.5

func UserSelect(v Value) Decl

func Visibility added in v0.0.5

func Visibility(v Value) Decl

func Width added in v0.0.2

func Width(v Value) Decl

func ZIndex added in v0.0.2

func ZIndex(v Value) Decl

type KeyframeStep added in v0.0.3

type KeyframeStep struct {
	At    string
	Decls []Decl
}

KeyframeStep is one step of a keyframes animation. At is the percentage or named position ("0%", "50%", "100%", "from", "to").

func At added in v0.0.3

func At(at string, decls ...Decl) KeyframeStep

At builds a KeyframeStep. Variadic Decls match the DSL's existing rule shape.

type KeyframesItem added in v0.0.3

type KeyframesItem struct {
	// contains filtered or unexported fields
}

type MediaItem added in v0.0.2

type MediaItem struct {
	// contains filtered or unexported fields
}

type RawItem added in v0.0.2

type RawItem string

type RuleContent added in v0.0.2

type RuleContent interface {
	// contains filtered or unexported methods
}

type RuleItem added in v0.0.2

type RuleItem struct {
	// contains filtered or unexported fields
}

type Selector added in v0.0.2

type Selector string

Selector is a raw CSS selector string used by the DSL.

type Stylesheet added in v0.0.2

type Stylesheet struct {
	// contains filtered or unexported fields
}

func NewStylesheet added in v0.1.0

func NewStylesheet(items ...item) *Stylesheet

func RenderCSS added in v0.0.2

func RenderCSS() *Stylesheet

func RootCSS added in v0.0.2

func RootCSS() *Stylesheet

func (*Stylesheet) String added in v0.0.2

func (s *Stylesheet) String() string

type Token added in v0.0.2

type Token struct{ Name, Fallback string }

Token is a design token: a named visual decision with a fallback value. Industry-standard term (W3C Design Tokens CG, Material, Carbon, Primer, Spectrum).

func (Token) Var added in v0.0.2

func (t Token) Var() string

type Value added in v0.0.2

type Value interface {
	// contains filtered or unexported methods
}
var (
	Auto    Value = kw("auto")
	None    Value = kw("none")
	Block   Value = kw("block")
	Flex_   Value = kw("flex")
	Grid    Value = kw("grid")
	Inline  Value = kw("inline-block")
	Center  Value = kw("center")
	Zero    Value = kw("0")
	Pointer Value = kw("pointer")

	Fixed       Value = kw("fixed")
	Absolute    Value = kw("absolute")
	Unset       Value = kw("unset")
	Initial     Value = kw("initial")
	FlexEnd     Value = kw("flex-end")
	SpaceAround Value = kw("space-around")
	Row         Value = kw("row")
	Column      Value = kw("column")
	Hidden      Value = kw("hidden")
	Visible     Value = kw("visible")
	Uppercase   Value = kw("uppercase")
	Capitalize  Value = kw("capitalize")
	RightText   Value = kw("right")
)

func Calc added in v0.0.5

func Calc(expr string) Value

func Em added in v0.0.2

func Em(f float64) Value

func Hex added in v0.0.2

func Hex(s string) Value

func Pct added in v0.0.2

func Pct(n int) Value

func Px added in v0.0.2

func Px(n int) Value

func Rem added in v0.0.2

func Rem(f float64) Value

func Str added in v0.0.2

func Str(s string) Value

func Vh added in v0.0.5

func Vh(f float64) Value

func Vw added in v0.0.5

func Vw(f float64) Value

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL