# Filter bar > The viewer needs to narrow a large set by several attributes and see what's applied. - Canonical: https://patterns.konigi.com/dashboards/filter-bar - Group: Product mechanics - Level: flow - Status: published - Updated: September 10, 2026 - Also called: facet bar, query bar, filter chips --- ## Problem There are nine hundred thousand events and the viewer cares about the production ones, from the checkout service, in the last hour, that failed. Four narrowings, and after applying them they need to be able to see at a glance which four they applied. ## Solution A persistent row of controls above the content, each narrowing the set, with every active filter visible as a removable chip. The state is the bar; the content is a consequence. Two properties do nearly all the work, and both are about visibility rather than about filtering. **Applied filters must be legible without opening anything.** A dropdown that says "Service" when three services are selected has hidden the thing that determines what is on screen. Chips showing `service: checkout` are longer and correct. This is Nielsen's first heuristic applied to state rather than to progress: the person has to be able to see what the system is currently doing. **Removal must be as cheap as application.** Filtering is exploratory, and exploration means overshooting. One click to add and three to remove produces viewers who stop narrowing. Beyond that, the interesting design questions are about the filter values themselves. Should the bar show only values that exist in the current set, and update as filters are applied? Doing so prevents dead ends where a viewer selects a combination that matches nothing. Not doing so is much cheaper to build, and is why so many filter bars let you construct an empty result and then leave you wondering which choice caused it. Grafana's approach is worth studying because it is structurally different: variables are declared on the dashboard, populated by their own queries, and referenced inside panel queries, with the selection carried in the URL. That makes filtering explicit, shareable and chainable—one variable's options can depend on another's selection—at the cost of every filter being something an author had to build in advance. ## Use when The population is large, several attributes matter, and different viewers narrow differently. Any triage surface. ## Don't use when There is one dimension and few values. Three tabs beat a filter bar with one dropdown. Also avoid a filter bar as the only way in: a page whose default state is unfiltered and unusable has pushed its information architecture onto the viewer. ## Trade-offs Filter bars accumulate. Every new attribute someone wants is one more control, and a twelve-control bar is a form. State becomes invisible in screenshots, so a filtered dashboard shared into a channel is routinely misread. Filters can conflict with each other in ways only discoverable by hitting an empty result. And a bar that persists filters across sessions will eventually greet someone with yesterday's narrowing and no memory of having set it, which is the most confusing five minutes a dashboard can produce. ## Checklist - Can a viewer see every applied filter without opening a control? - Is removing a filter as cheap as adding one, and is there a clear-all? - Do the offered values reflect the current set, or can a viewer construct an empty result? - If the result is empty, does the page say which filter caused it? - Does the filter state go into the URL? - Do filters persist across sessions, and does the viewer know? - Can filters be chained, so one narrows the options of the next? - How many controls before this stops being a bar and becomes a form? - Does everything on the page honour the filters, and do exceptions say so? - Does a screenshot of this page carry enough to be read correctly? ## Compare **Grafana** makes filters a declared object rather than an ad-hoc control: template variables are defined on the dashboard, populated by queries, chained so one constrains the next, and carried in the URL, which makes state shareable and every filter something someone had to anticipate. **Honeycomb** puts a query builder where the bar would be, so narrowing is composing a query and there is no fixed set of filterable attributes—the cost is a higher floor for a casual viewer. **Sentry** uses a single search field with a tag syntax, trading discoverability for speed once learned, and softens it with autocomplete over real tag values. **Datadog** scopes a whole page by tags from one control, so filters apply uniformly across every widget by construction rather than by each panel remembering to honour them. ## Related Template variable is Grafana's implementation of this and the entry that covers the chained-variable case. Cross-filter is the gestural alternative that narrows by selecting rather than by choosing. Search across panels covers free-text narrowing. Saved view is how a useful set of filters stops being retyped. Ranked list is what usually sits underneath and only means something once the population is narrowed. ## Examples ### Tableau Public (Salesforce) Thousands of dashboards made by people who are not designers, published without a review step. The best available sample of what the pattern language looks like in the wild. **Emergency Department / Clinical Dashboard** — captured September 11, 2026, Tableau Public embed view; emergency department patient flow workbook. analytical, dense density, light theme, desktop-web. Worth recording partly for what it is not. I went looking for a bed map, and what the public web has instead is this: analysis about an emergency department rather than the board the department actually runs on. There is no row per bed, no occupancy, no waiting-for column. Track boards live inside the patient record and never leave it, which is why that pattern has no example here and probably never will. What this does have is the punch card the calendar-heatmap entry names as the better answer for anything with a daily rather than weekly shape: weekday down the side, hour of day across the top, and the busy band from roughly ten to twenty-one is legible instantly without anyone labelling it. Its ramp is the problem—a blue-to-orange diverging scale on a patient count, which has no meaningful centre, so the midpoint sits wherever the data happened to average. The treemap beneath it degenerates into a mosaic of unlabelled slivers about a third of the way across. Hotspots in this capture: - [Calendar heatmap](https://patterns.konigi.com/dashboards/calendar-heatmap) — The punch-card variant: hour of day against weekday. The busy band reads in a second, from the layout alone. - [Small multiples](https://patterns.konigi.com/dashboards/small-multiples) — Twelve month panels on one shared y-axis, so the seasonal fall from 265 in May to 52 in December is comparable across all of them. - [Sequential and diverging scales](https://patterns.konigi.com/dashboards/sequential-and-diverging-scales) — A diverging blue-orange ramp on wait time, which has no meaningful centre, so the midpoint is wherever the mean fell. - [Target and progress](https://patterns.konigi.com/dashboards/target-and-progress) — Each unit against a median reference line, green below and red above. A target marker doing the work of a threshold. - [Filter bar](https://patterns.konigi.com/dashboards/filter-bar) *(this pattern)* — One dropdown, full width, showing its selected value rather than a count. Everything below is scoped to it. ### Grafana (Grafana Labs) The reference implementation for panel grids, template variables, and stat panels; most other tools are defined by how they differ from it. **Examples / Alert List** — captured September 10, 2026, Grafana Play (signed out; no version string exposed). operational, medium density, dark theme, desktop-web. Seven alerts, and the durations are the story. "Browser market share > 50%" has been firing for 17 days, 15 hours and 12 minutes. Two more have been firing for over three days. An alert that has been true for two and a half weeks is not telling anyone anything—it has become part of the background, and the list it sits in is now a list you scroll past. The other thing worth reading is the names. Six alerts, six conventions: a full sentence, a metric identifier in snake case, a camel-case service name, a two-word phrase, and two that just say "Dynamic". Somebody arriving at this list at three in the morning cannot tell from the names what is broken or how badly, which is work the naming could have done for free. Hotspots in this capture: - [Alert rule attached to panel](https://patterns.konigi.com/dashboards/alert-rule) — Seven rules in six naming conventions. Nothing in the list conveys severity or subject. - [Alert rule attached to panel](https://patterns.konigi.com/dashboards/alert-rule) — Firing for 17 days. Still actionable, in principle; nobody has acted for two and a half weeks. - [Semantic status color](https://patterns.konigi.com/dashboards/semantic-status-color) — Pending rather than firing: the threshold is met and the duration isn't. Two states, both named. - [Filter bar](https://patterns.konigi.com/dashboards/filter-bar) *(this pattern)* — "1 instance, 24 hidden by filters"—the list saying what it is not showing you. - [Drill-down](https://patterns.konigi.com/dashboards/drill-down) — The route from an alert back to the rule that defined it, on every row. **Demo / Annotations** — captured September 10, 2026, Grafana Play (signed out; no version string exposed). operational, medium density, dark theme, desktop-web. The header on this dashboard says annotations "appear as vertical lines and icons on all graph panels—events visible at a glance", and the panel directly beneath it is the counter-example. Roughly fifty red dashed lines across twenty-four hours, evenly spaced, and the request-rate series behind them is genuinely hard to follow: the fence is denser than the data. Every one of those lines is a real event correctly recorded, and the tag filter in the top left is switched on, so this is the filtered view. That is the whole problem with automatic annotations—they are complete and they never stop arriving, and completeness at this cadence is indistinguishable from noise. The list panel at the bottom is what makes them usable again: the same events, four of them, timestamped and tagged, in a form you can read. Hotspots in this capture: - [Annotation](https://patterns.konigi.com/dashboards/annotation) — Fifty deploy markers on a 24-hour chart. Each one is correct and together they are a picket fence. - [Annotation](https://patterns.konigi.com/dashboards/annotation) — The same events as a list, tagged release and timestamped. Readable in a way the chart is not. - [Filter bar](https://patterns.konigi.com/dashboards/filter-bar) *(this pattern)* — The tag filter that makes this survivable, already on. The chart above is the filtered version. - [Time-range picker](https://patterns.konigi.com/dashboards/time-range-picker) — Twenty-four hours, which is what sets the marker density. An hour here would be three lines. **Examples / Dashboard Variables** — captured September 10, 2026, Grafana Play (signed out; no version string exposed). analytical, medium density, dark theme, desktop-web. Six selectors across the top and the page is unusually honest about what they cost. The middle panel says there is a hidden variable called bestfood, currently set to pizza, which has no control anywhere on screen—state affecting the page that a viewer cannot see or change. The overview panel says that setting Instance and then changing the Prometheus source will clear your selection, because the two variables are chained and the second one invalidates the first. Both of those are correct behaviour and both are the reason parameterised pages get distrusted. What the top row gets right is the display: Instance and CPU Usage Type show their selected values as chips with an × rather than as a count, so what is filtering the page is legible without opening anything. Hotspots in this capture: - [Template variable](https://patterns.konigi.com/dashboards/template-variable) — Six selectors bound to every panel's query, with the chosen values carried in the URL. - [Filter bar](https://patterns.konigi.com/dashboards/filter-bar) *(this pattern)* — Values as removable chips rather than a dropdown saying Instance (3). - [Explain this metric](https://patterns.konigi.com/dashboards/explain-this-metric) — Names a hidden variable set to pizza. Prose is doing the work a control should. - [Categorical series palette](https://patterns.konigi.com/dashboards/categorical-series-palette) — Twelve-plus hostnames differing only in the middle digits, with twelve-plus colours to match. - [Data table](https://patterns.konigi.com/dashboards/data-table) — Four columns visible, the fourth cut mid-word, with no horizontal scroll offered. ### Kibana (Elastic) Query-first rather than panel-first: the search bar is the primary control and the charts are downstream of it, which inverts Grafana's arrangement. **Discover / filebeat logs** — captured September 10, 2026, Elastic demo environment (guest session; no version string exposed). analytical, dense density, light theme, desktop-web. Two panes: 315 fields down the left, 13,637 documents on the right, and a volume histogram over both. The left pane is the good half—it opens with a search box rather than a tree, which is the only sane way to navigate that many fields. The right pane is where it falls over. The documents table ships with two columns, a timestamp and "Summary", and Summary is every field on the record concatenated into one cell: agent.ephemeral_id, agent.id, agent.name, agent.type, agent.version, cloud.account.id, cloud.availability_zone, and on for three wrapped lines per row. It is technically complete and it cannot be scanned, so the first thing anyone does here is pick columns—which is to say the default view's job is to make you configure it. Underneath, the pager reads 100 rows per page across 137 pages, and the sort control sits above a table showing the first of them. Hotspots in this capture: - [Two-pane list and detail](https://patterns.konigi.com/dashboards/two-pane-list-detail) — Fields on the left, records on the right, both on screen at once. The oldest working shape for a queue there is. - [Detail on demand](https://patterns.konigi.com/dashboards/detail-on-demand) — An expander on every row. Inline rather than a side panel, so it pushes the rest of the list down. - [Data table](https://patterns.konigi.com/dashboards/data-table) — One column called Summary holding every field on the record. Complete, and unreadable at a glance. - [Search across panels](https://patterns.konigi.com/dashboards/search-across-panels) — 315 fields, so the sidebar opens with a filter box. Past a certain count a tree is a filing system nobody browses. - [Filter bar](https://patterns.konigi.com/dashboards/filter-bar) *(this pattern)* — A query language in the bar rather than chips. Powerful, and it hides what's applied from anyone who didn't type it. - [Time-range picker](https://patterns.konigi.com/dashboards/time-range-picker) — Relative by default, with the refresh control beside it rather than buried in a settings menu. - [Histogram and distribution](https://patterns.konigi.com/dashboards/histogram) — Volume over the window at a 30-second auto interval. The final bar is the bucket still filling, and it always reads low. **Dashboards / [Flights] Global Flight Dashboard** — captured September 10, 2026, Elastic demo environment, sample flight data (guest session). analytical, dense density, light theme, desktop-web. Two things on this page are worth arguing with. The first is the table on the right, sorted by delay rate: Chicago/Rockford 100%, Syracuse 100%, Birmingham 75%. A hundred percent of flights delayed is either a catastrophe or one flight, and nothing in the table says which, because the denominator isn't a column. The cells are on a red ramp, so the two rows that are almost certainly a sample of one are the loudest thing in the panel. The second is the tile row: Delayed 25.2%, then beside it "Delayed vs 1 week earlier—76.9%". Seventy-six point nine percent of what? It could be last week's rate, it could be this week as a proportion of last week, it could be the change. Three different numbers, one label, and the tile picks whichever the query returned. What the page gets right is the filtering: a KQL bar for people who know the syntax and three declared controls underneath for people who don't, both visible at once. Hotspots in this capture: - [Ratio and rate](https://patterns.konigi.com/dashboards/ratio-and-rate) — Delay rates up to 100% with no denominator anywhere. One flight and a thousand flights render identically. - [Compare periods](https://patterns.konigi.com/dashboards/compare-periods) — "vs 1 week earlier, 76.9%"—the comparison base is named and the expression isn't. - [Share and embed](https://patterns.konigi.com/dashboards/share-and-embed) — Share, export and full-screen in the header. Whether the range and filters travel with them is the whole question. - [Filter bar](https://patterns.konigi.com/dashboards/filter-bar) *(this pattern)* — Declared controls under the query bar: two pickers and a price range. Both mechanisms on screen at once. - [Panel grid](https://patterns.konigi.com/dashboards/panel-grid) — Twelve columns, and the biggest panel is a table rather than the headline chart. Size isn't carrying priority here. - [Stacked composition](https://patterns.konigi.com/dashboards/stacked-composition) — Stacked to 100%, so the total is discarded on purpose and only the mix of delay types remains. - [Annotation](https://patterns.konigi.com/dashboards/annotation) — Event markers along the top of the series, numbered and grouped, on the data's own axis. - [Header KPI strip](https://patterns.konigi.com/dashboards/header-kpi-strip) — Five tiles in three different sizes and two different layouts, so the row reads as five things. ## Related patterns - [Template variable](https://patterns.konigi.com/dashboards/template-variable) — One dashboard layout is right for fifty services, forty hosts, or three environments, and nobody should build it fifty times. - [Cross-filter](https://patterns.konigi.com/dashboards/cross-filter) — Selecting something in one panel should narrow every other panel to it. - [Search across panels](https://patterns.konigi.com/dashboards/search-across-panels) — The dashboard has sixty panels and the viewer knows the name of the one they want. - [Saved view](https://patterns.konigi.com/dashboards/saved-view) — The team re-selects the same five filters every morning. - [Ranked list](https://patterns.konigi.com/dashboards/ranked-list) — The viewer needs to know which few items dominate, not the distribution of all of them. ## Sources - [Grafana, Variables](https://grafana.com/docs/grafana/latest/visualizations/dashboards/variables/) - [Nielsen Norman Group, Visibility of System Status](https://www.nngroup.com/articles/visibility-system-status/) - [Bach et al., Dashboard Design Patterns](https://dashboarddesignpatterns.github.io/patterns.html) --- Screenshots on patterns.konigi.com are reproduced for commentary and criticism. Product names and marks belong to their owners.