Table Views — design fixes

The changes from the design review, before and after.

Both halves of each pair are the same running build at the same size — the “before” simply has the old values put back, so nothing but the change itself differs. Live at the preview.

1

Error message + clear button

The message was 12px with a 16px line — two steps below body text, so it read as a caption about the list rather than as something about what had just been typed. It is now 14px / 20px, the size the product writes its own field validation in.

The X is shown for as long as there is a query to clear. It used to appear only under the pointer; a way out of a filter you have to go looking for is not one most people find, and it left the slot empty for the whole time a query was being written. In both shots below the pointer is away from the box.

Error message + clear button
2

Icons in 32px controls are 14px

Everywhere in the toolbar: the magnifier, the clear, the View button’s cog and the chevron on each tab.

Icons in 32px controls are 14pxIcons in 32px controls are 14pxIcons in 32px controls are 14px
3

“You have unsaved changes” banner

It was a wash mixed from --primary, which ties it to the brand — green on a Prime install, so an informational line read as a success message. It now uses var(--info-badge), rgba(31, 103, 219, .10): the same wash the Provisioning state badge is drawn on, and the closest token in the product to the #E8EFFD on the Figma. Font-size 13px → 14px.

“You have unsaved changes” banner
4

Sub menu lines up with its row

The Group By list opened 3px high. Both panels carry the same 3px inset, so lining the two panels up lines their first rows up — the offset was overshooting by exactly that inset.

Sub menu lines up with its row
5

A list too long for the room rides up

It used to open where it was placed and scroll, leaving the space above it unused. Now it slides up so the whole list fits. The window below is 560px tall and every row is on screen, with no scrollbar.

A list too long for the room rides up
6

… and stops 16px under the header

When even the whole region is not enough it goes as far as it may and only then scrolls. Measured on the 430px window below: 17px of gap above the panel (the 16 plus its 1px border) and 17px at the fold.

… and stops 16px under the header
7

Typing no longer triggers on every keystroke

The box stays live — what you type appears at once, and so do its suggestions. What waits is the table: the rows re-filtering, the request to the api, the count fetched for each tab. That now holds off until 400ms after the last keystroke, the same delay the cluster switcher’s search uses; both read it from one shared constant (SEARCH_DEBOUNCE in shell/config/search.ts) so the product types at one speed.

A query arriving whole — a saved view applied, a shared one from a url — is not typing, so it still takes effect at once.

Measured on the running build: typing state:active (12 keystrokes) fired 1 list request, and the filter still lands — 2 rows, tab reads “Explorer (2)”.

8

Suggestion list — a select’s container

The container is a select’s, and wears the product’s own vs__dropdown-menu class rather than a copy of its rules kept here. The two boxes touch on a shared 1px line (−1px, measured the same on the namespace picker), the corners they meet at are square on both sides, one --primary-border, no shadow, 10px above and below, a 350px ceiling. What is overridden is only what has to be: that sheet places a dropdown absolutely at its field’s width, this one is placed by hand and is as wide as its entries need. The rows inside keep their own spacing.

Open question — the third shot. The list tracks the caret along the box, so the moment you type past the first word the join it just made comes apart: the square top corners end up hanging in mid-air. Touching like a select and following the caret cannot both hold. Worth deciding before this is done.

select container
9

Arrow keys scroll the list, and wrap

Arrowing past the last entry on screen used to leave the highlight out of sight, so it looked as though the keys had stopped working — and as though the list would not wrap. It now scrolls by as little as will show the entry, and goes all the way to the end when it wraps round. A pointer resting over the list no longer steals the highlight when the scroll slides a new row underneath it.

Measured on the running build: walked all 19 entries — every one on screen; wrapping from the last lands on the first with the list back at the top; wrapping backwards from the first lands on the last, visible.

arrow key scrolling
10

Labels removed from the suggestions

They were never listable. The api indexes every metadata.labels[key] path, so a label typed by hand filters exactly and its values are counted across the whole set — but there is no call that returns which keys exist (summary=metadata.labels is refused, and the schema only describes the table’s columns). The only way to name them was to scan the rows in hand, which made the list whatever the loaded page happened to carry: empty while a fetch was in flight, shorter the moment a query narrowed the rows, gone entirely once it matched nothing.

A menu that empties itself as you type towards the thing you wanted is worse than no menu, so labels are left to be typed. Verified: empty box now offers 6 entries, 0 of them labels; label:test9:test9 typed by hand still filters to 1 row.

suggestions without labels
11

Group By opens on the current grouping

When the list is taller than the room it is given, it now opens scrolled to the field in force rather than at the top with the tick out of sight — the one row you opened the menu to check. nearest scrolls by as little as will show it, so grouping by None or State does not move the list at all.

Keyed on the panel arriving rather than on which sub menu is open: the menu remembers the last one, so re-opening View and going back to the same row shows the list again without that value ever changing. Watching it would have missed exactly the case being asked about.

Verified on a 360px window grouped by Age, the last field: opens at scrollTop 87 with Age on screen; forced back to the top it is not.

group by auto-scroll
12

Sticky Add View, and a cue that the tabs scroll

The strip clipped its tabs silently. It now carries the same edge shadow the app bar’s list carries, built the same way — a sticky pseudo-element, hidden by default so a strip with nothing to scroll draws nothing, revealed by a scroll-driven animation, and faded back out at the far end where there is nothing left to reach. Browsers without scroll-driven animations get a permanently visible shadow rather than none.

Add View is held at the end of the strip, with 8px of its own background to its left so a tab disappears under it instead of stopping dead against the +. Aligning it also turned up a pixel it had always been out by: the strip hangs its last pixel over the row’s rule so an active tab’s underline lands on it, and this button, having no wrap of its own, sat on that pixel — harmless while transparent, but once it had a background it was painting over the rule and the row’s line stopped short of the end.

Measured: shadow opacity 1 at the start and mid-scroll, 0 at the end; Add View pinned 3px from the strip’s right edge throughout; its bottom edge now 182 — the same as the tabs — with the row’s rule at 182 left clear.

sticky add view and scroll shadow