Text
Renders a piece of text with typography controlled by a text style or explicit font parameters.
Text displays the string on its text input. Typography comes either from a project-wide textStyle (preferred, keeps the app consistent) or from explicit fontFamily/fontSize/color parameters that override it. Like all visual nodes it sits in the children hierarchy, has size/margin/alignment parameters, and reports basic interaction signals (onClick, hover) and geometry. Text has no box of its own: it takes margins, but padding, background colour, border and corner radius are not ports on it — a padded, filled or rounded label is a Text inside a Group carrying those, which is what the design system's own components do.
When to use it
Any static or data-bound text: headings, labels, list-item fields, error messages. Not for user-editable text (use net.noodl.controls.textinput) and not for button captions (the Button control has its own label). For anything with an inset, a fill or a rounded edge, wrap the Text in a Group and set padding, backgroundColor and borderRadius on the Group.
At a glance
| Category | Visual |
| Type name | Text |
| Available in | browser |
| SSR compatibility | safe |
| Provided by | noodl-viewer-react |
Inputs
Values
| Name | Type | Default | Description |
|---|---|---|---|
acceptFileDrops | Boolean | false | Lets a file dragged from the desktop be dropped onto this element, which reveals the File Drop outputs below |
acceptedFileTypes | String | — | Comma-separated extensions or MIME types this element will take — ".png, .jpg" or "image/*"; leave blank to accept every file. A drop of nothing but rejected files fires Files Rejected instead of Files Dropped |
alignX | Enum (left, center, right) | — | Horizontal alignment of this element within the space its parent gives it |
alignY | Enum (top, center, bottom) | — | Vertical alignment of this element within the space its parent gives it |
as | Enum (div, h1, h2, h3, h4, h5, h6, p, span) | div | HTML element to render the text as, which changes nothing visually but matters for screen readers and SEO |
blockTouch | Boolean | — | Stops every pointer event that lands here from reaching the nodes this one sits inside. Blunt: it takes hover and pointer-down with it, so reach for Click Bubbling first if it is only clicks you want to keep in |
clickBubbling | Enum (auto, always, never) | auto | Whether a click here also fires Click on the nodes this one sits inside. Automatic keeps it here as soon as this node's own Click is connected, so a button inside a clickable card runs the button and not the card; Always is the older behaviour where both run; Never keeps every click here, wired or not. Note that an element at zero opacity takes no pointer events at all |
color | Color | — | Colour of the text itself, not of the element behind it |
cssClassName | String | `` | Extra CSS class names to put on this element, for styling from a stylesheet you supply |
fontFamily | Font | — | Typeface to render the text in, either a web-safe family name or a font file added to the project |
fontSize | Number | — | Height of the text, in pixels |
fontStyle | Enum (normal, italic) | normal | Renders the text upright or italic |
fontVariantNumeric | Enum (normal, tabular-nums) | normal | Tabular draws every digit at the same width so columns of numbers align; Normal follows the font |
fontWeight | Number | Auto | How heavy the text is drawn, from 100 (thin) to 900 (black); leave as Auto to use the weight the font family sets |
height | Dimension | 100 | Height of the element; how the value is read depends on Size Mode |
letterSpacing | Number | Auto | Extra space added between characters; leave as Auto to use the spacing built into the font |
lineHeight | Number | Auto | Vertical space each line of text occupies; leave as Auto to follow the font |
marginBottom | Number | — | Space outside the element's bottom edge, between it and its neighbours |
marginLeft | Number | — | Space outside the element's left edge, between it and its neighbours |
marginRight | Number | — | Space outside the element's right edge, between it and its neighbours |
marginTop | Number | — | Space outside the element's top edge, between it and its neighbours |
maxHeight | Number | — | Largest height the element may grow to, taking priority over Height |
maxWidth | Number | — | Largest width the element may grow to, taking priority over Width |
minHeight | Number | — | Smallest height the element may shrink to, taking priority over Height |
minWidth | Number | — | Smallest width the element may shrink to, taking priority over Width |
mixBlendMode | Enum (normal, multiply, screen, overlay, darken, lighten, color-dodge, color-burn, hard-light, soft-light, difference, exclusion, hue, saturation, color, luminosity) | normal | How this element's colours blend with whatever is painted behind it |
mounted | Boolean | true | Removes the element from the page entirely when false, unlike Visible which leaves its space behind |
opacity | Number | 1 | How opaque this element is, from 0 for invisible to 1 for solid |
pointerEventsEnabled | Boolean | true | When disabled, mouse and touch events pass through to whatever is behind this element |
pointerEventsMode | Enum (inherit, explicit) | inherit | Whether pointer handling is inherited from the parent or set explicitly on this element |
position | Enum (relative, absolute, sticky, fixed) | relative | How the element is placed: In Layout follows its siblings, Absolute ignores them, Sticky pins to the parent edge on overflow, Fixed stays put and takes no space |
sizeMode | Enum (explicit, contentWidth, contentHeight, contentSize) | contentHeight | Whether Width and Height are used as given, or the element sizes itself to fit its contents |
styleCss | String | /* background-color: red; */ | Raw CSS declarations applied to this element, overriding the styling ports above |
text | String | Text | The text to show; an empty value renders nothing rather than the words null or undefined |
textAlignX | Enum (left, center, right) | left | Aligns the text within its own box on the horizontal axis |
textAlignY | Enum (top, center, bottom) | top | Aligns the text within its own box on the vertical axis, which is only visible when the box is taller than the text |
textOverflow | Enum (wrap, clip, ellipsis) | wrap | What a line too long for its box does. Needs a width the text can exceed, so it has no effect while the size mode is content-sized |
textStyle | TextStyle | None | Applies one of the project's saved text styles; the individual font ports below override whatever it sets |
textTransform | Enum (none, uppercase, lowercase, capitalize) | none | Forces the text to upper case, lower case or capitalised without changing the underlying value |
transformOriginX | Number | 50 | Horizontal point the element rotates and scales around, as a fraction of its width |
transformOriginY | Number | 50 | Vertical point the element rotates and scales around, as a fraction of its height |
transformRotation | Number | 0 | Rotates the element clockwise in degrees, without affecting the layout |
transformScale | Number | 1 | Scales the element about its transform origin; 1 leaves it unscaled |
transformX | Number | 0 | Moves the element right after layout, without moving its siblings |
transformY | Number | 0 | Moves the element down after layout, without moving its siblings |
variant | String | — | Name of a saved variant of this node type to apply, replacing the styling set here |
visible | Boolean | true | Hides the element while keeping the space it occupies in the layout |
width | Dimension | 100 | Width of the element; how the value is read depends on Size Mode |
wordBreak | Enum (normal, break-all) | normal | Word break Control where line breaks are allowed - Normal: Break on spaces and other whitespace characters - Break All: Allow line breaks between any two characters, including inside words |
zIndex | Number | — | Paint order among overlapping siblings; higher numbers paint on top |
Outputs
Values
| Name | Type | Default | Description |
|---|---|---|---|
boundingHeight | Number | — | Height this element actually ended up with after layout, in pixels |
boundingWidth | Number | — | Width this element actually ended up with after layout, in pixels |
childIndex | Number | — | This element's position among its parent's children, counting from 0 |
droppedFile | * | — | The first accepted file, in the form an Upload File node takes |
droppedFileName | String | — | Name of the first accepted file, extension included |
droppedFileSizeInBytes | Number | — | Size of the first accepted file, in bytes |
droppedFileType | String | — | MIME type the browser reports for the first accepted file, blank for one it does not recognise |
droppedFiles | Array | — | Every accepted file in the drop, as an array — a drop can carry more than one |
isDragOver | Boolean | — | True while a file is being dragged over this element — wire it to a border or background so the drop zone reacts |
screenPositionX | Number | — | Distance in pixels from the left edge of the window to this element's left edge |
screenPositionY | Number | — | Distance in pixels from the top edge of the window to this element's top edge |
this | Reference | — | A reference to this node itself, for ports that take a node rather than a value |
Signals
| Name | Type | Default | Description |
|---|---|---|---|
didMount | Signal | — | Fires once this element has been added to the page and can be measured |
filesDropped | Signal | — | Fires when one or more accepted files are dropped here, after every File Drop output is up to date |
filesRejected | Signal | — | Fires when a drop landed here but every file in it was excluded by Accepted file types |
hoverEnd | Signal | — | Fires when the pointer leaves this element |
hoverStart | Signal | — | Fires when the pointer moves over this element or any of its children |
onClick | Signal | — | Fires when this element is clicked or tapped |
pointerDown | Signal | — | Fires when a mouse button is pressed or a finger touches this element |
pointerEnter | Signal | — | Fires when the pointer moves onto this element, not counting its children |
pointerUp | Signal | — | Fires when the mouse button is released or the finger lifts over this element |
willUnmount | Signal | — | Fires just before this element is removed from the page, while it still exists |
Dynamic ports
This node's port list changes at runtime (declared-port-groups); the tables above may be incomplete for a given instance.
Declares conditional/expandable port groups whose visibility depends on parameter values (see declaredPortGroups).
| Condition | Inputs shown | Outputs shown |
|---|---|---|
| sizeMode = explicit OR sizeMode = contentHeight OR sizeMode NOT SET | width | — |
| sizeMode = explicit OR sizeMode = contentWidth | height | — |
| pointerEventsMode = explicit | pointerEventsEnabled | — |
| acceptFileDrops = true | acceptedFileTypes | filesDropped, filesRejected, droppedFile, droppedFiles, droppedFileName, droppedFileType, droppedFileSizeInBytes, isDragOver |
Ports at runtime
Text's ports are conditional on parameter values (declared-port-groups): explicit width/height ports appear only in the matching size mode, and advanced text ports depend on chosen options. Treat the catalog's list as the superset the editor filters contextually.
Patterns
- Bind
textfrom Component Inputs inside a Repeater item component to show per-record fields. - Drive
visiblefrom a Condition'sresult/isfalsefor inline error or empty-state messages.
Examples
List page: Repeater fed by Query Records
The canonical data-list shape. Query Records (DbCollection2) fetches a database class and exposes the result on its items array output; the Repeater (For Each) consumes that array and instantiates its template component once per record. Each record's properties are delivered to the item component through Component Inputs whose names match the record's property names — the item component reads them like any other input. The Repeater and its item template component are separate components by design.
Validate an input before acting on a click
The idiomatic gate shape: a Button click does not act directly — it evaluates a Condition. The Condition's boolean comes from an Expression that checks the text input's current value, so the same click either proceeds (ontrue) or reveals an error message (isfalse drives the error Text's visibility as a level, not a pulse). Note the two kinds of flow: text/booleans are values, onClick/eval/ontrue are momentary signals.
Page spine: full-bleed bands, a centred max-width shell, an announced section
The structure every designed page shares, and the one an unstyled page is missing. Three levels: a BAND is full width and owns a background (sections alternate --background and --surface so the page reads as parts, not a scroll); inside it exactly one SHELL, width 100% with maxWidth 1200px and --space-6 side padding, centred by alignItems "center" on the band; content lives in the shell. Content that touches the viewport edge is the loudest signal nobody designed the page. A section opens with an eyebrow, a heading and one optional sub-line capped at ~560px so it wraps at a readable measure, then --space-10 of air. Band padding is --space-20.
Split hero: copy column and image, with a display headline that looks set rather than typed
Two columns inside the shell, each width 100% so an UNWRAPPED row shrinks them to half each — this is why a plain row works where a wrapped grid does not. The copy column carries the page's one display headline (--display-lg — a fluid clamp() that is 44px on a phone and 96px on a wide desktop — with --font-bold, --leading-none and --tracking-tighter; tight tracking is what makes a large heading look set), an eyebrow above it, a lead paragraph capped at ~520px, and two buttons whose concrete parameters are copied from the style vocabulary because variant is a connection-only port. The image gets sizeMode "explicit" plus a width, a height and objectFit "cover" — without explicit sizing those three ports are inert and the photo renders at its natural size.
Stat tile row: one tile component, four instances, collapsing to two then one
The top of an admin screen. The tile is its own component — four hand-written copies is a repeated-sibling-subtree warning — and the row is a Columns node that folds 4 -> 2 -> 1 as the container narrows. Inside a tile the VALUE is the only large thing: a muted uppercase label, one --text-3xl semibold number, and a small delta line. A tile whose label competes with its number reads as a form, not a dashboard. Wire each value from a Query Records count or a Cloud Function output.
Related nodes
Group, Text Input, String Format, Label
This page is generated from node-catalog-enriched.json. Do not edit it by hand — run npm run docs:nodes to regenerate, and fix the source enrichment instead.