T44d Web · What a browser cannot do says why; fonts resolve; the bundle builds

Demos that open a second window, take files, move the window, read the
clipboard or set native menus show a note on the web in the blocked style.
IBM Plex Sans Regular joins the assets, unmodified, where gpui's svg
renderer loads it: gpui_web answers .SystemUIFont with it. The gallery's
web entry registers a Hebrew cut of Noto Sans Hebrew. scripts/web.sh builds
the bundle with wasm-bindgen and wasm-opt -Oz, 20.0 MB, and fails past 25 MiB.
This commit is contained in:
ZacharyZhang-NY committed 2026-09-29 19:16:41 -04:00
1 parent 48c7b09d8d
commit 2cd2ca8bc1
26 files changed
+381 -76

No files matched your search

+2 -1
View File
@@ -12,7 +12,7 @@ use gpui::{App, IntoElement, ParentElement, SharedString, Styled, Window, div, p
use crate::{
probe::probe,
ui::{change, keep, section},
ui::{NO_FILES, change, keep, section, web_note},
};
/// The switchers' demo: the account and workspace in use.
@@ -115,6 +115,7 @@ pub fn profile(window: &mut Window, cx: &mut App) -> impl IntoElement + use<> {
"Someone at a glance, and their profile to edit: Save waits for a change, a name and an email that reads; Discard puts the saved profile back.",
cx,
)
.children(web_note(NO_FILES, cx))
.child(
div()
.flex()
+2 -1
View File
@@ -15,7 +15,7 @@ use web_time::Instant;
use crate::{
probe::probe,
ui::{keep, noise, section, set},
ui::{NO_FILES, keep, noise, section, set, web_note},
};
const SYSTEM: &str = "You answer about color in plain words. Cite sources.";
@@ -160,6 +160,7 @@ pub fn composer(
"Where a message is written: attachments and context above the field, tools below, send at the end; Enter sends and Shift-Enter breaks the line. A slash at the start offers commands, an at sign offers context, and files dropped on it attach.",
cx,
)
.children(web_note(NO_FILES, cx))
.child(probe(
"chat-composer",
div()
+2 -1
View File
@@ -15,7 +15,7 @@ use gpui::{App, IntoElement, ParentElement, SharedString, Styled, Window, div};
use crate::{
probe::probe,
ui::{keep, picture, row, section, set, specimen, specimens},
ui::{NO_FILES, keep, picture, row, section, set, specimen, specimens, web_note},
};
const DUNES: &str = asset!("dunes-square.jpg");
@@ -119,6 +119,7 @@ pub fn avatars(window: &mut Window, cx: &mut App) -> impl IntoElement + use<> {
"A picture, or initials on a tone the name keeps, or an icon. Presence sits on the corner. Hover the last one, then press it to choose a picture, or drop one on it.",
cx,
)
.children(web_note(NO_FILES, cx))
.child(specimens().children(sizes.map(|(size, name)| {
specimen(name, Avatar::new(SharedString::from(format!("avatar-{name}")), "Kofi Mensah").size(size), cx)
})))
+2 -1
View File
@@ -10,7 +10,7 @@ use jiff::Timestamp;
use crate::{
probe::probe,
ui::{change, keep, section},
ui::{NO_FILES, change, keep, section, web_note},
};
pub fn context_menu(cx: &mut App) -> impl IntoElement + use<> {
@@ -84,6 +84,7 @@ pub fn drop_files(window: &mut Window, cx: &mut App) -> impl IntoElement + use<>
"Files dropped in, as forms::DropZone takes them; each lands in the list below.",
cx,
)
.children(web_note(NO_FILES, cx))
.child(probe(
"files-drop",
div()
+2 -1
View File
@@ -5,7 +5,7 @@ use gpui::{App, IntoElement, ParentElement, Styled, Window, div, px};
use crate::{
probe::probe,
ui::{keep, section, set, specimen, specimens},
ui::{NO_FILES, keep, section, set, specimen, specimens, web_note},
};
fn names(paths: &[PathBuf]) -> String {
@@ -44,6 +44,7 @@ pub fn files(window: &mut Window, cx: &mut App) -> impl IntoElement + use<> {
"Click a field or Browse for the system's dialog, or drop files from Finder. A folder, or two files on a one-file target, turns it red.",
cx,
)
.children(web_note(NO_FILES, cx))
.child(
specimens()
.child(specimen(
+2 -1
View File
@@ -10,7 +10,7 @@ use gpui::{App, IntoElement, Keystroke, ParentElement, SharedString, Styled, Win
use super::text::field;
use crate::{
probe::probe,
ui::{code, section},
ui::{NO_FILES, code, section, web_note},
};
pub fn mention(window: &mut Window, cx: &mut App) -> impl IntoElement + use<> {
@@ -99,6 +99,7 @@ pub fn path(window: &mut Window, cx: &mut App) -> impl IntoElement + use<> {
"Type a path, or Browse with the system's dialog.",
cx,
)
.children(web_note(NO_FILES, cx))
.child(probe(
"path",
div()
+5 -1
View File
@@ -9,7 +9,7 @@ use gpui::{App, IntoElement, ParentElement, SharedString, Styled, Window, div, p
use crate::{
probe::probe,
ui::{keep, picture, section, set},
ui::{keep, picture, section, set, web_note},
};
const ATRIUM: &str = asset!("atrium.jpg");
@@ -106,6 +106,10 @@ pub fn upload(window: &mut Window, cx: &mut App) -> impl IntoElement + use<> {
"A picture to send: drop one or browse for it, then crop it. Replace picks another; Remove empties it.",
cx,
)
.children(web_note(
"A browser hands gpui no files: on the web the file dialog fails, drops never arrive, and the picture this starts with, a file on disk, cannot be read.",
cx,
))
.child(probe(
"media-upload",
div().w(px(420.)).child(
+13 -2
View File
@@ -9,16 +9,27 @@ use gpui::{App, IntoElement, ParentElement, Styled, Window, div, px};
use super::rows::{ran, run};
use crate::{
probe::probe,
ui::{section, specimen},
ui::{section, specimen, web_note},
};
pub fn menu_bar(cx: &mut App) -> impl IntoElement + use<> {
let menus = cx.get_menus().expect("the gallery sets its menus in main");
let menus = match cx.get_menus() {
Some(menus) => menus,
None if cfg!(target_family = "wasm") => crate::app_menus()
.into_iter()
.map(gpui::Menu::owned)
.collect(),
None => panic!("the gallery sets its menus in main"),
};
section(
"MenuBar Menu",
"The app's own menus, the ones cx.set_menus gave the system, drawn in the window. Picking a row dispatches its action.",
cx,
)
.children(web_note(
"A browser page has no menu bar, and gpui on the web keeps no cx.set_menus: this bar draws the gallery's own list of the same menus.",
cx,
))
.child(specimen(
"hover moves between menus while one is open",
probe("menubar", MenuBar::new("app-bar", menus)),
@@ -8,7 +8,7 @@ use gpui::{App, Entity, IntoElement, ParentElement, SharedString, Window};
use crate::{
probe::{Opened, probe},
ui::{keep, row, section, set, specimen},
ui::{keep, own_window, row, section, set, specimen},
};
/// Moves `value` to the front of a recent list, keeping `size` entries.
@@ -398,7 +398,7 @@ pub fn search_palette(window: &mut Window, cx: &mut App) -> impl IntoElement + u
))
.child(specimen(
"a window above all others",
probe(
own_window(probe(
"launcher",
Button::new("launcher-button", "Open the launcher")
.variant(ButtonVariant::Ghost)
@@ -415,7 +415,7 @@ pub fn search_palette(window: &mut Window, cx: &mut App) -> impl IntoElement + u
Err(error) => log::error!("gallery: launcher: {error:#}"),
}
}),
),
), cx),
cx,
)),
)
+5 -1
View File
@@ -13,7 +13,7 @@ use gpui::{
use crate::{
probe::probe,
ui::{code, row, section},
ui::{code, row, section, web_note},
};
pub fn boxes(cx: &App) -> impl IntoElement + use<> {
@@ -445,6 +445,10 @@ pub fn clipboard(window: &mut Window, cx: &mut App) -> impl IntoElement + use<>
"write_to_clipboard and read_from_clipboard on App.",
cx,
)
.children(web_note(
"A browser reads its clipboard only as it pastes, into a field: on the web gpui's read_from_clipboard finds nothing, so Paste reports no text. Copy works.",
cx,
))
.child(
row()
.gap_3()
+2 -1
View File
@@ -11,7 +11,7 @@ use ely_gpui_component::{
use gpui::{AnyElement, App, Entity, IntoElement, ParentElement, Styled, div, px};
use super::window::{Fields, Prefs, SIZE};
use crate::ui::change;
use crate::ui::{NO_FILES, change, web_note};
/// The open section's page.
pub(super) fn page(prefs: &Entity<Prefs>, fields: &Fields, section: &str, cx: &App) -> AnyElement {
@@ -198,6 +198,7 @@ fn storage(prefs: &Entity<Prefs>, cx: &App) -> AnyElement {
}),
),
)
.children(web_note(NO_FILES, cx))
.child(
SettingsSection::new("Defaults")
.description("A larger font size shows here.")
+17 -1
View File
@@ -7,7 +7,7 @@ use ely_gpui_component::{
};
use gpui::{App, Div, IntoElement, ParentElement, Styled, Window, div, px};
use crate::ui::{code, row, section, specimen, specimens};
use crate::ui::{code, row, section, specimen, specimens, web_note};
/// A window drawn inside the page.
pub fn window_frame(width: f32, height: f32, cx: &App) -> Div {
@@ -116,6 +116,10 @@ pub fn window_controls(cx: &App) -> impl IntoElement + use<> {
"Minimize and zoom act on this window. Close here only logs.",
cx,
))
.children(web_note(
"A browser owns the page's window: gpui on the web only logs minimize and zoom.",
cx,
))
}
pub fn drag_area(window: &mut Window, cx: &mut App) -> impl IntoElement + use<> {
@@ -142,6 +146,10 @@ pub fn drag_area(window: &mut Window, cx: &mut App) -> impl IntoElement + use<>
.child("Double-click to zoom this window"),
)
.child(code("drag_region(id, window, cx)", cx))
.children(web_note(
"A browser owns the page's window: gpui on the web neither moves nor zooms it.",
cx,
))
}
pub fn resize_border(cx: &App) -> impl IntoElement + use<> {
@@ -154,6 +162,10 @@ pub fn resize_border(cx: &App) -> impl IntoElement + use<> {
"Linux draws its own edges. This macOS window keeps the system's, so the border lays out only.",
))
.child(code("ResizeBorder::new().child(app)", cx))
.children(web_note(
"A browser sizes the page's canvas itself: gpui on the web resizes no window from its edges.",
cx,
))
}
pub fn menus(cx: &App) -> impl IntoElement + use<> {
@@ -177,4 +189,8 @@ pub fn menus(cx: &App) -> impl IntoElement + use<> {
.child(Caption::new(
"MenuBar draws the same menus inside the window. It lands with Menus, chapter 8.",
))
.children(web_note(
"A browser page has no menu bar and no Dock: gpui on the web keeps neither cx.set_menus nor cx.set_dock_menu.",
cx,
))
}
+23 -17
View File
@@ -11,7 +11,7 @@ use gpui::{App, IntoElement, ParentElement, Styled, Window, div};
use super::chrome::window_frame;
use crate::{
probe::{Opened, probe},
ui::{row, section, specimen},
ui::{own_window, row, section, specimen},
};
fn log_action(name: &'static str) -> impl Fn(&mut Window, &mut App) + 'static {
@@ -59,14 +59,17 @@ pub fn update_window(cx: &App) -> impl IntoElement + use<> {
.child(update_dialog().on_later(log_action("later"))),
cx,
))
.child(probe(
"update-open",
Button::new("update-open", "Open update window")
.variant(ButtonVariant::Outline)
.on_click(|_, _, cx| match update_dialog().open(cx) {
Ok(handle) => Opened::insert("update", handle.into(), cx),
Err(error) => log::error!("gallery: update window failed: {error:#}"),
}),
.child(own_window(
probe(
"update-open",
Button::new("update-open", "Open update window")
.variant(ButtonVariant::Outline)
.on_click(|_, _, cx| match update_dialog().open(cx) {
Ok(handle) => Opened::insert("update", handle.into(), cx),
Err(error) => log::error!("gallery: update window failed: {error:#}"),
}),
),
cx,
))
}
@@ -101,14 +104,17 @@ pub fn crash_reporter(cx: &App) -> impl IntoElement + use<> {
.child(reporter(true)),
cx,
))
.child(probe(
"crash-open",
Button::new("crash-open", "Open crash window")
.variant(ButtonVariant::Outline)
.on_click(move |_, _, cx| match reporter(false).open(cx) {
Ok(handle) => Opened::insert("crash", handle.into(), cx),
Err(error) => log::error!("gallery: crash window failed: {error:#}"),
}),
.child(own_window(
probe(
"crash-open",
Button::new("crash-open", "Open crash window")
.variant(ButtonVariant::Outline)
.on_click(move |_, _, cx| match reporter(false).open(cx) {
Ok(handle) => Opened::insert("crash", handle.into(), cx),
Err(error) => log::error!("gallery: crash window failed: {error:#}"),
}),
),
cx,
))
}
+14 -2
View File
@@ -7,7 +7,7 @@ use gpui::{App, IntoElement, ParentElement, SharedString, Window};
use crate::{
probe::probe,
ui::{blocked, row, section},
ui::{blocked, row, section, web_note},
};
const ITEMS: [&str; 3] = ["Open gallery", "Toggle theme", "Quit"];
@@ -23,6 +23,10 @@ pub fn tray(window: &mut Window, cx: &mut App) -> impl IntoElement + use<> {
"An SF Symbol in the menu bar with a menu. macOS only.",
cx,
)
.children(web_note(
"A browser page has no menu bar to hold an icon, so showing one fails and logs why.",
cx,
))
.child(
row()
.child(probe(
@@ -113,6 +117,10 @@ pub fn dock(cx: &mut App) -> impl IntoElement + use<> {
"A count on the app's Dock icon. macOS only.",
cx,
)
.children(web_note(
"A browser page has no Dock icon to badge, so setting one fails and logs why.",
cx,
))
.child(
row()
.child(probe(
@@ -138,7 +146,11 @@ pub fn notification(cx: &App) -> impl IntoElement + use<> {
cx,
)
.child(blocked(
"Not yet shown: gpui posts a system notification only from an app bundle, and the gallery runs unbundled.",
if cfg!(target_family = "wasm") {
"Not shown: gpui on the web posts no system notification."
} else {
"Not yet shown: gpui posts a system notification only from an app bundle, and the gallery runs unbundled."
},
cx,
))
}
+2 -1
View File
@@ -4,7 +4,7 @@ use ely_gpui_component::{
};
use gpui::{App, IntoElement, ParentElement, SharedString, Styled, Window, div, px};
use crate::ui::{change, keep, section, specimen, specimens};
use crate::ui::{NO_FILES, change, keep, section, specimen, specimens, web_note};
/// Which code palette the demo last chose.
struct Chosen(SharedString);
@@ -17,6 +17,7 @@ pub fn importing(window: &mut Window, cx: &mut App) -> impl IntoElement + use<>
"A VS Code color theme dropped here reads into Ely's palette, the colors it leaves out kept from Ely's; Apply sets it on the whole gallery. Code palettes choose the colors of code for the mode shown.",
cx,
)
.children(web_note(NO_FILES, cx))
.child(
specimens()
.child(specimen(
+13 -9
View File
@@ -14,7 +14,7 @@ use gpui::{
use crate::{
probe::{Opened, probe},
ui::{change, keep, section, specimen, specimens},
ui::{change, keep, native_only, section, specimen, specimens},
};
const PLATFORMS: [(Platform, &str); 3] = [
@@ -38,10 +38,14 @@ pub fn platform(window: &mut Window, cx: &mut App) -> impl IntoElement + use<> {
.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)),
native_only(
probe(
"frosted-open",
Button::new("frosted-open", "Open a frosted window")
.on_click(|_, _, cx| frosted(cx)),
),
"A browser page is a single window, and gpui leaves what lies behind it to the browser, so no frosted window opens and nothing blurs through.",
cx,
),
cx,
)),
@@ -141,10 +145,10 @@ fn frosted(cx: &mut App) {
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);
match cx.open_window(options, |_, cx| cx.new(|_| Frosted)) {
Ok(handle) => Opened::insert("frosted", handle.into(), cx),
Err(error) => log::error!("gallery: frosted window failed: {error:#}"),
}
}
/// A window whose sidebar lets the desktop through.