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

Utilities

Scroll Shadow

A scrollable area with soft fading edges.

Rust
use herogpui::components::scroll_shadow::ScrollShadow;

ScrollShadow 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::ScrollShadow;
use herogpui::gpui::prelude::*;
use herogpui::gpui::px;
use herogpui::gpui;

ScrollShadow::new("scroll-shadow")
    .max_h(px(180.))
    .children((1..=14).map(|n| {
        gpui::div().py(px(6.)).child(format!("Row {n} of fourteen"))
    }),)

Orientation

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

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

gpui::div()
    .flex()
    .flex_col()
    .items_start()
    .justify_center()
    .gap(px(12.))
    .children(vec![
        ScrollShadow::new("scroll-shadow-or-v").max_h(px(140.)).children(
            (1..=10).map(|n| gpui::div().py(px(6.)).child(format!("Row {n}"))),
        )
            .into_any_element(),
        ScrollShadow::new("scroll-shadow-or-h")
            .orientation(Orientation::Horizontal)
            .max_w(px(360.))
            .gap(px(12.))
            .children((1..=12).map(|n| {
                gpui::div()
                    .flex_shrink_0()
                    .w(px(90.))
                    .h(px(60.))
                    .rounded(px(10.))
                    .bg(cx.colors().default.color)
                    .child(format!("{n}"))
            }))
            .into_any_element(),
    ])

Shadow Size

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

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

gpui::div()
    .flex()
    .flex_col()
    .items_start()
    .justify_center()
    .gap(px(12.))
    .children(vec![
        ScrollShadow::new("scroll-shadow-size-sm")
            .size(px(8.))
            .max_h(px(120.))
            .children(
                (1..=10)
                    .map(|n| gpui::div().py(px(6.)).child(format!("Row {n}"))),
            )
            .into_any_element(),
        ScrollShadow::new("scroll-shadow-size-lg")
            .size(px(40.))
            .max_h(px(120.))
            .children(
                (1..=10)
                    .map(|n| gpui::div().py(px(6.)).child(format!("Row {n}"))),
            )
            .into_any_element(),
    ])

With Card

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

Rust
use herogpui::prelude::{Card, CardContent, CardHeader, CardTitle, ScrollShadow};
use herogpui::gpui::prelude::*;
use herogpui::gpui::px;
use herogpui::gpui;

Card::new()
    .w(px(320.))
    .child(
        CardHeader::new().child(CardTitle::new().child("Release notes"))
    )
    .child(CardContent::new().child(
        ScrollShadow::new("scroll-shadow-card").max_h(px(140.)).children(
            (1..=12).map(|n| {
                gpui::div().py(px(6.)).child(format!("Change {n}"))
            }),
        ),
    ),)

Hide Scroll Bar

`hideScrollBar` omits the painted overlay thumb and leaves the shadows as the only affordance; the first specimen keeps the default bar for contrast. An element expression with window: &mut Window and cx: &mut App in scope.

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

gpui::div()
    .flex()
    .flex_col()
    .items_start()
    .justify_center()
    .gap(px(12.))
    .children(vec![
        ScrollShadow::new("scroll-shadow-bar")
            .max_h(px(140.))
            .children(
                (1..=12)
                    .map(|n| gpui::div().py(px(6.)).child(format!("Row {n}"))),
            )
            .into_any_element(),
        ScrollShadow::new("scroll-shadow-no-bar")
            .hide_scroll_bar(true)
            .max_h(px(140.))
            .children(
                (1..=12)
                    .map(|n| gpui::div().py(px(6.)).child(format!("Row {n}"))),
            )
            .into_any_element(),
    ])

Visibility Change

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::{ScrollShadow, ScrollShadowVisibility};
use herogpui::gpui::prelude::*;
use herogpui::gpui::px;
use herogpui::gpui;

gpui::div()
    .flex()
    .flex_col()
    .items_start()
    .justify_center()
    .gap(px(12.))
    .children(vec![
        ScrollShadow::new("scroll-shadow-vis-auto")
            .visibility(ScrollShadowVisibility::Auto)
            // `onVisibilityChange` fires when the shaded
            // edges change, which `Auto` does as it scrolls.
            .on_visibility_change(cx.listener(
                |this, visibility: &ScrollShadowVisibility, _, cx| {
                    this.set_demo_text_value(
                        "ss-visibility",
                        format!("{visibility:?}"),
                    );
                    cx.notify();
                },
            ))
            .max_h(px(120.))
            .children(
                (1..=10)
                    .map(|n| gpui::div().py(px(6.)).child(format!("Row {n}"))),
            )
            .into_any_element(),
        ScrollShadow::new("scroll-shadow-vis-both")
            .visibility(ScrollShadowVisibility::Both)
            .max_h(px(120.))
            .children(
                (1..=10)
                    .map(|n| gpui::div().py(px(6.)).child(format!("Row {n}"))),
            )
            .into_any_element(),
        ScrollShadow::new("scroll-shadow-vis-top")
            .visibility(ScrollShadowVisibility::Top)
            .max_h(px(120.))
            .children(
                (1..=10)
                    .map(|n| gpui::div().py(px(6.)).child(format!("Row {n}"))),
            )
            .into_any_element(),
    ])

Vertical

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

Rust
use herogpui::prelude::ScrollShadow;
use herogpui::gpui::prelude::*;
use herogpui::gpui::{AnyElement, px};
use herogpui::gpui;

let lines: Vec<AnyElement> = (1..=20)
    .map(|i| {
        gpui::div()
            .py(px(4.))
            .child(format!("Row {i}"))
            .into_any_element()
    })
    .collect();

ScrollShadow::new("scroll-shadow-main")
    .max_h(px(200.))
    .children(lines)

Horizontal

Scroll sideways to reveal more cards. Vertical wheel input continues to the page. An element expression with window: &mut Window and cx: &mut App in scope.

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

ScrollShadow::new("scroll-shadow-h")
    .orientation(Orientation::Horizontal)
    .max_w(px(520.))
    .size(px(56.))
    .children((1..=14).map(|i| {
        gpui::div()
            .flex_shrink_0()
            .px(px(16.))
            .py(px(10.))
            .rounded(px(10.))
            .bg(cx.colors().surface_secondary)
            .child(format!("Card {i}"))
            .into_any_element()
    }))

Shadows disabled

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

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

ScrollShadow::new("scroll-shadow-off")
    .max_h(px(140.))
    .is_enabled(false)
    .children((1..=10).map(|i| {
        gpui::div()
            .py(px(4.))
            .child(format!("Row {i}"))
            .into_any_element()
    }))

Anatomy

Rust types

ScrollShadow

Scroll Shadow 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 Scroll Shadow 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

Scroll Shadow styling
MethodValuesDescription
orientation(Orientation)Orientation::Vertical | Orientation::HorizontalAxis along which content scrolls and fades appear.
size(Pixels)numberDepth of each fade gradient in pixels.
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: 11 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

Scroll Shadow builders
BuilderValuesDefaultDescription
orientation(Orientation)Orientation::Vertical | Orientation::HorizontalOrientation::VerticalAxis along which content scrolls and fades appear.
size(Pixels)number40Depth of each fade gradient in pixels.
offset(Pixels)number0Scroll distance before the corresponding fade appears.
hide_scroll_bar(bool)true | falsefalseOmits the painted overlay thumb that stands in for the browser scrollbar.
is_enabled(bool)true | falsetrueTurns fade rendering and visibility reporting on or off.
visibility(ScrollShadowVisibility)ScrollShadowVisibility::Auto | ScrollShadowVisibility::Both | ScrollShadowVisibility::Top | ScrollShadowVisibility::Bottom | ScrollShadowVisibility::Left | ScrollShadowVisibility::Right | ScrollShadowVisibility::NoneScrollShadowVisibility::AutoControls which edge fades are eligible to render.
on_visibility_change(callback)Fn(visibility: ScrollShadowVisibility) -> ()โ€”Reports resolved visible edges when they change.
Not ported2 HeroUI entries not ported
Scroll Shadow builders not ported
HeroUI v3Why it is not ported
ScrollShadow.variantThe documented API has one visual variant, which is the port's built-in treatment.
ScrollShadow.classNameBrowser styles are unavailable.

Parts

Scroll Shadow parts
PartDescription
ScrollShadowScrollable root plus edge-fade overlays.

States

Scroll Shadow states
StateBuilderDescription
Leading edgeScrollHandle::offsetLeading fade appears after content moves beyond the configured offset.
Trailing edgeScrollHandle::max_offsetTrailing fade appears while more content remains after the viewport.
Both edgesScrollShadowVisibility::BothBoth fades render when content can scroll in either direction.