VSTDOCSv0.0.34

DOCS / UI REFERENCE

Styling

Styling is a Tailwind-style utility subset, resolved in JS by the tw() resolver — C++ only ever sees final style objects. Classes compose left to right; unknown classes warn once in dev instead of failing.

Supported classes

FAMILYCLASSES
Flexboxflex-row flex-col flex-1 flex-auto flex-none grow shrink-0 flex-wrap items-* justify-* self-* basis-*
Sizing & spacingw-* h-* size-* (width + height together) min-w-* max-h-* p-* px-* pt-* m-* mx-* mt-* gap-* gap-x-* gap-y-* — 4px scale, fractions (w-1/2), w-full, arbitrary w-[220], negatives -mt-2 -left-1/2
Positionabsolute relative inset-* inset-x-* inset-y-* top-* right-* bottom-* left-*
Colorbg-* text-* border-* — the full Tailwind palette (all 22 families, 50–950), theme tokens, hex bg-[#0B0B0A], opacity suffix bg-black/40
Borders & radiusborder border-2, per side border-t border-b-2 border-l-[3] (square strips — corner radii ignored), rounded rounded-sm…3xl/full, per corner rounded-t-lg rounded-br-full, arbitrary rounded-[10]
Gradientsbg-gradient-to-t/tr/r/br/b/bl/l/tl bg-gradient-radial bg-gradient-conic with from-* via-* to-* (palette, tokens, or from-[#111])
Transformsrotate-45 -rotate-90 rotate-[10.5] scale-95 scale-[1.25] translate-x-4 -translate-y-2, percent of own size translate-x-1/2, origin origin-top-left etc. (since 0.0.25) — layout is untransformed, but painting and hit-testing follow the transform (since 0.0.20)
Stackingz-10 z-[3] -z-1 — reorders both painting and hit-testing among siblings (tree order breaks ties)
Visibilityhidden (display: none — leaves layout entirely) vs invisible/visible (keeps its space, paints nothing, takes no input)
Typographytext-xs…text-6xl text-[15] font-normal/medium/semibold/bold font-mono text-left/center/right tracking-* tracking-[3] leading-* leading-[18] truncate line-clamp-3 uppercase/lowercase/capitalize underline line-through
Effectsopacity-* shadow…shadow-xl shadow-inner overflow-hidden overflow-y-scroll overflow-x-scroll overflow-auto aspect-square cursor-pointer/text/default/grab/move/ns-resize/ew-resize/crosshair pointer-events-none/auto select-text/none border-solid/dashed/dotted object-contain/cover/fill
Filtersblur-sm…blur-3xl blur-[6] (CSS filter: blur — the node and its subtree render offscreen and soften) backdrop-blur-sm…backdrop-blur-3xl backdrop-blur-[10] (frosted glass: blurs whatever is painted beneath the node — pair with a translucent bg-* tint)
Motiontransition transition-all/colors/opacity/transform/none duration-150 delay-75 ease-linear/in/out/in-out — style changes tween from their currently displayed values instead of jumping. Presets: animate-spin animate-pulse animate-bounce animate-none. One honest limit: native hover:/active: merges don't transition — animate hover with onMouseEnter state instead
Variantshover: active: focus: — resolved to native hover/active/focus style layers, applied by the C++ hit-tester with no JS round-trip

Composing classes — cx()

For conditional classNames the SDK ships cx, a tiny clsx: strings, arrays, and object maps, falsy values dropped.

TSX
import { cx } from "@vsreact/core";

<View className={cx(
  "px-4 py-2 rounded-lg",
  active && "bg-lime-400",
  { "opacity-40": disabled },
)} />

Theme tokens

Register your palette once and use semantic names everywhere — the resolver expands them like any other color:

theme.ts
import { configureTheme } from "@vsreact/core";

configureTheme({
  colors: {
    surface: "#0F1210",
    raised:  "#161B17",
    accent:  "#C6F135",
    text:    "#ECF2E8",
    faint:   "#8B948C",
  },
});

// then: <View className="bg-surface border-raised hover:bg-raised">
//       <Text className="text-accent" />

accent is special: since 0.0.27 every built-in control paints its value with it — knob arcs, slider fills, meters, the keyboard's active keys, the envelope editor. One token themes the whole panel, and you only pass a colour prop where you want a control to differ. Without a theme they stay VSReacT lime. Reading it yourself, for custom controls that should match: accentColor(), or accentColor("66") for a translucent fill.

Custom fonts

fontFamily is a system-font lookup by default. Since 0.0.27, registerFont({ family, src }) registers a bundled typeface from font-file bytes — src is a file path or a base64 data: URI, like images. fontFamily resolves against registered families before the system lookup; unregistered names behave exactly as before. An optional weight (default 400, "bold" → 700) tags the face.

fonts.ts
import { registerFont } from "@vsreact/core";

registerFont({
  family: "Panel Grotesk",
  src: "data:font/otf;base64,T1RUTwAK...", // or a .ttf/.otf file path
});

// then: <Text style={{ fontFamily: "Panel Grotesk" }} />

The style prop

For computed values, pass style directly — the same keys the resolver produces (width, backgroundColor, fontSize, opacity…). Classes and style merge, with style winning.

TSX
<View
  className="rounded-full bg-zinc-800"
  style={{ width: size, height: size, opacity: fadeIn }}
/>

Arc painting (knobs)

Two style families exist only as style keys:

  • Arcs — arcTrackColor, arcColor, arcStart, arcEnd, arcValueStart, arcValueEnd, arcThickness: the natively painted knob arc, angles in degrees around the View’s center. The built-in Knob uses −135°…+135°; arcValueStart is what powers its bipolar mode. Strokes default to rounded caps, which turn short slices into capsule blobs — set arcCap: "butt" (since 0.0.18) for radial tick marks and crisp dashes.
  • Text input chrome — caretColor, placeholderColor.
  • Gradients (structured) — beyond the classes: gradientType (linear|radial|conic), gradientAngle (CSS degrees, 0 = up, clockwise), gradientStops ([{ offset: 0, color: "#ff0000" }, …]) for more than three stops. Radial fills are farthest-corner ellipses; conic renders are cached per size + spec.
  • Shadows — outer shadowColor/Radius/OffsetX/OffsetY (path-shaped), inset insetShadowColor/Radius/OffsetX/OffsetY (CSS box-shadow: inset), and glyph-shaped textShadowColor/Radius/OffsetX/OffsetY on <Text> (CSS text-shadow — LED glows without a bounding-box halo).
  • Shadow stacks — boxShadow (since 0.0.27): an array [{ color, radius, offsetX, offsetY, inset? }, …] stacks multiple shadows on one node in CSS order — outer entries paint behind the background, inset: true entries over it. Composes with the flat shadowColor keys.
  • Background layers — backgroundLayers (since 0.0.27): an array of gradient/color specs painted over the base background in order, each entry using the same keys as the structured gradients above — multi-layer metallic knob caps in one View.
  • Text stroke & length — textStrokeColor + textStrokeWidth (since 0.0.27) stroke the glyph outline under the fill (CSS paint-order: stroke); textLength scales a single line horizontally to a fixed width (SVG textLength/lengthAdjust), so digit readouts hold their box as the digits change.
  • Transforms — rotate (degrees), scale, translateX/Y, applied about the frame centre in CSS order (translate → rotate → scale); children inherit. Layout is untransformed, but since 0.0.20 hit-testing follows the transform, so rotated controls receive input where they actually paint.
  • Clip polygons — clipPolygon: a flat [x, y, x, y, …] array in percent of the frame (CSS clip-path: polygon()). Shapes the background, borders, shadows, and overflow clipping — beveled LED segments, chamfered plates, meters.
  • Repeating gradients — gradientRepeat: N tiles the stop pattern N times across the span (any gradient type): knurl rings, scanlines, ruler ticks.
a bare arc, no Knob component
<View
  className="items-center justify-center"
  style={{
    width: 72, height: 72,
    arcTrackColor: "#2A2F27", arcColor: "#C6F135",
    arcStart: -135, arcEnd: 135,
    arcValueEnd: -135 + 270 * value,
    arcThickness: 6,
  }}
/>
Performance: the resolver caches by class string, so repeated renders of the same className cost one map lookup. Hover/active/focus variants repaint natively — the JS side is not involved after mount.