Skip to content

[6.x] UI tweaks: centered utility content and nav badges, type, shadow, and keycap polish - #20544

Merged
brandonkelly merged 4 commits into
6.xfrom
ui-tweaks
Nov 10, 2026
Merged

brandonkelly merged 4 commits into
6.xfrom
ui-tweaks

Conversation

@brandonkelly

@brandonkelly brandonkelly commented Nov 10, 2026 •

Copy link
Copy Markdown
Member

Description

Small control panel layout fixes and visual polish.

Utilities can cap and center their content

Utility pages had no way to ask for the centered, readable-width column that settings pages use. System Messages got one by calling useAppLayout({contentMaxWidth: true}) from its own Vue component. Server-rendered utilities such as Yii2 Loose Ends couldn't do that, so Loose Ends capped its body at max-w-4xl and sat against the left edge on wide screens, with its title still at the left.

 Utility (src/Utility/Utility.php)
+  public static function contentMaxWidth(): bool|string   // false by default; a CSS length caps it at that width

 UtilitiesController::show()
+  'contentMaxWidth' => $class::contentMaxWidth()

 pages/utilities/Show.vue
-  useAppLayout(() => ({title}))
+  useAppLayout(() => ({title, ...(contentMaxWidth ? {contentMaxWidth} : {})}))

 SystemMessages (utility)          + contentMaxWidth(): true
 SystemMessages.vue                - useAppLayout({contentMaxWidth: true})
 LooseEndsUtility                  + contentMaxWidth(): true
 LooseEnds.twig                    - max-w-4xl

Show.vue only passes the option when a utility sets it, so a utility whose own component still calls useAppLayout({contentMaxWidth: …}) isn't overridden.

Count badges and unread dots sit on their row's center line

craft-badge-indicator's host had no display, so it was inline (or blockified, as a flex item), and the inline-flex pill inside it sat on the text baseline of a full line box. The host came out a line tall with the pill at its bottom, so in a centered row, such as a nav item's count badge or a notification's unread dot, the pill sat low.

 badge-indicator.styles.ts
+  :host { display: inline-flex; }

 cp-notification-center.ts    .notification-trigger__badge  - display: inline-flex   (same workaround, now redundant)
 LooseEnds.twig               craft-badge-indicator         - class="inline-flex"     (same workaround, now redundant)

Visual polish through shared tokens and base styles

 base.css      body                -webkit-font-smoothing: subpixel-antialiased → antialiased (+ -moz-osx-font-smoothing: grayscale)
 base.css      :where(table, time) + font-variant-numeric: tabular-nums
 badge-indicator.styles.ts .number + font-variant-numeric: tabular-nums

 tokens.css    + --c-shadow-tint: 34 44 82 (light) / 2 6 20 (dark)
               rgb(0 0 0 / …) → rgb(var(--c-shadow-tint) / …)   in --c-shadow-*, sunken, input, slideout shadows and --c-modal-ring
 tokens.css    - --c-pane-shadow (built on the undefined --gray-200, so it was already invalid; fld.css's one use goes too)

 kbd.css (new) one keycap style: Inter, quiet neutral fill and border, 2px bottom edge
   ├─ cp.css imports it for every <kbd>   (was mono, in base.css)
   └─ craft-shortcut adopts it for its keys (was its own .shortcut__key rules)

 pane.styles.ts  :host([appearance='sunken'])  + --c-form-control-border-color: var(--color-slate-500)
 CommandPalette.vue  - border: 1px var(--c-modal-border-style) var(--c-modal-border-color)   (both undefined)
                     - style="--c-modal-border-width: 0px"

Evidence

Measured in the workbench at 1280px, before → after:

nav count badge (Utilities, "3")   pill center vs row center:  +1.86px → 0.00px
nav count badge (Users, "99+")     pill center vs row center:  +1.86px → 0.00px
nav status dot (source)            pill center vs row center:   0.00px → 0.00px   (unaffected)
notification bell dot              offset from button corner:   1px, 1px → 1px, 1px (unchanged)
notification unread dot            dot center vs title row:     → 0.00px
System Messages at 1920px          960px column, 362px margins each side (now from the PHP opt-in)
System Report at 1920px            unconstrained, fills the pane (unchanged)
  • New badge-indicator.browser.test.ts › centers a count / a dot in a row that centers its items: passes. Without the fix, they fail with the pill 2.8px and 1px low.
  • New UtilitiesControllerTest › caps and centers a utility's content only when the utility asks: passes. Without System Messages' opt-in, it fails with false is identical to true.
  • composer ci, vue-tsc, stylelint, and the utilities and notifications Vitest files pass.

Visual polish, measured in the workbench:

input border on a sunken pane, light    2.99:1 → 3.85:1
input border on a sunken pane, dark     4.76:1 → 5.99:1
keycap text on keycap fill              10.5:1 light, 8.1:1 dark
computed --c-shadow-sm, light           rgb(34 44 82 / .1) …   dark: rgb(2 6 20 / .15) …
computed font-variant-numeric on <td>   tabular-nums
  • card.browser.test.ts › gives a card the light/dark theme's shadow now expects the tinted colors; the full components-browser project passes (899 tests).
  • Command palette border and pane-shadow removals render identically: both declarations were already invalid.
  • Font smoothing only applies on macOS, so it isn't visible in the orb's Chromium.

The workbench doesn't load the Yii2 adapter, so Loose Ends itself was checked by reading the code, not by rendering it. There are no screenshots: I couldn't upload them to GitHub from the orb.

brandonkelly and others added 2 commits November 10, 2026 04:11
Add Utility::contentMaxWidth(), which the utility page passes to the
layout's contentMaxWidth option, the same one settings pages use. System
Messages moves to it from its Vue component, and Yii2 Loose Ends uses it
instead of capping its own body at max-w-4xl, which left it against the
left edge on wide screens.

Amp-Thread-ID: https://ampcode.com/threads/T-01a1c31e-5888-7773-8b7a-d6900d7cccbf
Co-authored-by: Amp <amp@ampcode.com>
craft-badge-indicator's host had no display of its own, so its inline-flex
pill sat on the text baseline of a full line box, and came out low in rows
that center their items, such as nav items' count badges and notifications'
unread dots. Make the host inline-flex, which the notification bell and the
Yii2 Loose Ends headings had each been doing for themselves.

Amp-Thread-ID: https://ampcode.com/threads/T-01a1c31e-5888-7773-8b7a-d6900d7cccbf
Co-authored-by: Amp <amp@ampcode.com>
@github-actions

github-actions Bot commented Nov 10, 2026 •

Copy link
Copy Markdown

📚 Storybook previews

@craftcms/ui — open Storybook

Changed components:

resources/js — open Storybook

No changed components detected in this Storybook.

Antialias text on macOS, give tables, times, and count badges tabular
figures, and tint every Craft shadow with a per-theme --c-shadow-tint
instead of black. Move <kbd> styling into a shared kbd.css that
craft-shortcut adopts too, so the shortcuts table and the command
palette's footer draw the same keycap. Darken input borders inside sunken
panes to 3:1. Drop --c-pane-shadow and the command palette's border,
which were built on undefined variables and never applied.

Co-authored-by: Amp <amp@ampcode.com>
Amp-Thread-ID: https://ampcode.com/threads/T-01a1c31e-5888-7773-8b7a-d6900d7cccbf
@brandonkelly brandonkelly changed the title [6.x] UI tweaks: centered utility content, centered nav badges [6.x] UI tweaks: centered utility content and nav badges, type, shadow, and keycap polish Nov 10, 2026
Amp-Thread-ID: https://ampcode.com/threads/T-01a1c31e-5888-7773-8b7a-d6900d7cccbf
Co-authored-by: Amp <amp@ampcode.com>

# Conflicts:
#	CHANGELOG-WIP.md
@brandonkelly
brandonkelly merged commit c8ee92a into 6.x Nov 10, 2026
22 checks passed
@brandonkelly
brandonkelly deleted the ui-tweaks branch November 10, 2026 05:54
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.

1 participant