Repository navigation
[6.x] UI tweaks - #19942
[6.x] UI tweaks#19942
Conversation
- 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>
# Conflicts: # CHANGELOG.md
# Conflicts: # CHANGELOG.md
# Conflicts: # CHANGELOG.md
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>
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
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>
# Conflicts: # CHANGELOG.md
|
This PR had conflicts with Claude's response
|
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>
# Conflicts: # CHANGELOG.md
|
This PR had conflicts with Claude's response
|
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Description
A round of control panel UI refinements.
Also includes the element details pane tweaks from #19930.
Link fields
Disclosures and toggles
<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 slottedcraft-buttontoggle’s chevron to its suffix and keeps its direction in sync, and workflow review headings’ own chevrons follow the same rule.appearanceattribute, which gave them a gray fill).appearance(lineorplain) andsizeproperties to<craft-disclosure>.plaindrops the hairline and indent, which the activity timeline and workflow reviews now use instead of overriding it, andsizesizes the default toggle.Element indexes
Element selection modals
Section and Matrix site settings
template/routevalues still apply as-is.Editable tables
centeredcolumn class. Row-action columns are thin, selects in thin columns are sized to their widest option, and checkboxes are standard-size.Ui/TableControlStorybook story, with a column of every type.Checkboxes, radio buttons and lightswitches
Form controls
--c-select-*,--c-input-spacing-blockand--c-form-control-spacing-blocktokens.Chips and component selects
<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).Navigation
aria-current="page".Element details pane
plainpane appearance rather thanoutline.outline-fillappearance to<craft-pane>(andCraftCms\Cms\Cp\Enums\PaneAppearance::OutlineFill): bordered, with a quiet tinted fill and no shadow, as cards have.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.border-box).Buttons and button groups
namefollow the exclusive button group pattern from 5.x: arole="group"of toggle buttons, each its own tab stop and reporting its state witharia-pressed, with no arrow-key navigation. They were aradiogroupof buttons, which mixed the two patterns. The group also keeps arolethe consumer gives it.ActionMenuhas a newinheritprop).iconattribute or a slotted<craft-icon>(the attribute version dropped to 0.8em, shrinking its label too). The disclosure’s chevron math follows suit.button-group.a11y.md.Radio groups drawn as buttons
<craft-radio-group>has a newbuttonsattribute (andRadioGroup::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.Buttonscontrols. Multi-select button controls stay toggle buttons.radio-group.a11y.md, including a forced-colors check.Element fields and selection
<craft-badge>s with a label are as tall as a checkbox.data-color="white"on itself and the white style outranked the selected one, and a tile’s border rule outranked its selected border.--c-table-border-colortoken for the lines between table rows.User preferences
Asset index actions
Craft.ElementActionTriggerJS, which the Inertia index never runs. They were serialized ashttpactions, so clicking one posted to the perform endpoint, did nothing, and cleared the selection.craft:preview-fileclient event, which the bulk actions bar handles by opening the preview modal.AssetIndexViewModelserializes (assets:rename-file,assets:move-assets, …), handled by a newuseAssetFileActionscomposable 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.movable,replaceable,imageEditable,hasUrl, via a newextraCapabilities()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 activatesCurrentElementIndexwith 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.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.ElementPickergets a folder mode: folder rows are selectable (bardisabledFolderIds) and still open from their title link or Enter, and the open folder's breadcrumb trail feeds the controller'ssourcePath, so Move with nothing highlighted still picks the open folder. It starts indefaultSource/defaultSourcePath(also read fromindexSettings, as legacy callers pass them), hides the site menu, and removes itself once closed. It's single-select: element indexes take a newmultiSelectoption (TanStack'senableMultiRowSelection), and single-select lists leave out the select-all checkbox.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'ttable.restore()now compares the persisted mode withviewState.modefrom 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
thumbDimensions()hook.hasStatuses()returnsfalse(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.positionandmargin, 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