T09b overlays: lightbox, spotlight and tour, floating toolbar, peek; images fill their box; overlays take focus back when its element leaves the tree
This commit is contained in:
18 files changed
+1754
-228
No files matched your search
@@ -0,0 +1,152 @@
|
||||
use ely_gpui_component::{
|
||||
buttons::{Button, ButtonVariant},
|
||||
forms::Switch,
|
||||
overlays::{HoverCard, Popover},
|
||||
primitives::IconName,
|
||||
theme::{ActiveTheme, TextSize},
|
||||
};
|
||||
use gpui::{AnyElement, App, FontWeight, IntoElement, ParentElement, Styled, Window, div};
|
||||
|
||||
use crate::{
|
||||
probe::probe,
|
||||
ui::{keep, row, section, set, specimen},
|
||||
};
|
||||
|
||||
pub fn popovers(window: &mut Window, cx: &mut App) -> impl IntoElement + use<> {
|
||||
let public = keep("share-public", || true, window, cx);
|
||||
let on = *public.read(cx);
|
||||
let theme = cx.theme();
|
||||
let muted = theme.colors.fg_muted;
|
||||
let panel = move |_: &mut Window, cx: &mut App| {
|
||||
let theme = cx.theme();
|
||||
div()
|
||||
.flex()
|
||||
.flex_col()
|
||||
.gap_3()
|
||||
.w_72()
|
||||
.child(
|
||||
div()
|
||||
.font_weight(FontWeight::SEMIBOLD)
|
||||
.child("Share this page"),
|
||||
)
|
||||
.child(
|
||||
div()
|
||||
.text_color(theme.colors.fg_muted)
|
||||
.child("Anyone with the link can view it."),
|
||||
)
|
||||
.child(
|
||||
Switch::new("share-switch", on)
|
||||
.label("Public link")
|
||||
.on_change(move |next, _, cx| set(&public, next, cx)),
|
||||
)
|
||||
.child(
|
||||
Button::new("share-copy", "Copy link")
|
||||
.icon(IconName::Link)
|
||||
.full_width(),
|
||||
)
|
||||
};
|
||||
section(
|
||||
"Popover / DropdownPanel / InlinePopup",
|
||||
"A panel of any content under its button. A press outside or Escape closes it, and Tab stays inside. The Link variant sets the trigger inline.",
|
||||
cx,
|
||||
)
|
||||
.child(
|
||||
row()
|
||||
.child(probe(
|
||||
"share",
|
||||
Popover::new("share", "Share", panel).icon(IconName::Share2),
|
||||
))
|
||||
.child(
|
||||
div()
|
||||
.flex()
|
||||
.items_center()
|
||||
.gap_1()
|
||||
.text_color(muted)
|
||||
.child("Read the")
|
||||
.child(
|
||||
Popover::new("terms", "terms", |_, cx| {
|
||||
div()
|
||||
.w_72()
|
||||
.text_color(cx.theme().colors.fg_muted)
|
||||
.child("Plain words: you own your work, and we keep it private.")
|
||||
})
|
||||
.variant(ButtonVariant::Link),
|
||||
)
|
||||
.child("before you share."),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
fn profile(cx: &App) -> AnyElement {
|
||||
let theme = cx.theme();
|
||||
let colors = &theme.colors;
|
||||
div()
|
||||
.flex()
|
||||
.flex_col()
|
||||
.gap_3()
|
||||
.w_64()
|
||||
.child(
|
||||
div()
|
||||
.flex()
|
||||
.items_center()
|
||||
.gap_3()
|
||||
.child(
|
||||
div()
|
||||
.flex()
|
||||
.items_center()
|
||||
.justify_center()
|
||||
.size_10()
|
||||
.rounded_full()
|
||||
.bg(colors.hover)
|
||||
.font_weight(FontWeight::SEMIBOLD)
|
||||
.child("AL"),
|
||||
)
|
||||
.child(
|
||||
div()
|
||||
.flex()
|
||||
.flex_col()
|
||||
.child(
|
||||
div()
|
||||
.font_weight(FontWeight::SEMIBOLD)
|
||||
.child("Ada Lovelace"),
|
||||
)
|
||||
.child(
|
||||
div()
|
||||
.text_size(theme.text_size(TextSize::Xs))
|
||||
.text_color(colors.fg_subtle)
|
||||
.child("Design · London"),
|
||||
),
|
||||
),
|
||||
)
|
||||
.child(
|
||||
div()
|
||||
.text_color(colors.fg_muted)
|
||||
.child("Writes the first programs for machines not yet built."),
|
||||
)
|
||||
.child(Button::new("ada-follow", "Follow").primary())
|
||||
.into_any_element()
|
||||
}
|
||||
|
||||
pub fn hover_card(cx: &App) -> impl IntoElement + use<> {
|
||||
let theme = cx.theme();
|
||||
section(
|
||||
"HoverCard",
|
||||
"Rest the pointer on a name and a card opens. It stays while the pointer is on either, and never takes focus.",
|
||||
cx,
|
||||
)
|
||||
.child(specimen(
|
||||
"rest the pointer on the name",
|
||||
probe(
|
||||
"ada",
|
||||
HoverCard::new(
|
||||
"ada",
|
||||
div()
|
||||
.text_color(theme.colors.link)
|
||||
.font_weight(FontWeight::MEDIUM)
|
||||
.child("@ada"),
|
||||
|_, cx| profile(cx),
|
||||
),
|
||||
),
|
||||
cx,
|
||||
))
|
||||
}
|
||||
@@ -1,207 +1,21 @@
|
||||
use ely_gpui_component::{
|
||||
buttons::{Button, ButtonVariant},
|
||||
forms::{Input, Switch, TextInput},
|
||||
overlays::{AlertDialog, ConfirmDialog, Dialog, HoverCard, Popover, PromptDialog},
|
||||
primitives::{IconName, Severity},
|
||||
theme::{ActiveTheme, TextSize},
|
||||
forms::{Input, TextInput},
|
||||
overlays::{AlertDialog, ConfirmDialog, Dialog, PromptDialog},
|
||||
primitives::Severity,
|
||||
theme::ActiveTheme,
|
||||
typography::Caption,
|
||||
};
|
||||
use gpui::{
|
||||
AnyElement, App, Entity, FontWeight, IntoElement, ParentElement, SharedString, Styled, Window,
|
||||
div, prelude::*,
|
||||
AnyElement, App, Entity, IntoElement, ParentElement, SharedString, Styled, Window, div,
|
||||
prelude::*,
|
||||
};
|
||||
|
||||
use super::Page;
|
||||
use crate::{
|
||||
probe::probe,
|
||||
script::Step,
|
||||
ui::{keep, row, section, set, specimen},
|
||||
};
|
||||
|
||||
pub const PAGE: Page = Page {
|
||||
number: 9,
|
||||
slug: "overlays",
|
||||
title: "Overlays",
|
||||
summary: "Panels over the page: anchored to a control, over a scrim, or over everything.",
|
||||
render,
|
||||
script: SCRIPT,
|
||||
};
|
||||
|
||||
const SCRIPT: &[Step] = &[
|
||||
Step::Rest,
|
||||
Step::Click("share"),
|
||||
Step::Wait(400),
|
||||
Step::Shot("popover"),
|
||||
Step::Key("escape"),
|
||||
Step::Hover("ada"),
|
||||
Step::Wait(900),
|
||||
Step::Shot("hovercard"),
|
||||
Step::Hover("share"),
|
||||
Step::Wait(400),
|
||||
Step::Click("edit-profile"),
|
||||
Step::Wait(500),
|
||||
Step::Shot("dialog"),
|
||||
Step::Key("escape"),
|
||||
Step::Click("alert"),
|
||||
Step::Wait(500),
|
||||
Step::Shot("alert"),
|
||||
Step::Key("escape"),
|
||||
Step::Click("confirm"),
|
||||
Step::Wait(500),
|
||||
Step::Shot("confirm"),
|
||||
Step::Key("escape"),
|
||||
Step::Click("prompt"),
|
||||
Step::Wait(400),
|
||||
Step::Type("drafts/2027"),
|
||||
Step::Wait(300),
|
||||
Step::Shot("prompt"),
|
||||
Step::Key("escape"),
|
||||
Step::Click("fullscreen"),
|
||||
Step::Wait(600),
|
||||
Step::Shot("fullscreen"),
|
||||
Step::Key("escape"),
|
||||
Step::Rest,
|
||||
];
|
||||
|
||||
fn popovers(window: &mut Window, cx: &mut App) -> impl IntoElement + use<> {
|
||||
let public = keep("share-public", || true, window, cx);
|
||||
let on = *public.read(cx);
|
||||
let theme = cx.theme();
|
||||
let muted = theme.colors.fg_muted;
|
||||
let panel = move |_: &mut Window, cx: &mut App| {
|
||||
let theme = cx.theme();
|
||||
div()
|
||||
.flex()
|
||||
.flex_col()
|
||||
.gap_3()
|
||||
.w_72()
|
||||
.child(
|
||||
div()
|
||||
.font_weight(FontWeight::SEMIBOLD)
|
||||
.child("Share this page"),
|
||||
)
|
||||
.child(
|
||||
div()
|
||||
.text_color(theme.colors.fg_muted)
|
||||
.child("Anyone with the link can view it."),
|
||||
)
|
||||
.child(
|
||||
Switch::new("share-switch", on)
|
||||
.label("Public link")
|
||||
.on_change(move |next, _, cx| set(&public, next, cx)),
|
||||
)
|
||||
.child(
|
||||
Button::new("share-copy", "Copy link")
|
||||
.icon(IconName::Link)
|
||||
.full_width(),
|
||||
)
|
||||
};
|
||||
section(
|
||||
"Popover / DropdownPanel / InlinePopup",
|
||||
"A panel of any content under its button. A press outside or Escape closes it, and Tab stays inside. The Link variant sets the trigger inline.",
|
||||
cx,
|
||||
)
|
||||
.child(
|
||||
row()
|
||||
.child(probe(
|
||||
"share",
|
||||
Popover::new("share", "Share", panel).icon(IconName::Share2),
|
||||
))
|
||||
.child(
|
||||
div()
|
||||
.flex()
|
||||
.items_center()
|
||||
.gap_1()
|
||||
.text_color(muted)
|
||||
.child("Read the")
|
||||
.child(
|
||||
Popover::new("terms", "terms", |_, cx| {
|
||||
div()
|
||||
.w_72()
|
||||
.text_color(cx.theme().colors.fg_muted)
|
||||
.child("Plain words: you own your work, and we keep it private.")
|
||||
})
|
||||
.variant(ButtonVariant::Link),
|
||||
)
|
||||
.child("before you share."),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
fn profile(cx: &App) -> AnyElement {
|
||||
let theme = cx.theme();
|
||||
let colors = &theme.colors;
|
||||
div()
|
||||
.flex()
|
||||
.flex_col()
|
||||
.gap_3()
|
||||
.w_64()
|
||||
.child(
|
||||
div()
|
||||
.flex()
|
||||
.items_center()
|
||||
.gap_3()
|
||||
.child(
|
||||
div()
|
||||
.flex()
|
||||
.items_center()
|
||||
.justify_center()
|
||||
.size_10()
|
||||
.rounded_full()
|
||||
.bg(colors.hover)
|
||||
.font_weight(FontWeight::SEMIBOLD)
|
||||
.child("AL"),
|
||||
)
|
||||
.child(
|
||||
div()
|
||||
.flex()
|
||||
.flex_col()
|
||||
.child(
|
||||
div()
|
||||
.font_weight(FontWeight::SEMIBOLD)
|
||||
.child("Ada Lovelace"),
|
||||
)
|
||||
.child(
|
||||
div()
|
||||
.text_size(theme.text_size(TextSize::Xs))
|
||||
.text_color(colors.fg_subtle)
|
||||
.child("Design · London"),
|
||||
),
|
||||
),
|
||||
)
|
||||
.child(
|
||||
div()
|
||||
.text_color(colors.fg_muted)
|
||||
.child("Writes the first programs for machines not yet built."),
|
||||
)
|
||||
.child(Button::new("ada-follow", "Follow").primary())
|
||||
.into_any_element()
|
||||
}
|
||||
|
||||
fn hover_card(cx: &App) -> impl IntoElement + use<> {
|
||||
let theme = cx.theme();
|
||||
section(
|
||||
"HoverCard",
|
||||
"Rest the pointer on a name and a card opens. It stays while the pointer is on either, and never takes focus.",
|
||||
cx,
|
||||
)
|
||||
.child(specimen(
|
||||
"rest the pointer on the name",
|
||||
probe(
|
||||
"ada",
|
||||
HoverCard::new(
|
||||
"ada",
|
||||
div()
|
||||
.text_color(theme.colors.link)
|
||||
.font_weight(FontWeight::MEDIUM)
|
||||
.child("@ada"),
|
||||
|_, cx| profile(cx),
|
||||
),
|
||||
),
|
||||
cx,
|
||||
))
|
||||
}
|
||||
|
||||
/// Which dialog is open, if any.
|
||||
#[derive(Clone, Copy, PartialEq)]
|
||||
enum Open {
|
||||
@@ -225,7 +39,7 @@ fn opener(
|
||||
)
|
||||
}
|
||||
|
||||
fn dialogs(window: &mut Window, cx: &mut App) -> impl IntoElement + use<> {
|
||||
pub fn dialogs(window: &mut Window, cx: &mut App) -> impl IntoElement + use<> {
|
||||
let open = keep("overlay-open", || None::<Open>, window, cx);
|
||||
let said = keep("overlay-said", || None::<SharedString>, window, cx);
|
||||
let (name, email, rename) = {
|
||||
@@ -360,22 +174,13 @@ fn dialogs(window: &mut Window, cx: &mut App) -> impl IntoElement + use<> {
|
||||
.children(overlay)
|
||||
}
|
||||
|
||||
fn pointers(cx: &App) -> impl IntoElement + use<> {
|
||||
pub fn pointers(cx: &App) -> impl IntoElement + use<> {
|
||||
section(
|
||||
"Tooltip / Sheet / Drawer",
|
||||
"Tooltip / Sheet / Drawer / DropdownPanel / InlinePopup / ToastViewport",
|
||||
"They live with the pieces they are made of.",
|
||||
cx,
|
||||
)
|
||||
.child(Caption::new(
|
||||
"Tooltip is primitives::Tooltip, on Primitives, chapter 1. Sheet and Drawer are layout::Sheet and layout::Drawer, on Layout, chapter 3.",
|
||||
"Tooltip is primitives::Tooltip, on Primitives, chapter 1. Sheet and Drawer are layout::Sheet and layout::Drawer, on Layout, chapter 3. DropdownPanel and InlinePopup are the Popover above. ToastViewport holds toasts, so it lands with Feedback, chapter 10.",
|
||||
))
|
||||
}
|
||||
|
||||
fn render(window: &mut Window, cx: &mut App) -> AnyElement {
|
||||
div()
|
||||
.child(popovers(window, cx))
|
||||
.child(hover_card(cx))
|
||||
.child(dialogs(window, cx))
|
||||
.child(pointers(cx))
|
||||
.into_any_element()
|
||||
}
|
||||
@@ -0,0 +1,222 @@
|
||||
use std::path::Path;
|
||||
|
||||
use ely_gpui_component::{
|
||||
buttons::{Button, ButtonVariant, IconButton},
|
||||
forms::{Input, TextInput},
|
||||
overlays::{FloatingToolbar, Lightbox, Peek, Slide, Spotlight, Tour, TourStep},
|
||||
primitives::{IconName, Image, Measure},
|
||||
theme::ActiveTheme,
|
||||
};
|
||||
use gpui::{
|
||||
App, Bounds, Entity, InteractiveElement, IntoElement, ObjectFit, ParentElement, Pixels,
|
||||
SharedString, StatefulInteractiveElement, Styled, Window, div,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
probe::probe,
|
||||
ui::{keep, row, section, set, specimen},
|
||||
};
|
||||
|
||||
const PHOTOS: [(&str, &str); 2] = [
|
||||
(
|
||||
concat!(
|
||||
env!("CARGO_MANIFEST_DIR"),
|
||||
"/examples/gallery/assets/dunes.jpg"
|
||||
),
|
||||
"Dunes at first light",
|
||||
),
|
||||
(
|
||||
concat!(
|
||||
env!("CARGO_MANIFEST_DIR"),
|
||||
"/examples/gallery/assets/atrium.jpg"
|
||||
),
|
||||
"An atrium, noon",
|
||||
),
|
||||
];
|
||||
|
||||
pub fn lightbox(window: &mut Window, cx: &mut App) -> impl IntoElement + use<> {
|
||||
let shown = keep("lightbox-at", || None::<usize>, window, cx);
|
||||
let thumbs = PHOTOS.iter().enumerate().map(|(ix, (path, _))| {
|
||||
let open = shown.clone();
|
||||
probe(
|
||||
["lightbox-0", "lightbox-1"][ix],
|
||||
div()
|
||||
.id(("thumb", ix))
|
||||
.w_48()
|
||||
.h_32()
|
||||
.cursor_pointer()
|
||||
.child(
|
||||
Image::new(("thumb-image", ix), Path::new(*path))
|
||||
.fit(ObjectFit::Cover)
|
||||
.size_full(),
|
||||
)
|
||||
.on_click(move |_, _, cx| set(&open, Some(ix), cx)),
|
||||
)
|
||||
});
|
||||
let overlay = (*shown.read(cx)).map(|at| {
|
||||
let (step, close) = (shown.clone(), shown.clone());
|
||||
Lightbox::new(
|
||||
"lightbox",
|
||||
PHOTOS.map(|(path, caption)| Slide::new(Path::new(path), caption)),
|
||||
at,
|
||||
move |_, cx| set(&close, None, cx),
|
||||
)
|
||||
.on_step(move |to, _, cx| set(&step, Some(to), cx))
|
||||
});
|
||||
section(
|
||||
"Lightbox",
|
||||
"A picture over a dark layer, one at a time. Arrows step, Escape or a press on the dark closes it, and each picture fades in.",
|
||||
cx,
|
||||
)
|
||||
.child(row().children(thumbs))
|
||||
.children(overlay)
|
||||
}
|
||||
|
||||
/// Where each tour target sits, measured as it renders.
|
||||
type Boxes = Entity<[Bounds<Pixels>; 3]>;
|
||||
|
||||
fn target(boxes: &Boxes, ix: usize, child: impl IntoElement) -> impl IntoElement {
|
||||
let boxes = boxes.clone();
|
||||
Measure::new(("tour-target", ix), move |bounds, _, cx| {
|
||||
let mut next = *boxes.read(cx);
|
||||
next[ix] = bounds;
|
||||
set(&boxes, next, cx);
|
||||
})
|
||||
.child(child)
|
||||
}
|
||||
|
||||
pub fn tour(window: &mut Window, cx: &mut App) -> impl IntoElement + use<> {
|
||||
let boxes: Boxes = keep("tour-boxes", || [Bounds::default(); 3], window, cx);
|
||||
let at = keep("tour-at", || None::<usize>, window, cx);
|
||||
let coach = keep("coach-open", || false, window, cx);
|
||||
let spots = *boxes.read(cx);
|
||||
let steps = [
|
||||
("Search", "Find any page, person or file from here."),
|
||||
("Invite", "Bring your team in. They see what you share."),
|
||||
("Settings", "Theme, density and keys live here."),
|
||||
];
|
||||
let overlay = (*at.read(cx)).map(|step| {
|
||||
let (next, close) = (at.clone(), at.clone());
|
||||
Tour::new(
|
||||
"tour",
|
||||
steps
|
||||
.iter()
|
||||
.zip(spots)
|
||||
.map(|((title, body), spot)| TourStep::new(spot, *title, *body)),
|
||||
step,
|
||||
move |_, cx| set(&close, None, cx),
|
||||
)
|
||||
.on_step(move |to, _, cx| set(&next, Some(to), cx))
|
||||
.into_any_element()
|
||||
});
|
||||
let coachmark = (*coach.read(cx)).then(|| {
|
||||
let close = coach.clone();
|
||||
Spotlight::new(
|
||||
"coach",
|
||||
TourStep::new(
|
||||
spots[1],
|
||||
"New: invites",
|
||||
"Invite by name or email; links expire in a week.",
|
||||
),
|
||||
move |_, cx| set(&close, false, cx),
|
||||
)
|
||||
.into_any_element()
|
||||
});
|
||||
let (start, show) = (at.clone(), coach.clone());
|
||||
section(
|
||||
"Spotlight / Coachmark / Tour",
|
||||
"The window dims around one control and a card explains it. A tour walks the stops; the lit box glides from one to the next.",
|
||||
cx,
|
||||
)
|
||||
.child(
|
||||
row()
|
||||
.child(target(&boxes, 0, Button::new("tour-search", "Search").icon(IconName::Search)))
|
||||
.child(target(&boxes, 1, Button::new("tour-invite", "Invite").icon(IconName::Users)))
|
||||
.child(target(&boxes, 2, IconButton::new("tour-settings", IconName::Settings)))
|
||||
.child(div().w_8())
|
||||
.child(probe(
|
||||
"tour",
|
||||
Button::new("tour-start", "Take the tour")
|
||||
.primary()
|
||||
.on_click(move |_, _, cx| set(&start, Some(0), cx)),
|
||||
))
|
||||
.child(probe(
|
||||
"coach",
|
||||
Button::new("coach-start", "Show a coachmark")
|
||||
.variant(ButtonVariant::Ghost)
|
||||
.on_click(move |_, _, cx| set(&show, true, cx)),
|
||||
)),
|
||||
)
|
||||
.children(overlay)
|
||||
.children(coachmark)
|
||||
}
|
||||
|
||||
pub fn toolbar(window: &mut Window, cx: &mut App) -> impl IntoElement + use<> {
|
||||
let field: Entity<TextInput> = window.use_keyed_state("toolbar-field", cx, |window, cx| {
|
||||
let mut input = TextInput::new(window, cx);
|
||||
input.set_text("Select some of these words to see the tools.", cx);
|
||||
input
|
||||
});
|
||||
let used = keep("toolbar-used", || None::<SharedString>, window, cx);
|
||||
let caption = used
|
||||
.read(cx)
|
||||
.clone()
|
||||
.map_or("select text in the field".to_string(), |tool| {
|
||||
format!("applied {tool}")
|
||||
});
|
||||
let tool = |name: &'static str, icon: IconName| {
|
||||
let used = used.clone();
|
||||
IconButton::new(SharedString::from(format!("tool-{name}")), icon)
|
||||
.tooltip(name)
|
||||
.on_click(move |_, _, cx| set(&used, Some(name.into()), cx))
|
||||
};
|
||||
section(
|
||||
"FloatingToolbar",
|
||||
"Tools float over a selection while the field has focus, and leave focus where it is.",
|
||||
cx,
|
||||
)
|
||||
.child(specimen(
|
||||
caption,
|
||||
probe(
|
||||
"toolbar",
|
||||
div().w_96().child(Input::new(&field)).child(
|
||||
FloatingToolbar::new("toolbar", &field)
|
||||
.child(tool("bold", IconName::Bold))
|
||||
.child(tool("italic", IconName::Italic))
|
||||
.child(tool("link", IconName::Link)),
|
||||
),
|
||||
),
|
||||
cx,
|
||||
))
|
||||
}
|
||||
|
||||
pub fn peek(window: &mut Window, cx: &mut App) -> impl IntoElement + use<> {
|
||||
let open = keep("peek-open", || false, window, cx);
|
||||
let shown = *open.read(cx);
|
||||
let (toggle, close) = (open.clone(), open.clone());
|
||||
let theme = cx.theme();
|
||||
section(
|
||||
"Callout / Peek",
|
||||
"A panel opens in the flow under its line, the way an editor peeks at a definition, and pushes what follows down.",
|
||||
cx,
|
||||
)
|
||||
.child(
|
||||
div()
|
||||
.w_128()
|
||||
.font_family(theme.mono_family.clone())
|
||||
.text_color(theme.colors.fg_muted)
|
||||
.child(
|
||||
div().flex().child("let colors = cx.").child(probe(
|
||||
"peek",
|
||||
Button::new("peek-theme", "theme()")
|
||||
.variant(ButtonVariant::Link)
|
||||
.on_click(move |_, _, cx| set(&toggle, !shown, cx)),
|
||||
)),
|
||||
)
|
||||
.child(
|
||||
Peek::new("peek-theme-def", "src/theme/mod.rs", shown, move |_, cx| set(&close, false, cx))
|
||||
.child("pub trait ActiveTheme { fn theme(&self) -> &Theme; }"),
|
||||
)
|
||||
.child(div().child("let accent = colors.accent;")),
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
mod anchored;
|
||||
mod dialogs;
|
||||
mod guides;
|
||||
|
||||
use gpui::{AnyElement, App, IntoElement, ParentElement, Window, div};
|
||||
|
||||
use super::Page;
|
||||
use crate::script::Step;
|
||||
|
||||
pub const PAGE: Page = Page {
|
||||
number: 9,
|
||||
slug: "overlays",
|
||||
title: "Overlays",
|
||||
summary: "Panels over the page: anchored to a control, over a scrim, or over everything.",
|
||||
render,
|
||||
script: SCRIPT,
|
||||
};
|
||||
|
||||
const SCRIPT: &[Step] = &[
|
||||
Step::Rest,
|
||||
Step::Click("share"),
|
||||
Step::Wait(400),
|
||||
Step::Shot("popover"),
|
||||
Step::Key("escape"),
|
||||
Step::Hover("ada"),
|
||||
Step::Wait(900),
|
||||
Step::Shot("hovercard"),
|
||||
Step::Hover("share"),
|
||||
Step::Wait(400),
|
||||
Step::Click("edit-profile"),
|
||||
Step::Wait(500),
|
||||
Step::Shot("dialog"),
|
||||
Step::Key("escape"),
|
||||
Step::Click("alert"),
|
||||
Step::Wait(500),
|
||||
Step::Shot("alert"),
|
||||
Step::Key("escape"),
|
||||
Step::Click("confirm"),
|
||||
Step::Wait(500),
|
||||
Step::Shot("confirm"),
|
||||
Step::Key("escape"),
|
||||
Step::Click("prompt"),
|
||||
Step::Wait(400),
|
||||
Step::Type("drafts/2027"),
|
||||
Step::Wait(300),
|
||||
Step::Shot("prompt"),
|
||||
Step::Key("escape"),
|
||||
Step::Click("fullscreen"),
|
||||
Step::Wait(600),
|
||||
Step::Shot("fullscreen"),
|
||||
Step::Key("escape"),
|
||||
Step::Click("lightbox-0"),
|
||||
Step::Wait(700),
|
||||
Step::Shot("lightbox"),
|
||||
Step::Key("right"),
|
||||
Step::Wait(500),
|
||||
Step::Shot("lightbox-next"),
|
||||
Step::Key("escape"),
|
||||
Step::Click("tour"),
|
||||
Step::Wait(700),
|
||||
Step::Shot("tour"),
|
||||
Step::Key("right"),
|
||||
Step::Wait(700),
|
||||
Step::Shot("tour-next"),
|
||||
Step::Key("escape"),
|
||||
Step::Click("toolbar"),
|
||||
Step::Key("secondary-a"),
|
||||
Step::Wait(400),
|
||||
Step::Shot("toolbar"),
|
||||
Step::Click("peek"),
|
||||
Step::Wait(500),
|
||||
Step::Shot("peek"),
|
||||
Step::Click("peek"),
|
||||
Step::Rest,
|
||||
];
|
||||
|
||||
fn render(window: &mut Window, cx: &mut App) -> AnyElement {
|
||||
div()
|
||||
.child(anchored::popovers(window, cx))
|
||||
.child(anchored::hover_card(cx))
|
||||
.child(dialogs::dialogs(window, cx))
|
||||
.child(guides::lightbox(window, cx))
|
||||
.child(guides::tour(window, cx))
|
||||
.child(guides::toolbar(window, cx))
|
||||
.child(guides::peek(window, cx))
|
||||
.child(dialogs::pointers(cx))
|
||||
.into_any_element()
|
||||
}
|
||||
Reference in new issue
Block a user