Skip to content

Tab Widgets

Tabs

Horizontal tab bar with clickable tabs.

PropTypeDescription
tabsVec<Tab>Tab items
tab(Tab)methodAdd a single tab
activeusizeActive tab index
dividercharSeparator between tabs
borderboolShow border
border_styleBorderStyleBorder style
paddingimpl Into<Padding>Padding
styleStyleBar idle style
focus_styleStyleBar focus style
hover_styleStyleBar hover style
tab_hover_styleStyleIndividual tab hover style
active_styleStyleActive tab style
disabledboolDisable all tabs
disabled_styleStyleStyle when disabled
focusableboolAccept focus
widthLengthWidth
heightLengthHeight
on_changeCallback<TabsEvent>Active tab changed
on_clickCallback<TabsEvent>Tab clicked
on_keyKeyHandlerKey handler
rust
Tabs::new()
    .tabs(vec![
        Tab::new("Editor"),
        Tab::new("Terminal"),
        Tab::new("Log"),
    ])
    .active(self.active_tab)
    .border(true)
    .active_style(Style::new().fg(Color::Cyan).bold())
    .on_change(ctx.link().callback(|e: TabsEvent| Msg::TabChanged(e.index)))

Tab construction:

rust
Tab::new("Label")
    .style(Style::new().fg(Color::White))
    .disabled(false)

TabsEvent fields: index: usize


DraggableTabBar

Editor-style tab bar with drag reordering, per-tab close buttons, file icons, and cross-bar transfer.

PropTypeDescription
tabsVec<DraggableTab>Tab items
tab(DraggableTab)methodAdd a single tab
activeusizeActive tab index
variantDraggableTabBarVariantBordered or FrameLine
draggableboolEnable drag reordering
drag_previewboolFloating tab label near the pointer while dragging (default: true)
reorder_modeDragReorderModeLive or OnDrop
drag_thresholdu16Pixels before drag starts
show_close_buttonsboolShow close buttons
close_symbol&strClose button symbol
close_on_hover_onlyboolShow close only on hover
tab_max_widthOption<u16>Maximum tab width in cells
scroll_wheelboolMouse wheel to scroll tabs
show_overflow_controlsboolShow < > overflow buttons
overflow_styleStyleOverflow button style
overflow_hover_styleStyleOverflow button hover style
scroll_offsetusizeControlled scroll offset
show_file_iconsboolShow file type icons
file_icon_styleFileIconStyleIcon style (Nerd, NerdColored, Emoji)
file_icon_paletteFileIconPaletteCustom icon colors
file_icon_overrideHashMap<Arc<str>, FileIconOverride>Per-extension overrides
bar_id&strBar identifier for drag groups
drag_group&strGroup name for cross-bar transfer
styleStyleBar idle style
focus_styleStyleBar focus style
hover_styleStyleBar hover style
tab_hover_styleStyleHover style for inactive tabs (active tab keeps active_style)
active_styleStyleActive tab style (takes priority over hover)
close_styleStyleClose button style
close_hover_styleStyleClose button hover style
dividercharTab separator character
accent_symbolcharLeft/right accent character
active_accent_symbolcharActive tab accent
accent_styleStyleAccent style
active_accent_styleStyleActive tab accent style
borderboolShow border
border_styleBorderStyleBorder style
paddingimpl Into<Padding>Padding
disabledboolDisable all tabs
disabled_styleStyleStyle when disabled
focusableboolAccept focus
widthLengthWidth
heightLengthHeight
on_changeCallback<TabsEvent>Active tab changed
on_closeCallback<DraggableTabCloseEvent>Close button clicked
on_reorderCallback<DraggableTabReorderEvent>Tab dragged to new position
on_transferCallback<DraggableTabTransferEvent>Tab transferred to another bar
on_clickCallback<TabsEvent>Tab clicked
on_keyKeyHandlerKey handler

Tab Construction

rust
DraggableTab::new("main.rs")
    .closeable(true)
    .style(Style::new())
    .path("src/main.rs")         // For file icon auto-lookup
    .icon(Span::new("󰙱 ").fg(Color::Red))  // Manual icon override
    .right_badge(Span::new("M").fg(Color::Yellow))  // Git status marker

To show a spinner in the icon position (replaces icon and file-icon when set):

rust
DraggableTab::new("Session 1")
    .leading(
        Spinner::new()
            .spinner_style(SpinnerStyle::Dots)
            .speed(SpinnerSpeed::Normal)
            .style(Style::new().fg(Color::Cyan))
            .into()
    )

Spinner label and layout properties are ignored in tabs because the tab owns its label and sizing.

The same slot also accepts Text elements for static fallbacks:

rust
DraggableTab::new("Session 1")
    .leading(Text::new("").style(Style::new().fg(Color::Cyan)).into())

The spinner glyph occupies the same slot as the icon - its width is determined by SpinnerStyle::width(). Tab spinners animate automatically with the app runtime. Spinner/text content takes priority over icon and file icons.

Events

rust
// TabsEvent { index: usize }
// DraggableTabCloseEvent { index: usize }
// DraggableTabReorderEvent { from: usize, to: usize }
// DraggableTabTransferEvent { from_bar: String, to_bar: String, from: usize, to: usize }

File Icons

rust
DraggableTabBar::new()
    .show_file_icons(true)
    .file_icon_style(FileIconStyle::NerdFontColored)
    .file_icon_palette(FileIconPalette { /* custom colors */ })

FileIconStyle variants: NerdFont, NerdFontColored, Emoji.

File icon is auto-resolved from DraggableTab::path(...). Use file_icon_override for per-extension customization.

Cross-Bar Drag (Drag Groups)

rust
// Left editor bar
DraggableTabBar::new()
    .bar_id("left-editor")
    .drag_group("editors")
    .tabs(self.left_tabs.clone())
    .on_transfer(ctx.link().callback(Msg::TransferFromLeft))

// Right editor bar
DraggableTabBar::new()
    .bar_id("right-editor")
    .drag_group("editors")
    .tabs(self.right_tabs.clone())
    .on_transfer(ctx.link().callback(Msg::TransferFromRight))

Tabs can be dragged between bars that share the same drag_group. The on_transfer callback fires on the source bar and reports from_bar, to_bar, from index, and to index.

Full Example

rust
rsx! {
    DraggableTabBar {
        tabs: vec![
            DraggableTab::new("main.rs").closeable(true).path("src/main.rs"),
            DraggableTab::new("lib.rs").closeable(true).path("src/lib.rs"),
            DraggableTab::new("README.md").path("README.md"),
        ],
        bar_id: "editor",
        drag_group: "editors",
        active: self.active_tab,
        variant: DraggableTabBarVariant::FrameLine,
        tab_max_width: Some(20),
        show_file_icons: true,
        file_icon_style: FileIconStyle::NerdFontColored,
        show_close_buttons: true,
        show_overflow_controls: true,
        active_style: Style::new().fg(Color::Cyan).bold(),
        on_change: ctx.link().callback(|e| Msg::SetActive(e.index)),
        on_close: ctx.link().callback(Msg::CloseTab),
        on_reorder: ctx.link().callback(Msg::ReorderTabs),
    }
}

Image Chip Bar Pattern

Use DraggableTabBar as an image attachment chip bar above TextArea:

rust
DraggableTabBar::new()
    .tabs(images.iter().enumerate().map(|(i, _)| {
        DraggableTab::new(format!("Image {}", i + 1))
            .closeable(true)
    }))
    .active(usize::MAX)       // No active tab (no highlight)
    .close_symbol("x")
    .draggable(false)
    .focusable(false)
    .on_close(ctx.link().callback(Msg::RemoveImage))
    .height(Length::Auto)

MIT OR Apache-2.0