diff --git a/AGENTS.md b/AGENTS.md index 43afe2f..d281d30 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -22,6 +22,7 @@ Ely GPUI Component. A component library for GPUI, in light and dark. - `cargo run --example gallery` opens the gallery. `-- --page ` starts on a page. - `cargo run --example gallery -- --capture ` writes PNGs of every page, light and dark, top to bottom, then each page's scripted states, including windows the demos open. macOS only. +- `cargo run --example gallery -- --narrow 280 --capture ` lays each page, header and body, at that width in a padded card and shoots it without its script, whose aims are measured at full width. Demos that set their own width run past the card. - `cargo test --lib --features test-support`, `cargo clippy --all-targets --features test-support -- -D warnings`, `cargo fmt --check`. `scripts/check.sh` runs them with the house rules. - `rm -rf target/debug/incremental` and `cargo clean -p ely-gpui-component` after each task item keep the disk lean. Cargo keeps every old build of the crate and its tests under a new hash; by T25 they had filled the disk. - `scripts/icons.sh ...` adds icons. Then add a line to `IconName` in `src/primitives/icon.rs`. @@ -111,7 +112,7 @@ Ely GPUI Component. A component library for GPUI, in light and dark. - Trackpad momentum arrives as `TouchPhase::Moved` after `Ended`, so a gesture acts only between `Started` and `Ended` (`lists::SwipeableListItem`). - Quartz scroll events carry no window. The harness hands them to the window itself, placed in window points (`Step::Swipe`). - A chevron that opens and closes is `primitives::Disclosure`. -- `uniform_list` does not stretch its rows; each row sets `w_full`, or `min_w_full` when the same row also sits in a flex column, where it stretches (`tables::DataTable`). +- `uniform_list` does not stretch its rows; each row sets `w_full`, or `min_w_full` when the same row also sits in a flex column, where it stretches (`tables::DataTable`). gpui's `list` lays rows at their content's width too; `chat::MessageList` boxes each row at the list's width. - Chapters import only earlier chapters, so a select of tree nodes lives in `lists` (`TreeSelect`) and reaches `forms::listing`. - Script clicks aim at a probe's corner, so a scripted target must fit in the window; a tall probe puts its top off screen. The log names each probe's bounds as the script aims, and a probe around content with no width of its own measures smaller than what it draws, so a scripted demo sets its width. - `scripts/check.sh` fails by its exit status; a pipe into `tail` hides it. @@ -152,7 +153,7 @@ Ely GPUI Component. A component library for GPUI, in light and dark. - A row that holds text beside fixed parts lets the text give way: the text takes `flex_1().min_w_0()` and an `Ellipsis`; counts, icons, dates and chevrons take `flex_none`. A label that must stay whole wraps in that block instead, as `forms::Checkbox`'s does. - A mark over a text field reads the field at paint time, from a canvas laid over it (`collab::RemoteCursor`): by then `TextInput::bounds_for` holds this frame's layout, and a still page never renders again to catch up. - A callback field holds a named `type` alias; clippy's type_complexity rejects `Option>`. A chapter shares one alias per shape. -- A component that fills its container takes no width on its root: a block or a flex column stretches it. Percents fill badly in taffy 0.9. `w_full` in a flex column that a block measures by content keeps its content's width: taffy lays the column out once at unknown width and keeps that layout when the width comes out the same. `min_w_full` resolves against a block's outer width, padding and all (`forms::FormField`). In a flex row the host gives it `flex_1`; as a window's root it sits in a `size_full` box. Roots made before T30d still say `w_full`; T44 takes it off. +- A component that fills its container takes no width on its root: a block or a flex column stretches it. Percents fill badly in taffy 0.9. `w_full` in a flex column that a block measures by content keeps its content's width: taffy lays the column out once at unknown width and keeps that layout when the width comes out the same. `min_w_full` resolves against a block's outer width, padding and all (`forms::FormField`). In a flex row the host gives it `flex_1`; as a window's root it sits in a `size_full` box. A root centered under a cap keeps `w_full`, since `mx_auto` needs a width to fill (`layout::Container`). A row that hands a text field a `flex_1` share keeps `w_full` too: stretched without a width, taffy 0.9 can keep a pass that laid the share at no width, and the field draws nothing (`forms::Input`, `InputGroup`, `TagInput`). - A field's `Highlight` sets color, wash, weight, slant and strike per span; measuring and painting share one set of runs, so wrapped heights match. - A block editor keeps one undo for the document: text and structure together, as snapshots through `forms::History`; it takes Undo and Redo before its fields do. - gpui calls focus listeners only while the window is active. A test that needs focus events activates its window with `window.activate_window()`. diff --git a/TASKS.md b/TASKS.md index 5440b4c..5f29fff 100644 --- a/TASKS.md +++ b/TASKS.md @@ -150,7 +150,7 @@ Per-component lines live in `tasks/`. Tags there: - [x] T43a Tooling · Workbench — `tasks/ch31-43.md` - [x] T43b Tooling · Inspection — `tasks/ch31-43.md` - [x] T43c Tooling · Catalogs — `tasks/ch31-43.md` -- [ ] T44a Capture · Roots: roots still on `w_full` drop it; every section checked at 280px and in a padded card +- [ ] T44a Capture · Roots: roots still on `w_full` drop it, checked at 280px and in padded cards - [ ] T44b Capture · Sections: every component's section shot on its own, light and dark, with a manifest the site reads - [ ] T44c Capture · Motion: clips of each page's scripted states in motion, for the site - [ ] T45 Website: `frontend/`, Vite 8, pnpm, light and dark: a home page in motion (three.js, smooth scroll), and a components page with every component, categories on the left and the chosen one's detail on the right, after astryx.atmeta.com diff --git a/examples/gallery/capture.rs b/examples/gallery/capture.rs index bfaa854..97fcab8 100644 --- a/examples/gallery/capture.rs +++ b/examples/gallery/capture.rs @@ -15,11 +15,17 @@ use crate::{ const SETTLE: Duration = Duration::from_millis(700); const SCROLL_SETTLE: Duration = Duration::from_millis(250); -/// Shoots one page, or all, in both modes, then quits. Exits 1 on failure. -pub fn run(window: WindowHandle, dir: PathBuf, only: Option, cx: &mut App) { +/// Shoots one page, or all, in both modes, then quits; exits 1 on failure. +pub fn run( + window: WindowHandle, + dir: PathBuf, + only: Option, + scripted: bool, + cx: &mut App, +) { Theme::update(cx, |theme| theme.reduced_motion = true); cx.spawn(async move |cx| { - let outcome = shoot_all(window, &dir, only, cx).await; + let outcome = shoot_all(window, &dir, only, scripted, cx).await; if let Err(error) = outcome.and_then(|()| cx.update(|cx| cx.quit())) { log::error!("capture failed: {error:#}"); std::process::exit(1); @@ -32,6 +38,7 @@ async fn shoot_all( window: WindowHandle, dir: &Path, only: Option, + scripted: bool, cx: &mut AsyncApp, ) -> Result<()> { std::fs::create_dir_all(dir).with_context(|| format!("create {}", dir.display()))?; @@ -70,7 +77,7 @@ async fn shoot_all( window.update(cx, |gallery, _, cx| gallery.scroll_to(offset, cx))?; cx.background_executor().timer(SCROLL_SETTLE).await; } - if !page.script.is_empty() { + if scripted && !page.script.is_empty() { window.update(cx, |gallery, _, cx| gallery.select(ix, cx))?; cx.background_executor().timer(SETTLE).await; let shot = |step: &str| dir.join(format!("{}-{step}-{name}.png", page.slug)); diff --git a/examples/gallery/main.rs b/examples/gallery/main.rs index bb66b3f..afaa3da 100644 --- a/examples/gallery/main.rs +++ b/examples/gallery/main.rs @@ -68,12 +68,14 @@ fn choose(window: WindowHandle, choice: shell::Choice, cx: &mut struct Args { page: Option, capture: Option, + narrow: Option, } fn parse_args() -> Result { let mut args = Args { page: None, capture: None, + narrow: None, }; let mut iter = std::env::args().skip(1); while let Some(flag) = iter.next() { @@ -85,6 +87,13 @@ fn parse_args() -> Result { args.page = Some(pages::find(&value).with_context(|| format!("no page {value}"))?) } "--capture" => args.capture = Some(PathBuf::from(value)), + "--narrow" => { + args.narrow = Some( + value + .parse() + .with_context(|| format!("bad width {value}"))?, + ) + } other => bail!("unknown flag {other}"), } } @@ -118,13 +127,15 @@ fn main() -> Result<()> { }; let window = cx .open_window(options, |window, cx| { - cx.new(|cx| shell::Gallery::new(args.page.unwrap_or(0), window, cx)) + cx.new(|cx| { + shell::Gallery::new(args.page.unwrap_or(0), args.narrow, window, cx) + }) }) .expect("gallery window failed to open"); menu_actions(window, cx); cx.activate(true); if let Some(dir) = args.capture { - capture::run(window, dir, args.page, cx); + capture::run(window, dir, args.page, args.narrow.is_none(), cx); } }); Ok(()) diff --git a/examples/gallery/pages/forms/mod.rs b/examples/gallery/pages/forms/mod.rs index e2076ab..04bc253 100644 --- a/examples/gallery/pages/forms/mod.rs +++ b/examples/gallery/pages/forms/mod.rs @@ -114,7 +114,6 @@ const SCRIPT: &[Step] = &[ Step::Shot("hotkey"), Step::DownAt("path", 380.0, 16.0), Step::UpAt("path", 380.0, 16.0), - Step::Wait(1200), Step::CancelPanel, Step::Wait(600), Step::DownAt("checks", 40.0, 66.0), @@ -242,7 +241,6 @@ const SCRIPT: &[Step] = &[ Step::Shot("gradient"), Step::DownAt("file-one", 100.0, 14.0), Step::UpAt("file-one", 100.0, 14.0), - Step::Wait(1200), Step::CancelPanel, Step::Wait(600), Step::Shot("files"), diff --git a/examples/gallery/script.rs b/examples/gallery/script.rs index a0d90f4..1c1a774 100644 --- a/examples/gallery/script.rs +++ b/examples/gallery/script.rs @@ -53,6 +53,8 @@ pub enum Step { } const FRAME: Duration = Duration::from_millis(120); +/// How long an out-of-process file panel may take to open. +const PANEL: Duration = Duration::from_secs(10); const DRAG_STEPS: u32 = 10; #[derive(Clone, Copy)] @@ -218,7 +220,15 @@ pub async fn play( let number = window.update(cx, |_, window, _| number(window))??; post_key(number, true, text, code)?; } - Step::CancelPanel => cancel_panel()?, + Step::CancelPanel => { + let mut waited = Duration::ZERO; + while !cancel_panel()? { + anyhow::ensure!(waited < PANEL, "no file panel became key in {PANEL:?}"); + cx.background_executor().timer(FRAME).await; + waited += FRAME; + } + log::info!("script: file panel cancelled after {waited:?}"); + } Step::ExpectClosed(key) => { let handle = opened(key, cx)?; let open = cx.update(|cx| cx.windows().contains(&handle))?; @@ -363,7 +373,8 @@ fn post_key(_: u32, _: bool, _: &str, _: u16) -> Result<()> { } #[cfg(target_os = "macos")] -fn cancel_panel() -> Result<()> { +/// Cancels a key file panel; false while none is key. +fn cancel_panel() -> Result { use cocoa::{ appkit::NSApp, base::{BOOL, NO, id, nil}, @@ -371,16 +382,20 @@ fn cancel_panel() -> Result<()> { use objc::{class, msg_send, sel, sel_impl}; unsafe { let key: id = msg_send![NSApp(), keyWindow]; - anyhow::ensure!(key != nil, "no key window to cancel"); + if key == nil { + return Ok(false); + } let panel: BOOL = msg_send![key, isKindOfClass: class!(NSSavePanel)]; - anyhow::ensure!(panel != NO, "the key window is not a file panel"); + if panel == NO { + return Ok(false); + } let _: () = msg_send![key, cancel: nil]; } - Ok(()) + Ok(true) } #[cfg(not(target_os = "macos"))] -fn cancel_panel() -> Result<()> { +fn cancel_panel() -> Result { anyhow::bail!("file panels need macOS") } diff --git a/examples/gallery/shell.rs b/examples/gallery/shell.rs index 7ec440e..77e8184 100644 --- a/examples/gallery/shell.rs +++ b/examples/gallery/shell.rs @@ -5,9 +5,9 @@ use ely_gpui_component::{ theme::{ActiveTheme, ControlSize, Mode, Radius, TextSize, Theme}, }; use gpui::{ - Bounds, Context, FocusHandle, FontWeight, InteractiveElement, IntoElement, ParentElement, - Pixels, Render, ScrollHandle, SharedString, StatefulInteractiveElement, Styled, Subscription, - Window, div, point, prelude::*, px, + AnyElement, App, Bounds, Context, FocusHandle, FontWeight, InteractiveElement, IntoElement, + ParentElement, Pixels, Render, ScrollHandle, SharedString, StatefulInteractiveElement, Styled, + Subscription, Window, div, point, prelude::*, px, }; use crate::pages; @@ -26,11 +26,18 @@ pub struct Gallery { choice: Choice, focus: FocusHandle, scroll: ScrollHandle, + /// Narrow check width, if any. + narrow: Option, _appearance: Subscription, } impl Gallery { - pub fn new(page: usize, window: &mut Window, cx: &mut Context) -> Self { + pub fn new( + page: usize, + narrow: Option, + window: &mut Window, + cx: &mut Context, + ) -> Self { let appearance = cx.observe_window_appearance(window, |gallery, window, cx| { if gallery.choice == Choice::System { Theme::set_mode(window.appearance().into(), cx); @@ -44,6 +51,7 @@ impl Gallery { choice: Choice::Light, focus, scroll: ScrollHandle::new(), + narrow: narrow.map(px), _appearance: appearance, } } @@ -174,6 +182,7 @@ impl Gallery { ]; let colors = &cx.theme().colors; div() + .flex_none() .flex() .gap_0p5() .p_0p5() @@ -198,6 +207,24 @@ impl Gallery { } } +impl Gallery { + /// Header and body; a padded card when narrow. + fn card(&self, header: impl IntoElement, body: AnyElement, cx: &App) -> AnyElement { + let content = div().child(header).child(body); + match self.narrow { + // Width plus padding and hairlines. + Some(width) => div() + .w(width + px(34.0)) + .p_4() + .border_1() + .border_color(cx.theme().colors.border) + .child(content) + .into_any_element(), + None => content.into_any_element(), + } + } +} + impl Render for Gallery { fn render(&mut self, window: &mut Window, cx: &mut Context) -> impl IntoElement { let page = &pages::ALL[self.page]; @@ -229,32 +256,38 @@ impl Render for Gallery { .pt(px(56.0)) .pb(px(96.0)) .child( - div() - .flex() - .items_start() - .justify_between() - .gap_6() - .child( - div() - .flex() - .flex_col() - .gap_2() - .child( - div() - .text_size(theme.text_size(TextSize::Xxl)) - .font_weight(FontWeight::SEMIBOLD) - .child(page.title), - ) - .child( - div() - .text_size(theme.text_size(TextSize::Md)) - .text_color(colors.fg_muted) - .child(page.summary), - ), - ) - .child(switcher), - ) - .child(body), + self.card( + div() + .flex() + .flex_wrap() + .items_start() + .justify_between() + .gap_6() + .child( + div() + .flex_1() + .min_w(px(200.0)) + .flex() + .flex_col() + .gap_2() + .child( + div() + .text_size(theme.text_size(TextSize::Xxl)) + .font_weight(FontWeight::SEMIBOLD) + .child(page.title), + ) + .child( + div() + .text_size(theme.text_size(TextSize::Md)) + .text_color(colors.fg_muted) + .child(page.summary), + ), + ) + .child(switcher), + body, + cx, + ), + ), ), ) } diff --git a/src/agent/changes.rs b/src/agent/changes.rs index 0946f8a..380392e 100644 --- a/src/agent/changes.rs +++ b/src/agent/changes.rs @@ -119,7 +119,6 @@ impl RenderOnce for FileChangeCard { let theme = cx.theme(); let colors = theme.colors.clone(); div() - .w_full() .rounded(theme.radius(Radius::Md)) .border_1() .border_color(colors.border) @@ -270,7 +269,6 @@ impl RenderOnce for MultiFileDiffReview { ) }); div() - .w_full() .flex() .flex_col() .gap_2() diff --git a/src/agent/control.rs b/src/agent/control.rs index 10d7472..8c18f22 100644 --- a/src/agent/control.rs +++ b/src/agent/control.rs @@ -88,7 +88,6 @@ impl RenderOnce for HumanInputRequest { let theme = cx.theme(); let colors = theme.colors.clone(); div() - .w_full() .flex() .flex_col() .gap_3() @@ -177,7 +176,6 @@ impl RenderOnce for CostBreakdown { ) }); div() - .w_full() .flex() .flex_col() .gap_3() diff --git a/src/agent/environment.rs b/src/agent/environment.rs index 75615ea..a301894 100644 --- a/src/agent/environment.rs +++ b/src/agent/environment.rs @@ -117,7 +117,6 @@ impl RenderOnce for SandboxStatus { let live = matches!(self.state, SandboxState::Starting | SandboxState::Busy); let color = self.state.color(&colors); div() - .w_full() .flex() .flex_col() .gap_3() diff --git a/src/agent/memory.rs b/src/agent/memory.rs index 957ed64..457dfc3 100644 --- a/src/agent/memory.rs +++ b/src/agent/memory.rs @@ -84,7 +84,6 @@ impl RenderOnce for MemoryPanel { ) }); div() - .w_full() .flex() .flex_col() .gap_3() diff --git a/src/agent/permission.rs b/src/agent/permission.rs index a02a0d9..a11b2c6 100644 --- a/src/agent/permission.rs +++ b/src/agent/permission.rs @@ -137,7 +137,6 @@ impl RenderOnce for PermissionPrompt { }) }; div() - .w_full() .flex() .flex_col() .gap_3() diff --git a/src/agent/progress.rs b/src/agent/progress.rs index 95b1d25..e5cf462 100644 --- a/src/agent/progress.rs +++ b/src/agent/progress.rs @@ -118,7 +118,6 @@ impl RenderOnce for AgentPlan { .filter(|(_, state)| *state == StepState::Done) .count(); div() - .w_full() .flex() .flex_col() .gap_2() @@ -284,7 +283,6 @@ impl RenderOnce for AgentProgress { let theme = cx.theme(); let colors = theme.colors.clone(); div() - .w_full() .flex() .flex_col() .gap_2() diff --git a/src/agent/registry.rs b/src/agent/registry.rs index 1064d94..1c35a0e 100644 --- a/src/agent/registry.rs +++ b/src/agent/registry.rs @@ -112,7 +112,6 @@ impl RenderOnce for ToolRegistry { let groups = grouped(&self.tools, &found(&self.tools, &self.query)); let empty = groups.is_empty(); div() - .w_full() .flex() .flex_col() .gap_4() diff --git a/src/agent/tools.rs b/src/agent/tools.rs index 19e7018..af6b807 100644 --- a/src/agent/tools.rs +++ b/src/agent/tools.rs @@ -109,7 +109,6 @@ impl RenderOnce for ToolCallCard { .child(text) }; div() - .w_full() .rounded(theme.radius(Radius::Md)) .border_1() .border_color(colors.border) @@ -217,7 +216,6 @@ impl RenderOnce for ToolCallGroup { let theme = cx.theme(); let colors = theme.colors.clone(); div() - .w_full() .flex() .flex_col() .gap_2() diff --git a/src/calendar/agenda.rs b/src/calendar/agenda.rs index 9f37370..7b50122 100644 --- a/src/calendar/agenda.rs +++ b/src/calendar/agenda.rs @@ -142,7 +142,6 @@ impl RenderOnce for AgendaView { if owners.is_empty() { return div() .debug_selector(|| "agenda-none".into()) - .w_full() .py_6() .flex() .justify_center() @@ -172,7 +171,6 @@ impl RenderOnce for AgendaView { }) }; div() - .w_full() .child( sections .selected(picked.read(cx).clone()) diff --git a/src/calendar/allday.rs b/src/calendar/allday.rs index 3810ffc..b024688 100644 --- a/src/calendar/allday.rs +++ b/src/calendar/allday.rs @@ -119,7 +119,6 @@ impl RenderOnce for AllDayRow { }); div() .relative() - .w_full() .h(pad * 2.0 + pitch * lanes as f32 - gap) .border_b_1() .border_color(theme.colors.border) diff --git a/src/calendar/chip.rs b/src/calendar/chip.rs index e963b5c..c39fc45 100644 --- a/src/calendar/chip.rs +++ b/src/calendar/chip.rs @@ -93,7 +93,6 @@ impl RenderOnce for EventChip { .flex() .items_center() .gap_1() - .w_full() .h(theme.calendar().chip) .px_1p5() .rounded(round) diff --git a/src/calendar/month.rs b/src/calendar/month.rs index 224eb3d..1f2c7bf 100644 --- a/src/calendar/month.rs +++ b/src/calendar/month.rs @@ -420,7 +420,6 @@ impl RenderOnce for CalendarMonthView { .collect(); let title = shown.strftime("%B %Y").to_string(); div() - .w_full() .flex() .flex_col() .gap_3() diff --git a/src/calendar/people.rs b/src/calendar/people.rs index e0e32cd..77a242f 100644 --- a/src/calendar/people.rs +++ b/src/calendar/people.rs @@ -173,7 +173,6 @@ impl RenderOnce for AttendeeList { }) .collect(); div() - .w_full() .flex() .flex_col() .gap_1() diff --git a/src/calendar/year.rs b/src/calendar/year.rs index 827486f..6f0f806 100644 --- a/src/calendar/year.rs +++ b/src/calendar/year.rs @@ -300,7 +300,6 @@ impl RenderOnce for YearView { }) .collect(); div() - .w_full() .flex() .flex_col() .gap_4() diff --git a/src/chat/actions.rs b/src/chat/actions.rs index 0c10dd7..b2be2f8 100644 --- a/src/chat/actions.rs +++ b/src/chat/actions.rs @@ -74,7 +74,6 @@ impl RenderOnce for QuoteReply { let colors = theme.colors.clone(); let line = self.text.lines().next().unwrap_or_default().to_string(); div() - .w_full() .flex() .items_center() .gap_2() @@ -261,7 +260,6 @@ impl RenderOnce for MessageEditor { self.on_cancel, ); div() - .w_full() .flex() .flex_col() .gap_2() diff --git a/src/chat/cite.rs b/src/chat/cite.rs index da203d0..a1d0f50 100644 --- a/src/chat/cite.rs +++ b/src/chat/cite.rs @@ -105,7 +105,6 @@ impl RenderOnce for SourceCard { let open = self.on_open; div() .id(self.id.clone()) - .w_full() .p_2p5() .rounded(theme.radius(Radius::Md)) .border_1() @@ -222,7 +221,6 @@ impl RenderOnce for SourceList { .take(3) .collect(); div() - .w_full() .flex() .flex_col() .gap_2() diff --git a/src/chat/code.rs b/src/chat/code.rs index 44d98d4..59fb5e8 100644 --- a/src/chat/code.rs +++ b/src/chat/code.rs @@ -94,7 +94,6 @@ impl RenderOnce for CodeBlock { let lines = code.lines().count(); let toggle = open.clone(); div() - .w_full() .flex() .flex_col() .rounded(theme.radius(Radius::Md)) diff --git a/src/chat/conversations.rs b/src/chat/conversations.rs index b8cb0e5..5a681bc 100644 --- a/src/chat/conversations.rs +++ b/src/chat/conversations.rs @@ -179,7 +179,6 @@ impl RenderOnce for ConversationItem { .id(self.id.clone()) .group(group.clone()) .track_focus(&focus) - .w_full() .flex() .items_center() .gap_1() diff --git a/src/chat/list.rs b/src/chat/list.rs index 8f45771..e634204 100644 --- a/src/chat/list.rs +++ b/src/chat/list.rs @@ -105,7 +105,16 @@ impl RenderOnce for MessageList { div() .relative() .size_full() - .child(list(state, move |ix, window, cx| render(ix, window, cx)).size_full()) + // gpui's list lays rows at content width. + .child( + list(state, move |ix, window, cx| { + div() + .w_full() + .child(render(ix, window, cx)) + .into_any_element() + }) + .size_full(), + ) .child( canvas( move |_, window, cx| { @@ -234,8 +243,10 @@ impl RenderOnce for DateSeparator { let theme = cx.theme(); let colors = theme.colors.clone(); let rule = || div().flex_1().h_px().bg(colors.border); + let name = day_name(self.day, self.today); + let shown = format!("date-separator-{name}"); div() - .w_full() + .debug_selector(move || shown) .flex() .items_center() .gap_3() @@ -245,7 +256,7 @@ impl RenderOnce for DateSeparator { div() .text_size(theme.text_size(TextSize::Xs)) .text_color(colors.fg_subtle) - .child(day_name(self.day, self.today)), + .child(name), ) .child(rule()) } diff --git a/src/chat/media.rs b/src/chat/media.rs index 66b1111..90f24db 100644 --- a/src/chat/media.rs +++ b/src/chat/media.rs @@ -72,7 +72,6 @@ impl RenderOnce for ImageMessage { let widest = theme.prose_width().to_pixels(window.rem_size()); let open = self.on_open; div() - .w_full() .flex() .flex_col() .gap_1() @@ -235,7 +234,6 @@ impl RenderOnce for FileMessage { let theme = cx.theme(); let colors = theme.colors.clone(); div() - .w_full() .max_w(theme.prose_width()) .flex() .items_center() @@ -339,7 +337,6 @@ impl RenderOnce for LinkPreviewCard { let open = self.on_open; div() .id(self.id.clone()) - .w_full() .max_w(theme.container_width(ContainerSize::Sm)) .flex() .gap_3() diff --git a/src/chat/params.rs b/src/chat/params.rs index 22b787c..ebb1df0 100644 --- a/src/chat/params.rs +++ b/src/chat/params.rs @@ -81,7 +81,6 @@ impl RenderOnce for ParameterPanel { let theme = cx.theme(); let colors = theme.colors.clone(); div() - .w_full() .flex() .flex_col() .gap_4() @@ -274,7 +273,6 @@ impl RenderOnce for SystemPromptEditor { fn render(self, _: &mut Window, cx: &mut App) -> impl IntoElement { let theme = cx.theme(); div() - .w_full() .flex() .flex_col() .gap_2() diff --git a/src/chat/play.rs b/src/chat/play.rs index 93f5c6a..1f55ff5 100644 --- a/src/chat/play.rs +++ b/src/chat/play.rs @@ -97,7 +97,6 @@ impl RenderOnce for AudioMessage { let playing = self.playing; let tall = theme.control_height(ControlSize::Md); div() - .w_full() .max_w(theme.prose_width()) .flex() .items_center() diff --git a/src/chat/projects.rs b/src/chat/projects.rs index dd0be47..5879947 100644 --- a/src/chat/projects.rs +++ b/src/chat/projects.rs @@ -62,7 +62,6 @@ impl RenderOnce for ProjectList { let theme = cx.theme(); let colors = theme.colors.clone(); div() - .w_full() .flex() .flex_col() .gap_0p5() @@ -163,7 +162,6 @@ impl RenderOnce for ProjectKnowledgePanel { let used: u64 = self.files.iter().map(|(_, bytes)| bytes).sum(); let share = used as f32 / self.capacity as f32; div() - .w_full() .flex() .flex_col() .gap_3() diff --git a/src/chat/search.rs b/src/chat/search.rs index 7bb9270..a5818dd 100644 --- a/src/chat/search.rs +++ b/src/chat/search.rs @@ -164,7 +164,6 @@ impl RenderOnce for WebResultCard { let open = self.on_open; div() .id(self.id.clone()) - .w_full() .flex() .flex_col() .gap_0p5() @@ -273,7 +272,6 @@ impl RenderOnce for DocumentChunkPreview { ..HighlightStyle::default() }; div() - .w_full() .flex() .flex_col() .gap_1p5() diff --git a/src/chat/status.rs b/src/chat/status.rs index 6200576..5dc4258 100644 --- a/src/chat/status.rs +++ b/src/chat/status.rs @@ -112,7 +112,6 @@ impl RenderOnce for RateLimitNotice { None => countdown, }; div() - .w_full() .flex() .items_center() .gap_3() @@ -198,7 +197,6 @@ impl RenderOnce for FeedbackForm { let ready = !self.picked.is_empty() || !self.note.read(cx).text().trim().is_empty(); let (pick, send) = (self.on_pick, self.on_send); div() - .w_full() .flex() .flex_col() .gap_3() @@ -356,7 +354,6 @@ impl RenderOnce for ThinkingBlock { ThinkingDuration::new(self.took).into_any_element() }; div() - .w_full() .flex() .flex_col() .gap_2() diff --git a/src/chat/tests/mod.rs b/src/chat/tests/mod.rs index 161f05c..c98c2a7 100644 --- a/src/chat/tests/mod.rs +++ b/src/chat/tests/mod.rs @@ -13,7 +13,8 @@ mod history; mod welcome; use super::{ - ImageMessage, MessageAvatar, MessageBubble, MessageEditor, MessageList, Role, ThinkingBlock, + DateSeparator, ImageMessage, MessageAvatar, MessageBubble, MessageEditor, MessageList, Role, + ThinkingBlock, }; use crate::{forms, forms::TextInput, theme::Theme}; @@ -361,3 +362,29 @@ fn the_reasoning_opens_from_the_keyboard(cx: &mut TestAppContext) { "Tab and Space open it: {closed:?} to {open:?}" ); } + +struct Dated; + +impl Render for Dated { + fn render(&mut self, _: &mut Window, _: &mut Context) -> impl IntoElement { + let day = jiff::civil::date(2026, 9, 28); + div() + .size_full() + .child(MessageList::new("dated", 1, move |_, _, _| { + DateSeparator::new(day, day).into_any_element() + })) + } +} + +/// A row no wider than its words still spans the list. +#[gpui::test] +fn a_narrow_row_spans_the_list(cx: &mut TestAppContext) { + cx.update(Theme::init); + let (_, cx) = cx.add_window_view(|_, _| Dated); + settle(cx); + let row = cx + .debug_bounds("date-separator-Today") + .expect("the separator draws"); + let width = cx.update(|window, _| window.viewport_size().width); + assert_eq!(row.size.width, width); +} diff --git a/src/chat/welcome.rs b/src/chat/welcome.rs index 1abb198..3be4ea6 100644 --- a/src/chat/welcome.rs +++ b/src/chat/welcome.rs @@ -180,7 +180,6 @@ impl RenderOnce for FollowUpSuggestions { let theme = cx.theme(); let colors = theme.colors.clone(); div() - .w_full() .flex() .flex_col() .children( @@ -253,7 +252,6 @@ impl RenderOnce for CapabilityCards { let theme = cx.theme(); let colors = theme.colors.clone(); div() - .w_full() .grid() .grid_cols(3) .gap_3() diff --git a/src/documents/blocks/tests.rs b/src/documents/blocks/tests.rs index 6ac87b2..31a3d70 100644 --- a/src/documents/blocks/tests.rs +++ b/src/documents/blocks/tests.rs @@ -12,12 +12,28 @@ fn open( forms::bind_keys(cx); crate::documents::bind_keys(cx); }); - let (editor, cx) = cx.add_window_view(|window, cx| BlockEditor::new(blocks, window, cx)); + let (full, cx) = + cx.add_window_view(|window, cx| Full(cx.new(|cx| BlockEditor::new(blocks, window, cx)))); + let editor = full.read_with(cx, |full, _| full.0.clone()); cx.update(|window, _| window.activate_window()); settle(cx); (editor, cx) } +/// The editor as a window's content, in the box that fills the window. +struct Full(Entity); + +impl gpui::Render for Full { + fn render( + &mut self, + _: &mut gpui::Window, + _: &mut gpui::Context, + ) -> impl gpui::IntoElement { + use gpui::{ParentElement, Styled}; + gpui::div().size_full().child(self.0.clone()) + } +} + fn settle(cx: &mut VisualTestContext) { cx.run_until_parked(); cx.update(|window, _| window.refresh()); diff --git a/src/documents/blocks/view.rs b/src/documents/blocks/view.rs index 5f515dc..a508e8e 100644 --- a/src/documents/blocks/view.rs +++ b/src/documents/blocks/view.rs @@ -253,7 +253,6 @@ impl Render for BlockEditor { let start = cx.entity(); div() .id(id.clone()) - .w_full() .flex() .flex_col() .capture_action(cx.listener(|editor, _: &Undo, window, cx| { diff --git a/src/documents/pages.rs b/src/documents/pages.rs index fc7f374..35dbf30 100644 --- a/src/documents/pages.rs +++ b/src/documents/pages.rs @@ -108,7 +108,6 @@ impl RenderOnce for PageCover { .id(self.id.clone()) .group(group.clone()) .relative() - .w_full() .h(theme.page_cover()) .child( Image::new((self.id.clone(), "picture"), source(&self.source)) diff --git a/src/documents/reading.rs b/src/documents/reading.rs index 3598944..8363ab9 100644 --- a/src/documents/reading.rs +++ b/src/documents/reading.rs @@ -208,27 +208,23 @@ impl RenderOnce for ReadingProgress { let theme = cx.theme(); let (track, bar) = (theme.colors.border, theme.colors.accent); let scroll = self.scroll; - div() - .w_full() - .h(theme.progress_thickness()) - .bg(track) - .child( - canvas( - |_, _, _| {}, - move |bounds, _, window, _| { - let share = read_share( - f32::from(scroll.offset().y), - f32::from(scroll.max_offset().height), - ); - let filled = Bounds::new( - bounds.origin, - size(bounds.size.width * share, bounds.size.height), - ); - window.paint_quad(fill(filled, bar)); - }, - ) - .size_full(), + div().h(theme.progress_thickness()).bg(track).child( + canvas( + |_, _, _| {}, + move |bounds, _, window, _| { + let share = read_share( + f32::from(scroll.offset().y), + f32::from(scroll.max_offset().height), + ); + let filled = Bounds::new( + bounds.origin, + size(bounds.size.width * share, bounds.size.height), + ); + window.paint_quad(fill(filled, bar)); + }, ) + .size_full(), + ) } } diff --git a/src/feedback/messages.rs b/src/feedback/messages.rs index 0d97641..b0200e5 100644 --- a/src/feedback/messages.rs +++ b/src/feedback/messages.rs @@ -166,7 +166,6 @@ impl RenderOnce for Banner { .items_center() .justify_center() .gap_2() - .w_full() .min_h(theme.control_height(ControlSize::Lg)) .py_1() .px_10() diff --git a/src/files/duplicates.rs b/src/files/duplicates.rs index 0eb4bec..5acaec3 100644 --- a/src/files/duplicates.rs +++ b/src/files/duplicates.rs @@ -212,7 +212,6 @@ impl RenderOnce for DuplicateFinder { }); div() .debug_selector(|| "duplicate-finder".into()) - .w_full() .flex() .flex_col() .gap_4() diff --git a/src/files/explorer.rs b/src/files/explorer.rs index b424055..b8b3dd4 100644 --- a/src/files/explorer.rs +++ b/src/files/explorer.rs @@ -278,7 +278,6 @@ impl RenderOnce for FileExplorer { }; div() .debug_selector(|| "file-explorer".into()) - .w_full() .flex() .flex_col() .gap_3() diff --git a/src/files/grid.rs b/src/files/grid.rs index c147f5d..b73cc05 100644 --- a/src/files/grid.rs +++ b/src/files/grid.rs @@ -177,7 +177,6 @@ impl RenderOnce for FileGrid { .id(self.id) .debug_selector(|| "file-grid".into()) .relative() - .w_full() .flex() .flex_wrap() .gap(gap) diff --git a/src/files/operation.rs b/src/files/operation.rs index c80e3b2..ffcdf43 100644 --- a/src/files/operation.rs +++ b/src/files/operation.rs @@ -174,7 +174,6 @@ impl RenderOnce for FileOperationProgress { ); div() .debug_selector(|| "file-operation".into()) - .w_full() .flex() .flex_col() .gap_2() diff --git a/src/files/preview.rs b/src/files/preview.rs index 0486af6..0805fc6 100644 --- a/src/files/preview.rs +++ b/src/files/preview.rs @@ -122,7 +122,6 @@ impl RenderOnce for FilePreview { }; div() .debug_selector(|| "file-preview".into()) - .w_full() .flex() .flex_col() .gap_3() diff --git a/src/files/recent.rs b/src/files/recent.rs index 336a1c8..ab14ba6 100644 --- a/src/files/recent.rs +++ b/src/files/recent.rs @@ -140,7 +140,6 @@ impl RenderOnce for RecentFiles { }); div() .debug_selector(|| "recent-files".into()) - .w_full() .flex() .flex_col() .gap_4() diff --git a/src/files/search.rs b/src/files/search.rs index 61cd831..e85d9f6 100644 --- a/src/files/search.rs +++ b/src/files/search.rs @@ -122,7 +122,6 @@ impl RenderOnce for FileSearch { }; div() .debug_selector(|| "file-search".into()) - .w_full() .flex() .flex_col() .gap_3() diff --git a/src/files/transfers.rs b/src/files/transfers.rs index 22418a7..ee985f8 100644 --- a/src/files/transfers.rs +++ b/src/files/transfers.rs @@ -80,7 +80,6 @@ impl RenderOnce for TransferQueue { let theme = cx.theme(); div() .debug_selector(|| "transfer-queue".into()) - .w_full() .flex() .flex_col() .gap_1() @@ -192,7 +191,6 @@ impl RenderOnce for DownloadManager { }); div() .debug_selector(|| "download-manager".into()) - .w_full() .flex() .flex_col() .gap_1() diff --git a/src/forms/catalogs.rs b/src/forms/catalogs.rs index f899ce0..c7ea809 100644 --- a/src/forms/catalogs.rs +++ b/src/forms/catalogs.rs @@ -138,13 +138,9 @@ impl RenderOnce for FontPicker { if let Some(on_change) = self.on_change { combobox = combobox.on_change(move |family, window, cx| on_change(family, window, cx)); } - div() - .flex() - .flex_col() - .gap_2() - .w_full() - .child(combobox) - .when_some(self.selected, |picker, family| { + div().flex().flex_col().gap_2().child(combobox).when_some( + self.selected, + |picker, family| { picker.child( div() .font_family(family) @@ -152,7 +148,8 @@ impl RenderOnce for FontPicker { .text_color(theme.colors.fg_muted) .child("The quick brown fox jumps over the lazy dog"), ) - }) + }, + ) } } diff --git a/src/forms/code.rs b/src/forms/code.rs index 716bd48..937809f 100644 --- a/src/forms/code.rs +++ b/src/forms/code.rs @@ -173,7 +173,6 @@ impl RenderOnce for CodeInput { "a code input is one line; JsonInput takes several" ); div() - .w_full() .font_family(cx.theme().mono_family.clone()) .child(Input::new(&self.state).size(self.size)) } @@ -205,7 +204,6 @@ impl RenderOnce for JsonInput { .flex() .flex_col() .gap_1() - .w_full() .child( div() .font_family(theme.mono_family.clone()) diff --git a/src/forms/color/gradient.rs b/src/forms/color/gradient.rs index b8d117d..78df02e 100644 --- a/src/forms/color/gradient.rs +++ b/src/forms/color/gradient.rs @@ -275,7 +275,6 @@ impl RenderOnce for GradientEditor { .flex() .flex_col() .gap_2() - .w_full() .child( div() .flex() diff --git a/src/forms/color/picker.rs b/src/forms/color/picker.rs index 97b3720..8593cdd 100644 --- a/src/forms/color/picker.rs +++ b/src/forms/color/picker.rs @@ -375,7 +375,6 @@ impl RenderOnce for ColorPicker { .flex() .flex_col() .gap_3() - .w_full() .px(knob * 0.5) .pt(knob * 0.5) .child(plane) diff --git a/src/forms/combobox.rs b/src/forms/combobox.rs index 03b1b19..0f689f6 100644 --- a/src/forms/combobox.rs +++ b/src/forms/combobox.rs @@ -214,7 +214,6 @@ impl RenderOnce for Combobox { div() .id(self.id.clone()) .relative() - .w_full() .capture_action(move |_: &Up, _, cx| { if open { cx.stop_propagation(); diff --git a/src/forms/expression.rs b/src/forms/expression.rs index dc6777f..57f6fea 100644 --- a/src/forms/expression.rs +++ b/src/forms/expression.rs @@ -276,7 +276,6 @@ impl RenderOnce for ExpressionInput { .flex() .flex_col() .gap_1() - .w_full() .child( div().font_family(mono).child( Input::new(&self.state) diff --git a/src/forms/hotkey.rs b/src/forms/hotkey.rs index 7cbe029..0ebb4c1 100644 --- a/src/forms/hotkey.rs +++ b/src/forms/hotkey.rs @@ -58,7 +58,6 @@ impl RenderOnce for HotkeyInput { .items_center() .justify_between() .gap_2() - .w_full() .h(theme.control_height(ControlSize::Md)) .px(theme.control_padding(ControlSize::Md)) .rounded(theme.radius(Radius::Md)) diff --git a/src/forms/inline.rs b/src/forms/inline.rs index 2625044..c91eafa 100644 --- a/src/forms/inline.rs +++ b/src/forms/inline.rs @@ -129,7 +129,6 @@ impl RenderOnce for InlineEdit { let (escape, enter) = (state.clone(), state.clone()); return div() .id(self.id) - .w_full() .on_key_down(move |event, window, cx| { if event.keystroke.key == "escape" { cx.stop_propagation(); diff --git a/src/forms/masked.rs b/src/forms/masked.rs index 8eecf04..5fee00d 100644 --- a/src/forms/masked.rs +++ b/src/forms/masked.rs @@ -270,7 +270,6 @@ impl RenderOnce for PhoneInput { ); div() .relative() - .w_full() .child(MaskedInput::new(self.id.clone(), &self.state, mask).prefix(code)) .child( canvas( diff --git a/src/forms/multi.rs b/src/forms/multi.rs index 414a86a..ed8cd49 100644 --- a/src/forms/multi.rs +++ b/src/forms/multi.rs @@ -153,7 +153,6 @@ impl RenderOnce for MultiSelect { .flex_wrap() .items_center() .gap_1() - .w_full() .min_h(theme.control_height(self.size)) .pl_1() .pr(theme.control_padding(self.size)) diff --git a/src/forms/pairs.rs b/src/forms/pairs.rs index 3173f9a..9b73be9 100644 --- a/src/forms/pairs.rs +++ b/src/forms/pairs.rs @@ -158,7 +158,6 @@ impl RenderOnce for FieldArray { .flex() .flex_col() .gap_2() - .w_full() .children(lines) .child( div().flex().child( diff --git a/src/forms/pattern.rs b/src/forms/pattern.rs index 37d67b6..43073a2 100644 --- a/src/forms/pattern.rs +++ b/src/forms/pattern.rs @@ -136,7 +136,6 @@ impl RenderOnce for RegexInput { .flex() .flex_col() .gap_1() - .w_full() .child( div().font_family(mono).child( Input::new(&self.state) diff --git a/src/forms/search.rs b/src/forms/search.rs index eef13b6..6e4ddab 100644 --- a/src/forms/search.rs +++ b/src/forms/search.rs @@ -81,7 +81,6 @@ impl RenderOnce for SearchInput { }); div() .relative() - .w_full() .child( Input::new(&self.state) .size(self.size) diff --git a/src/forms/signature.rs b/src/forms/signature.rs index 227507d..758178b 100644 --- a/src/forms/signature.rs +++ b/src/forms/signature.rs @@ -260,7 +260,6 @@ impl RenderOnce for SignaturePad { .flex_col() .items_end() .gap_1() - .w_full() .child(pad) .child( Button::new((self.id, "clear"), "Clear") diff --git a/src/forms/structure.rs b/src/forms/structure.rs index d30530b..b996504 100644 --- a/src/forms/structure.rs +++ b/src/forms/structure.rs @@ -55,7 +55,6 @@ impl RenderOnce for Form { .flex() .flex_col() .gap_8() - .w_full() .when_some(self.on_submit, |form, submit| { form.capture_action(move |_: &Submit, window, cx| { cx.stop_propagation(); @@ -102,7 +101,6 @@ impl RenderOnce for FormSection { .flex() .flex_col() .gap_4() - .w_full() .child( div() .flex() @@ -304,7 +302,6 @@ impl RenderOnce for InlineForm { .flex_wrap() .items_end() .gap_3() - .w_full() .children(self.children) } } diff --git a/src/forms/tests/colors.rs b/src/forms/tests/colors.rs index 6e12ca8..b6f6d4a 100644 --- a/src/forms/tests/colors.rs +++ b/src/forms/tests/colors.rs @@ -1,6 +1,6 @@ use gpui::{ - Context, Hsla, IntoElement, Modifiers, MouseButton, Render, TestAppContext, Window, point, px, - rgb, rgba, + Context, Hsla, IntoElement, Modifiers, MouseButton, ParentElement, Render, Styled, + TestAppContext, Window, div, point, px, rgb, rgba, }; use super::setup; @@ -13,14 +13,16 @@ struct Picked { impl Render for Picked { fn render(&mut self, _: &mut Window, cx: &mut Context) -> impl IntoElement { let view = cx.entity(); - ColorPicker::new("picked", self.color) - .opaque() - .on_change(move |color, _, cx| { - view.update(cx, |view, cx| { - view.color = color; - cx.notify(); - }) - }) + div() + .size_full() + .child(ColorPicker::new("picked", self.color).opaque().on_change( + move |color, _, cx| { + view.update(cx, |view, cx| { + view.color = color; + cx.notify(); + }) + }, + )) } } @@ -41,12 +43,14 @@ struct Gradient { impl Render for Gradient { fn render(&mut self, _: &mut Window, cx: &mut Context) -> impl IntoElement { let view = cx.entity(); - GradientEditor::new("gradient", self.stops.clone()).on_change(move |next, _, cx| { - view.update(cx, |view, cx| { - view.stops = next.to_vec(); - cx.notify(); - }) - }) + div().size_full().child( + GradientEditor::new("gradient", self.stops.clone()).on_change(move |next, _, cx| { + view.update(cx, |view, cx| { + view.stops = next.to_vec(); + cx.notify(); + }) + }), + ) } } diff --git a/src/forms/tests/other.rs b/src/forms/tests/other.rs index aaf784e..88987ee 100644 --- a/src/forms/tests/other.rs +++ b/src/forms/tests/other.rs @@ -48,12 +48,16 @@ struct Pad { impl Render for Pad { fn render(&mut self, _: &mut Window, cx: &mut Context) -> impl IntoElement { let view = cx.entity(); - SignaturePad::new("pad", self.strokes.clone()).on_change(move |next, _, cx| { - view.update(cx, |view, cx| { - view.strokes = next.to_vec(); - cx.notify(); - }) - }) + div() + .size_full() + .child( + SignaturePad::new("pad", self.strokes.clone()).on_change(move |next, _, cx| { + view.update(cx, |view, cx| { + view.strokes = next.to_vec(); + cx.notify(); + }) + }), + ) } } diff --git a/src/forms/text/actions.rs b/src/forms/text/actions.rs index fcde0e1..3ed9dc4 100644 --- a/src/forms/text/actions.rs +++ b/src/forms/text/actions.rs @@ -358,7 +358,6 @@ impl Render for TextInput { .id("ely-text-input") .key_context(CONTEXT) .track_focus(&self.focus) - .w_full() .cursor(if self.disabled { CursorStyle::OperationNotAllowed } else { diff --git a/src/forms/transfer.rs b/src/forms/transfer.rs index 9c3b7f7..fe006c0 100644 --- a/src/forms/transfer.rs +++ b/src/forms/transfer.rs @@ -181,7 +181,6 @@ impl RenderOnce for TransferList { div() .flex() .gap_3() - .w_full() .child(side("left", available_title, available, left, cx)) .child(buttons) .child(side("right", chosen_title, picked, right, cx)) diff --git a/src/generative/audio.rs b/src/generative/audio.rs index e0d5b3d..9c9db4a 100644 --- a/src/generative/audio.rs +++ b/src/generative/audio.rs @@ -152,7 +152,6 @@ impl RenderOnce for AudioGenerationPlayer { } }; div() - .w_full() .flex() .flex_col() .gap_3() diff --git a/src/generative/brush.rs b/src/generative/brush.rs index 3e03a11..53596ad 100644 --- a/src/generative/brush.rs +++ b/src/generative/brush.rs @@ -80,7 +80,6 @@ impl RenderOnce for MaskBrush { }) }; div() - .w_full() .flex() .flex_col() .gap_3() diff --git a/src/generative/compare.rs b/src/generative/compare.rs index dd2458a..3d3dd98 100644 --- a/src/generative/compare.rs +++ b/src/generative/compare.rs @@ -168,7 +168,6 @@ impl RenderOnce for ABCompareView { .collect(), }; div() - .w_full() .flex() .flex_col() .gap_3() diff --git a/src/generative/downloads.rs b/src/generative/downloads.rs index c55636e..73c5943 100644 --- a/src/generative/downloads.rs +++ b/src/generative/downloads.rs @@ -256,7 +256,7 @@ impl RenderOnce for ModelDownloadManager { ) .children(bar) }); - div().w_full().flex().flex_col().children(rows) + div().flex().flex_col().children(rows) } } diff --git a/src/generative/embed.rs b/src/generative/embed.rs index 568fead..7fe921b 100644 --- a/src/generative/embed.rs +++ b/src/generative/embed.rs @@ -313,12 +313,6 @@ impl RenderOnce for EmbeddingVisualizer { cx.notify(); }) }); - div() - .w_full() - .flex() - .flex_col() - .gap_3() - .child(legend) - .child(area) + div().flex().flex_col().gap_3().child(legend).child(area) } } diff --git a/src/generative/grid.rs b/src/generative/grid.rs index 9e71de7..45430cf 100644 --- a/src/generative/grid.rs +++ b/src/generative/grid.rs @@ -207,6 +207,6 @@ impl RenderOnce for GenerationGrid { .children((0..short).map(|_| div().flex_1())), ); } - div().w_full().flex().flex_col().gap_2().children(rows) + div().flex().flex_col().gap_2().children(rows) } } diff --git a/src/generative/hardware.rs b/src/generative/hardware.rs index d842389..aced899 100644 --- a/src/generative/hardware.rs +++ b/src/generative/hardware.rs @@ -45,8 +45,11 @@ impl HardwareMonitor { impl RenderOnce for HardwareMonitor { fn render(self, _: &mut Window, cx: &mut App) -> impl IntoElement { let spark = cx.theme().spark_size(); - div().w_full().flex().flex_col().gap_3().children( - self.readings.into_iter().enumerate().map(|(ix, reading)| { + div() + .flex() + .flex_col() + .gap_3() + .children(self.readings.into_iter().enumerate().map(|(ix, reading)| { div() .flex() .items_end() @@ -71,7 +74,6 @@ impl RenderOnce for HardwareMonitor { .child(Sparkline::new(reading.history).area()), ) }) - }), - ) + })) } } diff --git a/src/generative/models.rs b/src/generative/models.rs index 75e9f7a..a535c87 100644 --- a/src/generative/models.rs +++ b/src/generative/models.rs @@ -95,7 +95,6 @@ impl RenderOnce for ModelCard { }) }); div() - .w_full() .flex() .flex_col() .gap_3() @@ -260,7 +259,6 @@ impl RenderOnce for ModelStatus { _ => None, }; div() - .w_full() .flex() .flex_col() .gap_2() diff --git a/src/generative/playground.rs b/src/generative/playground.rs index d21ce6f..8d3e1ec 100644 --- a/src/generative/playground.rs +++ b/src/generative/playground.rs @@ -154,7 +154,6 @@ impl RenderOnce for PromptPlayground { ) }); div() - .w_full() .flex() .flex_col() .gap_3() diff --git a/src/generative/prompt.rs b/src/generative/prompt.rs index 9edb44f..f652ec1 100644 --- a/src/generative/prompt.rs +++ b/src/generative/prompt.rs @@ -199,7 +199,6 @@ impl RenderOnce for PromptEnhancer { ), ); div() - .w_full() .flex() .flex_col() .child(Input::new(&self.field)) diff --git a/src/generative/ratio.rs b/src/generative/ratio.rs index 73935e0..6ba3c7b 100644 --- a/src/generative/ratio.rs +++ b/src/generative/ratio.rs @@ -76,7 +76,6 @@ impl RenderOnce for AspectRatioPicker { let colors = theme.colors.clone(); let glyph = theme.icon_size(IconSize::Md); div() - .w_full() .flex() .flex_wrap() .gap_2() diff --git a/src/generative/style.rs b/src/generative/style.rs index 646e7bc..74918be 100644 --- a/src/generative/style.rs +++ b/src/generative/style.rs @@ -75,7 +75,6 @@ impl RenderOnce for StylePresetPicker { let colors = theme.colors.clone(); let side = theme.generative().preset; div() - .w_full() .flex() .flex_wrap() .gap_3() diff --git a/src/generative/tuning.rs b/src/generative/tuning.rs index 4b67f12..37796ee 100644 --- a/src/generative/tuning.rs +++ b/src/generative/tuning.rs @@ -185,7 +185,6 @@ impl RenderOnce for FineTuneJobCard { .h(theme.generative().loss) }); div() - .w_full() .flex() .flex_col() .gap_3() diff --git a/src/generative/variation.rs b/src/generative/variation.rs index 406468a..631c97d 100644 --- a/src/generative/variation.rs +++ b/src/generative/variation.rs @@ -120,7 +120,6 @@ impl RenderOnce for VariationPicker { }) }; div() - .w_full() .flex() .flex_col() .gap_3() diff --git a/src/generative/versions.rs b/src/generative/versions.rs index 4cbb014..350fbf1 100644 --- a/src/generative/versions.rs +++ b/src/generative/versions.rs @@ -84,7 +84,6 @@ impl RenderOnce for PromptDiff { Some((range, style)) }); div() - .w_full() .text_size(theme.text_size(TextSize::Sm)) .text_color(colors.fg) .child(StyledText::new(text).with_highlights(styles)) @@ -251,7 +250,6 @@ impl RenderOnce for PromptVersionHistory { }, ); div() - .w_full() .flex() .flex_wrap() .items_start() diff --git a/src/generative/video.rs b/src/generative/video.rs index bc0676a..9610a5c 100644 --- a/src/generative/video.rs +++ b/src/generative/video.rs @@ -287,7 +287,6 @@ impl RenderOnce for VideoGenerationTimeline { }) }); div() - .w_full() .flex() .flex_col() .gap_2() diff --git a/src/generative/voice.rs b/src/generative/voice.rs index ad9d719..b3a038b 100644 --- a/src/generative/voice.rs +++ b/src/generative/voice.rs @@ -224,6 +224,6 @@ impl RenderOnce for TTSVoicePicker { .children(voice.tags.into_iter().map(Badge::new)), ) }); - div().w_full().flex().flex_col().gap_0p5().children(rows) + div().flex().flex_col().gap_0p5().children(rows) } } diff --git a/src/layout/grid.rs b/src/layout/grid.rs index 384e54a..cbcdab0 100644 --- a/src/layout/grid.rs +++ b/src/layout/grid.rs @@ -87,7 +87,6 @@ impl RenderOnce for SimpleGrid { let columns = columns_for(*width.read(cx), self.min, self.gap); self.base .relative() - .w_full() .grid() .grid_cols(columns) .gap(self.gap) diff --git a/src/lists/sections.rs b/src/lists/sections.rs index 8d7757e..a7313de 100644 --- a/src/lists/sections.rs +++ b/src/lists/sections.rs @@ -115,6 +115,6 @@ impl RenderOnce for Sections { }), ) }); - div().w_full().flex().flex_col().gap_4().children(sections) + div().flex().flex_col().gap_4().children(sections) } } diff --git a/src/mail/boxes.rs b/src/mail/boxes.rs index c99ad42..20bfb4c 100644 --- a/src/mail/boxes.rs +++ b/src/mail/boxes.rs @@ -2,7 +2,7 @@ use std::rc::Rc; use gpui::{ App, ElementId, InteractiveElement, IntoElement, ParentElement, RenderOnce, SharedString, - Styled, Window, div, + Window, div, }; use super::labels::hue_dot; @@ -173,14 +173,11 @@ impl RenderOnce for MailboxList { sections.section(title.clone(), rows) }, ); - div() - .debug_selector(|| "mailbox-list".into()) - .w_full() - .child( - sections - .selected(self.open) - .on_select(open.clone()) - .on_activate(open), - ) + div().debug_selector(|| "mailbox-list".into()).child( + sections + .selected(self.open) + .on_select(open.clone()) + .on_activate(open), + ) } } diff --git a/src/mail/compose.rs b/src/mail/compose.rs index 0673d1c..c4df11a 100644 --- a/src/mail/compose.rs +++ b/src/mail/compose.rs @@ -330,7 +330,6 @@ impl RenderOnce for MailComposer { }); div() .debug_selector(|| "mail-composer".into()) - .w_full() .flex() .flex_col() .gap_3() diff --git a/src/mail/labels.rs b/src/mail/labels.rs index f982645..3fddfac 100644 --- a/src/mail/labels.rs +++ b/src/mail/labels.rs @@ -240,7 +240,6 @@ impl RenderOnce for LabelPicker { let (up, down, chosen) = (finding.clone(), finding.clone(), finding); div() .id(self.id.clone()) - .w_full() .flex() .flex_col() .gap_2() diff --git a/src/mail/list.rs b/src/mail/list.rs index 386bf65..9dbd0b1 100644 --- a/src/mail/list.rs +++ b/src/mail/list.rs @@ -290,7 +290,6 @@ impl RenderOnce for MailList { if self.mails.is_empty() { return div() .debug_selector(|| "mail-none".into()) - .w_full() .px_3() .py_4() .text_size(theme.text_size(TextSize::Sm)) @@ -320,7 +319,6 @@ impl RenderOnce for MailList { let (id, on_select) = (self.id.clone(), self.on_select); div() .debug_selector(|| "mail-list".into()) - .w_full() .child( list.selected(self.selected) .on_change(move |keys, window, cx| { diff --git a/src/mail/reader.rs b/src/mail/reader.rs index 2d3b8b8..46f08f1 100644 --- a/src/mail/reader.rs +++ b/src/mail/reader.rs @@ -344,7 +344,6 @@ impl RenderOnce for MailReader { let theme = cx.theme(); div() .debug_selector(|| "mail-reader".into()) - .w_full() .flex() .flex_col() .gap_4() diff --git a/src/mail/signature.rs b/src/mail/signature.rs index 97cf409..a2aacea 100644 --- a/src/mail/signature.rs +++ b/src/mail/signature.rs @@ -124,7 +124,6 @@ impl RenderOnce for SignatureEditor { let words = input.read(cx).text().to_string(); let theme = cx.theme(); div() - .w_full() .flex() .flex_col() .gap_3() diff --git a/src/mail/thread.rs b/src/mail/thread.rs index c9521fc..f58e94a 100644 --- a/src/mail/thread.rs +++ b/src/mail/thread.rs @@ -199,7 +199,6 @@ impl RenderOnce for MailThreadView { ); div() .debug_selector(|| "mail-thread".into()) - .w_full() .flex() .flex_col() .gap_3() diff --git a/src/media/annotate.rs b/src/media/annotate.rs index 3e41be4..2ff55bf 100644 --- a/src/media/annotate.rs +++ b/src/media/annotate.rs @@ -428,7 +428,6 @@ impl RenderOnce for ImageAnnotator { }) }); div() - .w_full() .flex() .flex_col() .gap_3() diff --git a/src/media/audio.rs b/src/media/audio.rs index 971cd50..6359638 100644 --- a/src/media/audio.rs +++ b/src/media/audio.rs @@ -145,7 +145,6 @@ impl RenderOnce for AudioWaveform { .id(self.id.clone()) .debug_selector(|| "audio-waveform".into()) .relative() - .w_full() .h(sizes.waveform) .border_1() .border_color(transparent_black()) @@ -226,7 +225,6 @@ impl RenderOnce for AudioSpectrum { let (color, round) = (theme.colors.fg_muted, theme.radius(Radius::Sm)); div() .debug_selector(|| "audio-spectrum".into()) - .w_full() .h(theme.media().waveform) .flex() .items_end() diff --git a/src/media/controls.rs b/src/media/controls.rs index 1de81bb..d62dd63 100644 --- a/src/media/controls.rs +++ b/src/media/controls.rs @@ -92,7 +92,6 @@ impl RenderOnce for VolumeControl { None => slider, }; div() - .w_full() .flex() .items_center() .gap_2() diff --git a/src/media/cropper.rs b/src/media/cropper.rs index f403869..8134e2b 100644 --- a/src/media/cropper.rs +++ b/src/media/cropper.rs @@ -200,7 +200,6 @@ impl RenderOnce for ImageCropper { div() .id(self.id.clone()) .relative() - .w_full() .p(side / 2.0) .border_1() .border_color(transparent_black()) diff --git a/src/media/listen.rs b/src/media/listen.rs index e6e875f..305a226 100644 --- a/src/media/listen.rs +++ b/src/media/listen.rs @@ -251,7 +251,6 @@ impl RenderOnce for AudioPlayer { }; let left = format!("-{}", clock(self.length - self.at)); div() - .w_full() .flex() .flex_col() .gap_3() diff --git a/src/media/record.rs b/src/media/record.rs index 3e89165..23775a0 100644 --- a/src/media/record.rs +++ b/src/media/record.rs @@ -255,7 +255,6 @@ impl RenderOnce for MicLevelMeter { let (unlit, round) = (colors.border, theme.radius(Radius::Sm)); div() .debug_selector(|| "mic-level".into()) - .w_full() .h(theme.meter_track()) .flex() .gap_0p5() diff --git a/src/media/scrubber.rs b/src/media/scrubber.rs index eba2132..a6a0b1d 100644 --- a/src/media/scrubber.rs +++ b/src/media/scrubber.rs @@ -264,7 +264,6 @@ impl RenderOnce for Scrubber { div() .id(self.id.clone()) .debug_selector(|| "scrubber".into()) - .w_full() .px(thumb / 2.0) .rounded(theme.radius(Radius::Sm)) .border_1() diff --git a/src/media/strip.rs b/src/media/strip.rs index 0098e4d..af741ab 100644 --- a/src/media/strip.rs +++ b/src/media/strip.rs @@ -251,7 +251,6 @@ impl RenderOnce for VideoThumbnailStrip { let (pressed_strip, moved_strip) = (strip.clone(), strip.clone()); div() .id(self.id.clone()) - .w_full() .px(handle / 2.0) .border_1() .border_color(transparent_black()) diff --git a/src/media/subtitles.rs b/src/media/subtitles.rs index d6622b8..fbe1d29 100644 --- a/src/media/subtitles.rs +++ b/src/media/subtitles.rs @@ -309,7 +309,6 @@ impl RenderOnce for SubtitleEditor { }) }); div() - .w_full() .flex() .flex_col() .gap_1() diff --git a/src/media/thumbnail.rs b/src/media/thumbnail.rs index 04f0033..418b86d 100644 --- a/src/media/thumbnail.rs +++ b/src/media/thumbnail.rs @@ -81,7 +81,6 @@ impl RenderOnce for ImageThumbnail { .children(label); div() .id(self.id) - .w_full() .rounded(outer) .border_1() .border_color(if self.selected { diff --git a/src/media/upload.rs b/src/media/upload.rs index 0ef0f87..bd76a45 100644 --- a/src/media/upload.rs +++ b/src/media/upload.rs @@ -189,7 +189,6 @@ impl RenderOnce for ImageUpload { .into_any_element(), }; div() - .w_full() .flex() .flex_col() .gap_3() diff --git a/src/messaging/call.rs b/src/messaging/call.rs index ea89f98..4e9081a 100644 --- a/src/messaging/call.rs +++ b/src/messaging/call.rs @@ -206,7 +206,6 @@ impl RenderOnce for VoiceCallBar { .then(|| AvatarGroup::new(self.people).max(3).size(AvatarSize::Xs)); div() .debug_selector(|| "voice-call-bar".into()) - .w_full() .flex() .flex_wrap() .items_center() diff --git a/src/messaging/channels.rs b/src/messaging/channels.rs index 0221c8b..8dac578 100644 --- a/src/messaging/channels.rs +++ b/src/messaging/channels.rs @@ -272,14 +272,11 @@ impl RenderOnce for ChannelList { sections.section(title, rows) }, ); - div() - .debug_selector(|| "channel-list".into()) - .w_full() - .child( - sections - .selected(self.open) - .on_select(open.clone()) - .on_activate(open), - ) + div().debug_selector(|| "channel-list".into()).child( + sections + .selected(self.open) + .on_select(open.clone()) + .on_activate(open), + ) } } diff --git a/src/messaging/gifs.rs b/src/messaging/gifs.rs index c887804..2676a1c 100644 --- a/src/messaging/gifs.rs +++ b/src/messaging/gifs.rs @@ -295,7 +295,6 @@ impl RenderOnce for GifPicker { .then(|| Masonry::new((self.id.clone(), "gifs"), 2, gap).children(tiles)); div() .debug_selector(|| "gif-picker".into()) - .w_full() .flex() .flex_col() .gap_2() diff --git a/src/messaging/header.rs b/src/messaging/header.rs index f635e1c..cf552be 100644 --- a/src/messaging/header.rs +++ b/src/messaging/header.rs @@ -104,7 +104,6 @@ impl RenderOnce for ChannelHeader { }; div() .debug_selector(|| "channel-header".into()) - .w_full() .flex() .flex_wrap() .items_center() diff --git a/src/messaging/members.rs b/src/messaging/members.rs index 3312d58..9bb1b5d 100644 --- a/src/messaging/members.rs +++ b/src/messaging/members.rs @@ -193,7 +193,6 @@ impl RenderOnce for MemberList { }); div() .debug_selector(|| "member-list".into()) - .w_full() .children(empty) .when(!self.members.is_empty(), |list| { list.child( diff --git a/src/messaging/messages.rs b/src/messaging/messages.rs index 7cd10fd..c6e9954 100644 --- a/src/messaging/messages.rs +++ b/src/messaging/messages.rs @@ -141,7 +141,6 @@ impl RenderOnce for ChatMessage { .id(self.id.clone()) .debug_selector(move || format!("message {}", self.id)) .group(group) - .w_full() .flex() .gap_3() .px_3() @@ -192,7 +191,6 @@ impl RenderOnce for UnreadDivider { let theme = cx.theme(); let danger = theme.colors.danger; div() - .w_full() .flex() .items_center() .gap_2() diff --git a/src/messaging/people.rs b/src/messaging/people.rs index 303deba..17efea8 100644 --- a/src/messaging/people.rs +++ b/src/messaging/people.rs @@ -176,7 +176,6 @@ impl RenderOnce for UserProfileCard { }); div() .debug_selector(|| "profile-card".into()) - .w_full() .flex() .flex_col() .gap_3() diff --git a/src/messaging/pins.rs b/src/messaging/pins.rs index e5ce17d..7d09f97 100644 --- a/src/messaging/pins.rs +++ b/src/messaging/pins.rs @@ -152,7 +152,6 @@ impl RenderOnce for PinnedMessages { }); div() .debug_selector(|| "pinned-messages".into()) - .w_full() .flex() .flex_col() .gap_1() diff --git a/src/messaging/status.rs b/src/messaging/status.rs index f18cd20..f17ebfa 100644 --- a/src/messaging/status.rs +++ b/src/messaging/status.rs @@ -300,7 +300,6 @@ impl RenderOnce for StatusSetter { }); div() .debug_selector(|| "status-setter".into()) - .w_full() .flex() .flex_col() .gap_4() diff --git a/src/messaging/thread.rs b/src/messaging/thread.rs index 2ff2a0f..8b40b77 100644 --- a/src/messaging/thread.rs +++ b/src/messaging/thread.rs @@ -68,7 +68,6 @@ impl RenderOnce for MessageThread { div() .id(self.id) .debug_selector(|| "message-thread".into()) - .w_full() .flex() .items_center() .gap_2() diff --git a/src/messaging/tiles.rs b/src/messaging/tiles.rs index 7cf08e3..4cb35f1 100644 --- a/src/messaging/tiles.rs +++ b/src/messaging/tiles.rs @@ -191,7 +191,6 @@ impl RenderOnce for VideoCallGrid { div() .debug_selector(|| "video-call-grid".into()) .relative() - .w_full() .flex() .flex_col() .children(rows) @@ -321,7 +320,6 @@ impl RenderOnce for ScreenShareView { }); div() .debug_selector(|| "screen-share".into()) - .w_full() .flex() .flex_col() .gap_2() diff --git a/src/motion/list.rs b/src/motion/list.rs index d7ad433..17fe762 100644 --- a/src/motion/list.rs +++ b/src/motion/list.rs @@ -155,7 +155,7 @@ impl RenderOnce for Flip { } } rest.append(&mut raised); - div().relative().w_full().h(total).children(rest) + div().relative().h(total).children(rest) } } diff --git a/src/motion/overlay.rs b/src/motion/overlay.rs index 542426d..abad707 100644 --- a/src/motion/overlay.rs +++ b/src/motion/overlay.rs @@ -143,7 +143,6 @@ impl RenderOnce for LazyLoad { }); } }) - .w_full() .child( Skeleton::new((self.id, "placeholder")) .w_full() diff --git a/src/motion/progress.rs b/src/motion/progress.rs index 63e716b..19ad489 100644 --- a/src/motion/progress.rs +++ b/src/motion/progress.rs @@ -123,13 +123,9 @@ impl RenderOnce for ProgressBar { let Some(value) = self.value else { let sweep = bar(0.3).bg(fill); if theme.reduced_motion { - return lane() - .w_full() - .child(sweep.left(relative(0.35))) - .into_any_element(); + return lane().child(sweep.left(relative(0.35))).into_any_element(); } return lane() - .w_full() .child( sweep.with_animation( (self.id, "sweep"), @@ -159,7 +155,6 @@ impl RenderOnce for ProgressBar { }) }; div() - .w_full() .flex() .gap_1() .with_animation( diff --git a/src/motion/skeleton.rs b/src/motion/skeleton.rs index a7f6f84..e8fd466 100644 --- a/src/motion/skeleton.rs +++ b/src/motion/skeleton.rs @@ -85,7 +85,6 @@ impl RenderOnce for SkeletonText { fn render(self, _: &mut Window, cx: &mut App) -> impl IntoElement { let line = cx.theme().text_size(TextSize::Base); div() - .w_full() .flex() .flex_col() .gap_2() @@ -141,7 +140,6 @@ impl RenderOnce for SkeletonCard { let line = theme.text_size(TextSize::Base); let id = |part: &'static str| (self.id.clone(), part); div() - .w_full() .flex() .flex_col() .gap_4() @@ -219,11 +217,7 @@ impl RenderOnce for SkeletonTable { ) })) }; - div() - .w_full() - .flex() - .flex_col() - .children((0..=self.rows).map(row)) + div().flex().flex_col().children((0..=self.rows).map(row)) } } diff --git a/src/navigation/editor_tabs.rs b/src/navigation/editor_tabs.rs index 4a783a4..318a337 100644 --- a/src/navigation/editor_tabs.rs +++ b/src/navigation/editor_tabs.rs @@ -345,7 +345,6 @@ impl RenderOnce for EditorTabs { .id(self.id) .flex() .items_center() - .w_full() .bg(colors.sunken) .border_b_1() .border_color(colors.border) diff --git a/src/navigation/goto.rs b/src/navigation/goto.rs index 21dbcc4..b299156 100644 --- a/src/navigation/goto.rs +++ b/src/navigation/goto.rs @@ -83,7 +83,6 @@ impl RenderOnce for GoToLine { .flex() .flex_col() .gap_1() - .w_full() .capture_action(move |_: &Enter, window, cx| { cx.stop_propagation(); match target(state.read(cx).text(), lines) { diff --git a/src/navigation/steps.rs b/src/navigation/steps.rs index f4eb484..8236777 100644 --- a/src/navigation/steps.rs +++ b/src/navigation/steps.rs @@ -333,7 +333,6 @@ impl RenderOnce for Wizard { .flex() .flex_col() .gap_6() - .w_full() .when(!self.headless, |wizard| { wizard.child( Steps::new((id.clone(), "steps"), self.steps, current).on_select( diff --git a/src/shell/dialogs.rs b/src/shell/dialogs.rs index 4815644..503b473 100644 --- a/src/shell/dialogs.rs +++ b/src/shell/dialogs.rs @@ -93,7 +93,6 @@ impl RenderOnce for AboutDialog { .px_8() .pt_4() .pb_8() - .w_full() .child(mark(&self.name, self.icon, cx)) .child(div().pt_3().child(Title::new(self.name.clone()))) .child(CopyableText::new( @@ -234,7 +233,7 @@ impl RenderOnce for SplashScreen { .flex_col() .items_center() .gap_2() - .child(track) + .child(div().w_full().child(track)) .child( div() .text_size(theme.text_size(TextSize::Xs)) diff --git a/src/shell/tabs.rs b/src/shell/tabs.rs index cdd353d..4afab2e 100644 --- a/src/shell/tabs.rs +++ b/src/shell/tabs.rs @@ -230,7 +230,6 @@ impl RenderOnce for TabBar { .flex() .items_center() .gap_1() - .w_full() .min_w_0() .children(tabs) .when_some(self.on_add, |bar, add| { diff --git a/src/shell/tests.rs b/src/shell/tests.rs index 75f0f51..2868c4e 100644 --- a/src/shell/tests.rs +++ b/src/shell/tests.rs @@ -261,3 +261,28 @@ fn a_short_title_sits_at_the_center(cx: &mut TestAppContext) { let middle = title.left() + title.size.width / 2.0; assert!((middle - px(140.0)).abs() < px(1.0), "{title:?} centered"); } + +struct Splash; + +impl Render for Splash { + fn render(&mut self, _: &mut Window, _: &mut Context) -> impl IntoElement { + div() + .size_full() + .child(super::SplashScreen::new("Ely").progress(Some(0.5))) + } +} + +/// The splash's bar spans its column, though the column centers what it holds. +#[gpui::test] +fn the_splash_bar_spans_its_column(cx: &mut TestAppContext) { + cx.update(Theme::init); + let (_, cx) = cx.add_window_view(|_, _| Splash); + settle(cx); + let fill = cx.debug_bounds("progress-fill-0").expect("the bar fills"); + let width = cx.update(|window, _| window.viewport_size().width); + let column = (width - px(80.0)) * 0.6; + assert!( + (fill.size.width - column * 0.5).abs() < px(1.0), + "half the column, not {fill:?}" + ); +} diff --git a/src/shell/update.rs b/src/shell/update.rs index 43affc5..ede95b8 100644 --- a/src/shell/update.rs +++ b/src/shell/update.rs @@ -133,7 +133,6 @@ impl RenderOnce for UpdateBanner { .flex() .items_center() .gap_3() - .w_full() .py_2() .pl_4() .pr_2() diff --git a/src/typography/fit.rs b/src/typography/fit.rs index 4f6f7a3..2c37a69 100644 --- a/src/typography/fit.rs +++ b/src/typography/fit.rs @@ -200,7 +200,6 @@ impl RenderOnce for EllipsisTooltip { div() .id(self.id) .relative() - .w_full() .truncate() .text_size(theme.text_size(TextSize::Base)) .line_height(relative(LEADING))