Brush
<Brush> adds a range selector below a cartesian chart. The chart shows only the rows inside the selected window. Drag a traveller to resize the window, or drag the window to move it.
Brush with a panorama
Put a small chart in the Brush's default slot to show the whole series behind the window. Drag the handles: the text below the chart follows v-model:range.
The panorama chart gets the parent's data, size and position from the Brush, so it needs only its series. Put exactly one chart in the slot (AreaChart, LineChart or BarChart); the Brush ignores the slot otherwise.
Control the range
<script setup lang="ts">
import { ref } from 'vue'
import type { BrushStartEndIndex } from 'vccs'
import { Bar, BarChart, Brush, XAxis } from 'vccs'
const range = ref<BrushStartEndIndex | null>({ startIndex: 0, endIndex: 5 })
</script>
<template>
<BarChart
:data="data"
:height="300"
>
<XAxis data-key="name" />
<Bar data-key="value" />
<Brush
v-model:range="range"
data-key="name"
/>
</BarChart>
</template>
The range is a pair of row indexes, both included. null selects all rows and hides the travellers.
- Without
range, the Brush owns its window. It starts with all rows. - With
range(includingnull), you own the window. The Brush asks for changes withupdate:range; the window changes only when you accept the value. - The Brush rounds indexes down, clamps them to the data, and puts them in order. Values that are not finite become
null. When it corrects a value you supplied, it emitsupdate:rangeonce with the corrected value.
When the data changes
An uncontrolled Brush keeps its window by row index:
- Same number of rows: the window does not change.
- Rows added, window ends at the last row: the window moves forward and keeps its width, so it follows the newest rows. A window over all rows stays over all rows.
- Rows added, window elsewhere: the window keeps its positions.
- Rows removed: the window is clamped to the new length. It resets only when no rows remain.
A moved or clamped window emits update:range. A controlled v-model:range is never changed by the Brush; it only asks.
When the data becomes empty, the Brush emits null. If you accepted that null, the Brush asks for all rows when rows come back, so a filter that briefly finds nothing does not remove the travellers.
This rule differs from Recharts, which resets the window when it gets a new data array.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
range | BrushStartEndIndex | null | — | Selected rows { startIndex, endIndex }. Use with v-model:range |
data-key | string | (row) => unknown | — | Field shown in the traveller text. Without it, the text shows the row index |
tick-formatter | (value, index) => string | — | Formats the traveller text |
height | number | 40 | Height of the brush in px |
width | number | plot width | Width of the brush in px |
x | number | plot left | Left edge in px |
y | number | below the plot | Top edge in px |
dy | number | — | Extra vertical offset in px |
traveller-width | number | 5 | Width of each handle in px |
gap | number | 1 | Index step for dragging. With 3, the window moves 3 rows at a time |
fill | string | var(--v-charts-background, #fff) | Background fill |
stroke | string | var(--v-charts-axis, #666) | Border, window and handle color |
padding | { top, right, bottom, left } | 1 on each side | Margin of the panorama chart inside the brush |
always-show-text | boolean | false | Show the traveller text all the time, not only while you drag, hover or focus |
leave-time-out | number | 1000 | Milliseconds after the pointer leaves the chart before a drag ends |
class | string | array | object | — | Class on the brush group |
Other attributes, such as aria-label and data-*, go to the brush group ([data-slot="brush"]).
Events
| Event | Payload | When |
|---|---|---|
update:range | BrushStartEndIndex | null | The Brush asks for a new window: drag, keyboard, a correction of your value, or data changes |
change | BrushStartEndIndex | The window changed through a drag or the keyboard |
drag-end | BrushStartEndIndex | A drag of the window or a handle ended |
Slots
| Slot | Description |
|---|---|
| default | One chart drawn inside the brush as a panorama. It receives data, x, y, width, height and margin from the Brush |
Keyboard
Each handle is a slider (role="slider") in the tab order, labelled "Range start" and "Range end". ArrowLeft and ArrowRight move the focused handle by one row. The slider reports the row index as aria-valuenow and the category text as aria-valuetext. A null range hides the handles.
Synchronised charts
Charts with the same sync-id share the Brush window. A chart without its own Brush follows the window of a synchronised chart that has one. See Events and v-model for the model rules and Accessibility for keyboard support in other components.