catalog: volume card overhaul (identity band + a11y pass)#5146
catalog: volume card overhaul (identity band + a11y pass)#5146QuiltSimon wants to merge 14 commits into
Conversation
…5125) Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…eview (#5127) Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…5128) Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Website register (landing bucket grid): - Expand seeded BucketIcon glyphs to a 79-entry scientifically-oriented library (labware, molecular bio, microbiology, chemistry, data-viz, clinical) in components/BucketIcon/seedGlyphs.ts. - Add page-level collision-free glyph assignment (assignGlyphs: hashed preferred slot + linear probe) so no two visible buckets share a glyph; wire glyphIndex through BucketGrid (cards) and BucketList (rows). - Tint still hashes from name for color variety independent of glyph. Shell: collapsible sidebar rail (animated width with content reflow), logo/wordmark assets, NavBar + Landing Buckets adjustments. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The collaborator count was a floating MUI Badge in the card's top-right
corner; its translate(50%,-50%) overhang collided with the rounded corner
and clipped. Replace it with a quiet lab-instrument readout in one visual
language, two densities:
- Cards (footer variant): "Shared with N" on a divider baseline that lines
up across every card, with an "Only you" private state. Card body reorders
to description -> tags -> flex spacer -> footer so rows stay uniform.
- Rows/list (inline variant): the label collapses to a visually-hidden span
(kept for screen readers; tooltip carries it), leaving a compact glyph +
tabular count that right-aligns down the list. A conditional right gutter
keeps tags and the title/address from sliding under the readout.
Collaborators gains a variant prop ('footer' default, 'inline' for rows);
count uses tabular-nums and mutes until hover. Unmanaged roles still surface
as "N+".
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Removes the localhost:8400 dev-only <script> injection that leaked into the committed HTML and was failing oxfmt --check (test-catalog). Co-authored-by: Cursor <cursoragent@cursor.com>
- tagStyles.ts: one tag vocabulary (square, soft-tertiary at rest, solid
when active) shared by the card, list row, and shortcuts so the three
call sites can't drift apart again.
- fix chip active-state false positive: match on tokenized filter terms
instead of substring (`filter.includes('rna')` was lighting up while
filtering "rna-seq").
- gate the card entrance animation behind prefers-reduced-motion: no-preference.
- title reads text.primary at rest, tertiary on hover (matches the list row).
- add-tile border uses the tertiary token, not the retired off-palette indigo.
- empty-search state: calmer h6 headline + a "Clear filter" recovery button.
Co-authored-by: Cursor <cursoragent@cursor.com>
Make the seeded bucket icon a real bucket attribute rather than a per-view render artifact. - BucketIcon: extend the quilt-glyph: scheme to carry an optional disc color (quilt-glyph:<name>?c=RRGGBB) via parseGlyphSrc/buildGlyphSrc, so an admin-chosen color rides inside the single iconUrl string with no backend schema change. Thread the color through seedToArt (it overrides the hashed tint; wash/ring still derive from the one tint so the chip stays coherent). Add defaultGlyphSrcForBucket for a deterministic per-bucket default. - seedGlyphs: fix the centrifuge glyph (was reading as a cloud at the 24px blind-read gate). Add a category model over the existing GLYPHS order (GLYPH_CATEGORIES boundaries + GLYPH_GROUPS) — metadata only, order is preserved because the website register hashes names into indices. - BucketGrid/BucketList: render stored iconUrl first; only fall back to the collision-free assignGlyphs pass for legacy buckets with no stored icon. The icon now looks identical in the grid, list, and admin, and persists on create / on the next admin save for legacy buckets. Co-Authored-By: Claude <noreply@anthropic.com>
…to-open Rebuild the admin glyph picker around the persisted glyph+color model. - Click-to-open: the live BucketIcon preview is itself the trigger (a keyboard-accessible button, amber two-layer focus ring that holds on both the white card and the canvas, reduced-motion-gated hover) — no separate "Choose a glyph" button. - Findability: a pinned autoFocus search field; at rest the ~200 glyphs render grouped under 12 sticky category headings (from GLYPH_GROUPS); typing collapses to a flat prefix-then-substring ranked list; empty → "No glyphs match". - Color: an Auto chip (name-hashed tint) + the six on-palette SEED_TINTS swatches (human-named) + an in-app Roboto Mono hex field (replaces the native OS colour dialog, which broke the light-theme surface). Selected swatch/Auto carry a checkmark — a non-colour selection cue. - The selected glyph's human label renders under the preview. - On create, a bucket with no chosen icon persists a deterministic default; the edit form pre-fills that default for legacy null-iconUrl buckets so a save materialises it. - Add a file-scoped detector ignore for broken-image on BucketIcon.tsx (the rule naive-matches the literal <img> token in code comments); gitignore the impeccable critique snapshots as per-session artifacts. Co-Authored-By: Claude <noreply@anthropic.com>
Design/UX polish thread that was in flight alongside the glyph work. - Sidebar: collapsible rail — logo crossfade (icon <-> wordmark) and label fade/slide on collapse, kept compositor-only (opacity/transform) except the rail's own width, which must reflow the content column. - Queries/Athena: align the query selector row with the workgroup Select (label + input rows match), layout containers, and empty/disabled-state handling so the columns line up instead of showing bare text. Co-Authored-By: Claude <noreply@anthropic.com>
The left-rail assistant entry reads just "Qurator" (the chat-input placeholder in the assistant panel keeps "Ask Qurator"). Co-Authored-By: Claude <noreply@anthropic.com>
Make the Home volume cards differentiate at a glance and read in clear priority order, within the Lab Instrument doctrine (quiet chrome, one accent, border-first, no gloss). - Identity band: promote the seeded glyph from a 32px corner avatar to a 44px identity mark on a quiet wash of the bucket's own tint. A wall of volumes now reads by colour+glyph instantly. Border-first bottom rule, no gradient. - Hierarchy: title (scan anchor) -> s3:// URI in Roboto Mono (Mono Identity Rule) -> description -> tags -> access footer. Card rests on a hairline, not a shadow (Elevation doctrine); a `meta` row is reserved as the seam for a future trust readout (the Home query doesn't carry lastIndexed / counts yet — deferred deliberately). - Access: the "Shared with N" collaborator readout is a first-class footer on a consistent baseline. - Hover: the card edge takes the bucket tint and lifts one step; single transition, reduced-motion-gated. - BucketIcon exports resolveTint so the card header and the list-row hover reuse the same tint hashing (explicit ?c= wins, else name-hash) instead of re-deriving it. BucketList row hover + title/name hover now track the bucket tint too, so grid and list stay one vocabulary. Co-Authored-By: Claude <noreply@anthropic.com>
…trast
Pre-PR critique fixes on the redesigned card (grid + list, kept in parity):
- Focus (WCAG 2.4.7): add a card-level :focus-within ring (tint border + a
soft tint outer ring) so keyboard focus is visible on both the white
surface and the tinted identity band. Previously only :hover was styled.
- Keyboard path: the s3:// URI link is now tabIndex={-1} in both the grid
card and the list row, so the title is the single tab stop per item — no
more confusing double-stop to the same route for keyboard/AT users. The
URI stays a mouse target with its title attr.
- Contrast: the s3:// URI moves from text.hint (~2.9:1, below AA) to
text.secondary (~4.6:1, AA) — it's copy-paste machine identity and must be
legible. List scheme prefix likewise lifted off the near-invisible hint.
- Hover: drop the transient box-shadow; the tint-border alone carries the
hover state, so the card is flat at rest AND on hover (Elevation doctrine,
border-first) — no shadow exception needed.
Co-Authored-By: Claude <noreply@anthropic.com>
|
Bugbot is not enabled for your account, so this pull request was not reviewed. Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs. |
|
@nl0 — new PR for the Home volume-card overhaul, off the dx-shell-rehome-simon line. The two new commits are b8f9352 (card redesign: tinted identity band, hierarchy, first-class access footer, single-sourced --bucket-tint shared with the icon + list row) and 20d0401 (a11y pass). Ran it through the Impeccable dual-agent critique as a pre-PR gate: 32/40, and the two P1 a11y blockers it found (focus-visible ring, keyboard double-stop) plus a P2 URI contrast token are all fixed in 20d0401. Detector clean, tsc clean, spec passing. Heads-up on scope: because the base (dx-shell-rehome) is behind this branch, the PR also carries everything already on #5135 — the card commits are the only new content here. Happy to rebase once #5135 lands so the card diff stands alone. Also: verified via a faithful standalone render, not the live app (tooling here can't screenshot the SPA route) — worth a real in-app look. |
| const Freeze = React.memo( | ||
| ({ children }: { children: React.ReactNode }) => <>{children}</>, | ||
| () => true, | ||
| ({ children }: { children: React.ReactNode; sig?: unknown }) => <>{children}</>, | ||
| (prev, next) => prev.sig === next.sig, | ||
| ) |
There was a problem hiding this comment.
Memoization freezes sidebar state
When bookmarks, subscription status, assistant availability, authentication, or roles change without a collapse toggle, this comparator treats the entire rail as unchanged because it compares only sig. The sidebar therefore retains stale badges, warnings, navigation entries, and account information until it is collapsed, expanded, or remounted.
Knowledge Base Used: Catalog Frontend (catalog/app)
Overhauls the Home volume cards so a wall of buckets differentiates at a glance and reads in clear priority order — within the Lab Instrument doctrine (quiet chrome, one accent, border-first, no gloss).
The new work (this PR's substance — top 2 commits)
b8f93526— volume card overhaul. Identity band: the seeded glyph is promoted from a 32px corner avatar to a 44px identity mark on a quiet wash of the bucket's own tint (border-first, no gradient). Hierarchy re-ranked: title →s3://URI in Roboto Mono (Mono Identity Rule) → description → tags → a first-class "Shared with N" access footer. Card rests on a hairline, not a shadow (Elevation doctrine).BucketIconnow exportsresolveTintso the card header, the hover edge, the title hover, and the siblingBucketListrow all read one shared--bucket-tint— card, icon, and list-row are provably one vocabulary. Ametarow is reserved as the seam for a future trust readout (the Home query doesn't carrylastIndexed/counts yet — deferred deliberately).20d04016— a11y pass (pre-PR critique fixes). Card-level:focus-withinring (tint border + soft tint outer ring, verified on both the white surface and the tinted band, WCAG 2.4.7); thes3://URI link istabIndex={-1}in grid + list so the title is the single keyboard tab stop per item (no double-stop); URI contrast lifted fromtext.hint(~2.9:1) totext.secondary(~4.6:1, AA); hover shadow dropped — the tint-border carries hover, so the card is flat at rest and on hover (no Elevation exception needed).Impeccable review
Ran the dual-agent critique as a pre-PR gate. Verdict 32/40, initially no-ship on two P1 a11y blockers (focus ring, keyboard double-stop) + one P2 contrast token — all fixed in
20d04016before this PR. Deterministic detector: clean (exit 0, zero findings) on both BucketGrid files.tscclean; BucketGrid spec passing.Deferred P3 follow-ups (not blockers): dead
metaCSS is a documented seam; custom-imageonErrorfallback; many-tags card-height balloon.Scope note
This branch is off
dx-shell-rehome-simon, and the basedx-shell-rehomeis behind it — so this PR also carries the commits already under review on #5135 (bucket-icon picker, glyph model, sidebar/Athena polish, the Qurator rename) plus earlier un-merged catalog work and 3 Dependabot bumps. The two card commits above are the new content here. If preferred, this can be rebased once #5135 lands so the card diff stands alone.Verification caveat
The card was verified via
tsc, the spec, the mechanical detector, and a faithful standalone render (real tints + glyph data + the actual style values) — not the live app, since the review tooling in this environment can't screenshot the React SPA route directly. Worth a real in-app look before merge.🤖 Generated with Claude Code
Greptile Summary
This PR overhauls the catalog’s volume identity and navigation presentation.
Confidence Score: 3/5
The PR should not merge until the sidebar is allowed to rerender when its live authentication, bookmark, assistant, and subscription inputs change.
The temporary
Freezecomparator treats the entire navigation rail as unchanged whenever collapse state is stable, leaving multiple user-visible context-driven controls stale.catalog/app/containers/Sidebar/Sidebar.tsx
Important Files Changed
Flowchart
%%{init: {'theme': 'neutral'}}%% flowchart LR Admin[Admin bucket form] -->|stores iconUrl| Config[Bucket configuration] Config --> Icon[BucketIcon resolver] Icon -->|quilt-glyph scheme| SVG[Inline seeded SVG] Icon -->|custom URL| Image[Custom image] SVG --> Grid[Volume grid/list] Image --> Grid Grid --> Identity[Identity band, tags, collaborators]Reviews (1): Last reviewed commit: "catalog: volume card a11y pass — focus r..." | Re-trigger Greptile
Context used: