LavaUI docs

protocol View

Swift

protocol View

A declarative UI description.

Sources/LavaUI/View.swift:29

Properties

@ViewBuilder var body: Body { get }

Not documented.

Sources/LavaUI/View.swift:32

var body: Never { get }

Not documented.

Sources/LavaUI/View.swift:82

Methods

func agentId(_ id: String) -> AgentIdentifiedView<Self>

Stable automation id for agents (layout_treesid, click --sid, …).

Prefer short kebab-case names (theme-toggle, sidebar-nav). When set, this wins over the structural path fallback.

Sources/LavaUI/AgentId.swift:80

func backdropBlur(radius: Float = 8) -> ModifiedView<Self>

Frosted-glass backdrop under this view's layout rect.

Captures UI already painted behind the rect, blurs it, composites the result, then draws this view's fill and children sharp on top. Typical use: .background(Color(...).opacity(0.15)).backdropBlur(radius: 6) on a panel or overlay so chrome reads as glass.

Sources/LavaUI/Modifiers.swift:585

func background(_ color: Color) -> ModifiedView<Self>

Not documented.

Sources/LavaUI/Modifiers.swift:447

func background(_ gradient: Gradient) -> ModifiedView<Self>

Fills the box with a two-stop linear ramp instead of a flat colour.

The start colour is also recorded as the flat fill, so anything that reads a background as one colour — and a renderer too old to know about gradients — still has an answer.

Sources/LavaUI/Modifiers.swift:456

func blur(radius: Float = 8) -> ModifiedView<Self>

Softens this view and its children.

The subtree is drawn into an offscreen target of its own, blurred, and composited back with its own alpha — so a blurred view has a genuinely soft edge and whatever sits behind it shows through unchanged. This is the SwiftUI meaning of .blur(); for frosted glass, where what is behind the view is what should soften, use backdropBlur(radius:).

Sources/LavaUI/Modifiers.swift:575

func border(_ color: Color, width: Float = 1) -> ModifiedView<Self>

Strokes this view's edge, width pixels thick, drawn over its content.

Text("Hi").padding(8).border(.purple, width: 4)

The stroke lies inside the layout rect, as in SwiftUI and CSS: the view still occupies exactly the space it was laid out in, and a border never nudges a sibling. It also follows .cornerRadius() — the two compose, and the border's inner edge is the true inward offset of the rounded shape, so the corners stay concentric.

Order matters the way it does in SwiftUI: .border() before .padding() frames the content, after it frames the padded box.

Sources/LavaUI/Modifiers.swift:492

func clipped() -> ModifiedView<Self>

Scissor this view's paint (and its children's) to its layout rect.

Yoga still sizes children freely; only drawing is clipped. That is what makes .frame(width:).clipped() on a Text work: the glyphs keep their intrinsic width, and the extra ink is cut off rather than drawn over the next view. Use on fixed chrome such as a menubar so hover fills cannot spill into content.

Sources/LavaUI/Modifiers.swift:596

func cornerRadius(_ radius: Float) -> ModifiedView<Self>

Not documented.

Sources/LavaUI/Modifiers.swift:474

func cursor(_ shape: CursorShape?) -> ModifiedView<Self>

The pointer image while the pointer is inside this view.

grabBar.cursor(.resizeUpDown)

The innermost view under the pointer that states one wins; ancestors answer for the gaps, so a whole panel can ask for .text and a button inside it ask for .pointer without either knowing about the other.

Stating a cursor makes the view hit-testable — the renderer has to report the pointer entering it before anything can act on this, which is the same node a hover fill needs. That is a scene node per such view, so it is not free; it is the same cost .hoverBackground already pays.

Sources/LavaUI/Cursor.swift:42

func defaultStructureLines(indent: Int) -> [String]

Not documented.

Sources/LavaUI/View.swift:48

func dumpStructure(indent: Int = 0)

Not documented.

Sources/LavaUI/View.swift:38

func flexGrow(_ value: Float = 1) -> ModifiedView<Self>

Not documented.

Sources/LavaUI/Modifiers.swift:560

func flexShrink(_ value: Float) -> ModifiedView<Self>

Not documented.

Sources/LavaUI/Modifiers.swift:564

func font(_ value: UIFont) -> EnvironmentModifiedView<Self>

Overrides the font for this subtree only.

Sources/LavaUI/Environment.swift:100

func frame(width: Dimension? = nil, height: Dimension? = nil, minWidth: Float? = nil, minHeight: Float? = nil, alignment: Alignment? = nil) -> ModifiedView<Self>

Fix this view's size, and optionally say where its content sits inside it.

Without alignment the size lands on the view's own node: a Text given .frame(width: 34) becomes a 34pt-wide text, and its glyphs start at the left edge because that is where a text's glyphs start. That is the historical behaviour of this modifier and every existing caller depends on it — a VStack given a width is expected to be that width and lay its children out across it, not to sit at its natural width inside a wider box.

With alignment it is SwiftUI's frame instead: a box of the stated size with the content placed inside at its natural size. That needs a node the content does not own, so stating an alignment always adds one. This is the version to reach for when a label has to sit in the middle of a fixed cell — a calendar day, a keypad key, a grid of counts:

Text("24").frame(width: .pt(34), height: .pt(28), alignment: .center)

The added node is where the click is not. Everything stated after this modifier — background, hoverBackground, cursor — lands on the wrapper, because that is now the outermost node. But whatever made the content interactive stays on the content: a Text(_:onClick:) keeps its click on the text, at the text's own size. The result is a control that fills 44pt, highlights across 44pt and shows a pointer over 44pt, while only the 27pt of glyphs in the middle actually respond — and nothing about the call site says so.

So do not reach for this to centre a clickable label. Text has an align: of its own, taking this same Alignment, that moves the pen inside the node that already exists and adds none:

Text("Fit", align: .center, onClick: …).frame(width: .pt(44))

Prefer it for any text, clickable or not — a grid of cells is a wrapper per cell, and TextAlignmentEquivalenceTests pins the two spellings to the same glyph positions. This modifier remains the right one for centring content that is not a text at all.

The default is nil and not .center on purpose. SwiftUI centres by default because its frame has only ever meant the second thing; here the two meanings share a modifier, so the default has to be the one that leaves existing layouts alone. nil is "never asked", which is not the same answer as .center.

Sources/LavaUI/Modifiers.swift:544

func hidden(_ isHidden: Bool = true) -> ModifiedView<Self>

Takes this view out of layout and drawing, without unmounting it.

The difference from if condition { view } is identity. An if that goes false destroys the subtree, and everything keyed to it goes with it — most visibly the scroll position, which the renderer holds against a node id that no longer exists when the view comes back. A hidden view keeps its nodes, so it comes back where it was.

That is what this is for: alternating panes that should each remember their own place. It is not a cheaper if — the subtree stays mounted, its state stays alive, and its body still recomputes when what it reads changes. Yoga skips it (display: none, so it occupies nothing rather than occupying nothing visibly) and the draw walk steps over it.

Long enough away and the renderer forgets anyway: it drops a node's state after SceneNodeIdentity.retentionPasses emit passes without seeing it, which is what stops a hidden pane pinning that state forever.

Sources/LavaUI/Modifiers.swift:617

func hoverBackground(_ color: Color) -> ModifiedView<Self>

Not documented.

Sources/LavaUI/Modifiers.swift:460

func hoverSnap(_ snap: Bool = true) -> ModifiedView<Self>

When true, the hover chip vanishes the frame the pointer leaves.

Default hover eases out, which is right for a button and wrong for a dense list: twenty full-width rows still fading is a trail. File lists and menu items opt out. It is not .transition(), which animates a view arriving or leaving, not the pointer moving across one.

Sources/LavaUI/Modifiers.swift:470

func onAnyPress(perform: @escaping (_ button: Int32) -> Void) -> BoxRegistrationView<Self>

Runs perform with the button for every press inside this view, before the press reaches what it landed on, and without taking it.

For a container that needs to know it was used — a pane becoming the active one — while every row and button in it keeps its own clicks. Before, so that the handler of what was pressed already sees the consequence.

Sources/LavaUI/DragGesture.swift:229

func onDragGesture(minimumDistance: Float = 6, perform: @escaping (DragGestureValue) -> Void) -> BoxRegistrationView<Self>

Runs perform as a left press on this view travels: .began once it has moved minimumDistance pixels, .changed on every move after — wherever the pointer goes, including out of the view — and .ended on release.

The press still goes to whatever is under it first, so a tab that selects on press and moves on drag is two modifiers, not a gesture that has to remember to select. It is resolved outwards through the hit chain, so a label inside the view does not hide it. A press something else captures — a slider inside it — never becomes this gesture.

Sources/LavaUI/DragGesture.swift:206

func onDrop(targeted: ((Bool) -> Void)? = nil, springLoaded: (() -> Void)? = nil, perform: @escaping ([URL]) -> Void) -> DropTargetView<Self>

Runs perform with the dropped file paths (as URLs) when the user releases an OS drag over this view.

While a drag is still over it: targeted hears true as the drag becomes aimed at this view and false as it leaves, is dropped, or ends elsewhere — the place to light a target up. springLoaded runs once the drag has rested here for DropRouter.springDelay, the way a tab or a folder opens under a file being carried to it. Both need a compositor to say where a drag is; a windowed app gets the drop alone.

Nested targets resolve innermost first, like the drop itself: a folder row inside a list is its own target, a file row is not and the list behind it answers.

Sources/LavaUI/DropTarget.swift:118

func onFileDrag<Chip>(offsetX: Float = 16, offsetY: Float = 12, paths: @escaping () -> [String], @ViewBuilder chip: @escaping () -> Chip) -> FileDragSourceView<Self, Chip> where Chip : View

Lets files be dragged out of this view — onto another window, into another app, anywhere a text/uri-list drop is understood.

paths is asked when the drag starts, not when the view is built, so it can answer with whatever is selected by then. chip is what follows the pointer: ordinary views, laid out at their natural size and drawn once by the compositor, which then only moves the result (see DragChipImage). It hangs offsetX,offsetY from the pointer — below and to the right by default, clear of what is being aimed at.

The left button only, after FileDrag.threshold of travel, and only where a compositor can carry a drag (DragBridge). The press is delivered as a press either way, so a row selects itself first.

Sources/LavaUI/DragSource.swift:168

func onFileDrag(paths: @escaping () -> [String]) -> FileDragSourceView<Self, EmptyView>

The same, with nothing but the cursor to show for it.

Sources/LavaUI/DragSource.swift:181

func onFrame(perform: @escaping (CanvasFrame) -> Void) -> BoxRegistrationView<Self>

Runs perform with this view's rectangle, in window coordinates, after each layout pass that places it.

For aiming at views from somewhere that is not their own handler: a tab dragged across a window needs to know which pane is under the pointer, and the panes are not what is receiving the moves.

Called from inside layout. Store the frame; do not change what the tree shows from here — that is a second layout the frame loop never asked for. Not called while the view is hidden.

Sources/LavaUI/DragGesture.swift:249

func overlay<OverlayContent>(alignment: OverlayAnchor, inset: Float = 0, style: OverlayStyle? = nil, @ViewBuilder content: () -> OverlayContent) -> ComposedOverlayView<Self, OverlayContent> where OverlayContent : View

Draws content over this view, taking no layout space.

The composition overlay, as distinct from overlay(isPresented:), which is a modal popup. Interaction underneath is unaffected: this imposes no input priority and no outside-click dismissal, so it suits a floating button, a badge, or an in-canvas control that is simply always there.

inset insets from the anchored edges; a centred axis ignores it.

style draws a panel under the content — fill, outline, corner radius, padding and frosted backdrop, the same OverlayStyle the presented overlay takes. Omitted, the content floats bare, which is what a badge or an already-styled button wants; the ordinary modifiers still work on whatever is inside the closure, so this is convenience rather than the only way to paint one.

Sources/LavaUI/ComposedOverlay.swift:269

func overlay<OverlayContent>(isPresented: Binding<Bool>, alignment: OverlayAlignment = .below, style: OverlayStyle = OverlayStyle(), @ViewBuilder content: () -> OverlayContent) -> OverlayView<Self, OverlayContent> where OverlayContent : View

Presents content above everything, anchored to this view.

Sources/LavaUI/Overlay.swift:383

func overlay<OverlayContent>(isPresented: Binding<Bool>, placement: OverlayPlacement, style: OverlayStyle = OverlayStyle(), @ViewBuilder content: () -> OverlayContent) -> OverlayView<Self, OverlayContent> where OverlayContent : View

Presents content above everything using a caller-defined frame.

Sources/LavaUI/Overlay.swift:400

func overlayLayer<Layer>(@ViewBuilder _ layer: () -> Layer) -> LayeredView<Self, Layer> where Layer : View

Draws layer over this view, covering its box and taking no layout space or input — presses go through it to what is underneath. See LayeredView.

Sources/LavaUI/Underlay.swift:163

func padding(_ amount: Float) -> ModifiedView<Self>

Uniform inset on every edge.

Sources/LavaUI/Modifiers.swift:428

func padding(_ edges: Edge, _ amount: Float) -> ModifiedView<Self>

Inset only the listed edges by amount.

content.padding(.horizontal, 12)
content.padding([.top, .leading], 4)

Sources/LavaUI/Modifiers.swift:438

func padding(_ insets: EdgeInsets) -> ModifiedView<Self>

Fully specified per-edge inset.

Sources/LavaUI/Modifiers.swift:443

func scrollIntoView(when active: Bool) -> BoxRegistrationView<Self>

Scrolls the nearest enclosing ScrollView so this view is in sight, each time active becomes true — the selected tab in a strip that overflows, say. Only as far as it takes: a view already in sight does not move anything.

Asks once per change rather than holding the view in place, so the container can still be scrolled away from it afterwards.

Sources/LavaUI/ScrollReveal.swift:84

func structureLines(indent: Int) -> [String]

Not documented.

Sources/LavaUI/View.swift:34

func structureLines(indent: Int = 0) -> [String]

Not documented.

Sources/LavaUI/View.swift:44

func structureLines(indent: Int = 0) -> [String]

Not documented.

Sources/LavaUI/View.swift:88

func theme(_ value: Theme) -> EnvironmentModifiedView<Self>

Overrides the theme for this subtree only; Theme.current (and every other subtree) is unaffected.

Sources/LavaUI/Environment.swift:95

func transition(_ transition: Transition = .opacity) -> TransitionView<Self>

Animates this view appearing and disappearing.

Only meaningful where a reconciler can actually insert or remove it: an if, an optional, or a ForEach row. On a view that is always present it animates in once, on first mount.

Sources/LavaUI/Transition.swift:163

func underlay<Layer>(@ViewBuilder _ layer: () -> Layer) -> LayeredView<Self, Layer> where Layer : View

Draws layer behind this view, covering its box and taking no layout space or input. See LayeredView.

Sources/LavaUI/Underlay.swift:154

func windowChrome() -> some View
  

Hidden while the window is maximized — the client-side half of dropping a compositor title bar. Wrap the VStack / strip that holds WindowControls(), not the whole window.

Sources/LavaUI/WindowControls.swift:470

func windowDrag(doubleClickMaximizes: Bool = true) -> WindowDragArea<Self>

Lets the window be dragged by this view's own empty space, and maximized by double-clicking it — what a title bar did, minus the bar.

A no-op in a windowed app, where the window manager's frame is still the thing that moves the window.

Sources/LavaUI/WindowControls.swift:463

Type aliases

associatedtype Body : View

Not documented.

Sources/LavaUI/View.swift:30