# Make a custom chart interactive
> Add cross-filtering, drill-through, and highlight effects to custom charts using Vega-Lite point and interval selections, with copy-ready code examples.
Custom charts can have the same interactions as Holistics's built-in charts, such as:
- [Cross-filtering](/docs/cross-filtering)
- [Drill-through](/docs/interactions/drill-through)
- [Date drills](/docs/interactions/date-drills)
You enable this in two steps. First, you declare the interactions your chart accepts. Then you wire those interactions to Holistics features. This guide walks you through both.
## How interactions work
Interactions come from two parts of the chart template:
- **Selections** declare what a user can do, such as clicking a data point or dragging to select a range. You define them with Vega-Lite [`params`](/reference/aml/custom-chart#params). Vega-Lite calls a selection a *signal*.
- **`holisticsConfig`** wires those selections to Holistics features. Two fields matter:
- `crossFilterSignals`: selections that trigger [Cross Filter](/docs/cross-filtering) on **click**.
- `contextMenuSignals`: selections that open the context menu (Date-drill, Drill-through) on **right-click**. Use a **hover** selection here so the menu targets the point under the cursor.
For the full property reference, see [`holisticsConfig`](/reference/aml/custom-chart#holisticsconfig) and [`params`](/reference/aml/custom-chart#params). If you are new to chart templates, start with [Understand Custom Chart](/docs/charts/understand-custom-chart).
### Selection types
A selection is either point-based or interval-based.
**Point selection (click).** A point selection fires when a user clicks a single value (left click), or selects several values (hold Shift and left click). To deselect, the user clicks a selected value again. Read more in the [Vega-Lite selection docs](https://vega.github.io/vega-lite/docs/parameter.html#select).
**Interval selection (drag).** An interval selection fires when a user holds left click and drags across a range of values. To deselect, the user double-clicks anywhere on the chart.
## Interaction examples
Each example below starts from a working chart and adds one interaction. The full, copy-ready code for each one lives in the [Custom Chart Library](https://github.com/holistics/custom-chart-library/tree/main/interactive_features).
### Highlight selected columns on point selection
**Outcome.** When a user selects one or more columns, those columns stay fully visible while the rest fade out. On hover, a stroke outlines the column.
1. In your template, declare two point selections in `params`: one that fires on click, and one that fires on hover.
```aml
template: @vgl {
...
"params": [
// effective only while the user hovers
{ "name": "pointSelectionOnMouseOver", "select": {"type": "point", "on": "mouseover"} },
// effective when the user clicks
{ "name": "normalPointSelection", "select": "point" }
]
...
}
```
2. Add a `fillOpacity` rule so selected columns keep full opacity while the rest fade.
```aml
template: @vgl {
...
"mark": {
"fill": "#484848" // base color of the columns
},
"encoding": {
"fillOpacity": {
// selected columns stay fully visible
"condition": {"param": "normalPointSelection", "value": 1},
// unselected columns fade to 30%
"value": 0.3
}
}
...
}
```
3. Try it. Click a single column, then select a range by holding Shift and clicking. The selected columns should stay highlighted.
4. Add a `strokeWidth` rule so hovered columns get a light stroke and selected columns get a bolder one.
```aml
template: @vgl {
...
"mark": {
"fill": "#484848",
"stroke": "black" // stroke color
},
"encoding": {
"strokeWidth": {
"condition": [
// bolder stroke (2) on selected columns
{ "param": "normalPointSelection", "empty": false, "value": 2 },
// light stroke (1) on hovered columns
{ "param": "pointSelectionOnMouseOver", "empty": false, "value": 1 }
],
"value": 0 // no stroke by default
}
}
...
}
```
5. Try selecting and hovering again. You should see a light stroke on hovered columns and a bolder stroke on selected ones.
**Full code example:** [Highlight stroke effect on point selection](https://github.com/holistics/custom-chart-library/blob/main/interactive_features/highlight_stroke_effect_on_point_selection.md).
### Cross-filter on point selection
:::info What is Cross Filter?
Cross Filter creates shared filters that apply to all report widgets in your dashboard. To learn more, see [Cross Filter](/docs/cross-filtering).
:::
**Outcome.** When a user selects data on your chart, a cross filter for that selection is applied to every widget in the dashboard.
**Prerequisite:** a chart with a point selection declared. The [highlight example](#highlight-selected-columns-on-point-selection) above is a good starting point.
1. In your template, declare a point selection in `params`.
```aml
template: @vgl {
...
"params": [
// effective when the user clicks
{ "name": "normalPointSelection", "select": "point" }
]
...
}
```
2. Add a `holisticsConfig` field with `crossFilterSignals`, and list the point selection from step 1.
```aml
template: @vgl {
...
"holisticsConfig": {
"crossFilterSignals": ["normalPointSelection"]
}
...
}
```
3. Try it. Click a single column, or select a range with Shift and click. A cross filter should be created and applied to the other reports in your dashboard.
**Full code example:** [Cross Filter on point selection](https://github.com/holistics/custom-chart-library/blob/main/interactive_features/cross_filter_on_point_selection.md).
### Cross-filter on interval selection
**Outcome.** When a user drags to select an interval on your chart, a cross filter for that range is applied to every widget in the dashboard.
**Prerequisite:** a working custom chart you can add a selection to.
1. In your template, declare an interval selection in `params`.
```aml
template: @vgl {
...
"params": [
{
"name": "intervalSelection",
"select": {"type": "interval", "encodings": ["x"]}
}
]
...
}
```
2. Add a `holisticsConfig` field with `crossFilterSignals`, and list the interval selection from step 1.
```aml
template: @vgl {
...
"holisticsConfig": {
"crossFilterSignals": ["intervalSelection"]
}
...
}
```
3. Try it. Hold left click and drag across a range of values. A cross filter should be created and applied to the other reports in your dashboard.
**Full code example:** [Cross Filter on interval selection](https://github.com/holistics/custom-chart-library/blob/main/interactive_features/cross_filter_on_interval_selection.md).
### Cross-filter all sub-charts in a combo chart
**Outcome.** A selection on a combo (mixed) chart applies the cross filter to every sub-chart in the layer, not just the one the user interacted with.
**Prerequisite:** a combo chart built with a Vega-Lite `layer`. See [Cross Filter on sub-charts in a combo chart](https://github.com/holistics/custom-chart-library/blob/main/interactive_features/cross_filter_on_subcharts_combo_chart.md) for how to build one.
1. In your template, find the sub-chart in the `layer` array that the cross filter should also apply to.
```aml
template: @vgl {
...
"layer": [
// your bar chart definition
{ ... },
// your line chart definition (the one we'll filter)
{ ... }
]
...
}
```
2. Add a `transform` to that sub-chart with a `filter` that takes the user's selection as its `param`.
```aml
template: @vgl {
...
"layer": [
{ ... }, // your bar chart definition
{
"transform": [
// filter this sub-chart by the user's interval selection
{ "filter": {"param": "intervalSelection"} }
]
// ...the rest of the sub-chart definition
}
]
...
}
```
3. Create a cross filter on your dashboard and confirm the sub-chart updates along with the rest.
**Full code example:** [Cross Filter on sub-charts in a combo chart](https://github.com/holistics/custom-chart-library/blob/main/interactive_features/cross_filter_on_subcharts_combo_chart.md).
### Drill-through on point selection
**Outcome.** When a user hovers a data point and right-clicks, the Holistics context menu opens so they can Date-drill or Drill-through, just like on a built-in chart.
**Prerequisite:** a chart you can add a selection to (see the [cross-filter example](#cross-filter-on-point-selection)).
The context menu opens on **right-click**, so it must read the point currently under the cursor. That means it needs a **hover** selection, not the click selection you use for Cross Filter. (A click selection has no target on right-click unless the user left-clicks the point first, which would also cross-filter.)
1. In your template, declare a **hover** point selection in `params`. The `"on": "mouseover"` trigger makes it track whichever point the cursor is over.
```aml
template: @vgl {
...
"params": [
{ "name": "hoverPointSelection", "select": {"type": "point", "on": "mouseover", "clear": "mouseout"} }
]
...
}
```
2. Add a `holisticsConfig` field with `contextMenuSignals`, and list the hover selection from step 1.
```aml
template: @vgl {
...
"holisticsConfig": {
"contextMenuSignals": ["hoverPointSelection"]
}
...
}
```
3. Try it. Hover a data point and right-click; the context menu appears, with options to Date-drill and Drill-through.
Cross Filter and the context menu use different triggers, so wire them to different selections: a **click** selection for `crossFilterSignals` (left-click cross-filters the dashboard) and a **hover** selection for `contextMenuSignals` (hover, then right-click opens the menu on that point). For the full property reference, see [`holisticsConfig`](/reference/aml/custom-chart#holisticsconfig).