ResolvedStyle Struct
Public Members
| std::string | fill |
| bool | fillIsGradient = false |
| std::string | borderFill |
| bool | borderIsGradient = false |
| double | borderThickness = 0 |
| double | radiusTL = 0 |
| double | radiusTR = 0 |
| double | radiusBL = 0 |
| double | radiusBR = 0 |
| double | marginL = 0 |
| double | marginT = 0 |
| double | marginR = 0 |
| double | marginB = 0 |
| double | paddingL = 0 |
| double | paddingT = 0 |
| double | paddingR = 0 |
| double | paddingB = 0 |
| std::string | textColor |
| std::string | codeBg |
| double | fontSize = 0 |
| double | fontWeight = 0 |
| std::string | fontFamily |
| bool | visible = true |
| bool | collapsed = false |
| std::string | direction |
| double | spacing = 0 |
| std::string | crossAlign |
| std::string | justify |
| std::string | scroll |
| double | grow = 0 |
| double | shrink = -1 |
| double | width = 0 |
| double | height = 0 |
| double | heightVp = 0 |
| double | maxWidth = 0 |
| double | aspectRatio = 0 |
| double | translateY = 0 |
| double | translateX = 0 |
| double | rotation = 0 |
| double | opacity = 1.0 |
| std::string | text |
| std::string | placeholder |
| bool | secret = false |
| bool | multiline = false |
| bool | readOnly = false |
| bool | wrap = true |
| std::string | iconSource |
| std::string | mediaSource |
| std::string | fit |
| bool | autoplay = false |
| bool | loop = false |
| bool | muted = false |
| bool | controls = false |
| std::string | qrData |
| std::string | intent |
| std::string | overlay |
| std::string | href |
| std::string | tag |
| std::string | anchor |
| std::string | bind |
Detailed Description
Fully-resolved styling for a single box/text node. Colors are hex strings ("#rrggbb" / "#aarrggbb"). Gradients are stored as comma-joined stops ("0:#3a3c42,1:#42454d") with the matching *IsGradient flag set.
Member Variable Documentation
double marginL = 0
Box model. margin = EXTERNAL space around the node, contributed by the parent's layout; padding = INTERNAL space between the node's border and its content. Content inset = borderThickness + padding.
double marginT = 0
Box model. margin = EXTERNAL space around the node, contributed by the parent's layout; padding = INTERNAL space between the node's border and its content. Content inset = borderThickness + padding.
double marginR = 0
Box model. margin = EXTERNAL space around the node, contributed by the parent's layout; padding = INTERNAL space between the node's border and its content. Content inset = borderThickness + padding.
double marginB = 0
Box model. margin = EXTERNAL space around the node, contributed by the parent's layout; padding = INTERNAL space between the node's border and its content. Content inset = borderThickness + padding.
std::string codeBg
Markdown nodes only: the resolved Theme/Secondary hex used as the surface color behind inline + fenced code (so code reads as a tinted pill/block over the body). Resolved in core from the active theme — not an author-facing attribute — so all three reconcilers theme code identically. Empty for every non-Markdown node.
double fontSize = 0
text point/px size (0 == reconciler default)
double fontWeight = 0
CSS-style numeric weight (100–900; 400 normal, 700 bold). 0 == unset, which each reconciler renders as its default/normal weight.
std::string fontFamily
Font family name ("" == reconciler default). The generic "monospace" maps to the platform's fixed-width face (code/raw-text views; web: CSS family).
bool visible = true
Visibility. False drops the node (and its subtree) from the render tree entirely — driven by a "Visible" attribute that can cascade on state (e.g. hide a tab's label in @Mobile). Defaults true.
bool collapsed = false
Collapsed. Unlike visible (which removes the node), a collapsed node STAYS
in the tree but the reconciler animates its height to 0 — and back to its
natural content height when un-collapsed. Driven by a "Collapsed" attribute
that cascades on state (the dashboard drawers collapse their body unless the
drawer carries @Expanded). Defaults false. The node persists across the
toggle so the height change can tween (a Visible toggle can't animate — the
node is gone). Reconcilers that don't animate may treat it as hide/show.
std::string direction
Layout — container properties (how this node arranges its children). direction: "Row" | "Column" (empty == "Column", the default). crossAlign: "Start" | "Center" | "End" | "Stretch" cross-axis placement of children (empty == "Center", the default). justify: "Start" | "Center" | "End" main-axis placement of the child block when nothing grows (empty == "Center", the default). scroll: "Vertical" | "Horizontal" | "Both" — overflow scrolls instead of clipping (empty == no scroll).
double spacing = 0
gap between children, px
double grow = 0
main-axis flex factor (0 == don't grow)
double shrink = -1
Main-axis shrink factor ("Layout.Shrink"). -1 == unset (the platform
default, CSS flex-shrink 1). 0 pins the node at its content size inside a
SCROLLABLE ancestor — the static-web idiom for "this section must never be
squashed to fit; overflow scrolls instead" (a page row that grows to push
the footer down, the footer itself). Mirrors the legacy sites' hand-written
flex: 1 0 auto / flex: none rules. Runtime reconcilers currently
ignore it (their scroll regions size children natively).
double width = 0
fixed width, px (0 == intrinsic)
double height = 0
fixed height, px (0 == intrinsic)
double heightVp = 0
Height as a FRACTION of the VIEWPORT height ("Size.Height Viewport",
0 == unset) — the viewport cousin of translateY's self-fraction. Folded
into height at build time against the platform-reported viewport
(VApp::set_viewport_height), so reconcilers only ever see the concrete
px value; an authored Size.Height doubles as the fallback when no
viewport height has been reported. A fraction (not a px length), so the
mobile metric scale leaves it alone. Sizes the scan drawer's camera to
the legacy "70% of the screen" drawer proportions.
double maxWidth = 0
Max width, px (0 == none). A constraint, NOT a fixed size: the node EXPANDS to fill its parent's cross axis up to this cap, then SHRINKS below it when the parent is narrower. Combined with the parent's Layout.Align (default Center) this yields the classic centered, max-width content column that stays comfortably wide on big windows yet reflows on small ones. Reconcilers implement the fill-then-cap behavior natively (flex width:100%+max-width on web; a centering container on Qt/Android).
double aspectRatio = 0
Image / Video nodes: width÷height ASPECT RATIO ("Aspect Ratio", e.g.
1.7778 for 16:9; 0 == unset). The node keeps its normal width behavior
(fill the parent's cross axis / a fixed Size.Width) and its HEIGHT
derives from the LAID-OUT width (height = width / ratio) — so a feed
card's media holds a proportional shape at any card width, instead of a
fixed pixel height cropping tall media. When set, Size.Height is
ignored. The mismatch between this ratio and the artwork's own resolves
via Fit as usual ("Cover" crops, "Contain" letterboxes). Overridable
per-row via the "Aspect:
double translateY = 0
Transform — a render-time offset along the main axis, expressed as a
FRACTION of the node's own measured height (1.0 == fully shifted off by its
own height; 0 == in place). The reconciler multiplies by the measured size,
so "fully hidden" stays correct regardless of the node's intrinsic height,
and animates the change. Drives the titlebar's hide-away-on-scroll slide
(a @Narrow&ControlsHidden variant pushes the bottom-pinned bar to 1.0).
double translateX = 0
Transform — the horizontal twin of translateY: a render-time offset
expressed as a FRACTION of the node's own measured WIDTH (1.0 == fully
shifted off by its own width; 0 == in place). Drives a "SideSheet" overlay's
slide-in from the right edge (a @Open variant pulls it from 1.0 to 0).
double rotation = 0
Transform — a render-time rotation in DEGREES, clockwise, about the node's own center. Purely visual: it does not affect layout/measurement (the slot the node occupies is its un-rotated box). Used to reorient an icon shared by two controls — e.g. the same downward "arrow" glyph rotated 180 for an upvote button. 0 == no rotation. Reconcilers apply it on icon nodes (CSS rotate / QPainter::rotate / View.rotation), all clockwise-positive.
double opacity = 1.0
Render-time opacity in [0,1], purely visual: it fades the node (and its
subtree) WITHOUT reflowing — the node keeps its full layout slot, unlike
visible=false which drops it. Mirrors CSS opacity / Android alpha /
QGraphicsOpacityEffect. 1 == fully opaque (the default). Drives the
space-preserving hide of a gated affordance — e.g. a feed post's vote
arrows when the viewer isn't verified, so the vote box keeps its size.
std::string text
Text nodes: static, design-owned literal copy authored directly in the style (mirrors iconSource for icons). The base value for node.text; a runtime bind_text() value or a dynamic "Bind" override takes precedence. Empty when the style supplies no literal (text then comes from code/bind). NOTE: literal copy here is not localizable — when i18n lands this should become a string-table key (e.g. "@app.title") resolved against app data.
std::string placeholder
Editor nodes: the floating placeholder copy — shown filling the field while
it is empty and unfocused, animating up + smaller to a label once the user
focuses or types (the legacy desktop line-editor behavior, now portable to
every reconciler). The editor's INITIAL/default value rides the normal
text field (the style's literal Text, overridable via bind_text); the
user's typed value is owned by the reconciler and read back via
VApp::editor_text(). Empty for non-editor nodes.
bool secret = false
Editor nodes: mask the typed value (password field) when true. Defaults false (a normal visible field).
bool multiline = false
Editor nodes: a multi-line text box (wrapping, top-aligned) instead of the single-line field. The floating placeholder is a single-line affordance, so multi-line fields show a STATIC placeholder that fills the box while empty. Height comes from the style's Size.Height (no auto-grow). Defaults false.
bool readOnly = false
Editor nodes: a display surface the user can select/copy from but not type into (Docuriser's streamed build log). The value still moves via app rebinds (bind_text); a read-only multi-line editor additionally pins its scroll to the bottom on each rebind — log semantics. Defaults false.
bool wrap = true
Text nodes wrap long lines to the available width by default (like web +
Android); "Wrap": 0 keeps them single-line. Editor nodes (multi-line):
wrap long lines to the box width (the default).
"Wrap": 0 disables wrapping and scrolls horizontally instead — the
log/code look (long paths stay on one line). Single-line fields ignore it.
std::string iconSource
Icon nodes: the .svg asset name (no extension) the reconciler loads and recolors (to textColor). Empty for non-icon nodes.
std::string mediaSource
Image / Video nodes: the media file path or URL the reconciler loads and displays (a photo, an mp4, an SVG logo). Raster/video render verbatim; an SVG Image renders as a live vector and — unlike a photo, but like an icon — recolors to textColor when the style sets Text Color (else full color is preserved). Resolves the same "Source" attribute icons use; the reconciler reads whichever of iconSource/mediaSource matches the node type. Empty otherwise.
std::string fit
Image / Video nodes: how the media fills its box when its aspect ratio differs from the box's — "Cover" (fill + crop) or "Contain" (fit whole, letterbox). Maps to CSS object-fit. Empty == the reconciler's default (Cover). Ignored by non-media nodes.
bool autoplay = false
Video nodes only: playback flags. autoplay starts on load (browsers require muted to honor it), loop restarts at the end, muted starts silent, controls shows the native scrubber/volume UI. All default false. Ignored elsewhere.
std::string qrData
QR nodes: the payload string encoded into the QR matrix (a node URL, a key blob, …). Resolves the "Data" attribute (a separate attribute from Source, so a QR and an icon/image can't be confused). The matrix is derived from this on demand — by the core when serializing for web/Android, by the desktop reconciler directly — so only the payload rides the resolved style. Empty for non-QR nodes (an empty payload paints just the box fill).
std::string intent
Optional semantic action a reconciler may bind to platform behavior, e.g. "window:minimize" / "window:maximize" / "window:close" on a button, or "window:drag" / "window:resize" on a box. Desktop-only today; other platforms ignore intents they don't handle. Empty for most nodes.
std::string overlay
Overlay mode. "" == this node lays out normally in its parent's flow.
"Modal" == the reconciler lifts this node out of the flow and presents it
as a dialog centered over a darkening backdrop covering the rest of the UI
(desktop = a movable, modal frameless window; web/Android = a fixed,
centered element). The node is shown/hidden via the normal visibility
overlay (bind_visible), so opening/closing the dialog rides the diff as a
single Insert / Remove.
"PinnedBottom" == the reconciler floats this node over the content, anchored
to the bottom edge (rather than occupying a slot in the flow), so it can
slide off-screen via translateY without reflowing content. Used by the
titlebar in @Narrow (where the bar sits at the bottom) to drive hide-away-
on-scroll. Empty for most nodes.
"BottomSheet" == like PinnedBottom (floated at the anchor's bottom edge,
centered up to Size.Max Width), but reserves NO bottom space: the node
OVERLAYS the content instead of pushing it. Used by the dashboard drawers,
which peek as just a header (their body carries a Visible "@Expanded"
variant) and grow upward over the list when expanded; the list reserves the
collapsed peek with its own bottom padding.
"SideSheet" == a modal detail panel floated at the anchor's RIGHT edge, full
anchor height, right-aligned and capped at Size.Max Width (0 == fill, i.e.
edge-to-edge in @Narrow). The reconciler draws a darkening scrim over the
rest of the anchor (click-to-dismiss; dispatches a "click" to THIS node's
path) and slides the panel in/out horizontally via translateX (rest at 1
off-screen; an @Open variant pulls it to 0), the scrim's opacity tracking
the slide. Stays in the tree across open/close (state-driven, like the
titlebar's translateY hide-away) so the slide animates both ways. Used by
the profile post-detail.
std::string href
Link nodes: the target URL (the "Href" attribute; overridable at runtime
via bind_href and per-row via a "Href:
std::string tag
Document tag hint (the "Tag" attribute): the semantic HTML element the static-web emitter uses instead of div/span — "h1".."h6", "nav", "main", "header", "footer", "section", "article", "ul", "li", … Authored per style for crawlable, reader-mode-friendly generated pages. Runtime reconcilers ignore it. Empty = the emitter's default element.
std::string anchor
Fragment anchor (the "Anchor" attribute): the emitted element's id, the target of "#anchor" deep links in generated documentation. Runtime reconcilers ignore it. Empty = no id.
std::string bind
Data binding handled in the core during tree-build (consumed there, never
sent to reconcilers): "ThemeList" makes a container generate one button
per loaded theme (from its first child as a template); "ActiveThemeName" /
"ActiveThemePublisher" set a text node to the active theme's
name/publisher; "ThemeName" / "ThemePublisher" do the same for the theme of
the enclosing generated theme button (its primary label + publisher
subtext), so each button reads its own theme rather than the active one.
Row-data forms (inside a "List: