---
title: Metrics bar
description: >-
  The metrics bar component arranges metric cards in a row with consistent
  spacing, sizing, and a shared loading state.
api_version: 2026-07
source_url:
  html: 'https://shopify.dev/docs/api/shopifyql/latest/web-components/metrics-bar'
  md: 'https://shopify.dev/docs/api/shopifyql/latest/web-components/metrics-bar.md'
api_name: shopifyql
---

# Metrics bar

The metrics bar (`s-metrics-bar`) lays out [metric cards](https://shopify.dev/docs/api/shopifyql/latest/web-components/metric-card) in a row with consistent spacing, sizing, and a shared loading state. It handles layout only and doesn't fetch data or run ShopifyQL. Add metric cards as children, and the row scrolls horizontally when the cards overflow.

The bar can also include a date range picker. The picker emits a `change` event, but it doesn't rewrite card queries. Listen for the event and update each card's `query`.

#### Use cases

* **KPI strip**: Group related headline metrics, like sales, sessions, and orders, into one scannable row.
* **Mixed chart types**: Combine cards that use different chart types, like a donut, a line, and a bar, in one row.
* **Shared date range**: Add a date range picker that updates every card at once.

***

## Properties

All three properties are optional. Set `accessibilityLabel` to describe the row, and `loading` to show a shared loading state.

| Property | Type | Default | Description |
| - | - | - | - |
| `loading` | `boolean` | `false` | Renders the bar and its cards in a loading state. Use it while the ShopifyQL plugin or queries are resolving. |
| `variant` | `'auto' \| 'secondary'` | `'auto'` | Visual variant of the bar. |
| `accessibilityLabel` | `string` | — | Accessible label that describes the contents of the bar. |

### Slots

The default slot accepts [metric card](https://shopify.dev/docs/api/shopifyql/latest/web-components/metric-card) children, which render in the order they appear. It also accepts one optional [`s-metrics-bar-date-picker`](#date-range-picker), which renders above the cards. The bar sizes its cards for you, so you don't need to set `size` on each card.

***

## Date range picker

Add an `s-metrics-bar-date-picker` as a child of the bar to show preset date ranges above the row.

The picker doesn't rewrite card queries. When the selection changes, the picker fires a `change` event that exposes the new range alias on `event.currentTarget.value`. In React, use `onChange`. Listen for that event and update each card's `query` with the matching [`SINCE`](https://shopify.dev/docs/api/shopifyql/latest/syntax/since-until-during) clause.

| Property | Type | Default | Description |
| - | - | - | - |
| `value` | `'today' \| 'last7days' \| 'last30days' \| 'last90days' \| 'last365days'` | — | The currently selected preset range. |
| `disabled` | `boolean` | `false` | Renders the picker as disabled. |

### Events

The date picker exposes one event so you can update your cards' queries when a user changes the range.

| Event | Description |
| - | - |
| `change` | Fires when the selected range changes. The new range alias is available on `event.currentTarget.value`. In React, use `onChange`. |

### Customizing the options

By default, the picker includes `today`, `last7days`, and `last30days`. To change which presets appear, add `s-metrics-bar-date-option` children. Each option must use one of the supported aliases: `today`, `last7days`, `last30days`, `last90days`, or `last365days`.

| Property | Type | Default | Description |
| - | - | - | - |
| `value` | `'today' \| 'last7days' \| 'last30days' \| 'last90days' \| 'last365days'` | — | The preset range that this option represents. |
| `disabled` | `boolean` | `false` | Renders the option as disabled. |

***

## Examples

Each example pairs a row layout you can copy and adapt with the bar it renders, ranging from a basic set of metrics to a picker-driven row that updates on range changes.

##### Lay out a row of metric cards

Arranges several metric cards in one row with consistent spacing and sizing. Use it for a set of related headline metrics, like total, net, and gross sales over 30 days.

##### Build a compact KPI row

The bar renders cards in a compact layout. Use it for a dense row of single-value metrics with titles, current values, and percent-change indicators.

##### Mix visualization types in one bar

Each card in a bar can visualize its query differently. This row combines a [`donut`](https://shopify.dev/docs/api/shopifyql/latest/syntax/visualize#part-to-whole-and-hierarchy-charts) chart, a [`line`](https://shopify.dev/docs/api/shopifyql/latest/syntax/visualize#line-and-area-charts) chart, and a [`bar`](https://shopify.dev/docs/api/shopifyql/latest/syntax/visualize#bar-charts) chart. The Sales by campaign card groups by a custom metafield, whose definition must have the [`analyticsQueryable`](https://shopify.dev/docs/apps/build/metafields/use-metafield-capabilities#analytics-queryable) capability enabled, or that card returns no data.

##### Add a date range picker

Add an `s-metrics-bar-date-picker` to the bar to show a range selector above the cards. By default, it includes today, the last seven days, and the last 30 days.

##### Customize the date range options

Add `s-metrics-bar-date-option` children to control which presets the picker shows.

##### Respond to date range changes in React

The picker doesn't rewrite card queries. Keep the selected range in state, listen for `onChange`, and rebuild each card's `query` with the matching `SINCE` clause. Types come from the `@shopify/analytics-ui-types` package.

##### Show a loading state

Set `loading` on the bar to render one loading state for the whole row.

## html

```html
<s-metrics-bar accessibilityLabel="Store performance">
  <s-shopifyql-metric-card
    heading="Total sales"
    query="FROM sales SHOW total_sales
      TIMESERIES day WITH TOTALS, PERCENT_CHANGE
      SINCE startOfDay(-30d) UNTIL endOfDay(-1d)
      COMPARE TO previous_period
      ORDER BY day ASC LIMIT 100
      VISUALIZE total_sales TYPE line"
  ></s-shopifyql-metric-card>
  <s-shopifyql-metric-card
    heading="Net sales"
    query="FROM sales SHOW net_sales
      TIMESERIES day WITH TOTALS, PERCENT_CHANGE
      SINCE startOfDay(-30d) UNTIL endOfDay(-1d)
      COMPARE TO previous_period
      ORDER BY day ASC LIMIT 100
      VISUALIZE net_sales TYPE line"
  ></s-shopifyql-metric-card>
  <s-shopifyql-metric-card
    heading="Gross sales"
    query="FROM sales SHOW gross_sales
      TIMESERIES day WITH TOTALS, PERCENT_CHANGE
      SINCE startOfDay(-30d) UNTIL endOfDay(-1d)
      COMPARE TO previous_period
      ORDER BY day ASC LIMIT 100
      VISUALIZE gross_sales TYPE line"
  ></s-shopifyql-metric-card>
</s-metrics-bar>
```

![A metrics bar showing three cards in a row — Total sales, Net sales, and Gross sales — each with a value, a percent-change indicator, and a sparkline.](https://shopify.dev/assets/assets/images/landing-pages/templated-apis/shopifyql-next/shopifyql-metrics-bar-row-light-iWIWapGx.png)

## html

```html
<s-metrics-bar accessibilityLabel="Key performance indicators">
  <s-shopifyql-metric-card
    heading="Total sales"
    query="FROM sales SHOW total_sales
      TIMESERIES day WITH TOTALS, PERCENT_CHANGE
      SINCE startOfDay(-30d) UNTIL endOfDay(-1d)
      COMPARE TO previous_period
      ORDER BY day ASC LIMIT 100
      VISUALIZE total_sales TYPE line"
  ></s-shopifyql-metric-card>
  <s-shopifyql-metric-card
    heading="Average order value"
    query="FROM sales SHOW average_order_value
      TIMESERIES day WITH TOTALS, PERCENT_CHANGE
      SINCE startOfDay(-30d) UNTIL endOfDay(-1d)
      COMPARE TO previous_period
      ORDER BY day ASC LIMIT 100
      VISUALIZE average_order_value TYPE line"
  ></s-shopifyql-metric-card>
  <s-shopifyql-metric-card
    heading="Orders"
    query="FROM sales SHOW orders
      TIMESERIES day WITH TOTALS, PERCENT_CHANGE
      SINCE startOfDay(-30d) UNTIL endOfDay(-1d)
      COMPARE TO previous_period
      ORDER BY day ASC LIMIT 100
      VISUALIZE orders TYPE line"
  ></s-shopifyql-metric-card>
</s-metrics-bar>
```

![A compact metrics bar showing Total sales, Average order value, and Orders as single-value cards, each with a percent-change indicator and a sparkline.](https://shopify.dev/assets/assets/images/landing-pages/templated-apis/shopifyql-next/shopifyql-metrics-bar-compact-light-BNgofVTY.png)

## html

```html
<s-metrics-bar accessibilityLabel="Store overview">
  <s-shopifyql-metric-card
    heading="Sales by campaign"
    query='FROM sales SHOW total_sales
      WHERE order.metafields."app--393038102529--loyalty".campaign_name IS NOT NULL
      GROUP BY order.metafields."app--393038102529--loyalty".campaign_name
      DURING last_year
      ORDER BY total_sales DESC
      VISUALIZE total_sales TYPE donut'
  ></s-shopifyql-metric-card>
  <s-shopifyql-metric-card
    heading="Total sales over time"
    query="FROM sales SHOW total_sales
      TIMESERIES day WITH TOTALS, PERCENT_CHANGE
      SINCE startOfDay(-30d) UNTIL today
      COMPARE TO previous_period
      ORDER BY day ASC LIMIT 100
      VISUALIZE total_sales TYPE line"
  ></s-shopifyql-metric-card>
  <s-shopifyql-metric-card
    heading="Inventory value by variant"
    query="FROM inventory SHOW ending_inventory_value
      GROUP BY product_title, product_variant_title
      ORDER BY ending_inventory_value DESC LIMIT 10
      VISUALIZE ending_inventory_value TYPE bar"
  ></s-shopifyql-metric-card>
</s-metrics-bar>
```

![A metrics bar mixing chart types: a Sales by campaign donut, a Total sales over time line chart, and an Inventory value by variant bar chart.](https://shopify.dev/assets/assets/images/landing-pages/templated-apis/shopifyql-next/shopifyql-metrics-bar-mixed-light-D3tSOven.png)

## html

```html
<s-metrics-bar accessibilityLabel="Store performance">
  <s-metrics-bar-date-picker value="last7days"></s-metrics-bar-date-picker>
  <s-shopifyql-metric-card
    heading="Total sales"
    query="FROM sales SHOW total_sales
      TIMESERIES day WITH TOTALS, PERCENT_CHANGE
      SINCE startOfDay(-7d) UNTIL today
      COMPARE TO previous_period
      ORDER BY day ASC LIMIT 100
      VISUALIZE total_sales TYPE line"
  ></s-shopifyql-metric-card>
  <s-shopifyql-metric-card
    heading="Orders"
    query="FROM sales SHOW orders
      TIMESERIES day WITH TOTALS, PERCENT_CHANGE
      SINCE startOfDay(-7d) UNTIL today
      COMPARE TO previous_period
      ORDER BY day ASC LIMIT 100
      VISUALIZE orders TYPE line"
  ></s-shopifyql-metric-card>
</s-metrics-bar>
```

![A metrics bar with a 7-day date range picker above two cards, Total sales and Orders.](https://shopify.dev/assets/assets/images/landing-pages/templated-apis/shopifyql-next/shopifyql-metrics-bar-date-picker-light-C_l2qOsX.png)

## html

```html
<s-metrics-bar accessibilityLabel="Store performance">
  <s-metrics-bar-date-picker value="last30days">
    <s-metrics-bar-date-option value="today"></s-metrics-bar-date-option>
    <s-metrics-bar-date-option value="last7days"></s-metrics-bar-date-option>
    <s-metrics-bar-date-option value="last30days"></s-metrics-bar-date-option>
    <s-metrics-bar-date-option value="last90days"></s-metrics-bar-date-option>
    <s-metrics-bar-date-option value="last365days"></s-metrics-bar-date-option>
  </s-metrics-bar-date-picker>
  <s-shopifyql-metric-card
    heading="Total sales"
    query="FROM sales SHOW total_sales
      TIMESERIES day WITH TOTALS, PERCENT_CHANGE
      SINCE startOfDay(-30d) UNTIL today
      COMPARE TO previous_period
      ORDER BY day ASC LIMIT 100
      VISUALIZE total_sales TYPE line"
  ></s-shopifyql-metric-card>
</s-metrics-bar>
```

![A metrics bar with a 30-day date range picker above a single Total sales card.](https://shopify.dev/assets/assets/images/landing-pages/templated-apis/shopifyql-next/shopifyql-metrics-bar-date-options-light-MjkZAeTL.png)

## tsx

```tsx
import type {CallbackEvent} from '@shopify/analytics-ui-types';
import {useState} from 'react';


const SINCE_BY_ALIAS = {
  today: 'today',
  last7days: 'startOfDay(-7d)',
  last30days: 'startOfDay(-30d)',
  last90days: 'startOfDay(-90d)',
  last365days: 'startOfDay(-365d)',
};


export function SalesMetrics() {
  const [range, setRange] = useState<keyof typeof SINCE_BY_ALIAS>('last7days');
  const since = SINCE_BY_ALIAS[range];


  function handleDateRangeChange(
    event: CallbackEvent<'s-metrics-bar-date-picker'>,
  ) {
    setRange(event.currentTarget.value as keyof typeof SINCE_BY_ALIAS);
  }


  return (
    <s-metrics-bar accessibilityLabel="Store performance">
      <s-metrics-bar-date-picker
        value={range}
        onChange={handleDateRangeChange}
      />
      <s-shopifyql-metric-card
        heading="Total sales"
        query={`FROM sales SHOW total_sales
          TIMESERIES day WITH TOTALS, PERCENT_CHANGE
          SINCE ${since} UNTIL today
          COMPARE TO previous_period
          ORDER BY day ASC LIMIT 100
          VISUALIZE total_sales TYPE line`}
      />
      <s-shopifyql-metric-card
        heading="Orders"
        query={`FROM sales SHOW orders
          TIMESERIES day WITH TOTALS, PERCENT_CHANGE
          SINCE ${since} UNTIL today
          COMPARE TO previous_period
          ORDER BY day ASC LIMIT 100
          VISUALIZE orders TYPE line`}
      />
    </s-metrics-bar>
  );
}
```

![A metrics bar driven by React state showing a 7-day range with Total sales and Orders cards.](https://shopify.dev/assets/assets/images/landing-pages/templated-apis/shopifyql-next/shopifyql-metrics-bar-react-light-evXgwZYl.png)

## html

```html
<s-metrics-bar loading accessibilityLabel="Store performance">
  <s-shopifyql-metric-card heading="Total sales"></s-shopifyql-metric-card>
  <s-shopifyql-metric-card heading="Net sales"></s-shopifyql-metric-card>
</s-metrics-bar>
```

![A metrics bar in its loading state, showing placeholder cards while the data resolves.](https://shopify.dev/assets/assets/images/landing-pages/templated-apis/shopifyql-next/shopifyql-metrics-bar-loading-light-DCsWXd0y.png)

***

## Best practices

These practices keep the row accessible and let the bar manage its own layout.

* **Let the bar own layout**: Add cards as children and let the bar size and scroll them. You don't need to set `size` on each card or manage the row yourself.
* **Provide an accessibility label**: Set `accessibilityLabel` to describe what the bar contains for assistive technologies.

***
