Repository navigation
feat: UX refinement pass: undo-first actions, Invoke card routing, queue cache popover, canvas without the generation lock, layered project settings - #10074
Conversation
…d aspect placeholders Unknown progress uses the shared spinner in gallery tiles and the Canvas staging placeholder. Queued tiles keep their aspect in aspect mode; following a tile reveals Preview where it is docked through one Workbench placement command that recall shares.
Required empty slots show a select prompt, an invalid state and the core missing message instead of "Model default".
…ction on Escape Media gets a Filter & sort menu sharing the boards menu frame; the starred toggle stays separate. Escape no longer clears the selection; Clear Selection has no default key.
…nd icons for canvas destinations Zoom gains a magnifier and a fixed width; save becomes one menu for canvas or frame with a busy state. The image menu, Preview Edit menu and paste dialog share one destination list with Layers panel icons.
…itle, align header controls Details stays open while working elsewhere, follows the selection and uses segment tabs with disabled states. An x after the image name clears the selection; auto-switch and zoom match the header size with mode icons.
…with Scrollable Every manager focuses its search on "/" through ManagerLayout; Settings composes the shared search field. The sidebar and open projects list use Scrollable, the list shrinking before the sidebar scrolls.
The models queue footer, table and rows move into platform ManagerQueue; nodes render through it with retry, open and remove actions, and Clear finished keeps installs that are still running.
A Behavior preference chooses the Launchpad or the most recent project when the app opens at its bare URL; deep links, reloads and later visits to Home are never redirected.
…its own group Menu titles use MenuHeadingGroup; app, project and queue menu chevrons brighten alike on hover and open. Donate moves after the Manage group, ahead of the account section and icon row.
Names MOSS-Image, Qwen-Image-2.1 and FLUX.3 Klein alongside the new video models.
…wners searchShortcut and layerTypeIcon join existing shared chunks so startup request counts hold. Owner sets gain the new modules; the build baseline is re-recorded.
Center-area header islands cap their width and show a fading edge cue with a button that jumps to the start or end. The cue blocks clicks on items beneath it and forwards wheel input to the strip.
Board submenus share a scrolling menu that fills the available height and keeps the keyboard highlight in view. Used by the image context menu, Gallery selection bar and board menu, and the layer save-to-board menu.
Every Generate settings toggle uses one row: the label toggles it, wraps instead of truncating, and keeps the switch at the trailing edge. Override switches are named after their setting, with the slider below when on; paired controls and previews sit outside the label.
Adds ChromeIsland, wheelScrollsHorizontally and ScrollableMenuContent to the editor owner sets and re-records route bytes.
…ct flush The heal dispatched its first no-op scroll synchronously inside the mount effect, so any virtualizer still using flushSync logged "flushSync was called from inside a lifecycle method" when the Projects page or the editor opened. The first check now runs in a microtask, still before the next paint, with a disposed guard. Projects browser opts out of flushSync like the other list virtualizers; comments describe the remaining reason.
…anel is open The lazily mounted panel paints one frame at the origin over its wide trigger, which fires a pointer leave and lets the tooltip reopen on top of the panel header. Force the tooltip shut while the popover is open.
…s and color swatches Project pin buttons and the color target chips relied on the native title attribute. They now use the platform Tooltip, and the swatch tooltip names the target and its hex through a locale key.
… menu
The settings popover repeated its group headings as field labels ("Thumbnails / Thumbnails", "Pagination /
Pagination"); fields now read "Thumbnail shape" and "Page loading" under a "Grid" group. Boards without videos
offer a plain "Download board", and the board menu's download, archive and delete labels use sentence case.
… scope Queue actions, queue header items and the graph menu mixed Title Case with the sentence-case labels around them. The fonts upload scope read "My font" next to "My fonts" elsewhere.
…nimap, data-list selector The splash heading wrapped the version mid-token; it is now a mono badge under the app name and the unused combined locale key is gone. Fonts' empty state used the node-pack icon. An empty workflow rendered a bare minimap panel. The data-list divider selector no longer triggers emotion's first-child warning.
… notices Notification actions are data (open widget, undo, reveal or retry a queue item) with typed handlers, undoable toasts carry project scope and supersede each other, and confirm dialogs take a cancel label.
…state Cheap actions never confirm and bulk actions always name their scope, failures stay as notices with Show in queue and Retry, stats become filter tabs, and rows take their titles from prompts.
…for moves Selection follows what is visible, delete dialogs list thumbnails, board delete keeps media by default, and "Saving to" names the destination with follow-the-selected-board as an opt-in.
…ues inline Switching the base model keeps LoRAs badged instead of deleting them, missing models stay selected with a fix path and rematch by hash, presets and reset offer Undo, and validation issues sit next to their fields.
…ad errors Programmatic prompt edits keep native undo and never target the wrong field, dynamic prompts get a switch and a comment warning, and templates and wildcards show proper error states.
The Invoke button opens a card naming each blocker with a jump to its fix, layout changes undo with Mod+Alt+Z, the Widgets dialog lists every widget and placement, and the router error screen offers Reload, Home and Copy details.
…artup escape Clearing saved data lives in a danger area, session expiry warns ahead and returns to where you were, load errors never look empty, and the startup redirect can be left for the Launchpad.
Placement checks no longer load widget implementations on open, and no-op layout steps stay out of the undo stack.
…bility model Tool options survive engine disposal, refused edits explain themselves, restore points cap per kind, layers have a single visibility, and the marquee, shape and color picker shortcuts move to M, U and I.
# Conflicts: # docs/src/content/docs/development/Guides/family-e2e.mdx
# Conflicts: # invokeai/frontend/webv2/src/features/generation/core/baseGenerationPolicies.test.ts # invokeai/frontend/webv2/src/features/generation/ui/promptFields/ExpandPromptSuggestion.browser.test.tsx # invokeai/frontend/webv2/src/features/generation/ui/promptFields/GeneratePromptFields.tsx # invokeai/frontend/webv2/src/features/generation/ui/promptFields/PositivePromptField.browser.test.tsx # invokeai/frontend/webv2/src/workbench/invocation.ts
…into feat/ui-tweaks-05
Review notes, round 2 (head
|
…r the dot actions A cog on a second Gallery view wrote pins onto that alias instance, which nothing reads; pins now live on the project's instance of the owner type and an instance target only fences. Use as my default, Follow my default and Reset to Invoke default report with an Undo that restores by project id while the state still holds what they wrote.
The undo closure was released when its toast unmounted, so the Notifications list lost Undo after eight seconds and untoasted notices never offered it. The listed record now owns the closure and toasts only hold it; entries go when run, superseded, delisted, their project closes or the account changes. Notices restored by Clear's Undo keep their actions and do not toast again.
…edited With Undo living for the session, a late Undo could replace painting done since. The restore checks for edits before and again after the paint barrier and leaves the point in History when it refuses.
…ed again Preset restore and the archive Undo were checked for a late run; the archive now supersedes by board.
Below 20rem the rail label drops the Gallery title and separator; below 15rem the destination shows only its icon and chevron, keeping its accessible name and tooltip. The destination used to cover the board button on iPad-width rails.
The button carries a hidden description of source, destination and lock, lists ArrowDown among its shortcuts, announces a popup only while blocked, and its card is named by its title. The accessibility journey asserts the bottom widget menu against the named built-ins instead of a floor of one.
A marker at or above the current version counts as layered instead of being coerced and re-stamped. The compatibility notes state that a build predating the marker drops it on save, so the next load drops pins equal to the built-in, and that the retired per-project antialias flag is dropped.
… and drop dead selectors The gallery's legacy follow sentinel is read through one exported predicate, the unused scoped-defaults selector is gone, and the video recall test mocks the metadata read it still uses instead of a removed export.
…kflow file as a 404
The first ResizeObserver report rendered after the first paint, so a Preview narrower than full painted one frame with full-density padding and chrome before shifting under the pointer. The arrow-button browser test lost its hover in that frame on slow runners.
Follow-up on round 2 (head
|
The fixed eight-grapheme tail was clipped to a fragment once the head collapsed, as in the narrow gallery rail header. The label measures on attach and resize and falls back to a plain end ellipsis when the tail and a few head graphemes do not fit, keeping its full accessible name.
The card exposes its mode for tests; the right-click and press-inside-preview tests move the pointer away and wait past the close delay, and a hover preview is shown to close.
The paragraph was read while the dialog's scale-in animation ran, so its bounding box depended on the frame.
Pfannkuchensack
left a comment
There was a problem hiding this comment.
Approving at 017a44126e. Both points from the follow-up are resolved, and I found nothing material in the new commits.
- Invoke card tests (
2c4ca38ec9): the right-click and press-inside tests now readdata-invoke-card-modeafter waiting past the close delay. The new control test shows that the same pointer moves do close a preview. I ran the file locally three times (34/34 each) and the three card tests five more times, all green. MiddleTruncate(2c78886399): the end-ellipsis fallback fixes the fragment in narrow rails. The measuring is cheap (only labels with a tail, one sharedResizeObserver), and the two forms can't flip back and forth because both are measured from the same text ranges.- Preview density (
277d2f2401) and the ConfirmDialog test (49cdea2e06): the density is now measured in the mounting commit, and its new test fails without the fix. The dialog test reads the layout height after the fonts load, which makes it more deterministic without weakening it. - The merge matches main exactly.
Optional nit: expect(cardMode()).toBe('closed') in the new control test relies on the card still being mid-exit when it is read. not.toBe('preview'), or just the not.toBeInTheDocument() poll that follows, would not depend on the exit animation's length.
CI is green apart from windows-arm64, which still reports no result.
Got approval from @Pfannkuchensack
Summary
A branch-wide UX refinement pass on the workbench, one shared metadata lifecycle for images and videos, and layered widget settings: a per-project pin over a user default over the built-in. Each area below is a few short rules; the behavior is otherwise unchanged.
Undo instead of confirm
Queue
Gallery
Gallery metadata and recall
Generate
Invoke
Canvas
Shell and Launchpad
Settings
Consistency
QA Instructions
From
invokeai/frontend/webv2under Node 22 and pnpm 10:Result on the current head: all gates pass.
Branch-only cost against main (committed baselines, same main point):
The locale grows by 731 keys (+46.7 KB raw, +9 KB brotli) for the new notices, issues, dialogs and settings copy. The script growth is the metadata lifecycle, the Invoke card, layered settings and the notifications registry; about 45 new editor sources and 11 Launchpad sources. Fonts, CSS and images are unchanged.
Manual checks, mock backend only, dark theme, Chromium:
Not observed here: real generation, model loading, reconnects, multi-user flows, Firefox.
Docs: the project switcher screenshot is retaken; the Invoke card has no screenshot yet.
Review
All material findings were resolved:
Remaining limits:
Compatibility / Rollout
Persisted layouts. Saved projects, session state, custom presets and built-in preset overrides that still dock the Project widget anywhere, or Diagnostics in the status bar, load with that placement dropped (the instance is kept if still placed elsewhere),
alignEndInstanceIdscleaned, the region's active widget falling back to the first remaining one, and the preset not reading as modified. Retired canvas editor placements get the same treatment on every region. No schema version bump; the stored copy updates on the next save.New per-project settings. Routing, auto-add destination and dynamic prompts have defaults, so older projects open unchanged.
Layered settings.
settingsLayeringmarker are coerced once at load (stored values equal to the built-in are dropped, the retired per-project antialias setting is dropped; the account preference starts off) and then carry the marker in the workspace half. A marker at or above the current version is never coerced again, so a newer build's documents keep their pins. Older builds keep loading the documents; a build predating the marker drops it on save, and the next load coerces again, which drops pins equal to the built-in so that project follows the user default for those settings.scopedDefaults. An older build saving preferences drops that key, so defaults set here are lost after a downgrade; projects are unaffected.Video recall, on purpose.
galleryVideos.metadatais removed in favor of the shared query. Thevideo_recall_requestedevent path (applyVideoRecallMetadata) keeps its contract.Checklist
What's Newcopy (if doing a release after this PR)