Skip to content

[6.x] UI tweaks - #19942

Merged
brandonkelly merged 89 commits into
6.xfrom
ui-tweaks
Oct 14, 2026
Merged

brandonkelly merged 89 commits into
6.xfrom
ui-tweaks

Conversation

@brandonkelly

@brandonkelly brandonkelly commented Oct 12, 2026 •

Copy link
Copy Markdown
Member

Description

A round of control panel UI refinements.

Also includes the element details pane tweaks from #19930.

Link fields

  • Link Type and the destination input now share a row, and the remaining settings (Label, URL Suffix, Target, etc.) are nested under a collapsible “Advanced” section, inside an outline pane — as Link fields were in Craft 5.

Disclosures and toggles

  • A <craft-disclosure> toggle’s chevron follows its label, pointing toward the end of the line while collapsed (right, or left in right-to-left text) and down while expanded. The disclosure moves a slotted craft-button toggle’s chevron to its suffix and keeps its direction in sync, and workflow review headings’ own chevrons follow the same rule.
  • Disclosures’ default toggles are now plain and flush (they had an invalid appearance attribute, which gave them a gray fill).
  • The activity timeline’s and workflow reviews’ expand/collapse toggles are now small, plain and flush. Collapsed activity change cards have even spacing around their toggle.
  • A disclosure’s hairline starts at its edge, rather than being inset beneath a leading chevron.
  • Added appearance (line or plain) and size properties to <craft-disclosure>. plain drops the hairline and indent, which the activity timeline and workflow reviews now use instead of overriding it, and size sizes the default toggle.

Element indexes

  • In thumb view, only an element’s label links to it. Clicking anywhere else on a thumb, card or table row selects it — including for asset folders, which only open from their link (or Return).
  • Asset folder labels are now links in thumb and card views, and asset file labels are links in thumb view.
  • Thumbnails in relational fields no longer link to the element.
  • The toolbar no longer reserves an empty column for actions, and its view mode buttons have tooltips.
  • More even spacing around card and thumb grids, with their headers and the asset breadcrumbs flush to the container.
  • Clickable table rows use the default cursor rather than a text cursor.
  • Empty states (“No results” and the like) are lighter: the message uses the quiet text color, which still meets 4.5:1, and the decorative icon uses slate-200.

Element selection modals

  • The modal header (and its close button) is gone; Cancel, Esc and the backdrop still dismiss it.
  • The toolbar stays on one row, with padding above it, and the loading spinner is centered.
  • Asset folders only open from their link.

Section and Matrix site settings

  • The separate Route Type column is gone. A single “Route To” field takes a template path, controller action or named route, and saving resolves which it is: namespaced values are routes, values with slashes are templates, and anything else is a route only if a named route by that name exists. Stored site settings are unchanged, and explicit template/route values still apply as-is.
  • “Route To” suggests templates and routes: the app’s named GET routes and the public actions of its controllers that aren’t already registered as routes, limited to those whose element parameter accepts the element type.
  • Enabled, Homepage, Default Status and Auto-Refresh columns are thin and centered, and the URI and Route To columns share the remaining width.

Editable tables

  • Header rows have a sunken background and semibold headings, row headings are semibold, and there’s no longer a doubled border under the header row.
  • Heading cells show their value as text rather than a read-only input.
  • Text and select inputs fill their cells, with no border, radius or shadow. Every other cell gets the same padding as header cells, and color and icon pickers and delete buttons are sized so they don’t grow the row.
  • Text and select cells act as their control, with a text cursor and a focus ring around the whole cell. Clicking anywhere in a text, select, color, icon, checkbox or lightswitch cell focuses its control.
  • Column classes apply to header cells too, and there’s a new centered column class. Row-action columns are thin, selects in thin columns are sized to their widest option, and checkboxes are standard-size.
  • Option fields’ Color column is thin, and their Default? column is centered.
  • The unused “prefix select” column option is removed.
  • New Ui/TableControl Storybook story, with a column of every type.

Checkboxes, radio buttons and lightswitches

  • Checkboxes and radio buttons are drawn in CSS, so they look the same in every browser and their focus rings follow their rounded shape.
  • Their boxes are centered on their label’s first line, and radio buttons’ label spacing matches checkboxes’.
  • Lightswitches have pill-shaped focus rings (without a second ring on the handle), a pointer cursor, and 50% opacity when disabled.

Form controls

  • Text inputs and selects take on their container’s background, with a slightly darker inset shadow.
  • Single-select comboboxes have a visible focus ring and an accessible name on their combobox element.
  • Action menu search inputs have spacing around them and match other text inputs.
  • Removed the unused --c-select-*, --c-input-spacing-block and --c-form-control-spacing-block tokens.

Chips and component selects

  • Chip handles are plain monospace text directly under the label.
  • Component select chips are spaced like relational fields’ chips, and their reorder button is hidden when there’s only one chip.
  • Relational fields’ sortable chips and cards use <craft-reorder-button>, so they can be moved from its menu as well as by dragging, including on touch devices (where the move button used to be hidden).
  • Chips’ action menu and reorder buttons are square, so they sit closer together.

Navigation

  • Nav items’ icons are closer to their labels, in the global nav and the content nav.
  • The selected parent’s blue indicator starts at the row’s edge, in line with its hover background, and expanded subnavs have a hairline centered on it.
  • Users is no longer marked as the current page on your own account or a user’s edit screen. It stays selected as their parent, but only the page itself gets aria-current="page".

Element details pane

  • Activity timeline day headings show the date as a rounded badge, and the timeline’s hairline continues through them.
  • Field labels in activity change lists are semibold rather than bold.
  • Workflow review panes use the plain pane appearance rather than outline.
  • Added an outline-fill appearance to <craft-pane> (and CraftCms\Cms\Cp\Enums\PaneAppearance::OutlineFill): bordered, with a quiet tinted fill and no shadow, as cards have.
  • Cards with data-color="white" now have white bodies to match their headers, the same border color and extra-small shadow as white chips, and header and footer dividers in the table row line color. Selected white cards look like selected white chips (accent fill and border), with dividers in the color between adjacent selected table rows.
  • Cards no longer overflow their grid cells by their 2px border (the card's box is now border-box).

Buttons and button groups

  • Buttons in button groups no longer have gaps between them. Adjacent buttons share a border, and the hovered, selected or focused button is drawn on top.
  • Button groups with a name follow the exclusive button group pattern from 5.x: a role="group" of toggle buttons, each its own tab stop and reporting its state with aria-pressed, with no arrow-key navigation. They were a radiogroup of buttons, which mixed the two patterns. The group also keeps a role the consumer gives it.
  • The selected button of a single-choice group no longer shows hover effects or a pointer cursor, and clicking it again no longer makes it look deselected. That includes groups whose owner manages the selection, like the sort direction buttons.
  • Element indexes’ view mode and sort direction groups are now named (“View Mode”, “Sort direction”).
  • Outline and dashed buttons have the same border color as text inputs and checkboxes, including the content sidebar’s Actions button (ActionMenu has a new inherit prop).
  • Grouped buttons with no border of their own (fill, solid, primary, plain…) have a divider between them, in a tint of their text color, except on either side of the selected button. It’s a 1px full-height line drawn by both neighbors, so it shows on hover and reaches a button nested in a grouped element (like the Save button’s menu).
  • The borders between buttons in outline and dashed groups are lighter than the group’s outer edge.
  • Small buttons are 0.9em whether their icon is an icon attribute or a slotted <craft-icon> (the attribute version dropped to 0.8em, shrinking its label too). The disclosure’s chevron math follows suit.
  • Added button-group.a11y.md.

Radio groups drawn as buttons

  • <craft-radio-group> has a new buttons attribute (and RadioGroup::buttons() in PHP) that draws its options as a row of joined buttons. Each native radio is stretched transparently over its button, so the options are still radios: one tab stop, with the arrow keys moving the selection. An option labeled only by an icon gets a square button.
  • Settings that pick one value use it: the Notification Position and Slideout Position preferences (which also no longer have large gaps under their labels, and have tooltips instead of title text), Button Group fields, and single-choice Buttons controls. Multi-select button controls stay toggle buttons.
  • The borders between their buttons are lighter than the group’s outer edge.
  • The checked option no longer shows a pointer cursor.
  • Added radio-group.a11y.md, including a forced-colors check.

Element fields and selection

  • The select-all toolbars above element selections, card grids and thumbnail grids have no fill and no padding at the sides or top, and are underlined in the same hairline color as content tabs. Their minimum height leaves room for the Clear selection button, so they don’t grow when something is selected.
  • An element field’s Add and Upload buttons follow its selections, rather than sitting above them.
  • The toolbar’s limit badge is left out for fields with no limit (it showed a dangling “3/”), and the toolbar’s Actions button is flush.
  • Small <craft-badge>s with a label are as tall as a checkbox.
  • Selected chips and thumbnail tiles show the accent fill with a stronger accent border. Neither showed it before: a chip stamps data-color="white" on itself and the white style outranked the selected one, and a tile’s border rule outranked its selected border.
  • Selected table rows keep their fill but no longer outline the selection in a dark accent; only the borders between adjacent selected rows take the accent.
  • Thumbnail tiles have the same shadow as chips.
  • New --c-table-border-color token for the lines between table rows.
  • Folder breadcrumbs’ bottom border matches the select-all toolbar’s, and on element indexes the card and thumbnail grid headers have equal top and bottom padding, so their checkbox is centered.

User preferences

  • The preferences screen’s General, Accessibility and Development sections are now content tabs. Development stays admin-only, and a tab holding a field with a validation error shows an error icon.

Asset index actions

  • Most asset actions in the index's Actions menu (Preview file, Download, Rename file, Replace file, Copy URL, Copy reference tag, Show in folder, Edit Image, and Move…) only worked through legacy Craft.ElementActionTrigger JS, which the Inertia index never runs. They were serialized as http actions, so clicking one posted to the perform endpoint, did nothing, and cleared the selection.
  • Preview file is now a craft:preview-file client event, which the bulk actions bar handles by opening the preview modal.
  • The others are client events that AssetIndexViewModel serializes (assets:rename-file, assets:move-assets, …), handled by a new useAssetFileActions composable on the assets page. Rename file opens a dialog like Rename folder; Move… opens the folder picker and reuses the drag-and-drop move with its conflict prompt; Replace file and Download share helpers with the element action menu.
  • Asset rows carry the capabilities those actions check (movable, replaceable, imageEditable, hasUrl, via a new extraCapabilities() hook), worked out from the asset's own chip attributes, plus the filename and image details the rename dialog and image editor need. Move is left out when there's nowhere to move to.
  • ElementActions::availableActions() now activates CurrentElementIndex with the index's query while the element type defines its actions, so Show in folder is offered when searching subfolders, and entries' actions see the selected site.
  • The folder picker (Craft.VolumeFolderSelectorModal, used by Move… and Move folder) is ported from the legacy jQuery element index, which opened unstyled since Inertia pages don't load the legacy CP stylesheet, to the Vue element selector modal. ElementPicker gets a folder mode: folder rows are selectable (bar disabledFolderIds) and still open from their title link or Enter, and the open folder's breadcrumb trail feeds the controller's sourcePath, so Move with nothing highlighted still picks the open folder. It starts in defaultSource / defaultSourcePath (also read from indexSettings, as legacy callers pass them), hides the site menu, and removes itself once closed. It's single-select: element indexes take a new multiSelect option (TanStack's enableMultiRowSelection), and single-select lists leave out the select-all checkbox.
  • The bulk Move folder action passes the same move target sources as Move…, so Temporary Uploads is no longer offered as a destination.
  • Element indexes keep their view mode in step with the rows they load. The server renders the first payload for the URL's viewMode, or the source's default mode, without knowing the mode the index remembers locally, so cards or thumbs could be drawn over table rows and come out empty — in selector modals (which never restored their view state), on pages whose URL named a mode, and for sources whose default isn't table. restore() now compares the persisted mode with viewState.mode from the payload: a mode named in the URL wins, and otherwise a differing persisted mode is re-requested if the index can show it. Selector modals now restore their view state, columns and sort too.

Other

  • Move icons (Matrix blocks, chips, cards, editable table rows) and action menu ellipsis icons are larger.
  • Metadata values in details panes are left-aligned.
  • Fields’ “Used by” metadata links asset volumes (previously an unlinked “1 asset field layout” count), and its icons are sized and spaced like entry types’.
  • Image thumbnails’ placeholders now cover exactly the image’s area in “fit” mode, rather than the whole thumbnail box, and the image’s box no longer shifts when it loads. Elements can provide their thumbnail’s display size via a new thumbDimensions() hook.
  • Asset previews’ image-color gradients are 40% opaque over a transparent background (rather than solid over black), so they take on the pane’s color. Asset edit pages have a hairline below the preview, drawn on its wrapper so it isn’t resolved against the preview’s dark theme.
  • Edit pages for element types whose hasStatuses() returns false (such as assets) leave out the header’s status badge and the “Status” metadata row. Drafts keep their badge, since it marks unsaved changes rather than a status.
  • Action menu separators’ spacing now matches the menu’s padding.
  • Tighter spacing below field labels and instructions.
  • Content sidebars no longer have a doubled bottom border when they sit beside the content; it only shows once the sidebar stacks above it.
  • The file preview modal's focal point button styles are trimmed to position and margin, which the template's utility classes can't override on unlayered legacy .buttons; the button now sits 8px from the corner.

🤖 Generated with Claude Code

brandonkelly and others added 17 commits October 9, 2026 14:40
- Activity timeline day headings show the date as a badge over a hairline
  that spans the details pane.
- Workflow review panes use the plain pane appearance.
- Added an `outline-fill` pane appearance: bordered with a quiet tinted fill
  and no shadow, as cards have.
- White cards have white bodies to match their headers, rather than a
  translucent body that picked up the background behind it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Link Type and the destination input share a row, the remaining settings
sit under a collapsible Advanced section, and the whole field sits in an
outline pane, as Link fields did in Craft 5.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A disclosure's chevron now points up while it's open. Its default toggle
is plain and flush, and the activity timeline and workflow toggles are
small, plain and flush too.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Fit-mode asset thumbnails now get the dimensions they're displayed at, so
craft-thumbnail can size the image's box before it loads and paint the
placeholder across exactly that box, rather than the whole thumbnail.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Only an element's label links in thumb view; clicking elsewhere on a
  thumb, card or row selects it, including for asset folders.
- Asset folder labels link in thumb and card views, and file labels in
  thumb view.
- Relational fields' thumbnails no longer link.
- Even spacing around grids, flush headers and breadcrumbs.
- The toolbar no longer reserves an empty actions column, and its view
  mode buttons get tooltips.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Drop the modal header; Cancel, Escape and the backdrop dismiss it.
- Keep the toolbar to one row, with padding above it.
- Center the loading spinner, by pinning dialog parts to their rows.
- Only a folder's link opens it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Oct 12, 2026 •

Copy link
Copy Markdown

brandonkelly and others added 11 commits October 11, 2026 19:37
The check waits on the button's icons, so a button removed in the
meantime was checked while detached. Its root is then itself, which
can't resolve an aria-labelledby ID, so the check threw. The element
index's view mode tooltips label their buttons that way, which surfaced
it as unhandled rejections in CI.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Native checkboxes always compute a zero border radius, so their focus
rings were square, and the components' ::slotted() styles never beat the
base reset. Checkboxes and radios are now drawn from light-DOM styles,
with a real radius so focus rings follow their shape, a checkmark,
indeterminate dash, radio dot, disabled state, and forced-colors fallbacks.

Also centers the boxes on their label's first line, matches the radio's
label gap to the checkbox's, and removes the dead choice input styles.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Text inputs and selects take on their container's background, with a
  slightly darker inset shadow.
- Lightswitches get a pill-shaped focus ring (dropping Lion's thumb
  outline), a pointer cursor, and 50% opacity when disabled.
- Single-select comboboxes get a focus ring on their textbox wrapper,
  since Lion turns off the textbox's own outline.
- Action menu search inputs get spacing around them and use the input
  tokens for their border, radius, fill, shadow, and text color.
- Removes the unused `--c-select-*`, `--c-input-spacing-block`, and
  `--c-form-control-spacing-block` tokens.
- Drops the gap between field labels and their instructions.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
In Chromium, Lion puts the combobox role on the textbox's wrapper (the
ARIA 1.1 pattern), but only labeled it for multiple-choice comboboxes,
leaving single-select ones with an unnamed combobox (WCAG 4.1.2).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Section and Matrix site settings no longer have a separate Route Type
column. The "Route To" field takes a template path, controller action, or
named route, and saving resolves it with `ElementRoute::isRoute()`:
namespaced values are routes, values with slashes are templates, and
anything else is a route only if a named route by that name exists.

The field suggests templates and routes: the app's named GET routes and
the public actions of its controllers that aren't already registered as
routes, filtered to those whose element parameter accepts the element
type. Stored site settings are unchanged, and explicit `template`/`route`
values still apply as-is.

Also tidies the section settings tables: thin, centered Enabled,
Homepage, Default Status, and Auto-Refresh columns, and equal-width URI
and route columns.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Nothing uses it now that site settings have a single "Route To" field.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Header rows get a sunken background and semibold headings; row
  headings are semibold.
- Heading cells render their value as text rather than a read-only
  input, and column classes apply to header cells too.
- Text and select inputs fill their cells with no border, radius, or
  shadow. Every other cell gets `th` padding, and its pickers and delete
  buttons are sized so they don't grow the row.
- Text and select cells act as their control: a text cursor, and a
  focus ring around the whole cell. Clicking anywhere in a text, select,
  color, icon, checkbox, or lightswitch cell focuses its control.
- New `centered` column class, `thin` row-action columns, thin selects
  sized to their widest option, standard-size checkboxes, and no doubled
  border under the header row.
- Option fields' Color column is thin and Default? is centered.
- Adds a TableControl story with a column of every type.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Chip handles are plain monospace text right under the label, without
  the code styling's border, padding, or background.
- Component select chip lists stack with the same spacing as relational
  fields.
- A component select's reorder button is hidden when there's only one
  chip to reorder.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
# Conflicts:
#	resources/js/modules/activity/components/ActivityTimeline.vue
#19930's changes were merged into #19942.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
brandonkelly and others added 16 commits October 13, 2026 07:22
A collapsed "X changes" card had more space above its toggle than below,
from the toggle's block flush margins and the line box it sat in. The toggle
is now only inline-flush, laid out in a flex column, and the card's block
padding matches the space to its left, so it's even on every side.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The sidebar's bottom border only divides it from the content once it's stacked above it; beside the content, it doubled up with the panel's own border.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Only named groups gave their selected button a default cursor, so groups whose owner manages the selection, like the sort direction buttons, still showed a pointer. Independent toggles keep theirs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The native input stretched over each button kept its pointer cursor even once it was checked.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Your own account and a user's edit screens sit under Users, but none of its subnav items claim them, so Users was the deepest match and got marked as the page itself.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The image's edge colors now sit at 40% over a transparent background, so the preview takes on the pane's color rather than a solid block. The hairline goes on the preview's wrapper, outside the container's dark theme, so it matches the other dividers in light mode.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Nothing marks a preview as editable or renders image actions anymore.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Assets showed an “Enabled” badge in the header and a Status row in their metadata, though they can't be disabled. Drafts keep their badge, since it says the changes aren't saved yet.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…e can't do

The template's utility classes already hide and fade the button, but legacy `.buttons` is unlayered and would win over their positioning, so only `position` and `margin` stay. Its `.btn` styles never matched the `craft-button`. The inset moves to the closest spacing token to the old 10px.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Preview file was serialized as an `http` action, so it posted to the perform endpoint, which had nothing to do, and the index refreshed and cleared the selection. Its legacy JS trigger, which opened the modal, never runs on the Inertia index. It's now a client event action, and the bulk actions bar opens the modal for the selected asset.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Download, Rename file, Replace file, Copy URL, Copy reference tag, Show in folder, Edit Image, and Move only did anything through legacy JS triggers, which the Inertia index never runs, so they posted to the perform endpoint, did nothing, and cleared the selection. The asset index now serializes them as client events that the page handles.

Asset rows carry the capabilities the actions check (movable, replaceable, imageEditable, hasUrl), worked out from the asset's own chip attributes, plus the filename and image details the rename and image editor need. Move reuses the drag-and-drop move and its conflict prompt, and the replace and native form helpers are shared with the element action menu.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Asset's Show in folder action, and Entry's site lookup, read the query from `CurrentElementIndex`, which only the legacy index activated. On the Inertia index it was never active, so Show in folder was never offered, even when searching subfolders.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
It drove the legacy jQuery element index, whose markup depended entirely on the legacy CP stylesheet that Inertia pages no longer load, so it opened unstyled. It's now the same Vue modal as other element selectors, with `ElementPicker` in a folder mode: folder rows are selectable (bar the disabled ones) and still open from their title link, and the open folder's breadcrumb trail stands in for the legacy index's `sourcePath`. It starts in the default source and folder, and removes itself once closed.

The bulk Move folder action now passes the same move target sources as the file Move, so Temporary Uploads isn't offered as a destination.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A move has one destination. Element indexes take a `multiSelect` option, which maps to TanStack's `enableMultiRowSelection`, so selecting a row deselects the others, and single-select lists leave out the select-all checkbox. The modal index turns it off in folder mode.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

This PR had conflicts with 6.x. Claude attempted an automatic resolution and pushed a merge commit. Please review the merge commit carefully before approving/merging.

Claude's response

I resolved the one conflict and committed the merge as 0212786. It hasn't been pushed.

The conflict was in CHANGELOG.md, in the unreleased "Fixed" list. Both branches had added different bullets to the end of the same section:

The entries don't overlap, so I kept all four, with this branch's first and 6.x's after. Nothing was ambiguous, so I didn't add any CONFLICT-REVIEW comments. Git merged the other files from 6.x (the MCP, GraphQL Matrix input and test files) without conflicts, and I didn't change them.

brandonkelly and others added 5 commits October 13, 2026 22:47
The server renders the first payload for the URL's `viewMode`, or the source's default mode, without knowing the mode the index remembers locally. When the two disagreed, cards or thumbs were drawn over table rows and came out empty: in selector modals, which never restored their view state, on pages whose URL named a mode, and for sources whose default isn't `table`.

`restore()` now compares the persisted mode with the one the payload was rendered for. A mode named in the URL wins; otherwise a differing persisted mode is re-requested, if the index can show it. Selector modals now restore their view state too.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Six tests put their user photo volume at `public_path('test')`, shared by every parallel test process. Each process has its own database, so two could both find `avatar.jpg` free and write it at once; the loser's asset save failed and the user was left without a photo, as in a CI run of `RegistrationTest`. The directory was never cleaned up either.

Each test now gets a unique directory under `storage/framework/testing`, deleted afterwards.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

This PR had conflicts with 6.x. Claude attempted an automatic resolution and pushed a merge commit. Please review the merge commit carefully before approving/merging.

Claude's response

I resolved the merge and committed it as 114794f. I haven't pushed it.

There was one conflict, in CHANGELOG.md. Both branches had added changelog entries at the same spot. The ui-tweaks branch added seven "Fixed a bug…" entries for #19942, and 6.x added the "Save" button redirect fix for #19970. I kept all of them, with the #19970 entry right after the #19942 entries, and didn't change their wording.

Nothing about this one was ambiguous, so I didn't leave any CONFLICT-REVIEW comments. The other changed files in this merge came in from 6.x without conflicts, and I left them as they were.

brandonkelly and others added 2 commits October 14, 2026 05:34
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@brandonkelly
brandonkelly merged commit f396b65 into 6.x Oct 14, 2026
20 checks passed
@brandonkelly
brandonkelly deleted the ui-tweaks branch October 14, 2026 13:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants