feat: new topic messages page behind enableNewTopicMessagesPage flag - #2588
Open
jvorcak wants to merge 21 commits into
Open
feat: new topic messages page behind enableNewTopicMessagesPage flag#2588jvorcak wants to merge 21 commits into
jvorcak wants to merge 21 commits into
Conversation
Redesigned messages UX (from the Console Messages UX prototype): - Read scope popover (newest/oldest/offset/timestamp) with live tail in the menu, continuous pagination for newest/oldest only, and an illustrated "how reading starts" doc sheet - Filter bar with typed tokens (partition:1, offset>5, key:abc), autocomplete with value suggestions and ghost completion, keyboard chip editing (ArrowLeft unwraps a badge into editable text, Enter recommits in place), and JS predicate filters with live preview - Field filters, partition, quick search and selected message persist in the URL; JS filters stay in sessionStorage - Message detail as docked resizable panel or expanded sheet, with persisted view state (mode, widths, section expansion) and a metadata table, headers grid and troubleshoot reports - View settings sidebar: row density, drag-reorderable columns with per-column config (timestamp format, deserializers, preview fields) - Quick info stats rebuilt on the registry Stat component Fixes surfaced while building it: - assignDeep now replaces arrays wholesale; the index-wise merge mutated shared elements through the uiSettings sync and corrupted reordered arrays (duplicate/lost message columns after drag'n'drop); getMessageColumns heals already-corrupted persisted entries - SidebarInset gets min-w-0 so wide content (messages table) scrolls inside its container instead of widening the page past the viewport
Standalone dev no longer seeds initialFlags from constants.ts defaults overlaid with debug-dialog overrides; back to only E2E globals.
Replace arbitrary pixel font sizes (text-[10px], text-[11px], text-[12.5px], text-[13px]) with the semantic text-caption/text-body-sm/text-label utilities from the redpanda-ui typography scale.
Contributor
🚨 Registry drift detectedApp:
Components needing attention
Refresh command: bunx shadcn@latest add @redpanda/combobox @redpanda/sidebar --overwrite🎨 Off-token colours (palette literals)Use semantic tokens (
🔢 Ad-hoc utility classes (arbitrary values)These bypass the design tokens. Prefer a named scale entry or add a new token.
Generated by lookout audit-changes. |
StatGroup now uses CSS subgrid so stat values align on a shared baseline across a row even when labels wrap.
Drop the client-side predicate preview sandbox (hit list, error highlighting, apply-gating) from the JS filter dialog. The backend already validates and applies the predicate on save.
jvorcak
marked this pull request as ready for review
August 7, 2026 16:26
Collaborator
Author
|
The filter bar is still under developments, other things can be reviewed |
…th pill highlights Replaces the chip-based filter bar with a single real text input whose caret behaves natively (click/arrow/select/backspace anywhere) while recognized field:value words are painted with a subtle pill highlight overlay — no discrete chip elements, no synthetic keyboard "browse" state. - New utils/filter-line.ts continuously parses the whole line into partitionId/fieldTokens/quickSearch, replacing the old commit-on-space model - Quote-aware value parsing (`field:"multi word"`) in filter-token.ts - Suggestions/ghost-completion now scope to the word under the caret - JS predicates keep a small separate chip (can't live inline in free text); js:<label> now seeds the new filter's name instead of its code when the typed text doesn't look like an actual JS expression - Fixes a duplicate-filter bug where a stray Enter after committing a token could reinsert it
…ogic Follow-up review pass on the filter bar rewrite: - Match the JS filter chip's border-only look on the highlighted pills (outline instead of a flat bg-muted fill) and extract a shared FILTER_BADGE_TEXT_CLASS so the chip, the pills, and the suggestion dropdown's labels can't drift out of sync again (they'd already diverged: 13px chip text next to 14px pill text) - Extract sameFieldTokens into filter-token.ts, shared by the filter bar's own resync check and use-messages-url-state's fieldTokensParser.eq (previously two independent copies of the same array-equality check) - parseFilterLine now returns tokenRanges directly instead of the filter bar re-tokenizing/re-parsing the same text a second way for the highlight overlay - Swap arbitrary text-[10.5px]/text-[11px] for the registry's text-caption utility in the suggestion dropdown's headers and sub-labels - Use registry Button (secondary-ghost, icon-xs) for the clear-all control instead of a hand-rolled icon button that happened to reinvent the same preset
…he registry Chip, HighlightedInput, and Listbox are now generic, domain-agnostic registry components (src/components/redpanda-ui/components/) — filter-bar.tsx keeps only the filter-parsing/suggestion logic, with rendering served from the registry.
…pe popover Renders the calendar/time panel as normal flowed content instead of a click-to-open popup nested inside the already-open read-scope popover, with a Unix timestamp label, a registry ToggleGroup for Local/UTC, and matching indigo-600 styling between the selected day and the Now button. Also excludes .playwright-mcp/ from rsbuild's dev-server watcher — it was triggering rebuilds (and occasional rspack panics) on every screenshot/log written into the project root while driving the dev server with Playwright.
malinskibeniamin
left a comment
Contributor
There was a problem hiding this comment.
Inline findings: P1/P2. No P0/P3 identified.
…d-scope popover Blocker: partition:<non-numeric> produced NaN that desynced the filter bar's resync guard and wiped whatever the user had typed. Majors: - Removed stat.tsx, which shadowed the newer subgrid-aligned stat/index.tsx via file-before-directory module resolution — it was never actually loaded. - Chip's remove button didn't stop propagation, so removing a JS-filter chip bubbled into the filter bar's container and reopened the suggestion dropdown. - Listbox had no ARIA roles; wired role="combobox"/aria-expanded/aria-controls/ aria-activedescendant on the filter input to match. - The filter bar's resync effect couldn't tell "still catching up to our own emission" from "genuinely external," so a parent whose three pieces of state echo back across separate renders (rather than atomically) could destroy in-progress typing. - tokenQueryText wasn't actually lossless — values with whitespace or embedded quotes changed meaning after a URL round-trip. Added backslash-escaping. - An unbalanced/stray quote could swallow the rest of the typed line into one token, silently discarding every filter after it. - offset:N matched via substring containment (offset:12 matched 1123); it now means equality, and the existing-but-unreachable offset comparison-suggestion UI is wired up to the current word-under-caret architecture. - neq returned false (excluding the message) when the field was absent, when "does not equal" should keep it. - The 'c' row-copy shortcut fired on Cmd/Ctrl+C too, clobbering the user's own clipboard selection with the row's JSON. - Keyboard nav stayed armed while the view-settings panel, docs sheet, or read-scope popover was open; ReadScopePopover now reports its own open state via a new onOpenChange prop so all of these can gate on it. - Toggling continuous pagination didn't reset pageIndex like every sibling read-scope handler, so staying on a later page could show a permanently blank table with no page controls to recover with. Every fix is paired with a regression test that fails on the prior behavior and passes with the fix (verified via temporary revert for each).
- Disable partition/max-results/deserializer controls while live tail is streaming, since edits there update state the running stream never picks up. - Stop showing JS filter chips as active when continuous mode has actually dropped them from the request; reset pageIndex when field tokens or quick search change. - Fix a shared-closure bug where hovering any filter suggestion row highlighted the last row instead of the hovered one. - Restrict the partition filter to exact match — reject partition>/</!= instead of silently collapsing them to equality.
…lter - Keyboard nav (visiblePageKeys) now skips re-sorting in continuous mode, matching the table's own sortingDisabled — previously it kept applying urlState.sorting even when the table fell back to server order, so j/arrow-key selection landed on a different row than what was displayed. Extracted messageKey into its own leaf module so the new pure-logic test doesn't pull in sonner/React transitively. - parseFilterInput/parseFilterLine take an optional partitionCount and reject an out-of-range partition:N (e.g. partition:9999 on a 3-partition topic) instead of sending it through as a real request. Threaded through FilterBar from topic.partitionCount.
…e gate Swap the enableNewTopicMessagesPage check from the custom feature-flag provider hook to the shared isFeatureFlagEnabled helper.
malinskibeniamin
left a comment
Contributor
There was a problem hiding this comment.
Automated /review: 3 finding(s).
offset<=N and offset>=N previously fell through to plain text since parseOperator matched the bare </> prefix first, stranding a leading = in the value. Adds gte/lte to FilterOp, wires them through parsing and client-side matching, and centralizes the operator<->symbol mapping in one table shared by parsing and display formatting.
- Fix "Download Record" silently doing nothing: append the anchor to the DOM before click() (required in Firefox) and revoke the object URL on a later tick instead of racing the download. - Fix keyboard nav (j/k, arrow keys) selecting a different row than what's rendered: derive which column is sortable from a single isSortableColumnId predicate shared by the table's enableSorting and visiblePageKeys, instead of independently guessing and defaulting unrecognized sort ids (stale key/value sorts from the legacy page) to an offset tiebreak the table itself never applies. - Fix column-visibility checkboxes having no accessible name by wiring each one to its label via aria-labelledby. Also drops .playwright-mcp/ from .gitignore per review feedback to use the Playwright CLI instead of MCP.
…-check on quick search - messages-footer.tsx: read onLoadMore/isLoadingMore through refs instead of effect deps, so a fresh inline onLoadMore from the parent no longer tears down and rebuilds the IntersectionObserver every render (which re-fired against the sentinel's current intersection state and auto-loaded the entire topic with no scrolling). - use-client-filters.ts: thread partitionCount through to parseFilterInput so quick search rejects out-of-range partition tokens the same way the filter bar already does, instead of silently blanking the table.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Redesigned messages UX (from the Console Messages UX prototype):
field:valuewords pill-highlighted (parsed continuously as you type, no commit step), word-scoped autocomplete/ghost-completion, and JS predicate filters as a separate chipFixes surfaced while building it:
Before:

After:

