Composables

Reactive state helpers and DOM behaviours. A factory is called and returns a controller built on runes; an action is attached to an element; a transition is handed to Svelte. The class behind a factory never leaves its module — call the factory, never new.

createMediaQuery

factory

Call it — createMediaQuery(query)

Reactive matchMedia, for layout that has to branch on a breakpoint in markup rather than in CSS. matches is seeded false and filled by an effect, so anything that must be decided before the first paint — prefers-reduced-motion inside a DOM action, say — has to call matchMedia directly instead, or it will act on the seed.

Parameters

Prop Type Default Description
query required string

A CSS media query, e.g. '(min-width: 768px)'.

MediaQueryController

Prop Type Default Description
matches required boolean

Whether the query matches right now.

Import from ground/composables/use-media-query, or from the barrel.

createTextScale

factory

Call it — createTextScale()

Reader-controlled text size, applied as the --text-scale multiplier on the document element so popovers and dialogs rendered outside the shell scale with it. AppShell owns one and passes it to DisplayControls — an app needs its own only for a shell it built itself.

TextScaleController

Prop Type Default Description
level required number

Index of the current step, 0 being the default size.

steps required number

How many steps exist, for labelling the control.

next required () => void

Advances one step, wrapping back to the default past the last.

Import from ground/composables/use-text-scale, or from the barrel.

createTheme

factory

Call it — createTheme(fallback?)

Colour-scheme controller for an app shell: reads the visitor's stored choice, falls back to the OS, and keeps .dark/.light on the document element in sync. Create one per app and hand it to AppShell, which forwards it to DisplayControls.

Parameters

Prop Type Default Description
fallback 'system'|'light'|'dark'

Scheme to use on a first visit only — once anything is stored, the visitor's own choice outranks it. An app with no dark design yet can pass 'light' so a dark-OS visitor doesn't land on a theme nobody drew.

ThemeController

Prop Type Default Description
mode required 'system'|'light'|'dark'

The stored preference. system follows the OS.

resolved required 'light'|'dark'

The scheme actually in effect, with system already resolved against the OS. This is what a control should display.

set required (mode: 'system'|'light'|'dark') => void

Pins a preference and persists it.

toggle required () => void

Flips between light and dark, pinning the result.

Import from ground/composables/use-theme, or from the barrel.

countUp

action

Attach it with use: — use:countUp={{ options? }}

use: action that counts every number inside an element up to the value already rendered, the first time it scrolls into view. The finished text is the target, so the real figure survives with no JS and under reduced motion; thousands separators and the copy around them ($, %, M+) stay exactly where they were. Eases out on --ease-entrance, because a linear count reads as a spinner still loading.

Parameters

Prop Type Default Description
node required HTMLElement
options CountUpOptions

CountUpOptions

Prop Type Default Description
duration number

How long the climb takes, in milliseconds.

delay number

Delay in milliseconds, for staggering a row of figures.

Import from ground/composables/use-count-up, or from the barrel.

lightSource

action

Attach it with use: — use:lightSource={{ options? }}

use: action that aims the theme's single light source at the pointer. It listens on window and writes --light-x on the document element rather than on the node, so every surface-sheen surface leans the same way — dialogs and popovers rendered outside this tree included. AppShell already applies it; an app needs it only for a shell of its own. Idle under reduced motion.

Parameters

Prop Type Default Description
node required HTMLElement
options LightSourceOptions

LightSourceOptions

Prop Type Default Description
swing number

Total travel of the hot spot across the full viewport width, in percentage points — a lean toward the pointer, not the lamp being dragged.

Import from ground/composables/use-light-source, or from the barrel.

scrollFade

action

Attach it with use: — use:scrollFade={{ options? }}

use: action that fades a scrolling box's clipped edges, so a cut-off list reads as "there is more" instead of as its own end. Required on any box that clips its content. Each edge is sized by its distance from the end, so it grows and shrinks with the scroll and is simply absent when the content fits — nothing to transition, nothing to tune.

Parameters

Prop Type Default Description
node required HTMLElement
options ScrollFadeOptions

ScrollFadeOptions

Prop Type Default Description
size number

Height of a fade at full strength, in pixels.

top boolean

Fade the top edge. Pass false where something else already covers it, e.g. a translucent header sitting over the scroll.

bottom boolean

Fade the bottom edge.

Import from ground/composables/use-scroll-fade, or from the barrel.

scrollReveal

action

Attach it with use: — use:scrollReveal={{ options? }}

use: action that fades and lifts an element into place the first time it scrolls into view. Does nothing at all when the visitor asked for reduced motion, and never hides anything without JS — the hidden state is written from script, so a crawler or a script-off render gets the finished page rather than an empty one.

Parameters

Prop Type Default Description
node required HTMLElement
options ScrollRevealOptions

ScrollRevealOptions

Prop Type Default Description
y number

Distance in pixels the element rises from.

duration number

Transition duration in milliseconds.

delay number

Delay in milliseconds, for staggering neighbours.

Import from ground/composables/use-scroll-reveal, or from the barrel.

flyAndScale

transition

Pass it to transition: — transition:flyAndScale={{ options? }}

Svelte transition for something that appears over the page — the small rise-and-settle a popover or menu panel uses. Pass it to transition:/in:, not use:; it is a transition, not an action.

Parameters

Prop Type Default Description
node required HTMLElement
options FlyAndScaleOptions

FlyAndScaleOptions

Prop Type Default Description
y number

Distance in pixels the element travels as it settles.

start number

Scale it grows from.

duration number

Duration in milliseconds.

Import from ground/composables/use-transition, or from the barrel.