theme

package
v1.0.3 Latest Latest
Warning

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

Go to latest
Published: Aug 3, 2026 License: MIT Imports: 9 Imported by: 0

Documentation

Overview

Package theme defines the per-project design system: a small, versioned set of tokens (colors, typography, spacing, corner radius, logo, legal links) that every end-user surface — the Flutter login screen, hosted web pages, emails — renders from. The token space is deliberately constrained so that every accepted theme produces a legible screen: Validate enforces WCAG AA contrast, curated fonts and sane ranges.

Index

Constants

View Source
const (
	MinScale        = 0.8
	MaxScale        = 1.4
	MinSpacingUnit  = 4
	MaxSpacingUnit  = 16
	MaxCornerRadius = 32
)

Token ranges accepted by Validate.

View Source
const MinContrast = 4.5

MinContrast is the WCAG AA contrast ratio required between every color and its "on" counterpart, in both the light and the effective dark palette.

View Source
const SchemaVersion = 1

SchemaVersion is the version stamped on every encoded theme document. Parse rejects documents with a different version; future schema changes bump it and add an explicit upgrade path.

Variables

View Source
var FontFamilies = func() []string {
	all := fonts.List()
	names := make([]string, len(all))
	for i, f := range all {
		names[i] = f.Name
	}
	return names
}()

FontFamilies is the curated set of open-license fonts embedded in the binary (internal/fonts), by display name; Typography.FontFamily must be one of them. Arbitrary font uploads are deliberately out of scope — a fixed set keeps mobile rendering predictable and the binary self-contained.

Functions

func ContrastRatio

func ContrastRatio(a, b Color) float64

ContrastRatio is the WCAG 2.x contrast ratio between two colors: (L1+0.05)/(L2+0.05) with L1 the lighter. Ranges from 1 (identical luminance) to 21 (black on white); order does not matter.

func Encode

func Encode(t Theme) ([]byte, error)

Encode serializes the theme as its canonical storage document (a moth.projectconfig.v1.StoredTheme protobuf message), stamping the current schema version. An encoded document is never empty: empty stored bytes keep meaning "the built-in default theme".

func ToProto

func ToProto(t Theme) *projectconfigv1.StoredTheme

ToProto converts the domain theme into its storage message.

Types

type Color

type Color struct {
	R, G, B uint8
}

Color is an opaque sRGB color.

func ParseColor

func ParseColor(s string) (Color, error)

ParseColor parses a strict "#RRGGBB" hex color (case-insensitive). Shorthand (#RGB) and alpha channels are rejected: the theme schema stores one canonical form.

func (Color) Hex

func (c Color) Hex() string

Hex formats the color as uppercase "#RRGGBB".

func (Color) Luminance

func (c Color) Luminance() float64

Luminance is the WCAG 2.x relative luminance of the color: 0 for black, 1 for white.

type ColorOverrides

type ColorOverrides struct {
	Primary      string
	OnPrimary    string
	Background   string
	OnBackground string
	Surface      string
	OnSurface    string
	Error        string
	OnError      string
}

ColorOverrides is a partial palette: any empty field is derived from the light palette instead.

type Colors

type Colors struct {
	Primary      string
	OnPrimary    string
	Background   string
	OnBackground string
	Surface      string
	OnSurface    string
	Error        string
	OnError      string
}

Colors is a complete palette: every role and its "on" (foreground) counterpart. Values are #RRGGBB.

func DeriveDark

func DeriveDark(light Colors, o *ColorOverrides) Colors

DeriveDark computes the effective dark palette from the light palette and the optional per-field overrides. The algorithm, applied to every field left empty in o (a nil o derives everything), is deterministic:

  1. background and surface: the light value blended 88% / 84% toward black — lands in the dark-neutral range while keeping a trace of the brand tint, with surface slightly lighter than background so elevation still reads.
  2. primary and error: the light value blended 40% toward white — the conventional pastel shift that keeps saturated brand colors legible on dark surfaces.
  3. every on* color: whichever of black/white contrasts more with its (derived or overridden) counterpart. This always meets WCAG AA: CR(c, white) x CR(c, black) = 21 for any c, so the larger of the two is at least sqrt(21) ~ 4.58 >= MinContrast.

light is assumed valid (see Validate); unparseable inputs derive from black.

type Legal struct {
	TermsURL   string
	PrivacyURL string
}

Legal holds the optional legal links rendered near signup.

type Logo struct {
	Light string
	Dark  string
}

Logo holds the server-managed asset paths of the uploaded logos, one per color scheme ("/assets/{project}/logo-light.png"). Empty = no logo.

type Shape

type Shape struct {
	// CornerRadius in logical pixels; 0..MaxCornerRadius.
	CornerRadius int
}

Shape controls component rounding.

type Spacing

type Spacing struct {
	// Unit is the base spacing step in logical pixels;
	// MinSpacingUnit..MaxSpacingUnit.
	Unit int
}

Spacing is the base spacing grid.

type Theme

type Theme struct {
	// Version is the schema version of the document (SchemaVersion).
	Version int
	// Colors is the light palette. All fields are required #RRGGBB values.
	Colors Colors
	// DarkColors optionally overrides individual dark-palette colors.
	// Omitted fields (and a nil struct) are derived from Colors — see
	// DeriveDark for the algorithm.
	DarkColors *ColorOverrides
	Typography Typography
	Spacing    Spacing
	Shape      Shape
	Legal      Legal
}

Theme is one project's complete design system. It is persisted as a moth.projectconfig.v1.StoredTheme protobuf document (see Encode/Parse).

func Default

func Default() Theme

Default returns the theme applied to projects that never customized anything: the Material baseline palette, Inter at scale 1, an 8px grid and 12px corners.

func FromProto

func FromProto(msg *projectconfigv1.StoredTheme) Theme

FromProto converts a storage message into the domain theme. Nil sub-messages become zero values; an absent dark_colors stays nil so the dark palette derives fully from the light one.

func Parse

func Parse(raw []byte) (Theme, error)

Parse decodes a stored theme document (moth.projectconfig.v1.StoredTheme). It rejects documents from a different schema version — including empty input, which callers treat as "default theme" before parsing; it does not validate token values (Validate does).

func ParseLegacyJSON

func ParseLegacyJSON(raw []byte) (Theme, error)

ParseLegacyJSON decodes a pre-0019 JSON theme document. BACKFILL ONLY: it is exported solely for the one-time store backfill and must not be called from any live read/write path.

func (Theme) EffectiveDark

func (t Theme) EffectiveDark() Colors

EffectiveDark returns the dark palette actually rendered: explicit DarkColors overrides where present, derived values everywhere else.

func (Theme) Validate

func (t Theme) Validate() error

Validate checks every token of the theme, including the effective dark palette after derivation, and returns the first violation. A theme that validates is guaranteed to render legibly: WCAG AA contrast on every color/on-color pair, a curated font, and in-range scale/spacing/radius.

type Typography

type Typography struct {
	// FontFamily must be one of FontFamilies.
	FontFamily string
	// Scale multiplies every text size; MinScale..MaxScale.
	Scale float64
}

Typography selects one of the curated embedded fonts and a global size multiplier.

Jump to

Keyboard shortcuts

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