unovis-vue-skilld

v2026.09.25

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.

GitHub
Install command
npx skhub add skilld-dev/unovis-vue-skilld
Markdown
SKILL.md

@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).
  • 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

<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).

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.

  • 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.

<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

<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.

Custom fills with svgDefs

<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).

<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.

<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.

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).
  • 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). 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).

References

Discovery
Tags

No tags published for this skill.

Version
Latest version metadata

Version

v2026.09.25

Published

Sep 25, 2026

Category

Uncategorized

License

MIT

Source path

skills/unovis-vue-skilld

Default branch

main

Latest commit

c8994af

Tree SHA

78224cb