Skip to content
PorabuildHeroGPUI component library
v0.14.0 · Apache-2.0

Layout

Separator

Separate content with a horizontal or vertical line.

Rust
use herogpui::components::separator::Separator;

Separator on docs.rsSource at v0.14.0

Usage

Showing Usage, live: HeroGPUI compiled to WebAssembly. The canvas has no accessibility tree; each example's description and code below carry the same information.

Usage

An element expression with window: &mut Window and cx: &mut App in scope.

Rust
use herogpui::prelude::Separator;
use herogpui::gpui::prelude::*;
use herogpui::gpui::px;
use herogpui::gpui;

gpui::div()
    .w_full()
    .flex()
    .flex_col()
    .gap(px(12.))
    .child(gpui::div().child("Above"))
    .child(Separator::new())
    .child(gpui::div().child("Below"))

With Surface

An element expression with window: &mut Window and cx: &mut App in scope.

Rust
use herogpui::prelude::{Separator, Surface};
use herogpui::gpui::prelude::*;
use herogpui::gpui::px;
use herogpui::gpui;

Surface::new()
    .padding(px(20.))
    .gap(px(12.))
    .child(gpui::div().child("Notifications"))
    .child(Separator::new())
    .child(gpui::div().child("Privacy"))

With Content

An element expression with window: &mut Window and cx: &mut App in scope.

Rust
use herogpui::prelude::{ActiveTheme, Separator};
use herogpui::gpui::prelude::*;
use herogpui::gpui::px;
use herogpui::gpui;

gpui::div()
    .max_w(px(448.))
    .children(
        [
            ("Set Up Notifications", "Receive account activity updates"),
            (
                "Set up Browser Extension",
                "Connect your browser to your account",
            ),
            ("Mint Collectible", "Create your first collectible"),
        ]
        .into_iter()
        .enumerate()
        .map(|(index, (title, subtitle))| {
            gpui::div()
                .child(
                    gpui::div()
                        .flex()
                        .flex_col()
                        .child(
                            gpui::div()
                                .text_size(px(14.))
                                .font_weight(gpui::FontWeight::MEDIUM)
                                .child(title),
                        )
                        .child(
                            gpui::div()
                                .text_size(px(14.))
                                .text_color(cx.colors().muted)
                                .child(subtitle),
                        ),
                )
                .when(index < 2, |el| el.child(Separator::new().my(px(16.))))
        }),
    )

Variants

An element expression with window: &mut Window and cx: &mut App in scope.

Rust
use herogpui::prelude::{ActiveTheme, Separator, SeparatorVariant};
use herogpui::gpui::prelude::*;
use herogpui::gpui::px;
use herogpui::gpui;

gpui::div()
    .flex()
    .flex_col()
    .items_start()
    .justify_center()
    .gap(px(12.))
    .children(SeparatorVariant::ALL
        .iter()
        .flat_map(|v| {
            vec![
                gpui::div()
                    .text_size(px(12.))
                    .text_color(cx.colors().muted)
                    .child(v.label())
                    .into_any_element(),
                Separator::new().variant(*v).into_any_element(),
            ]
        }))

Vertical

An element expression with window: &mut Window and cx: &mut App in scope.

Rust
use herogpui::prelude::{Orientation, Separator};
use herogpui::gpui::prelude::*;
use herogpui::gpui::px;
use herogpui::gpui;

gpui::div()
    .flex()
    .items_center()
    .gap(px(12.))
    .h(px(24.))
    .child("Docs")
    .child(Separator::new().orientation(Orientation::Vertical))
    .child("Blog")
    .child(Separator::new().orientation(Orientation::Vertical))
    .child("Support")

Resizable Panels

HeroGPUI extension, not a example: `ResizablePanelGroup` shares its space between `ResizablePanel`s by percentage, with a drag handle between each pair. Drag a handle, or Tab to it and use the arrow keys (Shift for a larger step, Home and End to the limits); each panel stays within its minimum and maximum. The right-hand panel holds a vertical group. Runs in a view's render: self is the view holding this example's state and cx is its Context<Self>.

Rust
use herogpui::prelude::{ActiveTheme, Orientation, ResizablePanel, ResizablePanelGroup, Separator};
use herogpui::gpui::prelude::*;
use herogpui::gpui::{AnyElement, App, SharedString, px};
use herogpui::gpui;

gpui::div()
    .flex()
    .flex_col()
    .items_start()
    .justify_center()
    .gap(px(12.))
    .children(vec![
        gpui::div()
            .w(px(560.))
            .h(px(240.))
            .rounded(px(12.))
            .border_1()
            .border_color(cx.colors().border)
            .overflow_hidden()
            .child(
                ResizablePanelGroup::new("separator-resizable-group")
                    .panel(
                        ResizablePanel::new()
                            .default_size(30.)
                            .min_size(20.)
                            .max_size(50.)
                            .child(resizable_pane("Sidebar", cx)),
                    )
                    .panel(
                        ResizablePanel::new().min_size(30.).child(
                            ResizablePanelGroup::new("separator-resizable-nested")
                                .orientation(Orientation::Vertical)
                                .panel(
                                    ResizablePanel::new()
                                        .default_size(65.)
                                        .min_size(25.)
                                        .child(resizable_pane("Editor", cx)),
                                )
                                .panel(
                                    ResizablePanel::new()
                                        .min_size(15.)
                                        .child(resizable_pane("Terminal", cx)),
                                ),
                        ),
                    )
                    .on_resize({
                        let view = cx.entity().downgrade();
                        move |sizes, _, cx| {
                            let text: Vec<String> = sizes.iter().map(|v| format!("{v:.0}")).collect();
                            view.update(cx, |this, cx| {
                                this.resizable_sizes = SharedString::from(text.join(", "));
                                cx.notify();
                            })
                            .ok();
                        }
                    }),
            )
            .into_any_element(),
        para(&format!("Sidebar and main, in percent: {}", self.resizable_sizes), cx),
    ])

Also calls resizable_pane, para (included when you copy).

Collapsible Panels

HeroGPUI extension: the sidebar is at least 120px wide whatever the group's width (`min_size_px`) and is `collapsible`. Drag its handle past halfway to its minimum to collapse it and back to expand it, or focus the handle and press Enter to collapse and restore it. `on_resize_end` reports once per gesture, when a drag is released or a key lands, which is where a layout would be saved. Runs in a view's render: self is the view holding this example's state and cx is its Context<Self>.

Rust
use herogpui::prelude::{ActiveTheme, ResizablePanel, ResizablePanelGroup, Separator};
use herogpui::gpui::prelude::*;
use herogpui::gpui::{AnyElement, App, SharedString, px};
use herogpui::gpui;

gpui::div()
    .flex()
    .flex_col()
    .items_start()
    .justify_center()
    .gap(px(12.))
    .children(vec![
        gpui::div()
            .w(px(560.))
            .h(px(200.))
            .rounded(px(12.))
            .border_1()
            .border_color(cx.colors().border)
            .overflow_hidden()
            .child(
                ResizablePanelGroup::new("separator-collapsible-group")
                    .panel(
                        ResizablePanel::new()
                            .default_size(25.)
                            .min_size_px(px(120.))
                            .max_size(50.)
                            .collapsible(true)
                            .child(resizable_pane("Sidebar", cx)),
                    )
                    .panel(ResizablePanel::new().child(resizable_pane("Main", cx)))
                    .on_resize_end({
                        let view = cx.entity().downgrade();
                        move |sizes, _, cx| {
                            let text: Vec<String> = sizes.iter().map(|v| format!("{v:.0}")).collect();
                            view.update(cx, |this, cx| {
                                this.resizable_settled = SharedString::from(text.join(", "));
                                cx.notify();
                            })
                            .ok();
                        }
                    }),
            )
            .into_any_element(),
        para(&format!("Last settled layout, in percent: {}", self.resizable_settled), cx),
    ])

Also calls resizable_pane, para (included when you copy).

Helpers used by these examples

Plain functions over the public API, defined once here and copied with each example that calls them.

resizable_pane
/// One labelled pane of the Resizable Panels demo.
fn resizable_pane(label: &'static str, cx: &gpui::App) -> AnyElement {
    gpui::div()
        .size_full()
        .p(px(12.))
        .text_size(px(14.))
        .text_color(cx.colors().muted)
        .child(label)
        .into_any_element()
}
para
fn para(text: &str, cx: &App) -> gpui::AnyElement {
    let colors = cx.colors();
    gpui::div()
        .text_size(px(14.5))
        .line_height(px(24.))
        .text_color(colors.foreground)
        .max_w(px(720.))
        .child(text.to_owned())
        .into_any_element()
}

Anatomy

Rust types

Separator

Separator is assembled from these builders. The API reference lists each one.

Customization

Shared appearance belongs on ThemeBuilder::components and .recipe("name"). Typed builders change how Separator looks at one call site. Every builder also carries sx for placement, width and flex: it takes GPUI's own styling methods and refines them over the component's root after the theme, so an instance override wins. Behaviour builders live in the API reference below.

Styling

Separator styling
MethodValuesDescription
orientation(Orientation)Orientation::Horizontal | Orientation::VerticalThe orientation of the separator.
variant(SeparatorVariant)SeparatorVariant::Default | SeparatorVariant::Secondary | SeparatorVariant::TertiaryThe visual variant of the separator.
Rust
// The one slot for caller-owned low-level styling: GPUI's
// styling methods, refined over the root element last.
.sx(|el| {
    el.bg(gpui::rgba(0xffa500ff))             // background
        .text_color(gpui::rgba(0x000000ff))   // text
        .w(gpui::px(13.))                     // size
        .h(gpui::px(12.))
})

API reference

Against HeroUI v3.2.6: 3 entries ported, 1 partial, 2 not ported. Partial rows are marked in the tables; entries not ported are listed under each table with the reason.

Builders

Separator builders
BuilderValuesDefaultDescription
id(ElementId)Partialstring—Optional GPUI identity. AccessKit 0.24 has no Role::Separator, so a named instance still produces no node.
orientation(Orientation)Orientation::Horizontal | Orientation::VerticalOrientation::HorizontalThe orientation of the separator.
variant(SeparatorVariant)SeparatorVariant::Default | SeparatorVariant::Secondary | SeparatorVariant::TertiarySeparatorVariant::DefaultThe visual variant of the separator.
Not ported2 HeroUI entries not ported
Separator builders not ported
HeroUI v3Why it is not ported
Separator.className; gpui has no class-name surface.
Separator.renderReplaces the element; gpui does not substitute nodes.

Parts

Separator parts
PartDescription
SeparatorRoot separator primitive and data-slot owner.