Getting Started With Vue
Vivid comes with a library of native Vue components that wrap the Vivid web components, called Vivid Vue.
While web components can also be used with Vue directly, Vivid Vue provides a seamless integration with Vue and reduces the amount of boilerplate required.
- Vivid Vue components can be imported and used like any other Vue component, including features like v-modeland slots.
- It comes with full type definitions providing type safety and auto-complete in your IDE.
- Vivid Vue is generated from the Vivid web components automatically, so it is always up-to-date with the latest version of Vivid.
- The version number is kept in sync with Vivid.
- There is no additional setup required, just install the library, and you are ready to go!
Add the NPM package to your repository:
npm install @vonage/vivid-vue
yarn add @vonage/vivid-vue
pnpm add @vonage/vivid-vue
Use the vivid3 plugin to initialize the library.
// main.ts
import { createApp } from 'vue';
import { vivid3 } from '@vonage/vivid-vue';
import App from './App.vue';
createApp(App)
	.use(vivid3, {
		font: 'spezia',
		customComponentPrefix: 'my-app',
	})
	.mount('#app');
The plugin accepts the following options:
| Option | Type | Default | Description | 
|---|---|---|---|
| tokens | 'light | 'dark' | 'none' | 'light' | The theme of tokens to use. | 
| font | 'oss' | 'spezia' | 'none' | 'oss' | Use 'spezia'to load the Vonage-specific Spezia font. | 
| customComponentPrefix | string | 'vvd3' | The prefix to use for custom components. It is recommended to set a prefix unique to your app to prevent conflicts if multiple instances or versions of Vivid are used in the same page. Learn more about custom prefixes. | 
| styles | Style[] | [] | An array of optional styles to use. | 
| addRootClassTo | 'root' | 'app' | 'none' | 'root' | Where to apply the vvd-rootclass to.- root: The<html>element- app: TheAppcomponent | 
Loading Optional Styles
To load optional styles, pass them to the styles option.
See the list of styles that come with Vivid for more information.
// main.ts
import { createApp } from 'vue';
import { optionalStyles, vivid3 } from '@vonage/vivid-vue';
import App from './App.vue';
createApp(App)
	.use(vivid3, {
		styles: [
			optionalStyles.theme,
			optionalStyles.typography,
			optionalStyles.vivid2Compat,
		],
	})
	.mount('#app');
Adding the vvd-root Class
The Vivid tokens require a vvd-root class to be present. It is recommended to add it on the <html> element, but it can also be added to your App component to scope it to the application.
<!-- index.html -->
<!DOCTYPE html>
<html lang="en" class="vvd-root">
	<!-- ... -->
</html>
<!-- App.vue -->
<template>
	<div class="vvd-root">
		<RouterView />
	</div>
</template>
Importing the Styles
Modify your App.vue file to import the Vivid styles.
See the list of styles that come with Vivid for more information.
<!-- App.vue -->
<template>
	<RouterView />
</template>
<style>
	/* Import Tokens For Light or Dark Theme */
	@import '@vonage/vivid/styles/tokens/theme-light.css';
	/* (Vonage only) Load Spezia Variable fonts */
	@import '@vonage/vivid/styles/fonts/spezia-variable.css';
	/* (Optional) Import Theme Styles */
	@import '@vonage/vivid/styles/core/theme.css';
	/* (Optional) Import Typography Styles */
	@import '@vonage/vivid/styles/core/typography.css';
	/* (Optional) Import Vivid 2 Compatibility Styles */
	@import '@vonage/vivid/styles/tokens/vivid-2-compat.css';
</style>
<!-- App.vue -->
<template>
	<RouterView />
</template>
<style lang="scss">
	/* Import Tokens For Light or Dark Theme */
	@forward '@vonage/vivid/styles/tokens/theme-light.css';
	/* (Vonage only) Load Spezia Variable fonts */
	@forward '@vonage/vivid/styles/fonts/spezia-variable.css';
	/* (Optional) Import Theme Styles */
	@forward '@vonage/vivid/styles/core/theme.css';
	/* (Optional) Import Typography Styles */
	@forward '@vonage/vivid/styles/core/typography.css';
	/* (Optional) Import Vivid 2 Compatibility Styles */
	@forward '@vonage/vivid/styles/tokens/vivid-2-compat.css';
</style>
Vonage uses the brand-specific Spezia font.
If you are not working on a Vonage project, you should use the Montserrat and Roboto Mono fonts.
Add the following to your <head> to load them from Google Fonts:
<head>
	<!-- ... -->
	<link rel="preconnect" href="https://fonts.googleapis.com" />
	<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
	<link
		href="https://fonts.googleapis.com/css2?family=Montserrat:wght@400;500;600&family=Roboto+Mono:wght@400;500&display=swap"
		rel="stylesheet"
	/>
	<!-- ... -->
</head>
Setting Custom Component Prefix (optional)
It is recommended to set a custom component prefix unique to your app. This will prevent conflicts if multiple instances or versions of Vivid are used in the same page.
To set a custom component prefix, use the setCustomComponentPrefix function in your main.ts file.
// main.ts
import Vue from 'vue';
import { setCustomComponentPrefix } from '@vonage/vivid-vue';
import App from './App.vue';
// set custom component prefix for the whole application (e.g. fraud-detection, etc.)
setCustomComponentPrefix('my-app');
new Vue({
	el: '#app',
	components: { App },
	template: '<App/>',
});
You are now ready to use the components in your application.
<script setup lang="ts">
	import { VButton } from '@vonage/vivid-vue';
</script>
<template>
	<VButton label="Click me" />
</template>
The v-model syntax allows us to implement a two-way binding in between a variable and the matching component.
This is an example of a two-way binding implementation for a web component:
<vwc-text-field
	label="Search"
	:value="searchText"
	@input="searchText = $event.target.value"
/>
This works fine, but with Vivid Vue we can use the v-model syntax to shorten this to:
<VTextField label="Search" v-model="searchText" />
The default slot maps to the same syntax in both Vivid Vue & web components.
Web component
<vwc-icon size="3">
	<img src="/custom-logo.svg" />
</vwc-icon>
Vivid Vue
<VIcon size="3">
	<img src="/custom-logo.svg" />
</VIcon>
While the default slots work the same, the web component's named slots are mapped to Vue named slots.
Web component
<vwc-banner text="A banner with an action button">
	<vwc-button
		slot="action-items"
		appearance="filled"
		connotation="accent"
		label="Filled"
	/>
	<vwc-button
		slot="action-items"
		appearance="outlined"
		connotation="accent"
		label="Outlined"
	/>
</vwc-banner>
Vivid Vue
<VBanner text="A banner with an action button">
	<template #action-items>
		<VButton appearance="filled" connotation="accent" label="Filled" />
		<VButton appearance="outlined" connotation="accent" label="Outlined" />
	</template>
</VBanner>
Components can be styled like any other Vue components, e.g. by using class or id attributes.
Although possible, avoid targeting the custom elements directly by their name (e.g. vwc-header), as you might need to change the prefix in the future.
<template>
	<VHeader class="header">Header Content</VHeader>
</template>
<style scoped lang="css">
	.header {
		margin-block-end: 12px;
		--header-bg-color: var(--vvd-color-neutral-200);
	}
	.header::part(base) {
		position: fixed;
	}
</style>
Components like VNavItem, VBreadcrumbItem or VButton become links when using the href prop.
They will render a regular <a> tag and therefore navigate to the specified URL with a full page reload.
If you are using Vue Router and want to perform client-side navigation, wrap the component with RouterLink:
<RouterLink v-slot="{ href, navigate }" to="/page" custom>
	<VButton :href="href" label="Page" @click="navigate" />
</RouterLink>
Vivid Vue supports auto-complete for components, props, slots, events and more in popular IDEs.
- IntelliJ IDEs (WebStorm, PhpStorm, etc.): Supported out of the box.
- VSCode: Install the Volar extension.
You can find examples for each component in the Vivid Vue Examples Library.