Skip to content

GPUI Kit v0.7.0

Latest

Choose a tag to compare

@huacnlee huacnlee released this 28 Sep 03:15
· 21 commits to main since this release

GPUI Kit v0.7.0

GPUI Kit v0.7.0 adds Toolbar, Questionnaire and TimeField, and makes window startup and overlay hosting consistent through a Base-owned Root. Plot primitives are now available without the styled component layer, while Input, TextView and charts gain richer editing, search, date/time and data-visualization APIs. This release also improves Dock interactions, accessibility, streaming and large-data performance; review the Breaking Changes below before upgrading.

New components

  • Toolbar and ToolbarGroup: compose application command rows with source-order controls, semantic groups, separators and flexible spacers. Left/Right moves focus through enabled controls with wrapping. The styled toolbar propagates its density to hosted controls and gives Buttons compact ghost presentation; child/children accept sized controls, while content/contents accept labels, separators and custom content. The default size is Small; XSmall and Medium are supported, and Large uses Medium. Disabling toolbar navigation does not disable its controls automatically. (#3128)

  • Questionnaire: build single-choice, multiple-choice and freeform questionnaires around QuestionnaireState, with composable question, choice, input, progress and action parts. The component handles validation, optional skipping, keyboard shortcuts, focus, navigation and submission, using existing Radio, Checkbox, Input and Button controls. (#2878)

  • TimeField and date/time picking: edit segmented hours and minutes, optionally seconds, using TimeFieldState, TimePrecision::{Minute, Second} and HourCycle::{H23, H12}. A styled TimeField works independently in forms, and DatePicker enables time editing through time_precision, hour_cycle and default_time. date_time/set_date_time expose the combined value; date/time presets use DateRangePreset::date_time. In time-enabled single mode, each edit emits Change while the popup stays open; range mode remains date-only. DatePicker Change payloads require migration below. (#3206)

Window hosting and framework boundaries

  • One window entry point: gpui_kit::open_window(options, cx, build) returns (AnyWindowHandle, Entity<V>) and always wraps application content in gpui_base::Root, independent of Cargo feature unification. Call gpui_kit::init(cx) first, return content from the builder, and retain the returned entity when you need application state. In async work, invoke the helper inside cx.update; quit/close actions and keybindings remain application-owned. (#3152)

  • Automatic overlay hosting: Root owns content, overlay hosting, keyboard traversal and selection copying; gpui_component::Root re-exports the Base type. Component initialization registers per-window presentation for dialogs, sheets, notifications, menus, tooltips, touch selection and window chrome. Manual layer-rendering APIs are removed; application operations remain on WindowExt. (#3152)

  • Root plugins: design systems can register typed RootPlugin implementations with Root::register_plugin, retrieve them with Root::plugin, and use preparation, styling and decoration hooks. Plugins are instantiated per window in registration order. Register them before creating windows; replacing a factory affects future windows, and existing roots are not retrofitted. (#3152)

  • Plot primitives in Base: scales, shapes, axes, grids, labels, the Plot trait, path caches and hover tracking move to gpui_kit::base::plot, enabling custom charts without a Component dependency. Existing gpui_kit::component::plot imports remain available through re-exports. PlotElement<P> is the element behind custom plots and #[derive(IntoPlot)]; PlotMotion and PlotTheme provide theme-projected pointer and hover motion. Base defaults to no motion, styled charts now accept f32, and Component forwards its decimal feature to Base. Custom primitive APIs require migration below. (#3258)

Simplified window startup

gpui_kit::init(cx) and gpui_kit::open_window provide a compact, standard startup sequence. The builder creates application content, and Kit supplies the Root and automatically hosts dialogs, sheets and notifications. Use WindowExt for Component operations, gpui_base::TextSelection for selection, and WindowOptions with window_border() for window decoration. (#3152)

gpui_kit::init(cx);
let (window_handle, content) =
    gpui_kit::open_window(options, cx, |window, cx| {
        build_content(window, cx)
    })?;

Updating existing window code

The following examples show how existing startup, overlay and window-operation code maps to the simplified APIs.

- cx.open_window(options, |window, cx| {
-     let content = build_content(window, cx);
-     cx.new(|cx| Root::new(content, window, cx))
- })
+ let (window_handle, content) =
+     gpui_kit::open_window(options, cx, |window, cx| {
+         build_content(window, cx)
+     })?;
- let sheet_layer = Root::render_sheet_layer(window, cx);
- let dialog_layer = Root::render_dialog_layer(window, cx);
- let notification_layer = Root::render_notification_layer(window, cx);
-
  div()
      .child(content)
-     .children(sheet_layer)
-     .children(dialog_layer.map(|layer| deferred(layer).with_priority(1)))
-     .children(notification_layer)
- Root::bordered
- Root::window_shadow_size
+ window_border()
- window.selected_text(cx)
+ TextSelection::selected_text(window, cx)
- window.has_text_selection(cx)
+ TextSelection::has_selection(window, cx)
- root.clear_text_selection(window, cx)
- window.clear_text_selection(cx)
+ TextSelection::clear(window, cx)
- window.end_text_selection(cx)
+ TextSelection::end(window, cx)
- root.open_dialog(build, window, cx)
+ window.open_dialog(cx, build)
- root.close_dialog(window, cx)
+ window.close_dialog(cx)
- root.close_all_dialogs(window, cx)
+ window.close_all_dialogs(cx)
- root.open_sheet_at(placement, build, window, cx)
+ window.open_sheet_at(placement, cx, build)
- root.close_sheet(window, cx)
+ window.close_sheet(cx)
- root.push_notification(notification, window, cx)
+ window.push_notification(notification, cx)
- root.remove_notification::<T>(window, cx)
+ window.remove_notification::<T>(cx)
- root.remove_notification1::<T>(key, window, cx)
+ window.remove_notification1::<T>(key, cx)
- root.clear_notifications(window, cx)
+ window.clear_notifications(cx)

Editor and text input

  • Atomic inline tokens: Input and Textarea can represent mentions, commands and resource references as InlineToken annotations. Use replace_with_token/replace_range_with_token to insert them, InputContent::with_token to restore validated ranges, and content() to save a draft. Caret movement, selection, deletion and undo treat each token as one unit, while values and clipboard content remain plain text. Customize presentation with token and activation with on_token_click or ActivateToken. Tokens are opt-in and unavailable in Editor, NumberInput, password and formatted-mask modes. (#3113)

  • Editor range decorations: independent consumers can create edit-tracked RangeDecorationCollection handles through EditorState::create_range_decorations_collection. RangeDecoration supports RangeDecorationStyle::{Fill, Frame} with optional color; collections can set, append, clear, read tracked ranges or dispose. Decorations use UTF-8 byte ranges and paint only visible spans, including soft wraps, CRLF and folded text. InputExtras::range_decorations has a default empty implementation, so existing implementers continue to compile. (#3040)

  • Textarea sizing and editor gutters: Textarea supports the standard size system like Input, and the line-number gutter adapts between three and seven digits instead of reserving an unsuitable fixed width. (#3191, #3205)

  • Focus, selection and asynchronous editing: corrected disabled-input pointer focus, preferred columns and vertical selection affinity, drag-selection autoscroll, stale completion/inline responses, IME selection direction and undo boundaries, replacement-field focus and explicit GoToDefinition requests. Accessibility Focus refuses disabled inputs; SetValue is advertised and applied only when editable. Re-requesting code actions refreshes an already-open menu, including empty results. (#3254, #3256, #3274)

  • Caret lifecycle and navigation: programmatic updates no longer start permanent blink/repaint loops on unfocused inputs; blur clears stale blink state so refocusing restores a blinking caret. Editing scrolls directly to a distant caret rather than animating through the whole document. (#3139, #3140, #3150)

  • Web clipboard paste: Input context menus offer Paste whenever the input is editable, and fall back to asynchronous clipboard reading when synchronous reading is unavailable. The paste request starts from the user action and rechecks editability when it resolves. (#3244)

  • Editor performance and Unicode safety: reduce diagnostic/definition-hover repaints, debounce transient hover requests, avoid inactive search rescans and query only visible search highlights. Syntax classification reuses Rope-backed parse results and injection trees. Tree-sitter receives bytes, preventing aborts when a read begins inside a multibyte character. (#3260, #3263, #3238)

  • Input context menus: documentation now makes clear that InputState::context_menu(false) disables the entire right-click menu, including a custom Input/Textarea/Editor menu. Keep the state menu enabled when supplying a custom builder; the builder replaces the built-in items. (#3275)

Markdown and text rendering

  • Source-aware selection: TextViewState::selected_source_range() returns the original Markdown byte range for the actual rendered selection, distinguishing repeated occurrences instead of guessing from selected text. (#3136)

  • Search highlights and reveal: search TextViewState::rendered_text() and apply RangeHighlight values with set_range_highlights; clear_range_highlights removes them. Ranges refer to UTF-8 bytes in rendered copy text, so searches can cross Markdown formatting. Highlights preserve layout, selection and copy behavior, and survive unchanged content and append-only streaming. reveal_range makes the starting line visible in a scrollable TextView or an application list; TextView::on_reveal supplies window-space bounds for custom scroll containers. Reveal is best effort, and highlights are currently Markdown-only. (#3215, #3216)

  • Heading refinements: Base TextViewStyle::with_heading accepts a level-aware StyleRefinement callback for typography, spacing, color and borders, layered over built-in heading defaults. Component keeps its existing compatibility heading fields and builders. (#3129)

  • Markdown correctness: preserve ordered-list starting numbers and prose in unclaimed math spans, pair inline HTML tags correctly, and keep lines containing inline code as tall as equivalent plain-text lines. (#3204, #3178, #3240)

  • Streaming and large documents: stream_fade staggers by word and skips oversized chunks, with throttled repaints. Reuse inline layout and paragraph render caches, avoid unnecessary hover/selection work, and remove quadratic source-mapping and table-highlight reconciliation paths. Text selection in a cached dock view stays registered instead of flickering and keeping the window repainting. (#3153, #3226, #3180, #3261, #3247, #3273, #3193)

Charts and plot motion

  • Stable live-series geometry: LineChart and AreaChart support y_domain(min, max) for a fixed value range and point_count(count) for reserved x-axis slots, so arriving data keeps its position. Values outside the fixed domain are clipped. BarChart adds band_count for the equivalent fixed-band layout. (#3209, #3220)

  • Axes, grids and reference lines: LineChart/AreaChart add y_axis, y_axis_label_placement, y_tick_count, y_tick_format, x_tick_count, grid_columns, grid_dashed, repeatable reference_line and y_padding. BarChart adds value_axis_label_placement, value_tick_format, band_tick_count and grid_dashed. AxisLabelPlacement::{Outside, Inside} controls value-label placement. chart.grid/ThemeColor::chart_grid separate grids from axis borders, with a 60%-opacity border fallback for themes that omit the token. (#3220, #3236)

  • Bar labels and spacing: label_color colors labels per datum, padding_inner/padding_outer expose band spacing, and min_length keeps zero or small bars visible. Vertical charts reserve space for labels. BarChart and CandlestickChart expose max_band_width, retaining their default 30px maximum while Base ScaleBand no longer imposes one. (#3217, #3258)

  • Tooltip customization: LineChart, AreaChart, BarChart, RadarChart and CandlestickChart add tooltip_title, tooltip_value, tooltip_value_color and tooltip_content. Multivalue chart callbacks also receive a row index. PieChart and SankeyChart add tooltip_name/tooltip_value independently of labels painted on the chart. Tooltip::value_color colors the latest row and plain_row adds totals without a swatch; a bar tooltip swatch follows the bar color. (#3228, #3176)

  • Interaction and motion: chart IDs default to their construction site so hover works without an explicit ID; provide distinct IDs when multiple charts share a construction site. interactive(false) removes hitboxes, hover emphasis, tooltips and path caches for placeholders or covered charts. Tooltip glides its own crosshair/dots and grows dot halos with hover progress; Tooltip::glide(false) disables that spring. Custom plots can use PlotHover::glide and the Base hover-motion helpers. (#3173, #3176, #3222, #3258)

  • Painting performance: LineChart and AreaChart use index-based point placement to avoid quadratic value lookups and correctly position duplicate x values at their own indices. Candlestick wicks avoid per-candle path tessellation, and chart hover/painting avoids redundant work. (#3262)

Dock and resizing

  • Nested docks and tab closing: moving a panel from a dock that does not own it no longer creates duplicate or ghost tabs. DockSkin::set_close_button_visible enables built-in close buttons, hidden by default; TabGroupContext::is_panel_closable respects both dock and panel constraints. Custom tab renderers retain control over presentation and frame geometry. (#3197)

  • Continuous bottom-dock resizing: drag a collapsible bottom dock below its minimum, through the closed strip and back open in one motion. Release snaps to the nearer closed or minimum-open state; transient sizes below the minimum are not persisted. Custom resize drivers finish with DockContext::end_resize. (#3229)

  • Resize indicators: dividers grow their indicator as the pointer engages, hugging handles paint their hairline on the seam, and dock hairlines no longer draw over popovers. (#3175, #3200, #3221)

Theme synchronization

  • Theme updates: Theme::update(cx, |theme| ...) edits the global theme, reconciles solid colors and gradient tokens, updates the Base projection, resolves changed fonts and refreshes all windows. Use it for palette, mode, typography and other theme edits instead of manually synchronizing each representation. Theme::global_mut and Theme::sync_base remain available for callers that manage synchronization themselves. (#3122)

Components and accessibility

  • Popover trigger styling: Popover::trigger_style now applies to the actual trigger container, so width/flex refinements affect both parent layout and popup anchoring. Base Popover implements Styled; DropdownMenu keeps Button styling on the Button instead of applying it twice. (#3245)

  • Attachment: composer attachments include on_remove, on_retry, progress(percent) and tooltip; interactive controls and tooltips require id. Progress is 0–100 and clamped. Media receives correctly rounded corners and upload/failure treatments, including retry when a failed image has no source. AttachmentGroup::track_scroll lets the application drive scrolling and with_edge_fade signals clipped attachments. Default chip geometry and failure styling change to the composer presentation. (#3195, #3233)

  • Settings and GroupBox: GroupBox::footer/SettingGroup::footer place supporting content outside the group surface. SettingGroup::variant overrides the Settings::with_group_variant default for one group; GroupBoxVariant::Normal presents items without a card surface. Selecting a group on another settings page now scrolls to the intended group. (#3133, #3203, #3219)

  • Table: TableSelection::{None, Row, Column, Cell} with TableState::selection/set_selection models the active selection as one value. Positional getters return only the active selection type; stale row appearance and accessibility selection state are corrected. Filler rows and cell rendering avoid redundant work. (#3143, #3264)

  • Popover: offset sets the trigger gap and arrow(true) adds an arrow for all eight anchors. Horizontal-center anchor placement is corrected. Popover/AppMenu triggers use the new default Selectable::open/is_open methods to distinguish an open popup from application selection; existing Selectable implementations retain the default compatibility behavior. (#3145, #3125)

  • Dialog: button_props merges explicitly supplied fields, preserving existing Cancel visibility and callbacks. AlertDialog adds ok_text, ok_variant, cancel_text and cancel_variant. Oversized dialogs reclaim the upper window space while normal and stacked dialogs retain their preferred placement. (#3126, #3188)

  • Select: closing an open menu emits DismissEvent, including after Confirm; the popup aligns with the trigger at the right edge. Long option labels truncate with an ellipsis while keeping the checkmark visible. Custom full-row renderers receive a shrinkable container and should apply text truncation themselves. (#3144, #3218, #3280)

  • Menus: context-menu actions fire once on the row actually pressed even when rows share a construction site. PopupMenu, DropdownMenu and Popover release their entities and subscriptions when their host disappears, preventing leaks and stale popup registrations from suppressing later Input context menus. (#3135, #3224, #3267, #3279)

  • Switch: the track shows a keyboard focus ring, with focus_ring(false), tab_stop and tab_index controls. Long labels no longer shrink the track. (#3120, #3154)

  • Sidebar and List: SidebarMenuItem exposes its visible label, TreeItem role and selected state to assistive technology. SidebarMenuItem, ListItem and SidebarToggleButton accept accessibility_label. The focused ListState container carries the List role, and a right-clicked list item retains its outline. (#3160, #3249, #3155)

  • Chat composition: Marker::alignment(MarkerAlignment::{Start, Center, End}) controls row and wrapped-text alignment across variants. Message::id/role provide stable accessibility identity; Message content inherits caller/bubble typography. Ghost Bubble children are no longer clipped. (#3151, #3171, #3172)

  • Form: caller styling such as padding, gaps and background takes effect, and Field::visible(false) actually hides fields without leaving empty grid rows. Hidden fields are not built or laid out. (#3248, #3269)

Performance and resource use

  • Command: unchanged command models retain their measured rows and search results across parent rerenders, while new callbacks and selection updates still apply. Models with custom child closures or changed layout continue to remeasure. (#3268)

  • Tree and SearchableVec: visible tree rows avoid deep subtree clones and defer context-menu entry cloning until the menu opens. SearchableVec filters by indices instead of cloning matching items or entire groups, evaluating each match once. (#3265, #3279)

  • Carousel and Rating: ancestor scrolling no longer rebuilds Carousel geometry or interrupts a running snap animation. Rating repaints on real hover-value changes rather than every pointer movement. (#3266, #3270)

  • Pagination, ColorPicker, Accordion and Notification: ellipsis menus show at most the 100 hidden pages nearest the current page; closed ColorPicker popups defer their bodies; Accordion content unmounts after the closing spring settles; persistent notifications stop lifecycle ticking once transitions finish. See the Accordion state-lifetime note below. (#3279)

Shell, runtime and platform

  • GPUI snapshot: Kit now pins the complete gpui-pre-* snapshot family to =0.3.7, including the newly published bench-metrics package. All 25 snapshot packages resolve together; the independent gpui-pre-reqwest fork remains at 0.12.15. (#3283)

  • Shell inline tokens and TimeField: JavaScript InputState/TextareaState mirror token insertion, draft content, token slots and token click callbacks. JavaScript ranges use UTF-16 offsets, while Rust uses UTF-8 bytes; validation failures expose error.code. Shell also exposes TimeField state/elements. Host integration adds optional retained-state methods via StateMethodDescriptor/StateDescriptor::with_methods and frame-owned interactive token subtrees. (#3113, #3206)

  • Script image policy: HTML/Markdown TextView document images obey the creating script's HTTP GET capabilities, including intrinsic-size measurement and every redirect. Loading is asynchronous, view-owned and canceled on disposal, with timeout/body/redirect limits and no HTTPS downgrade. Non-HTTP(S) document images, including data URLs, are refused; the application-asset image(path) API is unchanged. Base adds a narrow document-image source override for embedders. (#3230)

  • Base controls: Base Dialog centers a normal-flow popup by default and blocks popup presses from reaching its backdrop; Base AlertDialog implements Styled. Base single-line Input vertically centers its text within its frame, while multiline layout is unchanged. These defaults do not alter styled Component Dialog/Input placement. (#3277, #3278)

  • Web and touch: Base WASM examples bundle IBM Plex Sans so .SystemUIFont resolves and canvases render. Centered notification stacks work reliably on the web. A short touch drag that catches an active ScrollBounce no longer produces a reverse fling; intentional longer flings and edge bounce are preserved. (#3235, #3149, #3207)

Documentation and website

  • Versioned documentation: the latest release is served at /, development docs at /versions/main, and release snapshots at /versions/<tag>. Snapshot isolation and version-local links prevent newer pages or navigation from leaking into older docs; shared WASM examples load from the site root, and historical versions without component pages still build. (#3159, #3189, #3243, #3165, #3196)

  • Framework manual: expanded bilingual guides cover Entity, Window, Context, Render, RenderOnce, Element, Action/Event, ownership, focus, tasks, painting, text, accessibility, animation and WebAssembly, with runnable exercises and troubleshooting. New Packaging, Auto Update and Images guides cover distribution, user-level Linux installation, embedded assets, img, svg and HTTP caching. Menu-bar guidance documents binding keys before set_menus, and focus guidance explains explicit Tab stops. (#3179, #3181, #3225, #3232, #3239, #3124)

  • Website themes and navigation: the theme palette reads theme JSON directly, previews and confirms with keyboard navigation, restores on cancel, and synchronizes the chosen JSON with embedded WASM examples. Cmd+K/Ctrl+K opens theme selection; / opens docs search. Text selection uses selection.background, falling back to primary.background, and active sidebar entries are easier to identify. Custom website themes and design-guide illustrations are refined. (#3198, #3241, #3242, #3237, #3211, #3212)

  • Documentation licensing: eligible documentation prose and original illustrations carry CC BY 4.0 attribution; software and code examples retain Apache-2.0 permissions. (#3225)

Breaking Changes

Custom Plot primitives

Component plot import paths remain re-exported, but custom plots must migrate primitive APIs. StrokeStyle/stroke_style are removed in favor of Curve/curve; scale ranges become arrays, domains accept iterators, and PlotValue replaces the hidden Sealed bound. least_index becomes nearest_index; least_index_with_domain is removed. Arc paints/contains use the radii configured on the Arc, and Grid x/y accept iterators. ScaleBand has no implicit 30px cap: set max_band_width if needed. TooltipState, AxisText, label::Text, ArcData, StackPoint, StackSeries, SankeyLink, SankeyNodeLayout, SankeyLinkLayout and SankeyGraph are non-exhaustive and should use their constructors. PlotAxis::default() now equals new() with its x-axis line visible. IntoPlot derives use PlotElement<Self> rather than implementing Element directly; the hidden plot::tooltip::track_hover is removed. Base Theme struct literals need plot. Deprecated aliases remain this release for AXIS_GAP, dot_fill_color, dot_stroke_color, PlotHover::focus and Tooltip::focus; prefer axis_gutter, dot_fill, dot_stroke and progress. Existing chart curve builders remain unchanged. (#3258)

- use gpui_kit::base::plot::StrokeStyle;
+ use gpui_kit::base::plot::Curve;
- Line::new().stroke_style(StrokeStyle::StepAfter)
+ Line::new().curve(Curve::StepAfter)
- Area::new().stroke_style(StrokeStyle::Linear)
+ Area::new().curve(Curve::Linear)
- let y = ScaleLinear::new(values.collect(), vec![height, 0.]);
+ let y = ScaleLinear::new(values, [height, 0.]);
- where Y: Copy + PartialOrd + Num + ToPrimitive + Sealed
+ where Y: PlotValue
- let ix = scale.least_index(tick);
+ let ix = scale.nearest_index(tick);
- arc.paint(&data, color, None, Some(radius), &bounds, window);
+ Arc::new().outer_radius(radius).paint(&data, color, &bounds, window);
- Grid::new().y(ticks.collect())
+ Grid::new().y(ticks)
  gpui_base::Theme {
      appearance,
      tokens,
      scrollbar,
      resizable,
+     plot: gpui_base::PlotTheme::default(),
  }

DatePicker event values

DatePickerEvent::Change now carries DateTime, not Date. Date-only consumers can use value.date(); format keeps its signature. Exhaustive matches on DateRangePresetValue must handle the new DateTime variant. (#3206)

 cx.subscribe(&picker, |this, _, event, _| match event {
-    DatePickerEvent::Change(date) => match date {
+    DatePickerEvent::Change(value) => match value.date() {
         Date::Single(Some(date)) => { /* … */ }
         _ => {}
     },
 });

Base heading styling

Base TextViewStyle removes with_heading_base_font_size, heading_base_font_size, with_heading_font_size and heading_font_size. Use with_heading/heading and a StyleRefinement callback. The Component compatibility facade retains its old fields and builders. (#3129)

-TextViewStyle::default()
-    .with_heading_base_font_size(px(14.))
-    .with_heading_font_size(|level, base| resolve_size(level, base))
+TextViewStyle::default().with_heading(|level| {
+    StyleRefinement::default().text_size(resolve_size(level))
+})

Table selection getters

Each positional getter reports only its active selection type. To obtain the row of a selected cell, map selected_cell() or match selection(); keep inactive-selection history in the application if required. (#3143)

 table.set_selected_cell(5, 3, cx);
-let row = table.selected_row();
+let row = table.selected_cell().map(|(row_ix, _)| row_ix);
 table.set_selected_row(2, cx);
-assert_eq!(table.selected_cell(), Some((5, 3)));
+assert_eq!(table.selected_cell(), None);
+assert_eq!(table.selection(), TableSelection::Row(2));

BarChart tick counts

value_tick_count(n) now means n ticks, not n intervals. Add one to an explicit old count to preserve its appearance. The default changes from four intervals to five ticks, preserving the default chart layout. (#3209)

- BarChart::new(data).value_axis(true).value_tick_count(6)
+ BarChart::new(data).value_axis(true).value_tick_count(7)

Custom tooltip motion

Tooltip now springs its own crosshair/dots. Remove a custom spring or use Tooltip::glide(false) to avoid applying motion twice. Pass full Dot halo sizes; Tooltip applies hover progress itself. (#3222)

- let center = self.band_center.unwrap_or(state.cross_line.x);
- Tooltip::new(cursor, bounds.size)
-     .cross_line(CrossLine::new(point(center, state.cross_line.y)))
+ Tooltip::new(cursor, bounds.size)
+     .cross_line(CrossLine::new(state.cross_line))
- Dot::new(p).halo(px(20. * hover.focus()))
+ Dot::new(p).halo(px(20.))

Shell document image permissions

Script TextView signatures are unchanged, but remote document images now need explicit GET grants for their URL and every redirect target. Non-HTTP(S) sources, including data URLs, are refused; image(path) application assets are unaffected. (#3230)

- Policy::new()
+ Policy::new().with_capabilities(Capabilities::new().http_requests([
+     HttpRequestGrant::new("images.example", ["GET"], ["/image.png"], [] as [&str; 0]),
+ ]))

Select dismissal ordering

Existing DismissEvent subscribers now run when an open menu closes. Confirm emits SelectEvent::Confirm followed by DismissEvent; opening or closing an already-closed menu does not dismiss. (#3144)

 // An existing SelectState DismissEvent subscription after Escape:
-// No callback.
+// One callback after the menu transitions to closed.
 // After confirming an item:
-// SelectEvent::Confirm only.
+// SelectEvent::Confirm, then DismissEvent.

Popover horizontal-center anchors

LeftCenter places the popup to the right of the trigger; RightCenter places it to the left, both vertically centered. These no longer fall back to top-left positioning. Top/bottom anchors keep their default placement and do not flip when clamped. (#3145)

- .anchor(Anchor::LeftCenter)  // Legacy top-left fallback
+ .anchor(Anchor::LeftCenter)  // Right of the trigger, vertically centered
- .anchor(Anchor::RightCenter) // Legacy top-left fallback
+ .anchor(Anchor::RightCenter) // Left of the trigger, vertically centered

Individually disabled Accordion items

An item marked disabled stays disabled instead of being accidentally enabled by its parent. Explicitly enable it if expansion is intended; builder signatures are unchanged. (#3141)

 Accordion::new("settings").item(|item| item.title("Advanced").disabled(true))
-// Clicking Advanced can expand it.
+// Clicking Advanced leaves it closed.

Message typography inheritance

Message no longer imposes text_sm and a 1.25 line height on its subtree. Header/footer typography remains local; bare MessageContent inherits the surrounding style, so explicitly style content that depended on the previous row defaults. (#3171)

- Message::new().content(MessageContent::new().child("plain text"))   // rendered text_sm / 1.25
+ Message::new().content(MessageContent::new().child("plain text"))   // inherits the caller's text style

Base Dialog placement and pointer occlusion

Normal-flow Base popups center by default; style the host to recover top-left placement. Popup presses no longer reach the backdrop, so size popup parts to their content instead of using a full-window popup wrapper. Styled Component Dialog positioning is unchanged. (#3277)

- Dialog::new(cx).popup(popup)
+ Dialog::new(cx).items_start().justify_start().popup(popup)

Base single-line Input alignment

A Base single-line input fills its frame and vertically centers its line. If a tall frame relied on top placement, use a one-line-height frame for the previous appearance. Multiline and styled Component input layout is unchanged. (#3278)

Accordion content lifetime and pagination limits

Closed Accordion content unmounts after its close spring settles, dropping element/keyed state held inside the panel. Preserve durable state in entities. Under reduced motion this optimization keeps content mounted. Pagination ellipsis menus cap hidden-page choices at the nearest 100; use successive menus to reach farther pages. (#3279)

Form visibility and attachment presentation

Field::visible(false) now hides the field instead of being ignored. Attachment has new default chip sizing, radius, status overlays and failure colors; review applications that depended on its former content-sized geometry. (#3269, #3195)

Chart labels and duplicate x values

LineChart/AreaChart position duplicate x values at their individual indices, matching hover. Vertical BarChart with labels reserves slightly more top space (bars draw 2px shorter); PieChart tooltip labels are configured separately from leader-line labels. (#3262, #3217, #3176)

Thank you to everyone who contributed code, documentation, testing, and feedback!

What's Changed

  • chore: Add a /release-notes command by @huacnlee in #3117
  • chart: Start a pie leader line at the lifted slice edge by @madcodelife in #3121
  • chore: Move the tested consumer crate into the workspace by @huacnlee in #3118
  • chart: Fix the pie radius fallback and fit the gallery's region labels by @madcodelife in #3123
  • docs: Bind keys before the menu bar, and say what makes a handle a Tab stop by @huacnlee in #3124
  • input: Add atomic inline tokens to Input and Textarea by @suxiaoshao in #3113
  • switch: Draw the focus ring when the switch is focused by @huacnlee in #3120
  • theme: Add Theme::update to keep colors, tokens and the Base projection in step by @huacnlee in #3122
  • popover: Tell the trigger it is open instead of selected by @huacnlee in #3125
  • popup: Keep the client inset only on untiled window edges by @huacnlee in #3130
  • dialog: Merge button_props instead of replacing them by @huacnlee in #3126
  • questionnaire: Add a Questionnaire component by @suxiaoshao in #2878
  • menu: Draw a context menu only from the trigger that was pressed by @huacnlee in #3135
  • input: Clear the blink state when the cursor stops by @novakduc in #3139
  • input: Do not start the blink cursor on an unfocused input by @novakduc in #3140
  • table: Read and write the selection as one TableSelection value by @violetpurpleish in #3143
  • label: Skip highlights while masked by @violetpurpleish in #3142
  • setting: Add optional footers outside group surfaces by @AprilNEA in #3133
  • accordion: Preserve disabled state of individual items by @violetpurpleish in #3141
  • select: Emit dismissal when an open menu closes by @violetpurpleish in #3144
  • popover: Add offset and optional anchor-aligned arrows by @huacnlee in #3145
  • gpui-pre: Inject staged crates as git dependencies in the kit check by @huacnlee in #3146
  • gpui-pre: Publish even when gpui-kit fails the compatibility check by @huacnlee in #3148
  • kit: Update GPUI to gpui-pre 0.3.6 by @huacnlee in #3147
  • marker: Add alignment for centered and trailing rows by @madcodelife in #3151
  • text: Stagger stream_fade by word, dropping it for oversized chunks by @madcodelife in #3153
  • list: Restore the outline on the right-clicked item by @madcodelife in #3155
  • notification: Fix center notification stacks reliably on web by @huacnlee in #3149
  • kit: Pin gpui-pre to the exact snapshot each release is built against by @huacnlee in #3163
  • website: Publish versioned website builds by @huacnlee in #3159
  • text_view: Add TextViewState::selected_source_range by @tidely in #3136
  • input: Scroll straight to a far-off caret after an edit by @Tryanks in #3150
  • website: Load shared WASM examples from root by @huacnlee in #3165
  • message: Add id and role, stop setting the row's typography by @madcodelife in #3171
  • bubble: Do not clip the children of a Ghost bubble by @madcodelife in #3172
  • chart: Default a chart's id to its construction site by @madcodelife in #3173
  • story: Keep a chart card's legend inside the card by @madcodelife in #3174
  • root: Add Base window hosting and a single Kit startup entry point by @huacnlee in #3152
  • resizable: Grow an indicator as the pointer engages a divider by @madcodelife in #3175
  • markdown: Keep prose inside unclaimed math spans and pair inline HTML tags by @IHadACookie in #3178
  • chart: Let a chart stand down, and let its tooltip say what it means by @madcodelife in #3176
  • website: Add docs for GPUI action, event by @huacnlee in #3179
  • toolbar: Add Toolbar and ToolbarGroup components by @bipinnatus2k in #3128
  • switch: Preserve track width with long labels by @violetpurpleish in #3154
  • website: add GPUI core concept guides by @huacnlee in #3181
  • text: Refine heading styles by level by @wweziza in #3129
  • text_view: Lay an inline flow out once, not every frame by @stippi in #3180
  • website: isolate versioned documentation snapshots by @huacnlee in #3189
  • dialog: Reclaim top space for oversized content by @huacnlee in #3188
  • text_selection: Keep a participant whose cached view replayed its frame by @madcodelife in #3193
  • website: Fix historical website builds without component pages by @huacnlee in #3196
  • resizable: Draw a hugging handle's hairline on the seam by @madcodelife in #3200
  • website: add JSON-backed theme command palette by @huacnlee in #3198
  • dock: fix nested moves and add opt-in tab close controls by @huacnlee in #3197
  • input: Add collection-owned geometric range decorations by @feigeCode in #3040
  • editor: Size line-number gutter between three and seven digits by @huacnlee in #3205
  • input: Let Textarea take a size, like Input by @Alanaktion in #3191
  • highlighter: Remove deprecated usize import by @akeit0 in #3186
  • a11y: accessible names for SidebarMenuItem, ListItem and SidebarToggleButton by @noosxe in #3160
  • setting: let SettingGroup override the settings-level group variant by @ayangweb in #3203
  • mobile: stop reverse fling after short ScrollBounce catch by @huacnlee in #3207
  • website: Refine design guides and restore custom website themes by @huacnlee in #3211
  • chart: Pin the y axis and reserve points in line and area charts, count ticks in value_tick_count by @IHadACookie in #3209
  • website: Pace radius hierarchy animation in distinct phases by @huacnlee in #3212
  • story: Show slider scales through Story composition by @huacnlee in #3213
  • markdown: Fix Markdown ordered-list starting numbers by @wabzqem in #3204
  • select: Stop the popup from overhanging the trigger on the right by @madcodelife in #3218
  • setting: Scroll to a group selected from another page by @madcodelife in #3219
  • chart: Color a bar chart's labels per bar, set its band padding, and keep empty bars visible by @IHadACookie in #3217
  • resizable: Stop a dock handle's hairline from painting over popovers by @madcodelife in #3221
  • date_picker: Support editing the time of day with TimeField by @madcodelife in #3206
  • chart: Label the value axis, lay out the grid and mark reference lines in line, area and bar charts by @IHadACookie in #3220
  • plot: Glide the tooltip's crosshair and dots in Tooltip itself by @madcodelife in #3222
  • text_view: Add range highlights by @white07S in #3215
  • menu: Break Rc cycle that leaked PopupMenu entity on window close by @lysci in #3224
  • text: Throttle streamed-fade repaints to reduce CPU use by @Astro-Han in #3226
  • docs: expand GPUI core guides and improve documentation UI by @huacnlee in #3225
  • chart: Customize series chart tooltips by @IHadACookie in #3228
  • dock: Drag a bottom dock shut and back open in one continuous motion by @madcodelife in #3229
  • attachment: Adopt the composer design with built-in remove, retry and progress by @madcodelife in #3195
  • docs: deepen GPUI manual and add release guides by @huacnlee in #3232
  • base: Bundle IBM Plex Sans so the web examples resolve .SystemUIFont by @ihavecoke in #3235
  • text_view: Add TextViewState::reveal_range by @white07S in #3216
  • highlighter: Read tree-sitter input as bytes to avoid aborting inside multi-byte chars by @huacnlee in #3238
  • website: Make the active sidebar item stand out by @huacnlee in #3237
  • chart: Add chart.grid theme color for grid lines by @madcodelife in #3236
  • text: Keep a line with inline code as tall as a plain line by @huacnlee in #3240
  • docs: add an Images guide covering img, svg and HTTP caching by @huacnlee in #3239
  • website: fix text selection theme token by @yuuzhou5 in #3241
  • shell: Enforce script network policy for TextView images by @lurenjia534 in #3230
  • website: Fall back to primary.background for themes without selection.background by @madcodelife in #3242
  • attachment: Show retry control when failed media has no source by @huacnlee in #3233
  • website: Keep versioned docs links inside their version by @huacnlee in #3243
  • docs: Share repository instructions across coding agents by @suxiaoshao in #3251
  • input: Fix accessibility focus and SetValue by @steipete in #3246
  • text: Avoid quadratic table highlight remapping by @lurenjia534 in #3247
  • form: Apply Styled refinements to Form by @Yi-111-a in #3248
  • list: Paint Role::List on focusable ListState container by @Yi-111-a in #3249
  • input: Revert #3246 to restore reverse tab traversal by @huacnlee in #3253
  • input: Restore guarded accessibility actions without changing tab order by @huacnlee in #3254
  • input: Cover UI workflows and fix disabled focus and vertical selection by @huacnlee in #3256
  • docs: base manual UI review checks on test coverage by @huacnlee in #3257
  • perf(input): reduce redundant work in the code editor by @huacnlee in #3260
  • perf(chart): speed up painting and hover by @huacnlee in #3262
  • perf(text): reduce streaming, hover and selection work in TextView by @huacnlee in #3261
  • perf(table): speed up cell rendering by @huacnlee in #3264
  • perf(carousel): stop relayout on ancestor scroll by @huacnlee in #3266
  • perf(highlighter): reuse injection trees by @huacnlee in #3263
  • perf(tree): avoid cloning subtrees by @huacnlee in #3265
  • perf(form): skip rendering hidden fields by @huacnlee in #3269
  • perf(rating): skip redundant hover repaints by @huacnlee in #3270
  • input: Refresh an open code action menu on a new request by @huacnlee in #3274
  • perf(command): skip remeasuring unchanged rows by @huacnlee in #3268
  • perf(menu): fix DropdownMenu memory leak by @huacnlee in #3267
  • text_view: Avoid quadratic Markdown source mapping by @lurenjia534 in #3273
  • docs(input): context_menu(false) also turns off a custom menu by @huacnlee in #3275
  • input: Paste from the context menu on the wasm by @Muhammad-Owais-Warsi in #3244
  • base: Center the Dialog popup by default and keep presses on it by @huacnlee in #3277
  • base: Center a single-line Input in its frame by default by @huacnlee in #3278
  • perf: reduce redundant work in six components by @huacnlee in #3279
  • select: Truncate overflowing option labels with an ellipsis by @huacnlee in #3280
  • plot: Move plot primitives to gpui-base by @huacnlee in #3258
  • release: Skip Kit compatibility checks when publishing GPUI by @huacnlee in #3282
  • popover: Apply trigger_style to the trigger container by @Yi-111-a in #3245
  • kit: Update GPUI to gpui-pre 0.3.7 by @huacnlee in #3283

New Contributors

Full Changelog: v0.6.6...v0.7.0