Releases
Release notes for every HeroGPUI version, from the repository changelog.
These notes are generated from CHANGELOG.md. Each version is also published as a GitHub Release with the gallery binaries at github.com/Porabuild/HeroGPUI/releases.
v0.14.0
Added
ContextMenu::recipe(name)forwardsTheme.components.menurecipes to the panel, asDropdown::recipedoes, so a context menu takes the same row hover fill,panel_min_width, padding and radius as the app's other menus.ContextMenu::item_contentforwards the row label render closure.item_start_content(|key, InteractiveState| -> Option<AnyElement>)onMenu,DropdownandContextMenu(HeroGPUI extension) draws a caller element as each row's leading content in place ofMenuItem::icon's asset path.Nonekeeps the item's icon, and submenus inherit the closure.
Fixed
extend::app_focus_rootno longer steals the focus from a handle focused before its first paint, such as a view focusing itself while its window opens. The root now claims the focus only when the window has none or the focused element has left the tree; the first Tab with nothing focused still reaches the first tab stop.
v0.13.0
Changed
- The component integration tests run as nine feature-area suite binaries instead of one binary per source file. Module filters retain focused runs, and a suite integrity test catches unregistered sources.
- Keyboard ContextMenu opening uses the focused HeroGPUI control's last painted bounds as its anchor when available; unrecorded content keeps the area-corner fallback. Dismissal still restores the previous focus.
- Website: the search palette follows the ARIA combobox pattern (a
comboboxinput witharia-activedescendantover alistboxofoptions, and a polite result count), and it indexes each component's Rust builders and types from the generated reference data, soselection_modeorListBoxItemfinds the component and opens its builder table. - Website: every page has its own canonical URL, Open Graph and Twitter title and description; the site serves
sitemap.xmlandrobots.txt; component pages link their primary type on docs.rs and their source file on GitHub at the release tag. - Website: a
Content-Security-Policywithframe-ancestorson every route (the WebAssembly gallery gets'wasm-unsafe-eval'and hashes of its inline scripts), and the security headers now also reach the bare/herogpuiroot. The landing specimen starts fetching the artifact on pointer, focus or touch intent instead of on the click. The 82 full-page captures no page showed are no longer published underweb/public/shots/(the catalog tiles stay;.shots/keeps the goldens), and the unusedNativeShotandShotWindowcomponents are removed.web/DEPLOYMENT.mdrecords that pull requests already get Vercel preview deployments.
Added
- Components with an
sxroot slot implement GPUI'sStyledtrait, so callers can use.bg,.w,.roundedand other style methods directly. Direct methods andsxcompose in builder order on the same root slot; independent child parts retain their own styling. TableColumn::frozen(true)fixes leading columns and the selection column while the other columns scroll horizontally. Frozen columns are displayed first; column moves stay within their region, and cell keyboard navigation reveals scrolling cells. The header and plain or virtual rows share the horizontal offset.- CI checks the four library crates' public API with
cargo semver-checksagainst their latest crates.io release on every pull request (a deliberate break carries thesemver:breakinglabel), and the release workflow runs the same check before the GitHub Release and any publish. - CI builds each library crate with
--no-default-features. .shots/lint.sh: the lint gate (workspace-lint inheritance, clippy with warnings denied, cargo-deny) in bash, so it runs on macOS and Linux without PowerShell; CI calls it with--require-deny, and--self-testproves the inheritance check..shots/lint.ps1now only forwards to it..shots/stale_docs_audit.py, part of the parity audit set: fails when a retired fact (a test-binary count, "Git GPUI", a stable wasm32 build, the PowerShell-only lint gate) reappears in CI or agent guidance..shots/package_audit.pyfails whenrust-toolchain.toml's pin stops being a release ofrust-versionor clippy'smsrvdiffers, the reason CI needs no separate MSRV job.docs/upstream/prs/: ready-to-submit upstream Zed patches and PR descriptions againstzed@d89e9c2(gpui-pre0.3.5) for the retired deviations (aria_current, spread-shadow corner radii, rounded content masks, web shift+wheel) and the web IME-mirror resync after paste, with submission steps; and the HeroGPUI-side design for anchoring a keyboard-opened ContextMenu at the focused element.docs/upstream/gpui-web-multithreaded.md: why the multi-threaded web platform (COOP/COEP) was evaluated and not adopted.docs/upstream/gpui-block-future-incompat.md: where theblock0.1.6 future-incompatibility warning on macOS builds comes from (the GPUI macOS stack, and HeroGPUI's ownlocale_configdependency) and the upstream fix to request.
Changed
- The
Cargo.toml-profile (-O1/-O3) test job also runs on pull requests labelledci:opt-levelsor touching build configuration (Cargo.toml,Cargo.lock,rust-toolchain.toml,.cargo/config.toml, the CI Rust environment or the test wrapper); it stays push-only otherwise. - The lint inheritance check now also covers
examples/*and only acceptsworkspace = trueinside[lints](or top-levellints.workspace), not under any other table. - The WebAssembly gallery artifact is no longer committed (the ~19 MB
web/public/gallery/herogpui_web_bg.wasmand its glue are removed from the tree; history keeps them). CI'swasmjob builds it with.shots/build-wasm.shand a new master-push-onlywasm-publishjob uploads it to thegallery-<key16>prerelease per hash of the wasm build inputs (assets attached while it is a draft, so it works with immutable releases on);pnpm run buildinweb/downloads the artifact for its checkout and verifies its SHA-256 first (web/scripts/gallery-artifact.mjs). Vercel pull request previews use master's artifact with an "earlier build" banner, production waits for CI and never ships a mismatched gallery, and a local.shots/build-wasm.shbuild takes precedence.wasm-parity.jsonnow records the artifact key and example bodies only (pnpm run wasm:manifestafter a Rust change; no rebuild). - The wasm build runs binaryen
wasm-opt -O1(version_133, pinned by version and archive digest in CI): -3.6% raw, -0.5% brotli.-Ozwas measured and rejected: 10.7% smaller raw but 3.8% larger compressed. .shots/lint.sh(CI's lint gate) runs clippy a second time with--all-features, somissing_docsand clippy reach the feature-gated code (herogpui-theme'sserdeandwatch,gallery-source).herogpui-componentsreads the system date/time locale itself (system_locale.rs) instead of throughlocale_config, which removes HeroGPUI's own path to theblock0.1.6 future-incompatibility warning on macOS. The sources and precedence are unchanged: the POSIX environment first on every platform (LC_ALL,LC_TIME,LANG, thenLANGUAGE), then the macOS Region (NSLocale.currentLocale) or the Windows regional format, with the preferred languages as fallbacks.
Removed
- Four dead
cargo-denyadvisory ignores and theallow-gitlist fromdeny.toml; the workspace has no git dependencies, so any git source is now denied.
Fixed
Table: a focused row's inset ring and a selected cell's ring no longer widen their column. Both are cell-wide overlays, and the intrinsic measurement that floors each column's track read them as content, so the floor grew by the cell padding on every frame they were shown.Autocomplete::radiusnow overrides only the detached panel, as documented; the closed trigger keeps the field chrome's--field-radiusinstead of also painting the override.- Stale CI, release and agent guidance: test-binary counts, "Git GPUI is not registry-publishable", "stable wasm32 build", "unpublished" crates, "does not publish to crates.io", and advisory reasons naming
gpui 0.2. - Website: a component page's live preview no longer takes keyboard focus when it boots, so Cmd/Ctrl+K search and page keys keep working; the frame takes focus on the first click or Tab into it, and forwards Cmd/Ctrl+K to the page while the reader works inside it.
Added
VirtualListuniform mode:VirtualListHandle::uniform(count)lays every row out at the first row's measured height (GPUI'suniform_list), and without.height(..)the list sizes to its rows.VirtualListScroll::Centercentres a row that is not fully visible, clamped at both ends (in measured mode, a row laid out in the last frame; any other falls back toTop). New handle readings for both modes:viewport_bounds(),remaining_below(),is_scrolled_to_top(),is_scrolled_to_end()andis_uniform().TreeView: Shift range selection inSelectionMode::Multiple— Shift+Up/Down and a Shift press select the visible, enabled rows between the anchor (the last row a press or Space selected) and the target, as React Stately'sextendSelectiondoes and asListBoxalready did; Shift+Home/End only move the cursor. Rows render through a uniformVirtualList, so under the newmax_h(px)(or in a height-bounding parent) only the rows in view are built and the keyboard cursor scrolls into view; an uncapped tree keeps its geometry. Each row reportsaria-posinset/aria-setsizeamong its siblings, as React Aria'suseGridListItemdoes for tree rows. A "Large Tree View" gallery section on the List Box page shows two thousand open rows.ResizablePanel: pixel limitsmin_size_px/max_size_px, combined with the percentage limits (the stricter wins) against the group's measured length for the initial layout, drags, keys and window resizes;collapsibleandcollapsed_size(default 0), so a panel can sit below its minimum at its collapsed size — a drag past halfway collapses or expands it, an arrow key crosses the gap, Home/End reach it, and Enter on a handle collapses the panel before it (or after it, when only that one is collapsible) and restores its pre-collapse size, per the WAI-ARIA window splitter pattern.ResizablePanelGroup::on_resize_endfires once per gesture: on the release of a drag that changed the sizes, and after each key that did. A "Collapsible Panels" gallery section on the Separator page shows them.- Icons:
IconSizesteps (Xs12,Sm14,Md16,Lg20,Xl24px), whichIcon::sizetakes beside a pixel length and throughSizable<Size = IconSize>;Icon::stroke_width(Lucide'sstrokeWidth, in the 24-unit viewBox;DEFAULT_STROKE_WIDTHis 2) andIcon::absolute_stroke_width(Lucide'sabsoluteStrokeWidth). Because gpui paints an SVG as one single-colour mask, a stroke width selectsIconName::path_with_stroke_width(w)(<path>?stroke-width=<w>), whichHeroGpuiAssetsserves as the same Lucide file with its rootstroke-widthrewritten; gpui caches it per path and size. Lucide icons only. .shots/lucide-icons.txtlists the embedded Lucide icons and pins thelucide-statictarball (version and integrity);python3 .shots/sync-lucide.pydownloads and verifies it, copies the listed icons and the license, and regeneratesIconNameandLUCIDE_VERSION.--check(offline, run in CI's parity job) fails when the list, the files, the enum and the NOTICE disagree.- Gallery: an Icons page under Getting Started with the size steps, stroke widths and a searchable grid of every
IconName.
Changed
- Breaking:
VirtualListScrollis#[non_exhaustive](it gainedCenter); amatchon it needs a wildcard arm. See `docs/migration-0.13.md`. - The fixed
row_heightbodies ofListBoxandTableand ComboBox's popover list render throughVirtualList's uniform mode instead of callinguniform_listthemselves. Behaviour is unchanged: the keyboard cursor is still centred, PageUp/PageDown still step by the declared row height over the laid-out viewport, andTable's load-more still arms from the row count times the measured row.
Upgrading from 0.12: see the migration guide for each breaking change with before/after code.
Breaking
i18n::LOCALESandi18n::UiString::ALLgrow (13 locales, 31 keys), so code that named their array lengths no longer compiles; useUiString::COUNTor iterate.NoResults,LoadingandSearchnow have translations in every built-in locale instead of falling back to en-US, so a de-DE app shows "Wird geladen" rather than "Loading" (override withset_ui_stringto keep English).
ThemeBuilder::role,ThemeBuilder::role_hoverandThemeColors::roletake the typedColorrole instead of a&str. An unknown string used to fall back toaccent, so a typo silently recoloured the accent and the focus ring; it is now a compile error.ThemeProvider::init/init_withno longer readHEROGPUI_REDUCE_MOTIONand no longer write GPUI's reduced-motion flag: the library reads no environment variable. Set the preference withset_reduce_motionfrom the application's own settings. The gallery mapsHEROGPUI_REDUCE_MOTION=1onto it, so the gallery's behaviour is unchanged.
Added
#[must_use]on every component (eachIntoElementbuilder) and on the builder data types (ThemeBuilder,ComponentTheme(s), the*Stylerecipes,Toast,TabItem,ListBoxItem,TableColumn,TableRow,TreeItem,ResizablePanel, …): a builder chain whose result is dropped now warns (unused_must_use) instead of silently rendering nothing.
- Every public item in
herogpui,herogpui-core,herogpui-themeandherogpui-componentsis documented, and those crates now#![warn(missing_docs)], so CI'sclippy -D warningskeeps it that way.
Color::from_tokenandimpl FromStr for Color(UnknownColorError): parse a role name from configuration, failing on an unknown name.- i18n: four more built-in locales, ja-JP, zh-CN, ko-KR and ru-RU, and 21 more
UiStringkeys, so the remaining hard-coded chrome strings resolve in the active locale: the NumberField and TimeField stepper names (Increase/Decrease, templates in the locale's word order), the DateField / TimeField segment names (Year…DayPeriod), the DatePicker trigger (Calendar), a selected calendar day (DateSelected), the ColorSlider channel names (Hue…Alpha,ColorChannel::localized_label), Autocomplete's clear button (ClearSelection) and Pagination's name (Pagination). The translations come from the pinned React Aria / React Stately dictionaries.i18n::ui_string_withandi18n::fillfill a template's placeholder. The web gallery bundles a Noto Sans KR subset for Hangul and a wider Noto Sans SC pre-reduction for the Japanese kanji. - Theme hot reload (HeroGPUI extension; new opt-in
watchfeature onherogpui-themeandherogpui, impliesserde):watch_themes_dir(dir, on_reload, cx)polls a theme directory everyTHEME_WATCH_INTERVAL(500ms) and re-registers changed and new*.jsonfiles, so an edit to the active theme applies live;ThemeReloadreports the reloaded ids and parse errors, and dropping the returnedThemeWatcherstops it. Polling on GPUI's executors keeps it dependency-free. The native gallery enables it forHEROGPUI_THEME_DIR=<dir>.
Added
- Table column reordering and cell selection (HeroGPUI extension, after gpui-kit's data table).
allows_column_reorderlets a header be dragged onto another column's place (with a drop indicator) or moved with Alt+Left / Alt+Right while focused;on_column_movereports aColumnMoveand the order is controlled (column_order) or uncontrolled (default_column_order). Cells, resized and measured widths and the tree column follow their column.cell_selectableselects single cells: a press, Left/Right/Home/End within a row, and the row keys to the same column of another row;on_cell_selectreports aTableCellby row key and given column index, and the cell is controlled (selected_cell) or uncontrolled (default_selected_cell). Tables that use neither are unchanged. Two gallery sections on the Table page show them. Toolbar::size,Toolbar::sized_childandToolbar::sized_children(HeroGPUI extension, after gpui-kit's toolbar): the toolbar's size reaches every control added withsized_childwhen the toolbar renders, whatever the order of the builder calls;childelements keep their own size.Toolbar::labelnames the toolbar, or the group a nested toolbar becomes (aria-labelon RAC'sToolbar).ToolbarimplementsSizable. A gallery section on the Toolbar page shows them.TitleBar,WindowBorder,TitleBarControlsandWindowAction(HeroGPUI extension): custom window chrome for frameless windows, on the pinnedgpui-pre0.3.5 window APIs.TitleBar::window_options()hides the system title bar, places the macOS traffic lights and marks the title bar app-owned. The bar's empty area drags the window (start_window_moveon macOS and Linux, theDragcaption area on Windows), a double-click zooms it (the macOS user setting viatitlebar_double_click,zoom_windowon Linux, the OS caption on Windows), and presses on the bar's children stay theirs.TitleBarControls::Autofollows the platform (native traffic lights on macOS; OS-performedMin/Max/Closecontrol areas on Windows; drawn buttons on client-decorated Linux; none on the web),Customdraws minimize, maximize/restore and close everywhere,Hiddennone;on_window_actionreplaces the defaultWindowAction::perform.WindowBorderdraws the shadow, border and resize edges of a Linux client-decorated window and passes its children through everywhere else. The browser has no window to move or zoom. A gallery section on the Toolbar page shows it.Sidebar,SidebarGroupandSidebarItem(HeroGPUI extension): a collapsible application sidebar with a header, groups of menu items (icon, label, badge) under optional labels, and a footer. One item is active (active_keyordefault_active_key, reported byon_select). A collapsible group's heading is a disclosure trigger withDisclosure's measured-height motion and rotating chevron (expanded_keysor each group'sdefault_expanded). The menu is one tab stop: Up/Down/Home/End move over items and collapsible headings (skipping disabled items and closed groups), Right/Left expand and collapse a group, Enter/Space activate, typeahead finds a label. The footer toggle (oris_collapsed/default_collapsed) narrows it tocollapsed_widthand shows each item as its icon named by a right-handTooltip, which opens on hover and on keyboard focus because the focus handle moves with the cursor row. Roles:Navigation,Group,Button+ expanded on collapsible headings,Linkon items. A gallery section on the Tabs page shows it.CommandPaletteandCommandItem(HeroGPUI extension): a modal command search on theModaloverlay stack. It takes the focus into its search field as it opens, keeps Tab inside, closes on Escape or an outside press and returns the focus. Every word of the query must occur in a command's label,keywordsor group (case- and accent-insensitive), through the shared matches cache; commands keep their order under their group headings. Up/Down move the highlight (wrapping, skipping disabled commands), a new query highlights the first match, Enter or a press runs a command (on_select) and closes it unlessclose_on_select(false); each command may show an icon, a description andKbdshortcut keys; no match showsempty_text. Open state is controlled or uncontrolled.is_command_palette_shortcutrecognises Cmd-K (Ctrl-K off macOS) for a root key handler. The gallery shell opens one from any page with that shortcut, and a section on the Modal page documents it.HoverCard(HeroGPUI extension): a card that previews rich content while its trigger is hovered or focused, after Radix'sHoverCard. Hovering the trigger opens it afteropen_delay(700ms by default) and keyboard focus inside the trigger opens it at once; leaving startsclose_delay(300ms), which the pointer reaching the card cancels, so the card's content can be read and pressed. Escape (from anywhere while it is the topmost overlay), a press outside and the focus leaving the trigger close it. The timers use the Tooltip's generation scheme, so a quick pass over a row of triggers opens nothing. Open state is controlled (is_open) or uncontrolled (default_open) and reported throughon_open_change. The card reportsRole::Groupnamed bylabel, not a tooltip. A gallery section on the Tooltip page shows it.
- Tests: the remaining source-text assertions in
crates/herogpui-components/tests/became behaviour and painted-scene tests. The shared harness now reads the painted quads (fill, corners, borders, content mask), the offset focus ring's gap band, and the text style inherited at a caller-owned slot, and observes motion on the real clock. Overlay panels (tooltip, modal, toast, popover, dropdown, alert dialog, the picker panels) are opened through their builders or real input; field-family chrome, radius, padding, font and hover-timing seams are read off the scene.include_str!of component sources went from 115 to 0, and the source-reading tests in the 21 affected files from 63 to 19; each one kept (svg paths and rotations, shadows, the cursor, AccessKit output, text with no probe slot) is listed with its reason intests/README.md. The conversion found thatAutocomplete::radiusreaches the trigger box despite documenting a panel-only override; that case is an ignored test naming the defect.
Added
- Field-trigger hover colours, the rest of the roadmap's phase 2 inventory:
Select::trigger_hover_bg,Autocomplete::trigger_hover_bgandAutocomplete::clear_hover_bg,NumberField::group_hover_bgandInputGroup::group_hover_bg. Each replaces only the hover endpoint of its part's existing fade; focus, invalid, disabled and bare chrome keep precedence. HeroGPUI extensions (v3 tints these parts with a class), shown in "Hover Colours" gallery sections. ColorField::sx, the one field without the slot: it refines the root column on the editable path (through the composedInput) and on the static display alike.ComboBox::min_widthandTabs::vertical_tab_min_width, the roadmap's phase 6 floors: the first replaces the 180px root minimum (still applied only while not full-width), the second the 80px floor on a vertical list's tabs. Gallery "Minimum Width" and "Vertical Tab Width" sections.text_sizeonCheckbox,RadioGroup,TabsandSwitch(phase 5 typography): the label's font size, with v3's 16/20/24 leading for a 12/14/16px size and 20px otherwise. Control boxes, marks, tracks, gaps and descriptions keep their size step. Gallery "Label Size" sections.font_familyonSearchField,NumberField,ColorField,Select,ComboBoxandAutocomplete, completing phase 5's field font seam: the composed fields forward it to theirInput(so caret measurement agrees), the pickers set it on the trigger; detached rows keeprow_font_family.
UiString::LoadingMore:Table's pending load-more row ("Loading…") is the last hard-coded chrome string and now resolves through the i18n catalogue in all 13 locales (UiString::ALLis 31 keys).
Fixed
Accordion(Surface): a solidsxbackground recolours the whole card. Each closed trigger's hover fade rested on the stock surface colour, so the headers painted that surface over the override; the resting endpoint is now the resolved card fill, and hover still fades tohover_bgorbg-default.
Changed
tests/sx_ownership.rshas no pending entries: every inventoried part is either wired to itssxextractor or ruled independent with its reason (the rootsxrefines a wrapper the part does not paint over), and an independent part whose function starts reading the extractor now fails the test until the entry is flipped deliberately.
v0.12.0
Added
MenuBarandMenuBarMenu(HeroGPUI extension): a horizontal bar of Dropdown menus. One trigger is a tab stop and Left/Right rove between the top-level items (wrapping, skipping disabled ones), Home/End jump; a press, Enter, Space or Down opens a menu, the keyboard paths with the first item focused. While a menu is open, Left/Right or hovering another trigger switches menus; Escape, a pick, an outside press or pressing the open trigger closes it and returns the focus to its trigger. It reportsRole::MenuBar, andRole::MenuItemwithexpandedon each trigger. A gallery section on the Dropdown page shows it.ResizablePanelGroupandResizablePanel(HeroGPUI extension): split panels, horizontal or vertical, sized in percent of the space they share, with a drag handle between each pair. A drag captures the pointer and keeps resizing outside the handle; a focused handle moves with the arrow keys along the group's axis (Shift for four timeskeyboard_step) and Home/End jump to the limits. Only the two adjacent panels change, clamped to theirmin_size/max_size;on_resizereports every change, andsizes(..)makes the group controlled. Each handle is a tab stop that reportsRole::Splitterwith its orientation and a value range. A gallery section on the Separator page shows it.TreeViewandTreeItem(HeroGPUI extension): a tree of expandable rows with one tab stop. Up/Down/Home/End move over the visible rows (skipping disabled ones), Right expands a parent and then enters its first child, Left collapses it and then moves to the parent, and typeahead finds a row; the chevron toggles a parent under the pointer. Selection followsListBox(None,Single,Multiple; Escape clears), and expanded and selected keys are each controlled or uncontrolled. It reportsRole::Tree, andRole::TreeItemwith level, expanded and selected. A gallery section on the List Box page shows it.IconandIconName(HeroGPUI extension): a public icon set of 245 curated Lucide icons, copied verbatim fromlucide-static1.31.0 and embedded inherogpui-components, soHeroGpuiAssetsserves them with no setup underherogpui/icons/lucide/<name>.svg.IconNameis#[non_exhaustive]withALL,name,path,svg,from_nameandfrom_path, and converts intoSharedString, so every builder that takes an icon path takes a name.Icon::new(name).size(px).color(hsla)draws one (16px in the theme foreground by default);Icon::from_pathdraws any other served SVG. Theiconschrome constants are unchanged. Lucide's ISC license (with the Feather MIT notice) ships beside the SVGs and is attributed inNOTICE;herogpui-componentstherefore declareslicense = "Apache-2.0 AND ISC AND MIT", the GitHub Release attaches the text asLICENSE-lucide, and the website serves it as/LICENSE-lucide.txt.- Gallery: a theme picker in the navbar switches live between the light and dark bases and every built-in preset (
ocean,forest,midnight,rose), natively and in the web build. A control request'stheme=now selects that base theme by id, so a capture never keeps a preset. ContextMenuopens from the keyboard: Shift+F10 or the ContextMenu key (menu;contextmenuon the web) while the focus is inside the area opens the menu at the area's top-left corner with its first item focused, and closing it returns the focus to the element that held it. The area owns a focus handle outside the tab order, so a primary press on non-focusable content makes it reachable. The area element is nowposition: relative(it measures itself with an absolutely placed probe), so absolutely placed content inside it positions against the area.
Fixed
HeroGpuiAssetsnow embeds everyiconschrome path. It was missing eight (calendar,info_circle,check_circle,circle_exclamation,warning_triangle,loader_2,trash,gear), so an app that registered it alone drew no DatePicker calendar glyph and no Alert, AlertDialog or Toast status icon; only the gallery's own asset source had them.
Changed
ListBoxandTablerender theirestimated_row_heightbodies throughVirtualList, on the sameListStateas before, so measurement, paging, load-more and scroll-into-view are unchanged. Their fixedrow_heightpath and ComboBox's popover list stay onuniform_list: it centres the keyboard cursor, ListBox and Table page by the declared row height, and Table arms load-more from the uniform list's viewport and content size; seedocs/customisation-roadmap.md.- 34
radiussource-text assertions intests/radius_builders.rs(the builder-stores and render-resolves checks of 17 components) are replaced by a painted-scene test (tests/radius_painted.rs) that checks, for each of those components, that the default paints its owning helper's radius and that.radius(..)replaces it on the rendered quads.
v0.11.0
The parity target moves from HeroUI v3.2.5 to HeroUI v3.2.6 (tag v3.2.6, commit e385ac20). Inherited behavior now follows React Aria 3.52.1, React Aria Components 1.21.1 and React Stately 3.50.0. HeroUI 3.2.6 changed no theme tokens, so herogpui-theme is unchanged.
Upgrading from 0.10: see the migration guide for each breaking change with before/after code.
Breaking
Separatorno longer implementsParentElement: the content mode (Separator::new().child("OR"), a line, the content, a line) is removed. v3'sseparator.tsxrenders a childless React Aria separator at both 3.2.5 and 3.2.6, and 3.2.6 deleted the never-applied.separator__container,__lineand__contentrules the mode was modelled on. Place separators between blocks instead, as v3's "With Content" example does.- Public API hardening:
herogpui_components::utilis private. The helpers supported for custom widgets move to the newextendmodule (herogpui::extend): the radius scale (control_radius,soft_radius,small_radius,mark_radius,key_radius,hairline_radius,micro_radius,field_radius,container_radius),FIELD_HEIGHT/FIELD_TEXT/FIELD_ICON,cursor_interactive/interactive_cursor,focus_visible/set_focus_visible,inner_fill_radius,shift_wheel_scroll_xandapp_focus_root. The render-prop payloadsFieldFocus,SelectionValueandInteractiveStateare re-exported at the crate root. Every other formerutilitem (field chrome, overlay stack, focus-ring plumbing,sxextraction) is no longer public; the unusedprominence_bg,placed_panel,placed_field_panelandfocusableare deleted.pub use anim::*is gone: motion tokens and wrappers are reached asherogpui::anim::…(herogpui_components::anim::…) instead of at the crate root.#[non_exhaustive]onTheme,ThemeColors,FieldColors,LayoutTheme,ComponentThemes,ComponentTheme,ButtonStyle,SliderStyle,SwitchStyle,SelectStyle,MenuStyle,TextFieldStyle,TabItem, and every render-prop payload (InteractiveState,FieldFocus,SelectionValue,AccordionItemState,CalendarCellState,RangeCalendarCellState,CheckboxState,SwitchState,RadioOptionState,ColorAreaThumbState,ColorSliderThumbState,ColorSwatchPickerItemState,ColorFieldRenderState,DateFieldRenderState,DatePickerRenderState,DateRangePickerRenderState,DisclosureRenderState,TextFieldRenderState,SearchFieldRenderState,NumberFieldRenderState,TimeFieldRenderState). Outside the crates they can no longer be built with a struct literal (not even with..Default::default()); use their constructors, builders orDefaultand assign fields.use_themeandThemeProvider::set_activereturnResult<(), UnknownThemeError>. An unregistered id (ids are case-sensitive) is refused and leaves the active theme and every window untouched; it previously installed the id and panicked on the next frame.Modal::on_closeandDrawer::on_closereceive&DismissReason(CloseButton,Escape,Backdrop,Drag) instead of a&ClickEvent, which Escape and backdrop dismissal used to fabricate withClickEvent::default().modal::OnClosechanges accordingly.herogpui::gpuiis now documented (it was#[doc(hidden)]) as the stable path to GPUI items, including the eight the HeroUI vocabulary shadows at the root. The rootuse herogpui::*;still carries all of GPUI.
Added
AvatarGroupandAvatarGroupCount, the v3.2.6 compound:size,colorandvariantflow to directAvatarchildren that omit them,maxtruncates and appends an automatic+Ncount, an explicit count is never truncated and suppresses the automatic one,is_gridwraps with a 12px gap, andoverlap(AvatarGroupOverlap::{Clip,Ring})selects the stacked seam. Upstream'sclipcrescent is a CSS alpha mask that pinned GPUI cannot draw; the port paints the seam in the surface colour instead (documented platform limitation).- An AvatarGroup gallery page and reference metadata; the Avatar page's hand-built "Avatar Group" section moves there.
- HeroGPUI extensions (not HeroUI v3 APIs), adopted from gpui-kit patterns:
- Shared builder traits
Disableable(is_disabled),Sizable(size, with the component's own scale asSizable::Size) andSelectable(is_selected), implemented by delegating to the existing inherent builders, which stay the documented API. herogpui_components::i18n: a component chrome string catalogue withset_locale,locale,ui_string,set_ui_stringandlookup. The Select/Autocomplete placeholder, Autocomplete's empty state, and the CloseButton, Spinner, calendar Previous/Next, Tag remove and Breadcrumbs names resolve through it. Built-in translations for de-DE, es-ES, fr-FR, it-IT, nl-NL, pl-PL, pt-BR and sv-SE come from the pinned React Aria dictionaries; en-US output is unchanged when no locale is set.- Theme files (
serdefeature):register_theme_json,load_themes_dir,ThemeLoadError, a checked-in JSON Schema (THEME_SCHEMA,crates/herogpui-theme/theme.schema.json) and four preset themes (presets::PRESETS,presets::register_presets: ocean, forest, midnight, rose).ThemeProvider::insertregisters without activating;ThemeProvider::theme_idslists the registry. herogpui::test(test-supportfeature):open_windowand theTestWindowExthelpers (find,expect,click,click_at,hover,press,type_text,scroll,settle) for downstream UI tests.VirtualList/VirtualListHandle/VirtualListScroll: a variable-row-height virtual list withscroll_to_item,spliceandset_item_count, with a "Virtual List" section on the ListBox page.ContextMenu: the DropdownMenuopened by a secondary press at the pointer, with a "Context Menu" section on the Dropdown page.examples/workspace crates (hello-button,form,theme-switch),CONTRIBUTING.mdwith a required## Public APIpull request section, and.github/pull_request_template.md.
Changed
- Internal:
CalendarandRangeCalendarshare one keyboard controller (calendar_keys) for grid navigation, visible-window paging and the year picker;Table::renderis split into named part renderers (header cells, resize handle, virtual projection, body rows, row keyboard, load-more). Behavior is unchanged. - Avatar: small fallback text is 12px/16px (
.avatar--sm .avatar__fallbackistext-xsin 3.2.6). - Breadcrumbs: the root gaps items by 6px (
gap-1.5), an item gaps its link and separator by 4px (gap-1), and neither the item nor the link carries padding any more. - Autocomplete gallery "Custom Value" example follows v3.2.6's currency specimen: symbol, code and muted name in the trigger.
- The pinned docs bundle, CSS and demo archives, reference metadata source links, audits, inventory and guides move to v3.2.6. The web site pins
@heroui/react3.2.6,react-aria3.52.1 andreact-aria-components1.21.1, adds@internationalized/date(now a HeroUI peer) and drops the unused@react-aria/i18n.
Fixed
- Theme documents (
serdefeature) reject a non-finiteoklch()component (NaN,inf) withThemeDocumentError::Color;f32parsing accepted them, so a theme file could register colours that are not numbers. - Text editing (
Input,TextField,SearchField,TextArea): Backspace, Delete and Left/Right (with or without Shift) step by extended grapheme cluster, so an emoji with a modifier, a ZWJ sequence, a flag or a letter with combining marks is one caret stop and one deletion instead of being split. Adds theunicode-segmentationdependency (MIT OR Apache-2.0, already in the graph through GPUI). - Switch: the built-in label uses the shared
.labelstyle, 14px/20px medium. It previously painted 16px/24px from a.switch__labelrule that v3 never applied (3.2.6 deleted it); this corrects a latent error, not a 3.2.6 behavior change.
v0.10.2
Security
InputwithInputType::Passwordno longer writes its value to the clipboard on Cmd/Ctrl+C or Cmd/Ctrl+X, and cut no longer deletes the selection, matching browser behavior fortype="password".
Changed
gpui-preandgpui-pre-platformare pinned exactly at=0.3.5;.shots/package_audit.pyrejects any non-exact requirement.- The release workflow runs the full CI workflow on the tagged commit and builds, releases and publishes nothing unless it passes.
Fixed
- Documentation:
herogpuiis on crates.io (herogpui = "0.10"); the retired setup script,.vendor/, git-hook and patch instructions are gone from the README;gpui-preis correctly attributed to crates.io user huacnlee (Jason Lee, the gpui-kit maintainer), not zed-industries.
v0.10.1
Added
- Tabs: per-segment
width,heightandpadding_xoverrides for icon-only toolbars, a tray-inset override, andhover_fill(false)to use a text-colour hover instead of the fill wash.
v0.10.0
Breaking
MenuItem::Itemgained theis_interactivefield andMenuItemis now#[non_exhaustive];MenuItem::newand its builders are unchanged.
Changed
- Menu separators default to HeroUI v3.2.5's proportional rule (3% inset per edge, 94% width);
MenuStyle::separator_inset/separator_thicknesspin pixels explicitly.
Added
- Menu:
is_interactiverows; Select trigger and option rows stop click propagation so hosted controls compose. - Select:
SelectStyle::padding_y,Select::item_leading. - Tooltip: element bodies via
Tooltip::body. - Theme:
RoleColor::with_hover,ThemeBuilder::role_hover/accent_hover,roles.<role>.hoverinThemeDocument. - Facade: GPUI's
FluentBuilderre-exported at the crate root. - Button:
width,min_width,height,padding_x,text_size,font_weight,grow. - Spinner:
size_pxand a replaceable glyph. - Tabs: icon-only
TabItem::trigger,radius,list_bg,indicator_bg,indicator_shadow. - Scrollbar:
track,inset,radius,thumb_color,thumb_hover_color,auto_hide(false),sx. - ColorField:
on_blurand built-in revert-on-blur of invalid text.
v0.9.0
Added
- First crates.io release of
herogpui,herogpui-core,herogpui-theme,herogpui-componentsand theherogpui-galleryCLI, built on the publishedgpui-pre0.3.5 crates with no GPUI fork.
How releases work
HeroGPUI uses one version across its crates and the herogpui-gallery CLI. Each release is cut from a vX.Y.Z Git tag that must match the workspace version in Cargo.toml. The release workflow runs the workspace test suite, builds the gallery for Windows, macOS and Linux, attests the binaries, and creates the GitHub Release that ships them. See the installation guide to add HeroGPUI to a Rust project.