Grids & Layout¶
Whether the host is a terminal or a browser, layout in [xnano]{data-preview} is a 2D grid of cells.
A BaseGrid is a resizable, focusable, rectangular region. Fields on the grid mark smaller regions that can:
- Render content (text, components, nested grids)
- Hold typed state (including
state=Truefields that never paint) - Handle input through
@on_*hooks
The z axis
Along with x and y, fields and grids accept a z value. For each cell, the
highest z wins. Use it for overlays and stacked panels.
Creating a Grid¶
BaseGrid is declared like a Pydantic model: subclass it and annotate slots
with Field.
Interactive
This code block runs in the browser via Pyodide.
Try editing the code!
- Change
directionbetween"vertical"and"horizontal". - Change the
titlefield'sdefault=.
from xnano import BaseGrid, Field, render
class App(BaseGrid, direction="vertical"):
title: str = Field(default="My App", border="rounded")
body: str = Field(default="Hello")
name: str = Field(default="Hammad", state=True)
render(App())
from xnano import BaseGrid, Field
class App(BaseGrid, direction="vertical"): # (1)!
title: str = Field(default="My App", border="rounded") # (2)!
body: str = Field(default="Hello")
name: str = Field(default="Hammad", state=True) # (3)!
- Grid settings go on the class header (
direction,gap,border, …) or on agrid_settingsattribute. Field(...)sizes and styles the slot, and holds the value.state=Truekeeps the value off the paint path.
Grid Settings¶
Settings that apply to the whole grid — layout direction, gap, outer frame — are separate from individual fields.
Interactive
This code block runs in the browser via Pyodide.
Try editing the code!
- Change
gap(e.g.0or2). - Change
directionto"vertical".
from xnano import BaseGrid, Field, render
class Dashboard(BaseGrid, direction="horizontal", gap=1, border="rounded", title=" Dashboard "):
left: str = Field(default="Left", width="1fr")
right: str = Field(default="Right", width="1fr")
render(Dashboard())
from xnano import BaseGrid, Field
class Dashboard(BaseGrid, direction="horizontal", gap=1, border="rounded", title=" Dashboard "): # (1)!
left: str = Field(default="Left", width="1fr")
right: str = Field(default="Right", width="1fr")
- Everything after
BaseGridin the class header is a grid setting.
The same settings can be declared on grid_settings:
Both forms merge if used together; a subclass's grid_settings wins over
inherited class-header values.
direction and gap are the common ones. Color, borders, padding, title, and
modifiers use the same vocabulary as Field, applied
to the grid's outer frame. See GridSettings.
Nested Grids¶
A field value can be another BaseGrid. Nested grids are ordinary content.
from xnano import BaseGrid, Field
class Sidebar(BaseGrid, direction="vertical"):
home: str = Field(default="Home", height=1)
search: str = Field(default="Search", height=1)
class App(BaseGrid, direction="horizontal"):
sidebar: Sidebar = Field(default_factory=Sidebar, width="1/3")
content: str = Field(default="…", width="2fr")
overlay=True on a field takes that field out of flow and centers it over the
grid (with z for stacking). See Getting Started for a
full popup example.
Useful grid methods:
| Method | Role |
|---|---|
grid_render / grid_render_* |
Refresh fields each frame (or per size tier) |
grid_set_field(name, ...) |
Mutate a field value or layout metadata at runtime |
grid_effect(...) |
Animate field areas — Effects |
Displaying Content¶
Grids do not know which host will run them. The same instance (or class) can go to a Terminal or a Web host.
Terminal¶
Web¶
HTTP request hooks on grids are a separate surface — see Requests.
API
BaseGrid ·
GridSettings ·
Field ·
Terminal ·
Web