Skip to content

Remove Dashboard “Clear all” control and make filter strips horizontally scroll instead of wrapping #294

Description

@BorisTyshkevich

Problem

PR #293 (Dashboard v1 phases 1–4) added a visible Dashboard Clear all filter control and retained the N active status. In practice the control is visually disruptive, and when several filters are present the Dashboard toolbar wraps filter fields and the clear/count affordances onto additional rows.

The result is a tall, unstable filter area. A representative current layout is:

[from] [to] [exception_code] [metric] [is_initial_query]
[query_kind] [user] [query_hash]
[Clear all] 1 active

This is especially undesirable for dashboards, where vertical space should remain available for data. Filter controls should behave like editor tabs and the existing Workbench variable strip: remain on one row and scroll horizontally when they do not fit.

The relevant current implementation is:

  • src/ui/filter-bar.ts
    • filterClearAllButton(...)
    • filterActiveCount(...)
    • shared buildFilterBar(...)
  • src/ui/dashboard.ts
    • composes bar.el, clearAllNode, and filterCountNode
    • calls session.clearAllFilters() from the visible button
  • src/styles.css
    • desktop .dash-toolbar and .dash-filters currently use flex-wrap: wrap
    • horizontal scrolling is enabled only inside the mobile max-width: 768px rule
  • src/ui/workbench/workbench-shell.ts
    • .var-strip is already documented as a one-row horizontal strip; this behavior must be preserved and covered alongside Dashboard

This issue intentionally reverses the visible clear-all UX decision made in #286/#293. The bulk action may be useful in theory, but it is not worth permanent toolbar chrome in the current product.

Required behavior

1. Remove the visible Clear-all control

Remove the Clear all button from the Dashboard filter UI at every viewport width.

Required code cleanup:

  • remove Dashboard creation and reconciliation of clearAllNode;
  • remove the filterClearAllButton UI factory if it has no remaining UI consumer;
  • remove/update tests that require the visible button;
  • remove obsolete button/host CSS;
  • update comments and CHANGELOG.md that say the Dashboard toolbar exposes clear-all.

This issue removes the visual control. It does not require deleting DashboardViewerSession.clearAllFilters() if that application-level operation remains useful or is part of a stable tested contract. If it becomes genuinely unused, it may be removed in the same change, but do not create unrelated runtime churn merely to eliminate the button.

Per-filter editing/deactivation behavior remains unchanged. No replacement bulk-clear menu is required in this issue.

2. Keep the active-filter count, without allowing it to wrap

Retain the current N active status:

  • hidden when the active count is zero, as today;
  • visible when one or more filters are active;
  • remains on the same filter row;
  • must not be pushed onto a second line;
  • should be a compact, non-shrinking trailing status outside the scrolling filter viewport, so it stays visible while fields scroll.

Recommended Dashboard structure:

.dash-filter-host
├── .filter-strip-scroll
│   └── .dash-filters
│       ├── .var-field
│       ├── .var-field
│       └── ...
└── .dash-filter-count-host

Equivalent structure is acceptable, but the ownership must remain clear: only the field region scrolls; the active count remains fixed and compact.

3. Dashboard filters must never wrap

At all viewport widths, not only mobile:

  • the Dashboard filter field region is exactly one horizontal row;
  • .var-field controls retain their normal/intrinsic width and do not shrink into unreadable controls;
  • excess fields are reached through horizontal scrolling;
  • the Dashboard toolbar does not grow vertically as the number of filters increases;
  • no horizontal overflow is introduced on .dash-page, body, or #root;
  • the layout selector remains fixed on desktop and does not scroll with the filters;
  • on mobile, where the layout selector is hidden, the filter strip uses the available width;
  • combobox menus/popovers continue to escape the scroll viewport correctly and are not clipped;
  • relative-time preview text below a field remains visible;
  • focus and typed input survive normal horizontal scrolling.

The Dashboard toolbar should therefore follow this flex behavior conceptually:

.dash-toolbar {
  flex-wrap: nowrap;
}

.dash-layout-wrap {
  flex: 0 0 auto;
}

.dash-filter-host {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  align-items: flex-start;
}

.filter-strip-scroll {
  flex: 1 1 auto;
  min-width: 0;
  overflow-x: auto;
}

.dash-filters {
  flex-wrap: nowrap;
  width: max-content;
  min-width: 100%;
}

.dash-filters > .var-field {
  flex: 0 0 auto;
}

The exact CSS may differ. Do not blindly apply overflow: hidden in a way that clips field previews or fixed-position combobox behavior.

4. Workbench variable filters must use the same interaction contract

The Workbench .var-strip is already intended to be a single horizontally scrolling row. Treat that as a required cross-surface behavior rather than an incidental CSS detail.

For Workbench:

  • parameter/filter fields never wrap;
  • fields retain their normal width;
  • excess fields scroll horizontally;
  • the strip does not cause page-wide horizontal overflow;
  • horizontal scrolling works with trackpad, mouse/Shift-wheel where supported, keyboard focus, and touch;
  • focusing or tabbing to a field outside the visible viewport scrolls it into view through normal browser behavior or an explicit small helper if required;
  • relative-time, enum, curated, recent-value, and plain-text controls all behave identically to before.

Prefer one shared CSS utility or small DOM/CSS pattern for horizontally scrolling control strips, used by both:

  • Workbench .var-strip;
  • Dashboard .dash-filters field viewport.

Do not merge the Workbench and Dashboard state/rendering implementations merely to share scrolling CSS.

5. Follow the editor-tab interaction precedent

Use the existing editor tabs as the interaction precedent:

  • one stable-height row;
  • controls retain their width;
  • overflow is local to the strip;
  • final controls remain reachable;
  • scrolling the strip does not scroll the entire page horizontally;
  • keyboard focus remains usable.

The scrollbar may use the same visible/hidden styling policy as editor tabs. Do not sacrifice discoverability on desktop if the tab implementation relies on a visible scrollbar or wheel behavior.

Accessibility

  • Removing Clear all must not remove labels or accessible names from individual filter controls.
  • N active retains role="status" and its current accessible label semantics.
  • Every filter remains keyboard reachable.
  • Tabbing through off-screen controls must reveal the focused control.
  • The scroll region should have an accessible label only if it is itself made focusable; do not add unnecessary tab stops.
  • Do not use drag interactions for filter-strip navigation.

Tests

Unit / DOM tests

Update or add tests proving:

  • Dashboard does not render a Clear all filters button at active count 0 or greater than 0;
  • active count still renders accurately;
  • Dashboard filter host has a separate scrolling field region and fixed count region;
  • no clear-all click expectation remains;
  • filter execution, activation, debounce, recents, curated choices, and validation behavior are unchanged;
  • Workbench still renders all parameter fields in its variable strip.

Real-browser layout tests

CSS wrapping and overflow cannot be validated reliably in happy-dom. Add or extend a focused Playwright harness for both Workbench and Dashboard.

At minimum test:

  1. Desktop Dashboard with enough filters to exceed the viewport:

    • all field bounding boxes have the same row/top position;
    • toolbar height does not increase when additional filters are added;
    • scrollWidth > clientWidth on the field viewport;
    • horizontal scroll reaches the final filter;
    • active-count status remains visible and on the same row;
    • no Clear-all button exists;
    • document.documentElement.scrollWidth does not exceed the viewport.
  2. Mobile Dashboard:

  3. Workbench with many {name:Type} parameters:

    • fields stay on one row;
    • the .var-strip scrolls horizontally;
    • the last field can be focused and becomes visible;
    • editor/workbench width does not overflow the page.

Run the layout checks in Chromium and WebKit at minimum because overflow/focus and scrollbar behavior can differ.

Non-goals

  • Redesigning filter types or filter semantics.
  • Changing DashboardViewerSession execution waves, defaults, or persistence.
  • Adding a replacement bulk-clear menu.
  • Adding per-filter × buttons.
  • Adding collapsible More filters behavior from old Dashboard filter bar: clear actions, active count, impact hints, and overflow #188.
  • Changing Dashboard filter definitions or Portable Bundle schemas.
  • Redesigning editor tabs.

Acceptance criteria

  • No visible Clear all filter control exists in Dashboard.
  • N active remains accurate, accessible, fixed on the filter row, and hidden at zero.
  • Dashboard filter controls never wrap at desktop, tablet, or mobile widths.
  • Dashboard excess filters scroll horizontally inside a local viewport.
  • Workbench variable/filter controls never wrap and scroll horizontally using the same interaction contract.
  • Filter controls keep readable intrinsic widths.
  • The final filter is reachable by mouse/trackpad, keyboard focus, and touch.
  • Combobox popovers and relative-time previews are not clipped.
  • No page-level horizontal overflow is introduced.
  • Existing filter values, activation, validation, debounce, recents, and query rerun behavior are unchanged.
  • Real-browser tests cover Dashboard and Workbench overflow behavior.
  • Obsolete clear-all DOM helpers, styles, tests, comments, and changelog wording are removed or corrected.

Context

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions