Files
Ely-GPUI-Components/examples/gallery/pages/layout/regions.rs
T

253 lines
7.4 KiB
Rust

use ely_gpui_component::{
buttons::{Button, ButtonVariant, IconButton},
layout::{
Accordion, AccordionItem, Card, CardHeader, Collapsible, Fieldset, Frame, Panel, Section,
SplitPane, Well, resize_handle,
},
primitives::IconName,
theme::{ActiveTheme, ControlSize, Radius},
typography::{Caption, Label, Paragraph},
};
use gpui::{App, Axis, IntoElement, ParentElement, Styled, Window, div, px};
use super::basics::tile;
use crate::{
probe::probe,
ui::{code, row, section},
};
fn pane(label: &'static str, cx: &App) -> gpui::Div {
div()
.size_full()
.flex()
.items_center()
.justify_center()
.bg(cx.theme().colors.sunken)
.text_color(cx.theme().colors.fg_subtle)
.child(label)
}
fn frame(cx: &App) -> gpui::Div {
let theme = cx.theme();
div()
.w(px(560.0))
.h(px(220.0))
.overflow_hidden()
.rounded(theme.radius(Radius::Lg))
.border_1()
.border_color(theme.colors.border)
}
pub fn split_pane(cx: &App) -> impl IntoElement + use<> {
section(
"SplitPane",
"Drag a divider. Panes nest across and down.",
cx,
)
.child(probe(
"split",
frame(cx).child(
SplitPane::new("split-outer", Axis::Horizontal, px(96.0))
.sizes(&[0.3, 0.7])
.pane(pane("files", cx))
.pane(
SplitPane::new("split-inner", Axis::Vertical, px(48.0))
.pane(pane("editor", cx))
.pane(pane("terminal", cx)),
),
),
))
.child(code(
"ResizablePanel and ThreeColumnLayout are SplitPane.",
cx,
))
}
pub fn resize_handles(cx: &App) -> impl IntoElement + use<> {
section(
"ResizeHandle",
"A hairline with a wide grab. Hover lights it.",
cx,
)
.child(
row()
.gap_8()
.child(
div()
.h(px(80.0))
.child(resize_handle("handle-x", Axis::Horizontal, cx)),
)
.child(
div()
.w(px(160.0))
.child(resize_handle("handle-y", Axis::Vertical, cx)),
),
)
}
pub fn collapsible(window: &mut Window, cx: &mut App) -> impl IntoElement + use<> {
let open = window.use_keyed_state("collapse-open", cx, |_, _| true);
let is_open = *open.read(cx);
section(
"Collapsible",
"Height animates to the measured content.",
cx,
)
.child(
div()
.w(px(420.0))
.flex()
.flex_col()
.gap_2()
.child(probe(
"collapse-toggle",
Button::new(
"collapse-toggle",
if is_open { "Collapse" } else { "Expand" },
)
.variant(ButtonVariant::Outline)
.trailing_icon(if is_open {
IconName::ChevronUp
} else {
IconName::ChevronDown
})
.on_click(move |_, _, cx| {
open.update(cx, |open, cx| {
*open = !*open;
cx.notify();
})
}),
))
.child(
Collapsible::new("collapse", is_open).child(
Paragraph::new(
"Content keeps its natural height. The frame grows to it, then lets go.",
)
.pt_2(),
),
),
)
}
pub fn accordion(cx: &App) -> impl IntoElement + use<> {
section(
"Accordion / AccordionItem",
"One open at a time. The chevron turns with it.",
cx,
)
.child(probe(
"accordion",
div().w(px(480.0)).child(
Accordion::new("faq")
.first_open()
.item(
AccordionItem::new("What is Ely?")
.child("A component library for gpui, in light and dark."),
)
.item(
AccordionItem::new("Does it animate?")
.child("Where motion explains a change, and nowhere else."),
)
.item(
AccordionItem::new("Can I theme it?")
.child("Every color, size and radius comes from one token set."),
),
),
))
}
pub fn card(cx: &App) -> impl IntoElement + use<> {
section(
"Card / CardHeader / CardBody / CardFooter",
"Flat: a hairline, no shadow.",
cx,
)
.child(
Card::new()
.w(px(380.0))
.header(
CardHeader::new("Storage")
.description("Across all workspaces")
.action(IconButton::new("card-more", IconName::Ellipsis).size(ControlSize::Sm)),
)
.child(Label::new("42.8 GB of 100 GB"))
.child(Caption::new("Media takes the most room."))
.footer(
div()
.flex()
.gap_2()
.child(Button::new("card-cancel", "Later").variant(ButtonVariant::Ghost))
.child(Button::new("card-go", "Manage").primary()),
),
)
}
pub fn panel(cx: &App) -> impl IntoElement + use<> {
section(
"Panel / PanelHeader",
"An app region: a quiet header bar and a body.",
cx,
)
.child(
Panel::new("Outline")
.w(px(320.0))
.h(px(160.0))
.action(IconButton::new("panel-filter", IconName::Filter).size(ControlSize::Sm))
.action(IconButton::new("panel-more", IconName::Ellipsis).size(ControlSize::Sm))
.child(
div()
.p_3()
.flex()
.flex_col()
.gap_2()
.child(tile("fn render", cx))
.child(tile("struct Theme", cx)),
),
)
}
pub fn section_demo(cx: &App) -> impl IntoElement + use<> {
section(
"Section / SectionHeader",
"A page block: title, note, action.",
cx,
)
.child(
Section::new("Members")
.w(px(520.0))
.description("People who can open this workspace.")
.action(Button::new("invite", "Invite").icon(IconName::Plus))
.child(
row()
.child(tile("Ada", cx))
.child(tile("Grace", cx))
.child(tile("Linus", cx)),
),
)
}
pub fn fieldset(cx: &App) -> impl IntoElement + use<> {
section("Group / Fieldset", "Related fields under one name.", cx).child(
Fieldset::new("Shipping address")
.w(px(420.0))
.child(tile("Street", cx))
.child(row().child(tile("City", cx)).child(tile("Postcode", cx))),
)
}
pub fn frame_demo(cx: &App) -> impl IntoElement + use<> {
section("Frame", "A bordered region with no fill.", cx).child(
Frame::new()
.w(px(320.0))
.child(Caption::new("Framed content sits on the page tone.")),
)
}
pub fn well(cx: &App) -> impl IntoElement + use<> {
section("Well", "A recessed region on the sunken tone.", cx).child(
Well::new()
.w(px(320.0))
.child(Caption::new("Wells hold secondary material.")),
)
}