# ltk widget catalogue A flat reference of every widget and layout exported at the crate root. Each entry has the same four sections: **what it is**, **when to use it**, **minimal example**, **see also**. The full builder API and per-method docs live on `cargo doc`; this file is the at-a-glance index. For mental model and architecture, read [`docs/onboarding.md`](./onboarding.md) and [`docs/architecture.md`](./architecture.md) first. For copy-pasteable patterns built from these widgets, see [`docs/cookbook.md`](./cookbook.md). ## Table of contents - [Buttons and activations](#buttons-and-activations) - [`button`](#button) · [`icon_button`](#icon_button) · [`pressable`](#pressable) · [`window_button`](#window_button) · [`list_item`](#list_item) - [Stateful binary controls](#stateful-binary-controls) - [`toggle`](#toggle) · [`checkbox`](#checkbox) · [`radio`](#radio) - [Continuous controls](#continuous-controls) - [`slider`](#slider) · [`vslider`](#vslider) · [`progress_bar`](#progress_bar) - [Text input and display](#text-input-and-display) - [`text`](#text) · [`text_edit`](#text_edit) - [Decoration and chrome](#decoration-and-chrome) - [`container`](#container) · [`separator`](#separator) · [`img_widget`](#img_widget) - [Clipping wrappers](#clipping-wrappers) - [`scroll`](#scroll) · [`viewport`](#viewport) · [`flex`](#flex) · [`carousel`](#carousel) - [Overlays and feedback](#overlays-and-feedback) - [`spinner`](#spinner) · [`toast`](#toast) · [`tooltip`](#tooltip) · [`combo`](#combo) · [`tabs`](#tabs) · [`notebook`](#notebook) · [`dialog`](#dialog) - [Pickers](#pickers) - [`date_picker`](#date_picker) · [`time_picker`](#time_picker) · [`color_picker`](#color_picker) - [Layouts](#layouts) - [`column`](#column) · [`row`](#row) · [`stack`](#stack) · [`grid`](#grid) · [`spacer`](#spacer) --- ## Buttons and activations ### `button` A standard text button. Activates on tap, Enter, or Space when focused. **When**: any place a normal app would have a "Save" / "Cancel" / "Send" control. ```rust,no_run # use ltk::{ button, Element }; # #[ derive( Clone ) ] enum Msg { Save } # fn _ex() -> Element { button( "Save" ).on_press( Msg::Save ) .into() # } ``` **See also**: [`pressable`](#pressable) for activation on a richer custom-shaped surface, [`icon_button`](#icon_button) for image-only buttons. ### `icon_button` A button whose visual is an RGBA bitmap instead of text. Same dispatch shape as [`button`](#button). **When**: toolbar icons, system tray glyphs, anywhere the visual is icon-first. ```rust,no_run # use std::sync::Arc; # use ltk::{ icon_button, Element }; # #[ derive( Clone ) ] enum Msg { OpenSearch } # fn _ex( rgba_bytes: Arc>, w: u32, h: u32 ) -> Element { icon_button( rgba_bytes, w, h ).on_press( Msg::OpenSearch ) .into() # } ``` **See also**: [`button`](#button), [`window_button`](#window_button) (specialised icon button for window decorations). ### `pressable` Wraps any [`Element`](../src/widget/mod.rs) so it dispatches a press message. Invisible to drawing — the wrapped child paints itself. **When**: a card, a custom-styled list row, or any non-trivial visual that should behave like a button. Inner widgets that are themselves interactive (a button nested inside) keep priority. ```rust,no_run # use ltk::{ column, container, pressable, row, Element, Pressable }; # #[ derive( Clone ) ] enum Msg { OpenWifiPicker } # fn _ex( # icon: Element, # title: Element, # subtitle: Element, # ) -> Pressable { pressable( container( row() .push( icon ) .push( column().push( title ).push( subtitle ) ) ) .surface( "surface-card" ) ) .on_press( Msg::OpenWifiPicker ) # } ``` **See also**: [`button`](#button) when a plain text button is enough, [`list_item`](#list_item) for the standard "label + subtitle + trailing" pattern. ### `window_button` A title-bar control button (minimize / maximize / restore / close). Comes with a special hover-tint for `Close`. **When**: building custom server-side window decorations. ```rust,no_run # use ltk::{ window_button, window_controls, Element, WindowButton, WindowButtonKind }; # #[ derive( Clone ) ] enum Msg { CloseWindow, Minimize, Maximize, Close } # fn _ex() -> ( WindowButton, Element ) { let close = window_button( WindowButtonKind::Close ).on_press( Msg::CloseWindow ); // Or the full standard set: let bar = window_controls( Some( Msg::Minimize ), WindowButtonKind::Maximize, Some( Msg::Maximize ), Some( Msg::Close ), ); # ( close, bar.into() ) # } ``` `focusable( true )` opts the button into the Tab cycle (off by default to match desktop convention). **See also**: [`crate::theme_window_controls`] for the colour tokens each mode supplies. ### `list_item` A row with a primary label, optional subtitle, optional right-aligned trailing text, and a tappable surface. **When**: settings menus, navigation lists, contact rows. Doubles its height when a subtitle is set. ```rust,no_run # use ltk::{ list_item, ListItem }; # #[ derive( Clone ) ] enum Msg { OpenWifi } # fn _ex() -> ListItem { list_item( "Wi-Fi" ) .subtitle( "Eduroam" ) .trailing( "›" ) .on_press( Msg::OpenWifi ) # } ``` **See also**: [`pressable`](#pressable) for free-form tappable rows, [`scroll`](#scroll) to wrap a list of items in a scrollable container. --- ## Stateful binary controls ### `toggle` A two-state on / off switch. Renders as a horizontal pill with a sliding thumb. **When**: prominent settings toggles ("Wi-Fi", "Do not disturb"). ```rust,no_run # use ltk::{ toggle, Toggle }; # #[ derive( Clone ) ] enum Msg { ToggleWifi } # struct App { wifi_enabled: bool } # impl App { fn _ex( &self ) -> Toggle { toggle( self.wifi_enabled ) .label( "Wi-Fi" ) .on_toggle( Msg::ToggleWifi ) # }} ``` **See also**: [`checkbox`](#checkbox) for less prominent opt-ins, [`radio`](#radio) for mutually-exclusive groups. ### `checkbox` A two-state opt-in with a square box and a check glyph. **When**: form fields, terms acceptance, multi-select lists. ```rust,no_run # use ltk::{ checkbox, Checkbox }; # #[ derive( Clone ) ] enum Msg { ToggleTerms } # struct App { accept_terms: bool } # impl App { fn _ex( &self ) -> Checkbox { checkbox( self.accept_terms ) .label( "I accept the terms" ) .on_toggle( Msg::ToggleTerms ) # }} ``` **See also**: [`toggle`](#toggle), [`radio`](#radio). ### `radio` A single option inside a mutually-exclusive group. Build one per variant; the application owns "which is selected". **When**: priority pickers, layout choices, anywhere exactly one of N is selected. ```rust,no_run # use ltk::{ column, radio, Element }; # #[ derive( Clone, PartialEq ) ] enum Priority { Low, Medium, High } # #[ derive( Clone ) ] enum Msg { SetPriority( Priority ) } # struct App { priority: Priority } # impl App { fn _ex( &self ) -> Element { column() .push( radio( self.priority == Priority::Low ).label( "Low" ).on_select( Msg::SetPriority( Priority::Low ) ) ) .push( radio( self.priority == Priority::Medium ).label( "Medium" ).on_select( Msg::SetPriority( Priority::Medium ) ) ) .push( radio( self.priority == Priority::High ).label( "High" ).on_select( Msg::SetPriority( Priority::High ) ) ) .into() # }} ``` **See also**: [`checkbox`](#checkbox), [`toggle`](#toggle). --- ## Continuous controls ### `slider` A horizontal slider for selecting a value in `[0.0, 1.0]`. **When**: brightness / volume / scrub bars. Drag the thumb or tap a position; the change message fires continuously during drag. ```rust,no_run # use ltk::{ slider, Slider }; # #[ derive( Clone ) ] enum Msg { SetBrightness( f32 ) } # struct App { brightness: f32 } # impl App { fn _ex( &self ) -> Slider { slider( self.brightness ) .on_change( |v| Msg::SetBrightness( v ) ) # }} ``` `accent_thumb( true )` swaps the default thumb for the two-circle brand-coloured variant. `track_surface( id )` and `fill_surface( id )` override the default theme slots. **See also**: [`vslider`](#vslider) for the vertical axis, [`progress_bar`](#progress_bar) for read-only progress display. ### `vslider` A vertical slider. Same value model as [`slider`](#slider) — `0.0` at the bottom, `1.0` at the top. **When**: column-shaped equalisers, compact volume / brightness picks inside narrow side panels. ```rust,no_run # use ltk::{ vslider, VSlider }; # #[ derive( Clone ) ] enum Msg { SetVolume( f32 ) } # struct App { volume: f32 } # impl App { fn _ex( &self ) -> VSlider { vslider( self.volume ).on_change( |v| Msg::SetVolume( v ) ) # }} ``` **See also**: [`slider`](#slider). ### `progress_bar` A read-only linear progress indicator. **When**: determinate operations with a known fraction (downloads, file copies, install steps). ```rust,no_run # use ltk::{ progress_bar, ProgressBar }; # struct App { download_fraction: f32 } # impl App { fn _ex( &self ) -> ProgressBar { progress_bar( self.download_fraction ) # }} ``` **See also**: [`spinner`](#spinner) for indeterminate operations without a known fraction. --- ## Text input and display ### `text` A single-line label. Truncates with an ellipsis when wider than its allocated rect. **When**: titles, captions, anything non-interactive. ```rust,no_run # use ltk::{ text, Color, Element }; # #[ derive( Clone ) ] enum Msg {} # fn _ex() -> ( Element, Element ) { let title = text( "Title" ).size( 24.0 ).color( Color::WHITE ); let centred = text( "Centred" ).align_center(); # ( title.into(), centred.into() ) # } ``` **See also**: [`text_edit`](#text_edit) for editable text. ### `text_edit` A single-line text input with cursor, Backspace, Enter / Submit, clipboard support, a `secure( true )` password mode that masks the visible characters and zeroizes the buffer on drop, and a `password_toggle( visible, on_toggle )` builder that pins a show / hide-password eye icon to the right edge of the field. **When**: login fields, chat inputs, search boxes. ```rust,no_run # use ltk::{ text_edit, Element }; # #[ derive( Clone ) ] enum Msg { # UsernameChanged( String ), PasswordChanged( String ), # TogglePassword, Submit, # } # struct App { username: String, password: String, show_password: bool } # impl App { fn _ex( &self ) -> ( Element, Element ) { let user = text_edit( "Username", &self.username ) .on_change( |s| Msg::UsernameChanged( s ) ) .on_submit( Msg::Submit ); // Password field with the built-in show / hide eye. The widget // owns the icon hit-testing — taps inside the eye zone fire // `TogglePassword` instead of moving the caret. Flip the bool in // your `update`; the widget reads it back on the next render. let pw = text_edit( "Password", &self.password ) .on_change( |s| Msg::PasswordChanged( s ) ) .password_toggle( self.show_password, Msg::TogglePassword ); # ( user.into(), pw.into() ) # }} ``` `password_toggle` keeps the wipe-on-drop and IME-bypass guarantees of `secure( true )` regardless of the current visibility, so flipping the eye does not weaken the field's threat model at runtime — only what the user sees on screen changes. **See also**: the password recipe in [`docs/cookbook.md`](./cookbook.md#password-field-with-pam-submit). --- ## Decoration and chrome ### `container` A wrapper that adds padding, a background colour or themed surface, a border radius, and (via theme slots) shadows / inset shadows / backdrop blur. **When**: cards, panels, callouts, anywhere a child needs a backdrop or elevation. ```rust,no_run # use ltk::{ column, container, Element }; # #[ derive( Clone ) ] enum Msg {} # fn _ex( title: Element, subtitle: Element ) -> Element { container( column().push( title ).push( subtitle ) ) .surface( "surface-card" ) .padding( 16.0 ) .radius( 24.0 ) .into() # } ``` Per-edge padding is available with `padding_top` / `padding_right` / `padding_bottom` / `padding_left`. Per-corner radius takes a [`Corners`] struct or a tuple. `max_width(px)` caps the container's outer width — when the parent offers a wider rect, the container reports `min( offered, px )` as its preferred width instead of stretching to fill. Mirrors the same flag on [`column`](#column) and [`row`](#row), so a single decorated child no longer needs a `column`-of-one wrap just to access a width cap. **See also**: [`pressable`](#pressable) wrapping a `container` makes a card interactive. ### `separator` A horizontal divider line with theme-default colour and 1 px thickness. **When**: visual breaks between settings groups, list categories, content blocks. ```rust,no_run # use ltk::{ column, separator, text, Element }; # #[ derive( Clone ) ] enum Msg {} # fn _ex() -> Element { column() .push( text( "General" ) ) .push( separator() ) .push( text( "Network" ) ) .into() # } ``` ### `img_widget` A static image rendered from RGBA pixel data shared via `Arc`. **When**: wallpapers, icons, illustrations. The shared `Arc` makes re-using the same buffer across frames a pointer copy. ```rust,no_run # use std::sync::Arc; # use ltk::{ img_widget, Element }; # #[ derive( Clone ) ] enum Msg {} # fn _ex( rgba_bytes: Arc>, width: u32, height: u32 ) -> Element { img_widget( rgba_bytes, width, height ) .opacity( 0.8 ) .into() # } ``` `cover()` scales to fill the rect preserving aspect; `size( w, h )` sets explicit display dimensions. **See also**: [`Image::from_path`](../src/widget/image.rs) helper for disk-loaded files (PNG, JPEG via the `image` crate). --- ## Clipping wrappers ### `scroll` A vertically-scrollable viewport. Drag the content to scroll; clipping is automatic. **When**: lists or grids that may overflow the available height. ```rust,no_run # use ltk::{ column, list_item, scroll, Element }; # #[ derive( Clone ) ] enum Msg {} # fn _ex() -> Element { scroll( column() .push( list_item::( "Item 1" ) ) .push( list_item( "Item 2" ) ) .push( list_item( "Item 3" ) ) ) .into() # } ``` The scroll widget owns its own gesture handling — drags inside it do not trigger the app-level `on_swipe_*` callbacks. **See also**: [`viewport`](#viewport) for passive clipping without gestures, [`grid`](#grid) inside a `scroll` for app drawers. ### `viewport` A passive clipping wrapper. Clips its child to the assigned rect; no scrolling, no gesture handling. **When**: panels that animate in via a parent translation, fade-in content, anywhere you want a hard clip without scrolling. The `fade_bottom( px )` builder feathers the bottom edge to transparent during slide-in animations (GLES backend; software backend renders a hard edge). ```rust,no_run # use ltk::{ viewport, Element }; # #[ derive( Clone ) ] enum Msg {} # fn _ex( panel_view: Element, panel_height: f32 ) -> Element { viewport( panel_view ) .height( panel_height ) .fade_bottom( 16.0 ) .into() # } ``` **See also**: the slide-in panel recipe in [`docs/cookbook.md`](./cookbook.md#slide-in-panel). ### `flex` A row-only filler wrapper. Treats its non-spacer child like a [`spacer`](#spacer) for leftover-width distribution but draws the child inside the allocated rect. **When**: a row where one non-trivial child should fill the remaining width (a card next to a fixed-size icon). ```rust,no_run # use ltk::{ column, flex, row, Element }; # #[ derive( Clone ) ] enum Msg {} # fn _ex( # icon: Element, # title: Element, # subtitle: Element, # ) -> Element { row() .push( icon ) .push( flex( column().push( title ).push( subtitle ) ) ) .into() # } ``` `weight( n )` sets the relative share when there are several flex / spacer siblings. **See also**: [`spacer`](#spacer) for invisible fillers, [`column`](#column) and [`row`](#row). ### `carousel` Horizontal carousel: the focused child sits centred in the viewport at `focused_width_frac` of the viewport width and its neighbours peek out on the left / right at `gap` separation. The widget is a pure layout primitive — the `offset` (positive shifts content right) is owned by the caller, so drag / inertia / snap-ease live in the host (compositor, gesture recogniser, etc.). **When**: mobile-style app switchers, image / story strips, any single-focus horizontal navigation where neighbours hint at the next / previous tile. ```rust,no_run # use ltk::{ button, carousel, container, Element, Color, Corners }; # #[ derive( Clone ) ] enum Msg { Open( usize ) } # fn _ex( offset: f32 ) -> Element { carousel() .focused_width_frac( 0.8 ) .gap( 16.0 ) .offset( offset ) .push( container( button::( "Tile 1" ).on_press( Msg::Open( 0 ) ) ) .background( Color::rgb( 0.95, 0.4, 0.4 ) ) .radius( Corners::all( 12.0 ) ) ) .push( container( button::( "Tile 2" ).on_press( Msg::Open( 1 ) ) ) .background( Color::rgb( 0.95, 0.85, 0.3 ) ) .radius( Corners::all( 12.0 ) ) ) .into() # } ``` Helpers on the widget translate between offsets and indices: `snap_offset( viewport_w, idx )` returns the offset that centres tile `idx`; `focused_index( viewport_w )` rounds the current offset to the nearest tile. The runnable demo at [`examples/carousel.rs`](../examples/carousel.rs) shows Prev / Next buttons and arrow-key navigation against an external `offset` state. **See also**: [`scroll`](#scroll) for free vertical / horizontal panning of arbitrary content; [`tabs`](#tabs) for a non-touch alternative. --- ## Overlays and feedback ### `spinner` Indeterminate progress indicator. Animates while in the tree. **When**: long-running operations with no known fraction (network calls, indexing, "waiting for compositor"). ```rust,no_run # use ltk::{ spinner, Spinner }; # fn _ex() -> Spinner { spinner().size( 24.0 ) # } ``` **See also**: [`progress_bar`](#progress_bar) for determinate progress. ### `toast` Transient notification that floats over the surface and dismisses itself after a timeout. **When**: confirmation snackbars ("Saved"), non-blocking errors, status flashes. ```rust,no_run # use ltk::{ toast, Toast }; # #[ derive( Clone ) ] enum Msg {} # fn _ex() -> Toast { toast( "Saved" ).duration( 3.0 ) # } ``` **See also**: [`tooltip`](#tooltip) for hover-anchored hints. ### `tooltip` Anchored hint that appears next to a target widget on hover or focus. **When**: discoverable affordances on icon-only controls, keyboard shortcut reminders, helper text that should not occupy permanent layout space. ```rust,no_run # use ltk::{ tooltip, Tooltip, WidgetId }; # #[ derive( Clone ) ] enum Msg {} # fn _ex() -> Tooltip { tooltip( "Ctrl+S", WidgetId( "btn/save" ) ).max_width( 240 ) # } ``` The widget paints next to the widget that registered the matching `WidgetId`. See [`docs/cookbook.md`](./cookbook.md) for the full overlay wiring. **See also**: [`toast`](#toast) for transient self-dismissing notifications. ### `combo` Editable single-select with a popup list. Supports type-to-filter and free-text entry. **When**: pick-one fields with too many options for a row of [`radio`](#radio) buttons but where a free typed answer is also valid (autocomplete, country list, theme picker). ```rust,no_run # use ltk::{ combo, Combo, ComboState }; # #[ derive( Clone ) ] enum Msg { Pick( usize ) } # fn _ex( state: ComboState ) -> Combo { let items = vec![ "One".to_string(), "Two".to_string(), "Three".to_string(), ]; combo( state, items ).on_select_idx( Msg::Pick ) # } ``` **See also**: [`radio`](#radio) for small mutually-exclusive sets, [`notebook`](#notebook) for tabbed mode switches. ### `tabs` A bare tab bar — visual selection without owning the page content. Use this when you want full control over what each tab shows. **When**: paged settings screens where the panes are large and you want to keep them as siblings in the tree, not as [`notebook`](#notebook) children. ```rust,no_run # use ltk::{ tabs, TabBar }; # #[ derive( Clone ) ] enum Msg { TabChanged( usize ) } # fn _ex( active: usize ) -> TabBar { tabs::( [ "Profile", "Network", "Privacy" ] ) .selected( active ) .on_select( Msg::TabChanged ) # } ``` **See also**: [`notebook`](#notebook) for tabs that own their pages. ### `notebook` Tabbed container. Owns the pages and shows only the active one. **When**: settings dialogs, multi-step forms, anywhere a flat [`tabs`](#tabs) bar over hand-managed pages would be more code than benefit. ```rust,no_run # use ltk::{ notebook, text, Notebook }; # #[ derive( Clone ) ] enum Msg { TabChanged( usize ) } # fn _ex( active: usize ) -> Notebook { notebook::() .page( "General", text( "general body" ) ) .page( "Advanced", text( "advanced body" ) ) .selected( active ) .on_select( Msg::TabChanged ) # } ``` **See also**: [`tabs`](#tabs) for a bare tab bar without page ownership. ### `dialog` Modal or non-modal centered confirmation card with a built-in scrim, optional title, subtitle, custom body, and a right-aligned action row. Pressing `Esc` fires the configured `cancel` message. **When**: destructive confirmations ("Delete file?"), guided pickers that block other interaction until resolved, "are you sure" gates before a long-running operation. ```rust,no_run # use ltk::{ button, dialog, ButtonVariant, Element }; # #[ derive( Clone ) ] enum Msg { Cancel, Confirm } # fn _ex() -> Element { dialog() .title( "Delete partition?" ) .subtitle( "This will erase every file on /dev/sda2." ) .cancel( Msg::Cancel ) .action( button::( "Cancel" ).variant( ButtonVariant::Tertiary ).on_press( Msg::Cancel ) ) .action( button::( "Delete" ).variant( ButtonVariant::Primary ).on_press( Msg::Confirm ) ) .into() # } ``` `modal( false ) + dismiss_on_scrim( msg )` makes a tap on the dim background fire `msg`; combining `dismiss_on_scrim` with `modal( true )` panics at lower time (the contracts contradict). `body( elem )` swaps a custom element in between the subtitle and the action row — the example app at `examples/dialog.rs` uses this for an in-dialog slider. **See also**: [`toast`](#toast) for non-blocking transient notifications, [`combo`](#combo) for a single-pick popup that does not require modal blocking. --- ## Pickers ### `date_picker` Calendar-grid date selector with month / year navigation. **When**: birthdays, deadlines, any single-date input. ```rust,no_run # use ltk::{ date_picker, Date, DatePicker }; # #[ derive( Clone ) ] enum Msg { Picked( Date ) } # fn _ex() -> DatePicker { date_picker( Date::new( 2026, 5, 7 ) ).on_change( Msg::Picked ) # } ``` ### `time_picker` Hour / minute selector. Wheel-style scrubbing on touch. **When**: alarms, scheduling, time-of-day input. ```rust,no_run # use ltk::{ time_picker, Time, TimePicker }; # #[ derive( Clone ) ] enum Msg { Picked( Time ) } # fn _ex( now: Time ) -> TimePicker { time_picker( now ).on_change( Msg::Picked ) # } ``` ### `color_picker` Hue + saturation/value picker with a hex/RGB readout. **When**: theming UIs, paint tools, accent customisation. ```rust,no_run # use ltk::{ color_picker, Color, ColorPicker }; # #[ derive( Clone ) ] enum Msg { Picked( Color ) } # fn _ex( current: Color ) -> ColorPicker { color_picker( current ).on_change( Msg::Picked ) # } ``` --- ## Layouts ### `column` Vertical flow. Children stack top-to-bottom with optional padding, spacing, alignment. ```rust,no_run # use ltk::{ button, column, spacer, text, Element }; # #[ derive( Clone ) ] enum Msg { Ok } # fn _ex() -> Element { column() .padding( 24.0 ) .spacing( 12.0 ) .push( text( "Title" ) ) .push( spacer() ) .push( button( "OK" ).on_press( Msg::Ok ) ) .into() # } ``` `max_width(px)` caps the inner content width; `fit_content()` reports the natural content width to the parent (otherwise the column claims the full available width). `center_y( true )` centres the content block vertically when there are no spacers. ### `row` Horizontal flow. Mirror of [`column`](#column) on the X axis. ```rust,no_run # use ltk::{ flex, row, Element }; # #[ derive( Clone ) ] enum Msg {} # fn _ex( # label: Element, # field: Element, # submit_button: Element, # ) -> Element { row() .spacing( 8.0 ) .push( label ) .push( flex( field ) ) .push( submit_button ) .into() # } ``` ### `stack` Z-order overlay. Each child gets explicit horizontal and vertical alignment (`HAlign` / `VAlign`) plus an optional margin and pixel translation. Children are drawn in declaration order — the last child sits on top. ```rust,no_run # use std::sync::Arc; # use ltk::{ button, column, img_widget, stack, text, Element, HAlign, VAlign }; # #[ derive( Clone ) ] enum Msg { Add } # fn _ex( background: Arc>, w: u32, h: u32 ) -> Element { stack() .push( img_widget( background, w, h ) ) .push_aligned( column().push( text( "Heading" ) ), HAlign::Center, VAlign::Center, ) .push_aligned_margin( button( "+" ).on_press( Msg::Add ), HAlign::End, VAlign::Bottom, 16.0, ) .into() # } ``` **See also**: [`column`](#column) and [`row`](#row) for flow layout. ### `grid` Fixed-column-count grid that wraps its children into rows. **When**: icon launchers, photo galleries, app drawers. ```rust,no_run # use std::sync::Arc; # use ltk::{ grid, icon_button, Element }; # #[ derive( Clone ) ] enum Msg { OpenApp1, OpenApp2 } # fn _ex( app1_rgba: Arc>, app2_rgba: Arc>, w: u32, h: u32 ) -> Element { grid( 4 ) .padding( 16.0 ) .spacing( 12.0 ) .push( icon_button( app1_rgba, w, h ).on_press( Msg::OpenApp1 ) ) .push( icon_button( app2_rgba, w, h ).on_press( Msg::OpenApp2 ) ) // ... .into() # } ``` Wrap inside [`scroll`](#scroll) when the grid may overflow. `centre_last_row( true )` shifts a partial last row so its tiles sit centred under the full rows above instead of left-aligned — useful for app switchers and gallery layouts where a 7-of-9 leftover band reads better balanced. ### `spacer` An invisible flexible filler. Inside a column / row, absorbs leftover space along the parent's main axis. ```rust,no_run # use ltk::{ column, spacer, Element }; # #[ derive( Clone ) ] enum Msg {} # fn _ex( header: Element, footer: Element ) -> Element { column() .push( header ) .push( spacer() ) // pushes footer to the bottom .push( footer ) .into() # } ``` `weight( n )` sets the relative share; `height( px )` / `width( px )` pin the spacer to a fixed size on its respective axis. **See also**: [`flex`](#flex) for a non-empty filler.