Vitral 0.2
Get started

Installation

One package, one plugin call, and what every option on it does.

Install

terminal
pnpm add @vitral/vue
# npm install @vitral/vue
# yarn add @vitral/vue

Vue 3.5 or newer is the only peer dependency. The other @vitral/* packages come with it.

Register the plugin

main.ts
import { createApp } from 'vue';
import { Vitral, Prism, ptBR } from '@vitral/vue';
import App from './App.vue';

createApp(App)
    .use(Vitral, {
        theme: {
            preset: Prism,           // Prism, Ink, Avalonia, Simple, or your own
            colorScheme: 'system',   // 'light' | 'dark' | 'system'
            storageKey: 'app-scheme' // remember the reader's choice
        },
        locale: ptBR,
        inputVariant: 'outlined',    // every field, unless it says otherwise
        cssLayer: 'vitral'           // wrap component CSS in @layer
    })
    .mount('#app');

There is no stylesheet to import. The plugin injects the theme as CSS variables, and each component injects its own CSS the first time it renders, so a page only carries the components it uses.

Options

OptionTypeDescription
theme{ preset, colorScheme, storageKey, options } | 'none'The preset and the scheme. 'none' injects nothing: bring your own variables, or go unstyled.
localeLocaleen and ptBR ship; a locale is a plain object, so a third is a literal.
inputVariant'outlined' | 'filled'The default look of every field. Reactive: change it at runtime and the page follows.
unstyledbooleanDrop every built-in class, everywhere. See unstyled mode.
ptGlobalPassThroughPass-through for every instance of a component, keyed by name. See pass-through.
cssLayerstring | falseWrap component CSS in @layer, so application CSS wins without !important.
zIndexPartial<ZIndexConfig>The stacking floors for modals, overlays, menus and tooltips.
csp{ nonce?: string }The nonce put on every injected <style>, for a strict Content-Security-Policy.

Without import lines

In Nuxt the module does this for you. In a plain Vite application, the same lists are behind @vitral/vue/resolver, for unplugin-vue-components and unplugin-auto-import:

vite.config.ts
import Components from 'unplugin-vue-components/vite';
import AutoImport from 'unplugin-auto-import/vite';
import { VitralResolver, vitralAutoImports } from '@vitral/vue/resolver';

export default defineConfig({
    plugins: [
        vue(),
        Components({ resolvers: [VitralResolver()] }),        // <Button>, v-tooltip
        AutoImport({ imports: [vitralAutoImports()] })        // useTheme(), Form
    ]
});

VitralResolver({ prefix: 'Vt' }) answers to <VtButton> instead, and leaves every other name to your own components.

Two components at the root

useToast() and useConfirm() send events, so the components that show them have to be on the page. Put them once, near the root, where they outlive the views that call them.

App.vue
<script setup lang="ts">
import { Toast, ConfirmDialog } from '@vitral/vue';
</script>

<template>
    <RouterView />
    <Toast />
    <ConfirmDialog />
</template>

Without JavaScript

A page that only wants the look can take the compiled theme and the components' CSS as two files.

index.html
<link rel="stylesheet" href="/node_modules/@vitral/themes/css/prism.css" />
<link rel="stylesheet" href="/node_modules/@vitral/styles/vitral.css" />

Working on Vitral itself

terminal
pnpm install
pnpm dev        # this site, at http://localhost:5180
pnpm test       # vitest + axe
pnpm typecheck
pnpm build