GPUI Kit 0.7.0: migration and capabilities
Read this when upgrading to 0.7.0 or choosing its new APIs. Audited on
2026-10-01 against the release notes,
tag commit 0c830f4d257e69fdd17200650533ab4ca9a40cc0,
manifest, and
facade source.
The complete 183-page documentation bundle supplies the
full API guides; this reference identifies upgrade decisions and routes them.
Version and framework choice
- Kit
0.7.0pins its GPUI snapshot to=0.3.7. Keep the related snapshot packages aligned through Kit; its independentgpui-pre-reqwestfork uses=0.12.15. Do not override GPUI separately to obtain a newer API. - Application imports remain
gpui_kit::*,gpui_kit::component,gpui_kit::base,gpui_kit::assets, andgpui_kit::platform.gpui-shellremains separate for JavaScript extension hosts. - Preserve the framework choice policy: recommend Kit and obtain agreement before adoption/migration. An authorized upgrade of an established Kit app does not reopen that choice.
- Some refreshed website examples still specify
0.6/0.6.5; they do not override the 0.7.0 release manifest. Confirm signatures in the selected tag and target lockfile instead of combining examples from incompatible versions. - Upstream advertises release docs at
/versions/<tag>and development docs at/versions/main. Verify availability before relying on them; tested 0.7.0 installation Markdown URLs returned 404 during this audit.
New components and changed capabilities
| Task | Read | 0.7.0 contract to preserve |
|---|---|---|
| Command rows | Toolbar | Toolbar/ToolbarGroup retain source order and accessible groups. child/children accept sized controls; content/contents preserve custom dimensions. Buttons become compact ghost controls. Small is the default; Large resolves to Medium. Left/Right wraps through enabled controls; disabling navigation does not disable them. |
| Structured questions | Questionnaire | One retained QuestionnaireState owns single/multiple-choice and freeform answers, validation, optional skip, keyboard navigation, progress, and submission. Compose its parts around that owner. |
| Time and date editing | TimeField, DatePicker | TimePrecision::{Minute, Second} and HourCycle::{H23, H12} configure segments. DatePicker exposes time_precision, hour_cycle, default_time, date_time/set_date_time, and date/time presets. Time-enabled single mode emits Change for each edit while staying open; range mode remains date-only. |
| Mentions and command tokens | Input | Opt-in InlineToken, insertion/replacement, InputContent, and token activation retain atomic navigation/deletion/undo while values and clipboard stay plain text. Rust ranges use UTF-8 bytes; Shell ranges use UTF-16 offsets. Tokens are unavailable in Editor, NumberInput, password, and masked inputs. |
| Editor decorations and menus | Input | InputExtras::range_decorations uses UTF-8 byte ranges. Textarea supports sizing. InputState::context_menu(false) disables the entire menu, including a custom builder; leave it enabled for custom menus. |
| Markdown selection/search | TextView, Base TextView | selected_source_range() refers to original Markdown bytes. Search rendered_text() for rendered-copy byte ranges, apply RangeHighlight with set_range_highlights, and reveal with reveal_range/on_reveal. Highlights are Markdown-only; reveal is best effort. Do not mix the two offset spaces. |
| Live and custom charts | Charts, Base plot | Fixed y_domain, reserved point_count/band_count, axes/grids/reference lines, labels, and tooltip callbacks support streaming series. chart.grid separates grid color from borders. Use distinct IDs for charts sharing a construction site; interactive(false) removes hover work. Base primitives need no Component dependency. |
| Dock movement and resizing | Dock, Base Dock | Nested moves preserve ownership. Close buttons are opt-in through DockSkin::set_close_button_visible. Bottom docks can close/reopen in one drag; finish custom resizing with DockContext::end_resize and avoid persisting transient sizes below minimum. |
| Theme changes | Theme | Prefer Theme::update(cx, ...) to reconcile colors, gradients, Base projection, fonts, and window refresh. global_mut/sync_base remain available for deliberate manual synchronization. |
| Forms and settings | Form, Settings, GroupBox | Form styling applies; hidden fields are not built or laid out. Group footers live outside their surface; per-group variants override Settings defaults. Cross-page group selection scrolls to its target. |
| Attachments and chat | Attachment, Message, Marker | Remove/retry/progress/tooltip controls require attachment identity; progress uses 0–100. Group scroll tracking and edge fades are available. Message has stable id/role and inherits content typography; Marker has Start/Center/End alignment. |
| Accessibility and popups | Switch, Sidebar, List, Popover, Dialog | Use exposed labels, focus rings, and explicit tab stops. Popover trigger styling affects its real geometry; Selectable::open distinguishes popup openness from selection. Dialog button properties merge supplied fields; AlertDialog supports text/variant customization. |
| Script host integration | Shell state, Host API, Capabilities | Inline tokens and TimeField are exposed to scripts. Retained state can expose StateMethodDescriptor through StateDescriptor::with_methods; token subtrees are frame-owned. Remote TextView images require HTTP GET grants for the original URL and every redirect. |
| Distribution and framework manual | Packaging, Auto Update, Images, complete index | Use the expanded ownership, focus, input, testing, and platform guides. Bind keys before set_menus; a focus handle needs an explicit Tab-stop contract. Packaging/updater ownership stays with the application. |
| Browser and mobile hosts | WebView, WebAssembly, Mobile | WebView is experimental on macOS/Windows with an unfinished Linux path. Browser examples use one top-level canvas/window. Mobile validation covers a limited chat subset; its pinned example uses GPUI 0.3.4 and needs platform/renderer alignment before using Kit 0.7.0's 0.3.7 snapshot. |
Window hosting migration
Read Root and Window.
Call gpui_kit::init(cx) before creating windows. The verified helper returns
Result<(AnyWindowHandle, Entity<V>)> and supplies one Base-owned Root:
let (window_handle, content) =
gpui_kit::open_window(options, cx, |window, cx| {
build_content(window, cx) // Entity<V>, not Entity<Root>
})?;In async work, call it within cx.update. Retain the content entity when
application state needs it. Quit/close actions and unsaved-change flows remain
application-owned.
- Delete
Root::render_dialog_layer,Root::render_sheet_layer, andRoot::render_notification_layercalls: those APIs are removed and Root mounts the layers itself. Do not wrap the helper's content in another Root. - Move old root-level dialog/sheet/notification operations to Component
WindowExt:window.open_dialog(cx, build),window.close_dialog(cx),window.close_all_dialogs(cx),window.open_sheet_at(placement, cx, build),window.close_sheet(cx), and the corresponding notification operations. - Use Base
TextSelection::{selected_text, has_selection, clear, end}for old window/root selection helpers. Usewindow_border()withWindowOptionsinstead of oldRoot::bordered/window_shadow_sizehelpers. Verify the actual imports and arguments in the locked source. - Custom design systems can register
RootPluginfactories before opening windows. Plugins run in registration order and are per-window; replacing a factory affects future windows and does not retrofit existing roots. - Explicit low-level
cx.open_windowremains possible with one correctly constructed Root. Cargo feature unification does not select a different root type. Do not migrate an older app's overlays without checking its source.
Breaking changes
Review every row against actual callers; many changes affect behavior or appearance even when the app still compiles.
| Affected API/behavior | Required adaptation |
|---|---|
| Custom plot location and element | Prefer gpui_kit::base::plot; Component paths remain re-exported. IntoPlot derives now produce PlotElement<Self> instead of implementing Element directly. Hidden plot::tooltip::track_hover is removed. |
| Plot curves, scales, and bounds | Replace StrokeStyle/stroke_style with Curve/curve. Scale ranges are arrays, domains accept iterators, and generic values use PlotValue instead of the hidden Sealed bound. least_index becomes nearest_index; least_index_with_domain is removed. Grid x/y accept iterators. |
| Plot geometry and construction | Configure Arc radii on the Arc before paint/contains. Base ScaleBand has no implicit 30px cap; set max_band_width when needed. PlotAxis::default() now shows the x-axis line, matching new(). Base Theme literals need plot. |
| Non-exhaustive plot types | Use constructors for TooltipState, AxisText, label::Text, ArcData, StackPoint, StackSeries, SankeyLink, SankeyNodeLayout, SankeyLinkLayout, and SankeyGraph. |
| Deprecated plot aliases | Prefer axis_gutter, dot_fill, dot_stroke, and progress over AXIS_GAP, dot_fill_color, dot_stroke_color, and PlotHover::focus/Tooltip::focus. Existing styled chart curve builders are unchanged. |
| DatePicker values | DatePickerEvent::Change carries DateTime, not Date. Date-only consumers use value.date(). Exhaustive DateRangePresetValue matches handle its DateTime variant. format keeps its signature. |
| Base headings | Replace with_heading_base_font_size, heading_base_font_size, with_heading_font_size, and heading_font_size with with_heading/heading and a level-aware StyleRefinement. Component retains compatibility builders/fields. |
| DataTable selection | Match TableSelection::{None, Row, Column, Cell} or use the active positional getter. A selected cell's row comes from selected_cell(), not selected_row(). Inactive selection history belongs to the application. |
| BarChart ticks | value_tick_count(n) now counts ticks rather than intervals. Increment an explicit old count by one to keep its appearance. The new default is five ticks, preserving the old four-interval layout. |
| Tooltip motion | Tooltip springs its own crosshair/dots. Remove a custom spring or choose glide(false); supply full dot halo sizes because Tooltip applies hover progress. |
| Shell document images | Grant GET for the URL and every redirect. Non-HTTP(S) sources, including data URLs, are refused; HTTPS downgrades are rejected. App asset image(path) is unchanged. |
| Select dismissal | Closing an open menu emits DismissEvent. Confirmation emits Confirm then DismissEvent; opening or closing an already-closed menu does not dismiss. Check callbacks that would now run twice. |
| Popover anchors | LeftCenter puts the popup to the trigger's right; RightCenter puts it to the left, both vertically centered. These replace the old top-left fallback; top/bottom anchors retain their placement. |
| Disabled Accordion items | An individually disabled item stays disabled. Explicitly enable it if expansion was intended. |
| Message typography | Bare MessageContent inherits caller typography instead of imposing text_sm/1.25. Explicitly style content that needs the old appearance. Header/footer styles remain local. |
| Base Dialog | Normal-flow popups center by default. items_start().justify_start() restores top-left hosting when needed. Popup presses no longer reach the backdrop; size popup parts to their content. Component Dialog placement is unchanged. |
| Base single-line Input | Text fills/centers vertically in its frame. Use a one-line-height frame for the former top-aligned appearance. Multiline and Component layout are unchanged. |
| Accordion lifetime / Pagination | Accordion content unmounts after its closing spring settles; store durable state in entities. Reduced motion keeps content mounted. Pagination ellipsis menus show only the nearest 100 hidden choices; farther pages need successive menus. |
| Field visibility / Attachment | Field::visible(false) now hides the field. Review attachment chip sizing, radius, status overlays, and failure colors against the new defaults. |
| Chart labels and duplicate values | Line/Area charts place duplicate x values by their own indices. Labeled vertical bars reserve slightly more top space (bars are 2px shorter). Pie tooltip labels are configured separately from leader-line labels. |
Validation for an upgrade
Record old/new versions, feature changes, lockfile, and release source. Build and test the owning crate using the project versioning workflow. Exercise affected UI contracts: one Root per window, overlay stacking and focus restoration, date-only/time editing events, selection transitions, popup confirmation/dismissal, close/reopen state, chart geometry/hover, theme changes, and script image permission failures as applicable.
Include Unicode token/range tests when touching editing: Rust UTF-8 bytes, Shell UTF-16 offsets, rendered Markdown copy offsets, and original source offsets are distinct contracts. Cover IME, undo, disabled focus, and stale async completions in the real input workflow. New input/text/chart caching and resource-release fixes do not establish performance in the downstream app; measure relevant large-data, streaming, hover, and close/disposal paths.
Launch the real app on each claimed platform and compare the affected visual states. This skill refresh does not claim to compile or run a Kit consumer.
Credit: GPUI Kit's release notes, tagged source, and official documentation. This is an adapted migration summary and documentation router. Eligible upstream documentation prose uses CC BY 4.0; software/code examples use Apache-2.0.