Expand description
NodeSpec and TextStyle: everything a node and a text declare,
as plain data with a builder.
A NodeSpec is the contract every frontend lowers into, whether a Rust
builder chain, a Lua table or a JSX element. It groups the layout
(LayoutSpec: sizing, direction, padding, gap, alignment, overflow),
the look (VisualStyle: background, border, radius, shadow, opacity)
and, boxed because most nodes declare none of it, the events, animation,
accessibility and interaction styling. Every builder method sets one of
those fields; the field docs below say what each means.
use kui_core::{Align, Color, NodeSpec, Sizing, TextStyle, TextWrap};
// A card: grows across its parent, fits its content down, 12 px padding
// and gap, rounded, with a hover background and a click payload.
let card = NodeSpec::column()
.width(Sizing::GROW)
.pad(12.0)
.gap(8.0)
.bg(Color::hex(0x1e2230ff))
.hover_bg(Color::hex(0x262b3aff))
.radius(8.0)
.on_click("open-card");
// A toolbar row: fixed height, children centred across it.
let toolbar = NodeSpec::row().size(Sizing::GROW, 36.0).cross_align(Align::Center);
// A one-line title, cut with an ellipsis when it does not fit.
let title = TextStyle::new(16.0).ellipsis().color(Color::WHITE);
let code = TextStyle::new(13.0).mono().wrap(TextWrap::Glyph);
assert_eq!(card.layout.padding.l, 12.0);
assert!(card.events().on_click.is_some());
assert_eq!(toolbar.layout.height, Sizing::Fixed(36.0));
assert_eq!(title.max_lines, 0); // `ellipsis` alone means one line
assert!(title.ellipsis && code.wrap == TextWrap::Glyph);Modules§
- corner
- Corner indices into
VisualStyle::radius/Quad::radius.
Structs§
- Access
Spec - Accessibility properties a view states outright, as opposed to the
ones the core derives (see
crate::access). Boxed onNodeSpec: read only while an access tree is being built, and unset on nearly every node. - Anim
Spec - Per-node animation declarations. Boxed on
NodeSpec:enterandexitare 60 bytes each and almost every node has neither. - Event
Spec - Event payloads a node declares. Boxed on
NodeSpecbecause most nodes declare none. - Float
Config - Takes a node out of flex flow: it does not consume space in its parent,
sizes Grow/Percent against its anchor, is positioned by attach points,
and escapes ancestor clips unless
FloatConfig::clipkeeps it in its parent’s. It paints as a layer of its own, above the in-flow tree and every float that opened before it and under every one that opened after, and takes input in the same order. - Font
Features - The OpenType features a style asks the shaper for: up to
FontFeatures::MAXfour-letter tags with a value each.liga0 keeps a coding font from joining->,tnum1 gives tabular figures,ss011 turns on a stylistic set. Plain data andCopy, since aTextStyleis; the spelling every binding shares isFontFeatures::parse’s. - Interact
Spec - Hover / pressed / focus styling and the sounds that go with them.
Boxed on
NodeSpecso the common node — which declares none of it — costs one null check inresolve_hover_styleinstead of reading severalOptions spread across the struct. - Layout
Spec - The layout half of a
NodeSpec: sizing, clamps, direction, padding, gap, alignment, overflow and floating. Set through theNodeSpecbuilders; read by the solver. - Min
- A lower clamp on one axis: a number of logical px, or the node’s own
fit size on that axis (
Min::FIT,minWidth: "fit"in the bindings).FITis what lets aGrowchild keep a content floor, like CSS’sflex: 1 0 auto: tabs split a bar evenly while they fit and sit at their label’s width, scrolling, once they do not. Layout resolves it to a number in the fit pass of its axis, so every later clamp reads one; until then it clamps like no floor at all. - Node
Spec - Everything one node declares. This, not any Rust trait, is the contract
every frontend (Rust builders, Lua, JSX, C) lowers into. Start from
NodeSpec::row,NodeSpec::columnorNodeSpec::tableand chain builders; see the module docs for an example. - PadShorthand
- The
padshorthand family as declared — any subset of the seven names, eachNonewhen the frontend did not see it.PadShorthand::resolvedecides what a missing edge falls back to; a binding only reports what it found. - Scrollbar
- A scrolling node’s bars, per node. Every field’s default is the stock
bar — the theme’s
scrollbar/scrollbar_activecolours, 4 px at rest and 6 px under the pointer, always drawn while the content overflows — so a binding that sets none of the four rows gets exactly what it always had. The bars are overlays and take no layout space whatever their width; the grabbable track is at least as wide as the active thumb plus its inset. - Shadow
- One outer drop shadow: the node’s rounded rect, moved by
dx/dy, grown byspreadand its edge blurred overblur, painted incolorbehind the node. CSS’sbox-shadowwithout the inset and multi-shadow forms. - Text
Style - How a run of text is shaped and painted: size, line height, colour, family, wrapping, line limits, OpenType features and decorations.
- Vec2
Offset - Plain offset pair (kept separate from geometry to stay
Copy+ FFI-flat). - Visual
Style - The paint half of a
NodeSpec: background, border, corner radii, opacity, shadow and pixel snapping.
Enums§
- Align
- Where children sit along an axis, and where a float attaches.
- Bound
- What a
min_width/max_width/min_height/max_heightdeclares: px, the node’s own fit size (a min only), or a size expression that layout resolves against the parent’s content box when it sizes the node. Until then a calc bound clamps like none, as a percentage clamp does in CSS’s intrinsic sizing. - Dir
- Which way a container stacks its children.
- Float
Anchor - What a floating node is positioned against.
- Font
Family - Which face a text shapes with: one of the three stock families, or a font registered with the core.
- Live
- How urgently a reader should read a change it was not asked to read:
ARIA’s
aria-live, AccessKit’sLive. Declared on the node holding the text (liveprop) and, for a one-off with no node behind it, the politeness of anAnnouncement. - Overscroll
- What a scroll gesture that starts over a scroller already at its limit
does: CSS’s
overscroll-behavior, spelled by theoverscrollrow. - Role
- What a node is to assistive technology. Most of these a view declares
(
roleprop;schema::ROLESis that list, and the wire order); the ones the core derives from a node’s content and behaviour instead areschema::DERIVED_ONLY, which says what derives each. Every variant is on one list or the other —schema’severy_role_is_declarable_or_derivedfails when a new one is on neither. - Scroll
Axes - Which axes an
on_scrollnode takes, spelled by thescrollAxesrow. - Scrollbar
Mode - When a scrolling node’s bars are drawn. Spelled by the
scrollbarrow (crate::schema::SCROLLBARS, in this order). - Sizing
- How a node sizes one axis. A plain number converts to
Fixed, so.width(120.0)and.width(Sizing::Fixed(120.0))are the same. - Text
Wrap - How a text node breaks lines at its width.
- Underline
Style - The shape of an underline: the face’s line, a wave under a diagnostic,
dots. Where it goes and how thick it is are the face’s
recommendation either way; a wave is three strokes tall around the
line’s centre with a six-stroke period, dots two strokes across and
four apart (
crate::deco).
Constants§
- FLOAT_
PRESETS - The float preset names, in wire order: the index of a name here is what
the binary protocol writes for it and what
KUI_FLOAT_*counts from. - OVERFLOW_
CLIP overflowas bits: the C struct’s field, the binary wire’s payload and what theclip/scrollX/scrollYbooleans OR together. One set of values so a binding cannot invent its own numbering.- OVERFLOW_
SCROLL_ X - OVERFLOW_
SCROLL_ Y
Functions§
- max_
calc - The size expression a
max_w/max_hwaits on, if it is one. - max_
of_ calc - A ceiling that is a size expression, as
max_w/max_hhold it until layout resolves it: -1 minus its number. - px_
ceiling - A px ceiling as
max_w/max_hhold it: never below zero, so a negative there is only evermax_of_calc’s. A negative orNaNceiling is a ceiling of 0. Every binding’s max clamp reaches the field throughNodeSpec::max_width/NodeSpec::max_height, which call this.
Type Aliases§
- Label
- The label type on
NodeSpec: shared, so cloning a spec is a refcount bump and a Rust view can keep oneArc<str>across frames.