mcpField
U
unovis-vue-skilld

unovis-vue-skilld

github.com/skilld-devDevelopment184111 installsUpdated 3w ago
Repository

About unovis-vue-skilld

A set of Vue 3 wrappers for Unovis visualization components, intended for developers building charts and other data visualizations. The wrappers update chart configuration and data in place, and expose the underlying @unovis/ts instances.

Key features

  1. 01Vue wrappers for Unovis components
  2. 02XY and single-visualization containers
  3. 03Charts, maps, and data visualization components
  4. 04In-place updates to config and data
  5. 05Access to underlying core instances

Use cases

  1. 01Building reactive charts from Vue data
  2. 02Combining multiple chart components in a container
  3. 03Calling core methods through a component reference

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/skilld-dev/vue-ecosystem-skills --skill unovis-vue-skilld

After installing, type/unovis-vue-skilldin Claude Code to confirm it loaded.

Bundled files

References and scripts installed along with SKILL.md.

references/
color-patterns.md
components.md
events-tooltips.md
migration-v1.7.md

Details

From the project README

@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/[email protected].
  • 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

Comments

Markdown supported