SuperAPI AI Directory

unovis-vue-skilld

Frontend & websites

View repository

Updated 10-16 00:21

About this skill

@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