Skip to content
silverpoint
Documentation menu

Getting started · Frameworks

Vue

Everything you need to use silverpoint with Vue: install, quickstart, app-wide configuration, precision mode, interaction, export, server rendering, the UI components and what 0.7 adds.

Install

Package@silverpoint/vue
Peersvue ^3.5.0; @knight-lab/timelinejs ^3.9.13 (optional, for SpTimeline)
IntegrationVite is validated; SSR is verified with @vue/server-renderer. Nuxt works but is not a validated integration.
ComponentsSpLineChart
Import from@silverpoint/vue/<chart>
App-wide configurationprovideSilverpoint (plugin)
shell
npm install @silverpoint/vue @silverpoint/grounds @silverpoint/fonts

Quickstart

Create a fresh app and install silverpoint:

shell
npm create vite@latest my-charts -- --template vue-ts
cd my-charts
npm install @silverpoint/vue @silverpoint/grounds @silverpoint/fonts
npm run dev

Then replace the app's entry with:

vue
<!-- src/App.vue -->
<script setup lang="ts">
import '@silverpoint/fonts/fonts.css';
import '@silverpoint/grounds/styles.css';
import { SpLineChart } from '@silverpoint/vue/line-chart';

const data = [
  { hour: '00', hits: 18 },
  { hour: '04', hits: 11 },
  { hour: '08', hits: 42 },
  { hour: '12', hits: 64 },
  { hour: '16', hits: 57 },
  { hour: '20', hits: 30 },
];
</script>

<template>
  <div style="width: 480px">
    <SpLineChart :data="data" x-key="hour" value-key="hits" title="Hits per hour" />
  </div>
</template>
Hits per hourHits per hour
Hits per hour
hourhits
0018
0411
0842
1264
1657
2030

The chart takes the width of its container. height is the height of the drawing area and defaults to 160 px. Omit data and a chart draws its own demo dataset.

One ground for the whole app

Set the ground, the substrate, the mode and the locale once for every chart. A prop on a chart always wins.

vue
// src/main.ts
import { createApp } from 'vue';
import { provideSilverpoint } from '@silverpoint/vue';
import App from './App.vue';

createApp(App)
  .use(provideSilverpoint({ ground: 'silverpoint', substrate: 'green', locale: 'en-GB' }))
  .mount('#app');

<!-- any component -->
<SpBarChart :data="sales" x-key="month" value-key="units" title="Units sold" unit="units" />
<SpDonutChart :data="channels" name-key="channel" value-key="share" title="Sales by channel" center-label="%" />
Units soldUnits sold
Units sold
monthunits
Jan120
Feb98
Mar143
Sales by channelSales by channel
Sales by channel
channelshareshare
Web5454%
Stores3131%
Partners1515%

Precision mode

vue
<SpLineChart :data="data" x-key="hour" value-key="hits" title="Hits per hour" mode="precision" />

Interaction and a custom readout

vue
<script setup lang="ts">
import { ref } from 'vue';
import { SpLineChart } from '@silverpoint/vue/line-chart';
import type { ActiveItem } from '@silverpoint/vue';

defineProps<{ data: { hour: string; hits: number }[] }>();
const active = ref<ActiveItem | null>(null);
</script>

<template>
  <SpLineChart
    :data="data"
    x-key="hour"
    value-key="hits"
    title="Hits per hour"
    @active-change="active = $event"
    @select="(item) => console.log('selected', item.datum)"
  >
    <template #tooltip="{ active: item }">
      <strong>{{ item.value }} hits</strong>
    </template>
  </SpLineChart>
  <p>Under the pointer: {{ active ? `${active.datum.hour}: ${active.value}` : '—' }}</p>
</template>

Export: the imperative handle

vue
<script setup lang="ts">
import { ref } from 'vue';
import { SpLineChart } from '@silverpoint/vue/line-chart';

defineProps<{ data: { hour: string; hits: number }[] }>();
const chart = ref<InstanceType<typeof SpLineChart>>();

function download() {
  const svg = chart.value?.toSVGString() ?? '';
  window.open(URL.createObjectURL(new Blob([svg], { type: 'image/svg+xml' })));
}
</script>

<template>
  <SpLineChart ref="chart" :data="data" x-key="hour" value-key="hits" title="Hits per hour" />
  <button @click="download">Export SVG</button>
</template>

Server rendering

vue
// entry-server.ts
import { createSSRApp } from 'vue';
import { renderToString } from 'vue/server-renderer';
import { provideSilverpoint } from '@silverpoint/vue';
import App from './App.vue';

export function render(): Promise<string> {
  return renderToString(createSSRApp(App).use(provideSilverpoint({ locale: 'en' })));
}

UI components

Since 0.3: 17 interface components from @silverpoint/vue/ui, drawn as the charts are. Import @silverpoint/grounds/ui.css once, beside styles.css. A form with a controlled input, a switch, tabs and a submit button:

vue
<script setup lang="ts">
import { ref, computed } from 'vue';
import { SpButton, SpInput, SpSwitch, SpTabPanel, SpTabs } from '@silverpoint/vue/ui';
import { SpBarChart } from '@silverpoint/vue/bar-chart';
import { SpLineChart } from '@silverpoint/vue/line-chart';

const city = ref('Caracas');
const precision = ref(false);
const view = ref('traffic');
const mode = computed(() => (precision.value ? 'precision' : 'ink'));
const tabs = [{ key: 'traffic', label: 'Traffic' }, { key: 'errors', label: 'Errors' }];

function save(event: SubmitEvent) {
  console.log(Object.fromEntries(new FormData(event.target as HTMLFormElement)));
}
</script>

<template>
  <form @submit.prevent="save">
    <SpInput v-model="city" label="City" name="city"
      :invalid="city === ''" message="Required: pick a city" />
    <SpSwitch v-model="precision" label="Precision" name="precision" />
    <SpTabs v-model="view" label="Views" :items="tabs">
      <SpTabPanel value="traffic"><SpLineChart title="Traffic" :mode="mode" /></SpTabPanel>
      <SpTabPanel value="errors"><SpBarChart title="Errors" :mode="mode" /></SpTabPanel>
    </SpTabs>
    <SpButton type="submit" variant="primary">Save</SpButton>
  </form>
</template>
Overview: the charts of this view.

Every component has a reference page with each of its states in this framework:

UI components: values, forms, keyboard →

New in 0.8.0: palettes, overlays, timeline

21 more UI components from the same @silverpoint/vue/ui subpaths — composed ones (table, pagination, statistic, collapse…) and overlays on the platform's <dialog> and Popover API (modal, drawer, popover, tooltip, select, menu, toast) —, a palette on every chart, component and provider, and SpTimeline on @silverpoint/vue/timeline. An overlay opens from a trigger you write:

vue
<script setup lang="ts">
import { ref } from 'vue';
import { SpButton } from '@silverpoint/vue/ui/button';
import { SpModal } from '@silverpoint/vue/ui/modal';

const open = ref(false);
</script>

<template>
  <SpModal v-model:open="open" title="Apply changes" description="The geometry of the data does not move.">
    <template #trigger><button type="button">Open the modal</button></template>
    <p>Apply the new ground to every chart on the page?</p>
    <template #footer><SpButton variant="primary" @click="open = false">Apply</SpButton></template>
  </SpModal>
</template>

The 60 charts

Every chart has a reference page with its example in this framework: