Layout Extras¶
This section introduces components for special arrangements that cannot be expressed by basic layouts like Column or Row.
Stack¶
Arranges elements in stacking order (Z-order). Use this when you want to place text over a background image or display a notification badge over an icon.
- The first written element goes to the back (bottom).
- The last written element goes to the front (top).
import nuiitivet as nv
import nuiitivet.material as md
import nuiitivet.modifiers as mod
nv.Stack(
width=240,
height=200,
alignment="center", # Default alignment position
children=[
md.Card(
md.Text(""),
width="100%",
height="100%",
).modifier(mod.background("#BBDEFB")),
md.Card(
md.Text(""),
width="80%",
height="80%",
).modifier(mod.background("#90CAF9")),
md.Card(
md.Text("Overlay Text"),
width="60%",
height="60%",
alignment="center",
).modifier(mod.background("#64B5F6")),
],
)

Deck (Conditional Display)¶
A component that displays only one child at a time from multiple children. Used for tab switching or content switching in side menus.
import nuiitivet as nv
import nuiitivet.material as md
import nuiitivet.modifiers as mod
def set_index(i: int) -> None:
# state is assumed to be defined elsewhere or part of a class
state.current_index.value = i
menu = nv.Column(
padding=8,
gap=8,
children=[
md.Button("Tab 1", on_click=lambda: set_index(0), style=md.ButtonStyle.filled()),
md.Button("Tab 2", on_click=lambda: set_index(1), style=md.ButtonStyle.filled()),
md.Button("Tab 3", on_click=lambda: set_index(2), style=md.ButtonStyle.filled()),
],
)
body = nv.Deck(
index=state.current_index,
width="100%",
height="100%",
children=[
nv.Container(
alignment="center",
width="100%",
height="100%",
child=md.Text("Tab 1 Content"),
).modifier(mod.background("#BBDEFB")),
nv.Container(
alignment="center",
width="100%",
height="100%",
child=md.Text("Tab 2 Content"),
).modifier(mod.background("#C8E6C9")),
nv.Container(
alignment="center",
width="100%",
height="100%",
child=md.Text("Tab 3 Content"),
).modifier(mod.background("#FFE0B2")),
],
)
contents = nv.Row(
gap=12,
width="100%",
children=[menu, body],
)

Flow (Wrap Layout)¶
Arranges elements from left to right and automatically wraps to the next line when exceeding the parent width. Suitable for tag lists or card lists.
import nuiitivet as nv
import nuiitivet.material as md
tags = ["Python", "UI", "Framework", "Layout", "Grid", "Flex"]
nv.Flow(
main_gap=8,
cross_gap=8,
padding=8,
children=[
md.Card(md.Text(tag), style=md.CardStyle.outlined()) for tag in tags
],
)

To generate the children from a data collection (including reactive updates), see layout_dynamic.md.
UniformFlow (Uniform Grid)¶
Arranges elements into a grid with uniform column widths. Use this for tile layouts where each cell should align and size consistently.
import nuiitivet as nv
import nuiitivet.material as md
tiles = ["A", "B", "C", "D", "E", "F", "G", "H", "I"]
nv.UniformFlow(
columns=3,
main_gap=8,
cross_gap=8,
padding=8,
aspect_ratio=1.0,
children=[
md.Card(md.Text(t), alignment="center", padding=12)
for t in tiles
],
)

Flow vs UniformFlow¶
- Use Flow for wrapping rows with variable-width items (tags, chips, variable text).
- Use UniformFlow for grid-like layouts with uniform columns (tiles, cards, image grids).
To generate the children from a data collection (including reactive updates), see layout_dynamic.md.
Container (Decoration/Size Control)¶
A wrapper with a single child element.
Used to add padding to child elements, fix sizes, or specify alignment.
(Similar to div in HTML)
import nuiitivet as nv
import nuiitivet.material as md
nv.Container(
md.Button("Centered Content", style=md.ButtonStyle.filled()),
width=250,
height=200,
alignment="center",
padding=16,
)

Spacer (Space Adjustment)¶
An invisible widget useful when you want to create flexible spacing.
Useful for pushing elements to both ends within Row or Column.
import nuiitivet as nv
import nuiitivet.material as md
nv.Row(
padding=16,
gap=16,
width=500,
children=[
md.Button("Left 1", style=md.ButtonStyle.outlined()),
md.Button("Left 2", style=md.ButtonStyle.outlined()),
nv.Spacer(width="100%"),
md.Button("Right", style=md.ButtonStyle.filled()),
],
)

Collapsible (Animated Expand/Collapse)¶
Smoothly expands or collapses a child widget, shifting the surrounding layout as it animates. Use this for expandable panels, side sheets, and accordion-style sections.
- When
openedisFalse, the child shrinks to zero size along the animated axis. - When
openedisTrue, it expands back to the child's natural size.
import nuiitivet as nv
import nuiitivet.material as md
nv.Collapsible(
md.Card(
nv.Column(
padding=16,
gap=8,
children=[
md.Text("Format: PDF / EPUB / HTML"),
md.Text("Size: 4.2 MB"),
md.Text("License: MIT"),
],
),
),
opened=self.opened,
)

visible() vs Collapsible¶
visible() modifier |
Collapsible |
|
|---|---|---|
| Layout space | Always occupied | Shrinks to zero when closed |
| Animation | Opacity / scale fade | Smooth expand/collapse with layout reflow |
| Use case | Fade in/out without shifting siblings | Accordion panels, side sheets |