---
name: unovis-vue-skilld
description: Vue 3 components for the Unovis data visualization framework, @unovis/vue 1.7.0. Use when writing, debugging, or updating code that imports @unovis/vue or renders Vis* components such as VisXYContainer, VisSingleContainer, VisArea, VisLine, VisStackedBar, VisCrosshair, or VisTooltip. Covers the component catalog, props, events, tooltips, colors, patterns, SSR, and the 1.7.0 API changes.
---

# @unovis/vue 1.7.0

Unovis is a modular data visualization framework. `@unovis/vue` provides autogenerated Vue 3 wrappers for the core classes in `@unovis/ts` (`README.md`).

## Version and environment

- Package: `@unovis/vue@1.7.0`.
- Peer dependencies: `@unovis/ts` pinned to exactly `1.7.0`, and `vue` `^3` (`package.json:56-59`). Install both at the exact same version: `npm install -P @unovis/ts @unovis/vue` (`README.md:16`). A version mismatch between the two packages breaks peer resolution.
- ESM first. The package has `type: module`, subpath exports under `./*`, and `sideEffects: false` (`package.json:28-39`).
- No CSS import. Styles are injected from JS at runtime (`index.js:1`).
- Docs: https://unovis.dev/docs/intro. Component docs live at `https://unovis.dev/docs/components/<Name>`. Gallery: https://unovis.dev/gallery.

## How the wrappers work

Every `Vis*` component is a thin wrapper around one `@unovis/ts` class. Verify these rules before writing code:

- Props map one to one to the core config interface, for example `AreaConfigInterface`. Use camelCase in script and kebab-case in templates: `:line-width="2"`, `:stack-min-height="true"`.
- Accessors are functions. Pass them as props: `:x="d => d.x"`, `:y="['sales', 'cost'].map(k => d => d[k])"`.
- `data` can live on the container or on a component. The container shares its `data` with all children. A child falls back to its own `data` only when the container has none (`components/area/index.js:35`). Pass data at the container level for multi component charts.
- Reactivity: a config change calls `setConfig` then `render` on the core class. A `data` change calls `setData`. Both update the chart in place, without remounting.
- Every wrapper exposes `component`, a ref to the core `@unovis/ts` instance, through `defineExpose`. Use a template ref to call core methods: `chart.value?.component?.destroy()`.
- Each module also exports selectors, for example `VisAxisSelectors` equals `Axis.selectors` from `@unovis/ts`. Use selectors with the `events` prop and tooltip `triggers` ([events and tooltips](./references/events-tooltips.md)).
- Containers collect children through provide and inject. Place `Vis*` children in the container's default slot. The XY container defers chart creation until at least one child registers (`containers/xy-container/index.js:50-52`), so `v-for` and conditional children work.
- Legends and maps are standalone. `VisBulletLegend`, `VisFlowLegend`, `VisRollingPinLegend`, `VisLeafletMap`, and `VisLeafletFlowMap` render into their own DOM node. Use them outside containers. All other components require a container context.

## Quick start

```vue
<script setup lang="ts">
import { ref } from 'vue'
import { VisXYContainer, VisLine, VisAxis } from '@unovis/vue'

type DataRecord = { x: number; y: number }
const data = ref<DataRecord[]>([
  { x: 0, y: 0 },
  { x: 1, y: 2 },
  { x: 2, y: 1 },
])
const x = (d: DataRecord) => d.x
const y = (d: DataRecord) => d.y
</script>

<template>
  <VisXYContainer :data="data" :height="300">
    <VisLine :x="x" :y="y" />
    <VisAxis type="x" />
    <VisAxis type="y" />
  </VisXYContainer>
</template>
```

Sizing: the container fits its parent's width. Set `height` explicitly, or the default of `300px` applies ([XY Container docs](https://unovis.dev/docs/containers/XY_Container)).

## Component catalog

Two containers: `VisXYContainer` for XY charts with axes, `VisSingleContainer` for one standalone visualization plus an optional tooltip. Full list with key props: [components.md](./references/components.md).

- XY components: `VisArea`, `VisLine`, `VisScatter`, `VisStackedBar`, `VisGroupedBar`, `VisBoxplot` (new in 1.7), `VisTimeline`, `VisXYLabels`.
- Auxiliary: `VisAxis`, `VisCrosshair`, `VisTooltip`, `VisBrush`, `VisFreeBrush`, `VisPlotband`, `VisPlotline`, `VisAnnotations`.
- Single container components: `VisDonut`, `VisNestedDonut`, `VisRadialBar` (new in 1.7), `VisHeatmap` (new in 1.7), `VisTreemap`, `VisSankey`, `VisChordDiagram`, `VisGraph`, `VisTopoJSONMap`.
- Standalone: `VisBulletLegend`, `VisFlowLegend`, `VisRollingPinLegend`, `VisLeafletMap`, `VisLeafletFlowMap`.

## Common tasks

### Ordinal x values

Return the index from the `x` accessor. Format the axis ticks back to labels.

```vue
<script setup lang="ts">
const x = (d: DataRecord, i: number) => i
const tickFormat = (i: number) => data.value[i]?.category ?? ''
</script>

<template>
  <VisXYContainer :data="data">
    <VisStackedBar :x="x" :y="d => d.value" />
    <VisAxis type="x" :tick-format="tickFormat" />
  </VisXYContainer>
</template>
```

### Tooltip with crosshair

```vue
<script setup lang="ts">
import { VisStackedBarSelectors } from '@unovis/vue'
const triggers = {
  [VisStackedBarSelectors.bar]: (d: DataRecord) => `${d.category}: ${d.value}`,
}
</script>

<template>
  <VisXYContainer :data="data">
    <VisStackedBar :x="x" :y="d => d.value" />
    <VisCrosshair :template="triggers" />
    <VisAxis type="x" />
  </VisXYContainer>
</template>
```

More patterns, including snap mode and events: [events-tooltips.md](./references/events-tooltips.md).

### Custom fills with svgDefs

```vue
<script setup lang="ts">
const gradientDef = `
  <linearGradient id="area-gradient" x1="0" y1="0" x2="0" y2="1">
    <stop offset="0%" stop-color="#4d8cfd" stop-opacity="0.8" />
    <stop offset="100%" stop-color="#4d8cfd" stop-opacity="0.1" />
  </linearGradient>`
</script>

<template>
  <VisXYContainer :data="data" :svg-defs="gradientDef">
    <VisArea :x="x" :y="y" color="url(#area-gradient)" />
  </VisXYContainer>
</template>
```

### Waterfall chart with the baseline accessor

`VisStackedBar` gained `baseline` in 1.7 for floating bars (`components/stacked-bar/index.js:11`). Pair it with `barStyle` for dashed projected values (`components/stacked-bar/index.js:10`).

```vue
<script setup lang="ts">
// data records carry the floating bar start and end
const baseline = (d: WaterfallRecord) => d.start
const y = (d: WaterfallRecord) => d.end - d.start
const color = (d: WaterfallRecord) => (d.delta >= 0 ? '#00c19a' : '#ff6b7e')
</script>

<template>
  <VisXYContainer :data="data">
    <VisStackedBar :x="x" :y="y" :baseline="baseline" :color="color" />
    <VisAxis type="x" />
    <VisAxis type="y" />
  </VisXYContainer>
</template>
```

### Align stacked charts with bleed

`bleed` overrides the space the container reserves for edge marks. It takes a `Spacing` object or a function. Capture the horizontal bleed of the chart with the largest marks from `onRenderComplete`, then pass it to the other charts (`containers/xy-container/index.js:29-30`). Guide: <https://unovis.dev/docs/guides/bleed>.

```vue
<script setup lang="ts">
import { ref } from 'vue'
const horizontalBleed = ref<{ left?: number; right?: number }>()
const onRenderComplete = (svg: SVGSVGElement, margin: unknown, bleed: { left: number; right: number }) => {
  horizontalBleed.value = { left: bleed.left, right: bleed.right }
}
</script>

<template>
  <VisXYContainer :data="data" :on-render-complete="onRenderComplete">
    <VisScatter :x="x" :y="y" :size="25" />
  </VisXYContainer>
  <VisXYContainer :data="data" :bleed="horizontalBleed">
    <VisLine :x="x" :y="y" />
  </VisXYContainer>
</template>
```

## Colors and patterns

1.7 adds chart wide color synchronization and pattern fills:

- `colorFunction` on `VisXYContainer`, `VisSingleContainer`, and `VisBulletLegend` maps a key to a color (`containers/xy-container/index.js:39`, `html-components/bullet-legend/index.js:17`).
- `colorKeys` on a component names the stable keys aligned with its `y` accessors (`components/area/index.js:25`).
- `pattern` on `VisArea`, `VisLine`, `VisScatter`, `VisGroupedBar`, `VisStackedBar`, `VisDonut`, and others adds stripes, dots, and hatches.

Details and examples: [color-patterns.md](./references/color-patterns.md).

## Gotchas

- Pin `@unovis/ts` and `@unovis/vue` to the same exact version. The peer range is `1.7.0`, with no caret (`package.json:57`).
- `VisCrosshair`, `VisTimeline`, and `VisBoxplot` declare only `data` as a Vue prop. All other config travels as attributes. If a config prop seems ignored on these three, upgrade to 1.7.0: their `data` prop was silently dropped between 1.6.5 and 1.7 ([fix PR](https://github.com/f5/unovis/pull/857)).
- Axis labels clipped at the top or bottom? Increase the container `margin`, for example `:margin="{ top: 10, right: 10, bottom: 10, left: 10 }"`.
- Nuxt and SSR: the core is SSR ready since 1.6.4. If hydration or `document` errors appear, wrap the chart in `<ClientOnly>` ([issue 607](https://github.com/f5/unovis/issues/607)). For headless rendering in Node 20+, use the separate `@unovis/ssr` package (<https://unovis.dev/releases/1.7>).
- Strict CSP: set `window.UNOVIS_NONCE` before the library is imported. Guide: <https://unovis.dev/docs/guides/csp>.
- Dark theme: add the class `theme-dark` to `body`. Override `--vis-dark-*` variables per component ([theming guide](https://unovis.dev/docs/guides/theming)).

## References

- [components.md](./references/components.md): full export catalog with container rules and key props.
- [events-tooltips.md](./references/events-tooltips.md): events, selectors, tooltips, crosshair, annotations.
- [color-patterns.md](./references/color-patterns.md): color synchronization, patterns, CSS variables, themes.
- [migration-v1.7.md](./references/migration-v1.7.md): changes from 1.6.x to 1.7.0 that affect Vue code.
