Expand description
Tabbed-container widgets.
Two public entry points:
-
TabBar<T>— a header strip driven by aListModel<T>/ListDataSourceand aTabDelegate<T>. Use it stand-alone when you want only the tab strip (e.g., a document tab strip whose content lives in a different panel or window). -
TabWidget— the all-in-one composition: bar above, contentSwitcherbelow, sharing one selection signal. Two construction flavors:static_tab(info, content)— fixed tabs accumulated at construction.dynamic_tab::<S>(kind, factory)+dynamic_model(model)— apps register a content factory per tabkind("plain-text-doc","image", …); the live tab list is a mutableListModel<TabHandle>mutated at runtime (open / close / reorder).
Static tabs always render first, in declaration order; dynamic
tabs follow. Selection is by stable TabId — drag-reorder and
model mutations never silently send the active selection to a
different tab.
§Activating a tab scrolls it into view
When more tabs are open than the strip can show, activating one always reveals it — including when the activation is programmatic (writing the selection signal, the “show all tabs” overflow dropdown, an assistive-technology click). Pointer and keyboard activation move focus and would be revealed by the framework’s focus follow anyway; the other paths move no focus, so the bar scrolls the header in itself, by the minimum needed to bring it fully inside the viewport.
The reveal is edge-triggered on the selection changing, not an invariant re-asserted every layout pass: once the reader has scrolled away from the active tab by hand, a rebuild for an unrelated reason — a retitled tab, a locale change, a tab opened elsewhere in the strip — leaves the viewport where they left it.
§Accessibility
Both TabWidget and TabBar emit Role::TabList on the bar
and Role::Tab on each header. ARIA APG (tabs
pattern)
recommends providing an accessible name for the tab list
whenever a page hosts more than one — call
.access_label(tr!(editor_tabs()))
on the widget so screen readers can distinguish “editor tabs”
from “tool tabs”:
TabWidget::new(selected)
.static_tab(TabInfo::new().title(tr!(welcome())), welcome_panel)
// ...
.access_label(tr!(editor_tabs()))Panels with no focusable descendants (a static text-only “About”
tab, a chart-only metrics tab) are unreachable by Tab key unless
opted in via TabInfo::focusable_panel(true).
Structs§
- TabBar
- A reactive header strip that pulls its tab list from a data source
and writes the active tab into a shared
Signal<Option<TabId>>. - TabBar
Drag Data - Drag payload published by a tab header when the user starts dragging it.
- TabDelegate
- Resolves per-tab UI from a model item.
- TabHandle
- One tab’s identity, presentation, and state pointer.
- TabId
- Stable identity of a tab. Cheap to copy; persists across model reorders, rebuilds, and reorders triggered by drag-and-drop.
- TabInfo
- Per-tab presentation metadata. Build with
TabInfo::newand fluent setters. - TabWidget
- All-in-one tabbed container. Builds a
TabBarabove aSwitcherof content panes, sharing one selection signal.
Enums§
- TabBar
Orientation - Bar orientation. Selects between a horizontal row of tabs (default for browser-style document tabs) and a vertical column of pills (sidebar / IDE perspective convention).
- TabBar
Visibility - Controls whether a
TabWidget’s tab strip is shown. - TabDisplay
Mode - Bar-level control over what each tab shows — its icon, its label, or both.
- TabOverflow
Button - When the trailing “show all tabs” overflow dropdown button appears.
- TabSizing
- How wide each tab is: shared across all unpinned tabs, chosen per-tab from content, or stretched to fill the bar.
Constants§
- DEFAULT_
BAR_ SLOT_ SPACING - Default spacing between the bar’s leading slot, scroll area, and trailing slot.
- DEFAULT_
MAX_ TAB_ WIDTH - Default max width for an unpinned tab.
- DEFAULT_
MIN_ TAB_ WIDTH - Default min width for an unpinned tab.
- DEFAULT_
PINNED_ TAB_ WIDTH - Default width (in dp) of a pinned tab — icon-only squares.
- DEFAULT_
TAB_ SPACING - Default spacing between tab headers in the row.
0.0so tabs sit flush against each other (Firefox / Chrome convention) — adjacent tab boundaries are visually separated by the per-tab borders, not by an empty gap. - STATIC_
KIND - Sentinel
kindreserved for static tabs accumulated viaTabWidget::static_tab. Application-levelkindstrings must not collide with this value — the framework panics with a clear message at registration ifdynamic_tabis called with this name.
Type Aliases§
- Context
Menu Factory - A reusable widget factory the framework calls every time a context menu opens. Returns a fresh widget instance each call (the framework can’t reuse a single widget across multiple openings).
- Icon
Factory - Reusable factory for an
IconWidget. Boxed inRcsoTabInfoisClonewithout forcingIconWidget: Clone. - Static
Content Factory - Closure that builds a static tab’s content widget. Called once
per static tab — on the
TabWidget’s first build that includes it. The resulting pane is then memoized: rebuilds caused by adjacent dynamic-model mutations reuse the same pane WidgetId, so internal state (focus, scroll, animation progress, …) survives.