Disclosure
A single collapsible section.
use herogpui::components::disclosure::{Disclosure, DisclosureGroup};Disclosure 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.
The measured panel animates height and opacity over 200ms and stays mounted until the close transition completes. An element expression with window: &mut Window and cx: &mut App in scope.
use herogpui::prelude::{Disclosure, DisclosureGroup};
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![Disclosure::new(
"disclosure-usage",
"Shipping details"
)
.child(gpui::div().child("Ships in 2-4 business days."))
.into_any_element()])The body is built from the Disclosure's current expanded and disabled state. Runs in a view's render: self is the view holding this example's state and cx is its Context<Self>.
use herogpui::prelude::{Disclosure, DisclosureGroup};
use herogpui::gpui::prelude::*;
use herogpui::gpui::px;
use herogpui::gpui;
{
let render_expanded = self.demo_flag("disclosure-render", true);
gpui::div()
.flex()
.flex_col()
.items_start()
.justify_center()
.gap(px(12.))
.children(vec![Disclosure::new("disclosure-render", "Account details")
.is_expanded(render_expanded)
.on_expanded_change(cx.listener(
|this, value: &bool, _, cx| {
this.set_demo_flag("disclosure-render", *value);
cx.notify();
},
))
.content(|state| {
gpui::div()
.child(format!(
"The render closure received is_expanded={} and is_disabled={}.",
state.is_expanded, state.is_disabled
))
.into_any_element()
})
.into_any_element()])
.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::{ActiveTheme, Disclosure, DisclosureGroup};
use herogpui::gpui::prelude::*;
use herogpui::gpui::{App, SharedString, px};
use herogpui::gpui;
use std::collections::HashSet;
let group = self.disclosure_group_expanded.clone();
gpui::div()
.flex()
.flex_col()
.items_start()
.justify_center()
.gap(px(12.))
.children(vec![
DisclosureGroup::new("disclosure-controlled")
.item("returns", "Returns", gpui::div().child("Thirty days."))
.item("warranty", "Warranty", gpui::div().child("Two years."))
.expanded_keys(group.clone())
.on_expanded_change(cx.listener(
|this, keys: &HashSet<SharedString>, _, cx| {
this.disclosure_group_expanded = keys.clone();
cx.notify();
},
))
.into_any_element(),
para(&format!("{} expanded", group.len()), cx),
])Also calls para (included when you copy).
Runs in a view's render: self is the view holding this example's state and cx is its Context<Self>.
use herogpui::prelude::{Disclosure, DisclosureGroup};
use herogpui::gpui::prelude::*;
use herogpui::gpui::px;
use herogpui::gpui;
let expanded = self.disclosure_expanded;
gpui::div()
.flex()
.flex_col()
.items_start()
.justify_center()
.gap(px(12.))
.children(vec![Disclosure::new(
"disclosure-single",
"Shipping details"
)
.is_expanded(expanded)
.on_expanded_change(cx.listener(|this, v: &bool, _, cx| {
this.disclosure_expanded = *v;
cx.notify();
}))
.child(gpui::div().child("Ships in 2-4 business days."))
.into_any_element()])An element expression with window: &mut Window and cx: &mut App in scope.
use herogpui::prelude::{Disclosure, DisclosureGroup};
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![DisclosureGroup::new("disclosure-group")
.item(
"item-1",
"Returns",
gpui::div().child("Free returns within 30 days."),
)
.item(
"item-2",
"Warranty",
gpui::div().child("Two years of coverage."),
)
.default_expanded_keys(["item-1"])
.into_any_element()])An element expression with window: &mut Window and cx: &mut App in scope.
use herogpui::prelude::{Disclosure, DisclosureGroup};
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![DisclosureGroup::new("disclosure-disabled-group")
.item("returns", "Returns", gpui::div().child("Thirty days."))
.item("warranty", "Warranty", gpui::div().child("Two years."))
.default_expanded_keys(["returns"])
.is_disabled(true)
.into_any_element()])Helpers used by these examples
Plain functions over the public API, defined once here and copied with each example that calls them.
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
Disclosure is assembled from these builders. The API reference lists each one.
API reference
Against HeroUI v3.2.6: 21 entries ported, 8 partial, 6 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 |
|---|---|---|---|
expanded_keys( | Set< | — | The currently expanded items (controlled). |
default_expanded_keys( | iterable of keys | — | The initially expanded items (uncontrolled). |
on_expanded_change( | Fn( | — | Reports the complete next expanded set. |
allows_multiple_expanded( | true | | false | Allows more than one item to remain expanded. |
is_disabled( | true | | false | Disables every disclosure trigger in the group. |
item(Partial | AnyElement | | — | Composed disclosure items; GPUI builds keyed items through a typed method. |
is_expanded( | true | | false | Controls whether the panel is expanded. |
default_expanded( | true | | false | Initial expanded state when the disclosure owns its state; inherited from pinned. |
content(Partial | AnyElement | | — | Compound heading, trigger and panel children; the GPUI control builds the trigger and accepts static body children through ParentElement or a state-aware body render closure. |
new(Partial | AnyElement | | — | Custom trigger content; accepts an id and title and builds a HeroGPUI Button. |
Not ported6 HeroUI entries not ported
| HeroUI v3 | Why it is not ported |
|---|---|
DisclosureGroup.className | |
Disclosure.className | |
Disclosure.render | Root substitution has no GPUI equivalent. |
Disclosure.Trigger.className | Additional trigger classes. |
Disclosure.Content.className | Additional content classes. |
Disclosure.Content.render | Root substitution has no GPUI equivalent. |
Parts
| Part | Description |
|---|---|
DisclosureGroup | Full-width owner of the expanded key set. |
Disclosure | Relative root for one trigger and panel. |
DisclosurePartial | Heading wrapper is built into the monolithic trigger row. |
DisclosurePartial | A built-in HeroGPUI Button rather than a separately composable trigger. |
Disclosure | Built-in 16px down-chevron that rotates through 180 degrees as expansion changes. |
Disclosure | Measured panel container that stays mounted during the 200ms closing transition. |
Disclosure | Eight-pixel padded body around caller content. |
States
| State | Builder | Description |
|---|---|---|
Expanded | is_expanded(bool) | Shows the body and rotates the shared down-chevron to its expanded endpoint. |
Disabled | is_disabled(bool) | Disables one trigger or every trigger in the group. |
Focus visible | Button tab_stop_handle | The built-in Button owns keyboard focus and its focus ring. |
Single expansion | allows_multiple_expanded(false) | Opening one item replaces the previous expanded set by default. |
Multiple expansion | allows_multiple_expanded(true) | Opt-in mode toggles membership without closing siblings. |