Surface
A container that applies surface-level styling to its children.
use herogpui::components::surface::Surface;Surface 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.
An element expression with window: &mut Window and cx: &mut App in scope.
use herogpui::prelude::Surface;
use herogpui::gpui::prelude::*;
use herogpui::gpui::px;
use herogpui::gpui;
Surface::new()
.padding(px(24.))
.child(gpui::div().child("A surface groups related content."))Runs in a view's render: self is the view holding this example's state and cx is its Context<Self>.
use herogpui::prelude::{ParagraphSize, Surface, SurfaceVariant, TextColor, Typography};
use herogpui::gpui::prelude::*;
use herogpui::gpui::px;
use herogpui::gpui;
let panel = |variant: SurfaceVariant| {
Surface::new()
.variant(variant)
// The upstream examples dress their skeletons through
// className (`p-6`, `gap-3`, plus `rounded-3xl`/borders).
// className customization stays unavailable, so the demo's
// paddings/gaps only exercise the layout knobs this port's
// Surface builders expose.
.padding(px(24.))
.gap(px(12.))
.child(Typography::heading(6, "Surface content").into_any_element())
.child(
Typography::paragraph(
ParagraphSize::Sm,
"Nested content inherits the surface foreground.",
)
.color(TextColor::Muted)
.into_any_element(),
)
};
gpui::div()
.flex()
.flex_col()
.items_start()
.justify_center()
.gap(px(12.))
.children(vec![
panel(SurfaceVariant::Default).into_any_element(),
panel(SurfaceVariant::Secondary).into_any_element(),
panel(SurfaceVariant::Tertiary).into_any_element(),
panel(SurfaceVariant::Transparent).into_any_element(),
])Runs in a view's render: self is the view holding this example's state and cx is its Context<Self>.
use herogpui::prelude::{FieldVariant, Input, Surface, TextArea};
use herogpui::gpui::prelude::*;
use herogpui::gpui::px;
Surface::new()
// Same as the variants panel: upstream adds its
// `p-6` + `gap-4` through className; these explicit
// paddings/gaps exercise the port's own layout
// knobs, and no radius/border is re-added here.
.padding(px(24.))
.gap(px(16.))
.child(
Input::new(self.input_name.clone())
.placeholder("Secondary input")
.variant(FieldVariant::Secondary),
)
.child(
TextArea::new(self.input_bio.clone())
.placeholder("Secondary text area")
.rows(3),
)Anatomy
Rust types
Surface 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 Surface 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
| Method | Values | Description |
|---|---|---|
variant(SurfaceVariant) | SurfaceVariant::Transparent | SurfaceVariant::Default | SurfaceVariant::Secondary | SurfaceVariant::Tertiary | The visual variant of the surface. The strict root is only `relative text-foreground` plus each variant's fill and foreground pair — no padding, gap, radius or border of its own. |
// 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: 2 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
| Builder | Values | Default | Description |
|---|---|---|---|
variant( | SurfaceVariant:: | SurfaceVariant:: | The visual variant of the surface. The strict root is only `relative text-foreground` plus each variant's fill and foreground pair — no padding, gap, radius or border of its own. |
ParentElement::Partial | AnyElement | — | Surface content, composed through ParentElement::extend. The port's `.padding`/`.gap` builders are repository conveniences standing in for the style skeleton every docs example adds (`flex flex-col gap-3 rounded-3xl p-6`) — not upstream props, and they default to zero because the component itself ships none. |
Not ported2 HeroUI entries not ported
| HeroUI v3 | Why it is not ported |
|---|---|
Surface.className | |
SurfaceContext.variant | Context that lets child components read the surrounding surface variant; GPUI has no ancestor context propagation, so nothing downstream reads the surface variant in this port. |
Parts
| Part | Description |
|---|---|
Surface | Strict component root: `relative` plus the variant's background and foreground pair. Zero default padding and gap, no radius and no border; the port's `.padding`/`.gap` builders are port conveniences, not props. |