Theme · Platform: one platform for buttons and caps, icon themes, frosted panes
theme::Platform moves out of typography and shell's ControlsStyle folds into it; the theme's platform starts as the system's. Window buttons Ely draws, the title bar's layout and every key cap follow it, secondary included, through typography::keys::keystroke; a title bar whose buttons the OS draws follows the OS. primitives::IconTheme lays an owner's rules by file name and extension over Ely's map, for every file icon. shell::Vibrancy fills a pane with the palette's new glass, translucent so a window opened Blurred shows its backdrop, solid under high contrast. gpui 0.2.2 has no Mica; that line stays blocked.
This commit is contained in:
1 parent
7f2205c811
commit
d3cfc71ead
30 files changed
+593
-162
No files matched your search
@@ -1,8 +1,8 @@
|
||||
use ely_gpui_component::{
|
||||
buttons::IconButton,
|
||||
primitives::IconName,
|
||||
shell::{ControlsStyle, TitleBar, WindowControls, drag_region},
|
||||
theme::{ActiveTheme, ControlSize, Elevation, Radius, TextSize},
|
||||
shell::{TitleBar, WindowControls, drag_region},
|
||||
theme::{ActiveTheme, ControlSize, Elevation, Platform, Radius, TextSize},
|
||||
typography::Caption,
|
||||
};
|
||||
use gpui::{App, Div, IntoElement, ParentElement, Styled, Window, div, px};
|
||||
@@ -25,9 +25,9 @@ pub fn window_frame(width: f32, height: f32, cx: &App) -> Div {
|
||||
.shadow(theme.elevation(Elevation::Raised))
|
||||
}
|
||||
|
||||
fn demo_bar(id: &'static str, style: ControlsStyle) -> TitleBar {
|
||||
fn demo_bar(id: &'static str, style: Platform) -> TitleBar {
|
||||
TitleBar::new(id)
|
||||
.style(style)
|
||||
.platform(style)
|
||||
.title("Ely — Projects")
|
||||
.on_close(|_, _| log::info!("gallery: demo close refused"))
|
||||
.child(IconButton::new((id, 1usize), IconName::PanelLeft).size(ControlSize::Sm))
|
||||
@@ -36,9 +36,9 @@ fn demo_bar(id: &'static str, style: ControlsStyle) -> TitleBar {
|
||||
|
||||
pub fn title_bar(cx: &App) -> impl IntoElement + use<> {
|
||||
let styles = [
|
||||
("tb-mac", ControlsStyle::Mac, "macOS"),
|
||||
("tb-windows", ControlsStyle::Windows, "Windows"),
|
||||
("tb-linux", ControlsStyle::Linux, "Linux"),
|
||||
("tb-mac", Platform::Mac, "macOS"),
|
||||
("tb-windows", Platform::Windows, "Windows"),
|
||||
("tb-linux", Platform::Linux, "Linux"),
|
||||
];
|
||||
section(
|
||||
"TitleBar",
|
||||
@@ -88,7 +88,7 @@ pub fn window_controls(cx: &App) -> impl IntoElement + use<> {
|
||||
"Mac",
|
||||
plate().child(
|
||||
WindowControls::new("wc-mac")
|
||||
.style(ControlsStyle::Mac)
|
||||
.platform(Platform::Mac)
|
||||
.on_close(|_, _| log::info!("gallery: demo close refused")),
|
||||
),
|
||||
cx,
|
||||
@@ -97,7 +97,7 @@ pub fn window_controls(cx: &App) -> impl IntoElement + use<> {
|
||||
"Windows",
|
||||
plate().px_0().child(
|
||||
WindowControls::new("wc-windows")
|
||||
.style(ControlsStyle::Windows)
|
||||
.platform(Platform::Windows)
|
||||
.on_close(|_, _| log::info!("gallery: demo close refused")),
|
||||
),
|
||||
cx,
|
||||
@@ -106,7 +106,7 @@ pub fn window_controls(cx: &App) -> impl IntoElement + use<> {
|
||||
"Linux",
|
||||
plate().child(
|
||||
WindowControls::new("wc-linux")
|
||||
.style(ControlsStyle::Linux)
|
||||
.platform(Platform::Linux)
|
||||
.on_close(|_, _| log::info!("gallery: demo close refused")),
|
||||
),
|
||||
cx,
|
||||
|
||||
@@ -11,8 +11,10 @@ use gpui::{
|
||||
|
||||
mod editing;
|
||||
mod importing;
|
||||
mod platform;
|
||||
|
||||
use super::Page;
|
||||
use crate::script::Step;
|
||||
use crate::ui::{section, specimen, specimens};
|
||||
|
||||
pub const PAGE: Page = Page {
|
||||
@@ -21,7 +23,12 @@ pub const PAGE: Page = Page {
|
||||
title: "Theme",
|
||||
summary: "Tokens every component reads. Light and dark share one grammar.",
|
||||
render,
|
||||
script: &[],
|
||||
script: &[
|
||||
Step::Click("frosted-open"),
|
||||
Step::Wait(700),
|
||||
Step::ShotWindow("frosted", "frosted-window"),
|
||||
Step::CloseWindow("frosted"),
|
||||
],
|
||||
};
|
||||
|
||||
fn render(window: &mut Window, cx: &mut App) -> AnyElement {
|
||||
@@ -149,6 +156,7 @@ fn render(window: &mut Window, cx: &mut App) -> AnyElement {
|
||||
)
|
||||
.child(editing::editor(window, cx))
|
||||
.child(importing::importing(window, cx))
|
||||
.child(platform::platform(window, cx))
|
||||
.into_any_element()
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,192 @@
|
||||
use ely_gpui_component::{
|
||||
buttons::{Button, SegmentedControl},
|
||||
files::FileIcon,
|
||||
forms::Switch,
|
||||
primitives::{IconName, IconTheme},
|
||||
shell::{Vibrancy, WindowControls},
|
||||
theme::{ActiveTheme, Platform, Theme},
|
||||
typography::{Kbd, KbdCombo},
|
||||
};
|
||||
use gpui::{
|
||||
App, AppContext, Bounds, Context, IntoElement, ParentElement, Render, Styled, TitlebarOptions,
|
||||
Window, WindowBackgroundAppearance, WindowBounds, WindowOptions, div, point, px, size,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
probe::{Opened, probe},
|
||||
ui::{change, keep, section, specimen, specimens},
|
||||
};
|
||||
|
||||
const PLATFORMS: [(Platform, &str); 3] = [
|
||||
(Platform::Mac, "macOS"),
|
||||
(Platform::Windows, "Windows"),
|
||||
(Platform::Linux, "Linux"),
|
||||
];
|
||||
|
||||
/// Whether the demo's own icon rules are on.
|
||||
struct Owned(bool);
|
||||
|
||||
pub fn platform(window: &mut Window, cx: &mut App) -> impl IntoElement + use<> {
|
||||
section(
|
||||
"Platform Style · IconThemeProvider · VibrancyBackground",
|
||||
"The theme's platform decides window buttons and key caps, and starts as the system's. An icon theme lays an owner's rules over Ely's file icons. A frosted pane lets a blurred window's backdrop through; gpui 0.2.2 blurs as vibrancy on macOS and acrylic on Windows, and has no Mica.",
|
||||
cx,
|
||||
)
|
||||
.child(
|
||||
specimens()
|
||||
.child(specimen("Platform", platforms(cx), cx))
|
||||
.child(specimen("IconTheme", icons(window, cx), cx))
|
||||
.child(specimen(
|
||||
"Vibrancy",
|
||||
probe(
|
||||
"frosted-open",
|
||||
Button::new("frosted-open", "Open a frosted window")
|
||||
.on_click(|_, _, cx| frosted(cx)),
|
||||
),
|
||||
cx,
|
||||
)),
|
||||
)
|
||||
}
|
||||
|
||||
fn platforms(cx: &App) -> impl IntoElement + use<> {
|
||||
let shown = cx.theme().platform;
|
||||
let label = PLATFORMS
|
||||
.iter()
|
||||
.find(|(platform, _)| *platform == shown)
|
||||
.map(|(_, label)| *label)
|
||||
.expect("a listed platform");
|
||||
let control = PLATFORMS.iter().fold(
|
||||
SegmentedControl::new("platform", label),
|
||||
|control, (_, label)| control.segment(*label, *label, None),
|
||||
);
|
||||
div()
|
||||
.w(px(320.))
|
||||
.flex()
|
||||
.flex_col()
|
||||
.gap_4()
|
||||
.child(control.on_change(|picked, _, cx| {
|
||||
let (platform, _) = PLATFORMS
|
||||
.iter()
|
||||
.find(|(_, label)| *label == picked.as_ref())
|
||||
.expect("a listed platform");
|
||||
Theme::update(cx, |theme| theme.platform = *platform);
|
||||
}))
|
||||
.child(
|
||||
div()
|
||||
.flex()
|
||||
.flex_wrap()
|
||||
.items_center()
|
||||
.justify_between()
|
||||
.gap_3()
|
||||
.child(WindowControls::new("platform-controls"))
|
||||
.child(
|
||||
div()
|
||||
.flex()
|
||||
.items_center()
|
||||
.gap_3()
|
||||
.child(Kbd::new("secondary-s"))
|
||||
.child(KbdCombo::new("secondary-k secondary-s")),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
fn icons(window: &mut Window, cx: &mut App) -> impl IntoElement + use<> {
|
||||
let owned = keep("icon-theme", || Owned(false), window, cx);
|
||||
let on = owned.read(cx).0;
|
||||
let muted = cx.theme().colors.fg_muted;
|
||||
let rows = ["Cargo.toml", "README.md", "main.rs", "logo.svg"].map(|name| {
|
||||
div()
|
||||
.flex()
|
||||
.items_center()
|
||||
.gap_2()
|
||||
.child(FileIcon::file(name))
|
||||
.child(div().text_color(muted).child(name))
|
||||
});
|
||||
div()
|
||||
.w(px(240.))
|
||||
.flex()
|
||||
.flex_col()
|
||||
.gap_2()
|
||||
.child(
|
||||
Switch::new("icon-theme", on)
|
||||
.label("The owner's icons")
|
||||
.on_change(move |on, _, cx| {
|
||||
let theme = if on {
|
||||
IconTheme::default()
|
||||
.name("Cargo.toml", IconName::Package)
|
||||
.name("README.md", IconName::BookOpen)
|
||||
.extension("rs", IconName::Braces)
|
||||
} else {
|
||||
IconTheme::default()
|
||||
};
|
||||
theme.apply(cx);
|
||||
change(&owned, cx, |owned| owned.0 = on);
|
||||
}),
|
||||
)
|
||||
.children(rows)
|
||||
}
|
||||
|
||||
fn frosted(cx: &mut App) {
|
||||
let options = WindowOptions {
|
||||
window_bounds: Some(WindowBounds::Windowed(Bounds::centered(
|
||||
None,
|
||||
size(px(560.), px(340.)),
|
||||
cx,
|
||||
))),
|
||||
titlebar: Some(TitlebarOptions {
|
||||
title: Some("Frosted".into()),
|
||||
appears_transparent: true,
|
||||
traffic_light_position: Some(point(px(16.0), px(18.0))),
|
||||
}),
|
||||
window_background: WindowBackgroundAppearance::Blurred,
|
||||
..Default::default()
|
||||
};
|
||||
let handle = cx
|
||||
.open_window(options, |_, cx| cx.new(|_| Frosted))
|
||||
.expect("the frosted window opens");
|
||||
Opened::insert("frosted", handle.into(), cx);
|
||||
}
|
||||
|
||||
/// A window whose sidebar lets the desktop through.
|
||||
struct Frosted;
|
||||
|
||||
impl Render for Frosted {
|
||||
fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
|
||||
let theme = cx.theme();
|
||||
let colors = &theme.colors;
|
||||
div()
|
||||
.size_full()
|
||||
.flex()
|
||||
.font_family(theme.font_family.clone())
|
||||
.text_color(colors.fg)
|
||||
.child(
|
||||
Vibrancy::new()
|
||||
.w(px(180.))
|
||||
.h_full()
|
||||
.pt_12()
|
||||
.px_3()
|
||||
.flex()
|
||||
.flex_col()
|
||||
.gap_1()
|
||||
.children(
|
||||
["Library", "Recents", "Shared"]
|
||||
.map(|name| div().px_2().py_1().child(name)),
|
||||
),
|
||||
)
|
||||
.child(
|
||||
div()
|
||||
.flex_1()
|
||||
.h_full()
|
||||
.p_6()
|
||||
.pt_12()
|
||||
.bg(colors.bg)
|
||||
.border_l_1()
|
||||
.border_color(colors.border)
|
||||
.min_w_0()
|
||||
.text_color(colors.fg_muted)
|
||||
.child(
|
||||
div().child("The sidebar lets the desktop through; this pane stays solid."),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user