Skip to content

Concepts

Stipe keeps daisyUI’s whole theme catalog open. Set any daisyUI theme name with data-theme on the root or on any element. Stipe adds its own maintained themes:

  • latte and mocha: the light and dark defaults.
  • field-guide and field-guide-night: flat ink linework, compact geometry and muted naturalist accents. The night theme uses dark blue-green paper and cream ink.
  • embed and embed-dark: small, flat, neutral themes for a widget framed inside another site.
  • phosphor and codec: optional terminal-style material presets.
  • pirate-radio and pirate-radio-night: a cream-paper print palette and its warm ink-black reverse.

applyTheme(theme, root?) sets data-theme on the root element, or on the element you pass. getTheme(root?) reads it. subscribeTheme(listener, root?) watches only that attribute and returns a cleanup function. These are plain DOM helpers. Stipe has no JavaScript theme provider and no token-object format.

Stipe owns the coral terminal tint (#f98284). terminalPalette("latte") and terminalPalette("mocha") return frozen semantic and ANSI colour sets that fit terminal emulators such as xterm.js. Other theme names return undefined. The Fungi wordmark art lives in cli-kit.

The stylesheet supplies one rem-based grid through Tailwind’s spacing namespace:

Name Value At a 16px root
2xs 0.125rem 2px
xs 0.25rem 4px
sm 0.5rem 8px
md 0.75rem 12px
lg 1rem 16px
xl 1.5rem 24px
2xl 2rem 32px
3xl 3rem 48px
4xl 4rem 64px

Use classes such as px-xs, py-sm, gap-md and p-lg. Plain CSS can use var(--spacing-sm). Theme changes keep these values. STIPE_SPACING_NAMES exports the names for class-merging configuration, and Caps already uses them. Zero, automatic layout, proportional sizing and measured geometry keep their ordinary CSS meaning. These tokens supply spacing. They do not constrain pane resizing or force content to a fixed height.

The main stylesheet maps Nunito to font-sans and Maple Mono to font-mono. Use the sans voice for interface copy and controls. Keep mono for machine values, code and identifiers. Editorial pages also get Fraunces for font-display, Nothing You Could Do for font-handwritten and Grenze Gotisch for font-nameplate.

Tailwind compilation alone does not load fonts. Hosts with an asset bundler such as Vite import @fungi.computer/stipe/fonts.css to load them. It references the bundled WOFF2 files relative to the Stipe package, so each host’s asset build emits them on its own origin. Nunito ships as separate Latin, Latin Extended, Cyrillic, Cyrillic Extended and Vietnamese subsets that load only for matching text. Normal Nunito weights 200 to 900 and Maple Mono weights 200 to 800 use font-display: swap. No Google Fonts request or runtime font dependency is needed. Font provenance records sources and checksums.

Stipe defines a few material properties on top of daisyUI’s own --depth, --noise, radius and colour variables. Caps reads them in ordinary component rules, with no selectors for individual themes:

CSS property Value type Default
--stipe-surface-frame-width Nonnegative CSS length Component frame scale: 2/6/10px for sm/md/lg
--stipe-surface-frame-image CSS background image, gradient, or none Frame gradient derived from the semantic palette
--stipe-shadow-raised Box-shadow list or none Component-specific raised shadow
--stipe-shadow-inset Box-shadow list or none Component-specific recessed shadow
--stipe-shadow-edge Box-shadow list or none Component-specific edge highlight
--stipe-display-texture-image CSS background image, gradient, or none none
--stipe-display-text-shadow Text-shadow list or none none

Frame and shadow overrides reset to initial at each data-theme boundary. For these unregistered custom properties, that selects the component’s var() fallback. It does not mean a zero-width frame. none explicitly removes an image or shadow. Stock daisyUI themes do not need to define these properties.

The frame width is decoration, not content padding or a hit target. In Caps, Surface supplies the frame, Screen the display face, and Display composes both with a gasket. --depth: 0 removes the gasket’s physical spacing. Texture is a decorative CSS image, separate from daisyUI’s noise. Never use it to carry information the reader needs.

embed and embed-dark are for a widget framed inside someone else’s page. The host picks one (for example by prefers-color-scheme) and applies embedThemeProperties({ accent, fontFamily }) to the themed element with style.setProperty. The owner’s #rrggbb accent drives daisyUI primary and accent. readableContentColor picks black or white content by WCAG luminance, so primary text always reaches 4.5:1. A supplied font-family list comes before system-ui. Without one the themes use system-ui. Your host parses the accent and font list before passing them in. EMBED_THEME_TOKENS repeats the default chrome colours for surfaces outside daisyUI, such as a launcher in a shadow root.

--stipe-art-{coral,blue,mint,grape,yellow,cream,ink,inkcap,graphite} are illustration roles, separate from control-state colours. Each has explicit light and dark defaults through light-dark() and resets at every theme boundary. Themes can override these roles to retint artwork. Drawings on the page use --stipe-sketch-ink. Figure eye cut-outs use --color-base-100 directly.

You can nest data-theme inside another theme. A complete palette declares its own typography and muted ink at its theme boundary, so nesting latte inside pirate-radio restores latte typography. A values-only finish inherits colours, color-scheme, fonts, button radius and muted ink. It sets --root-bg: transparent so daisyUI does not paint a new page behind it, and declares only the material values it changes.

CSS inherits through the DOM, not through React portals. Dialogs, dropdowns and popup comboboxes in Caps take a portal container option. For a nested theme, render them into an unclipped container inside that theme. The default body portal uses the document theme. An ancestor with clipping, transforms or containment can affect positioning, so choose the portal container as part of your overlay layout.

pirate-radio is a complete, nestable cream-paper palette with orange-red spot colour, mono labels, tight rules and a procedural print texture. pirate-radio-night reverses it to warm ink-black paper. It uses Instrument Sans for body text, Anton for headings and Departure Mono for every mono role, including labels and numerals. No external font request or raster texture is needed.

The theme sets generic Caps hooks instead of adding component props: --caps-heading-font, --caps-heading-weight, --caps-heading-case, --caps-heading-tracking (default -0.025em, 0.02em here), --caps-heading-line-height (1.2 here), --caps-label-font (mono here), --caps-card-image, --caps-window-image and --caps-print-texture-size. Each keeps the previous appearance when unset. --font-numeric defaults to var(--font-mono) at every theme boundary, and Caps’ numeric readouts use it with tabular numerals. --stipe-font-synthesis keeps browser defaults in other themes and is none here, so the regular-only fonts never get synthetic weights or italics. CSS motion uses short 60/90/140/200 ms press timings without overshoot. All of these reset at nested theme boundaries.