Section 15 · Integration
Vuetify.
VirtuProbe's app is Vue 3 + Vuetify. Vuetify gives us components for free, but its defaults feel like a vendor demo. This is how we make it look like us.
Theme
Define a single dark theme that mirrors our tokens. Light theme is not on the roadmap — the product runs at 02:00 in a hoodie.
vuetify.config.tsimport { createVuetify } from "vuetify"; export const vuetify = createVuetify({ theme: { defaultTheme: "virtuprobe", themes: { virtuprobe: { dark: true, colors: { background: "#0b0f0d", // --vp-color-bg surface: "#11161a", // --vp-color-bg-2 primary: "#b0f75a", // --vp-color-neon secondary: "#7e8a87", // --vp-color-fg-dim error: "#ff6b6b", info: "#78b4ff", success: "#b0f75a", warning: "#ffc864", "on-primary": "#06140d", // dark label on neon "on-surface": "#e8efe9", "on-background": "#e8efe9", }, variables: { "border-color": "#2a3338", "high-emphasis-opacity": 1, "medium-emphasis-opacity": 0.78, "disabled-opacity": 0.42, } } } }, defaults: { VBtn: { rounded: "md", flat: true, height: 36 }, VTextField: { variant: "outlined", density: "comfortable", hideDetails: "auto" }, VSelect: { variant: "outlined", density: "comfortable" }, VCard: { rounded: "md", flat: true }, VTabs: { sliderColor: "primary", density: "comfortable" }, } });
Component overrides
Vuetify's defaults will feel close-but-wrong. Add this stylesheet last, after Vuetify's own styles, to bring it home.
vuetify-overrides.css/* 1. Inputs use our bg-2 surface, not Vuetify's translucent grey */ .v-field--variant-outlined .v-field__overlay { background: var(--vp-color-bg-2); opacity: 1; } .v-field--variant-outlined .v-field__outline__start, .v-field--variant-outlined .v-field__outline__end, .v-field--variant-outlined .v-field__outline__notch::before, .v-field--variant-outlined .v-field__outline__notch::after { border-color: var(--vp-color-line-2); } .v-field--focused .v-field__outline { color: var(--vp-color-neon); } /* 2. Mono input where the content is structural */ .v-text-field.is-mono .v-field__input { font-family: var(--vp-font-mono); font-weight: 500; } /* 3. Buttons — kill Vuetify's elevation on primary, add our glow */ .v-btn.v-btn--variant-flat.bg-primary { box-shadow: 0 0 0 1px var(--vp-color-neon), 0 6px 20px -6px var(--vp-color-neon-glow); font-weight: 600; letter-spacing: 0; text-transform: none; } /* 4. Tabs — underline only, kill the hover ripple background */ .v-tab { text-transform: none; letter-spacing: 0.02em; min-width: 0; } .v-tab--selected { color: var(--vp-color-fg); font-weight: 600; } /* 5. Cards — flat, our line-2 border */ .v-card { background: var(--vp-color-bg-2); border: 1px solid var(--vp-color-line-2); } /* 6. Tables — strip Vuetify's stripes, use our line tokens */ .v-data-table { background: transparent; } .v-data-table__th { background: var(--vp-color-bg-3); font: 600 10.5px/1 var(--vp-font-mono); letter-spacing: 0.08em; text-transform: uppercase; color: var(--vp-color-fg-mute); } .v-data-table__td { font: 500 12.5px var(--vp-font-mono); } .v-data-table__tr:hover { background: var(--vp-color-bg-2); }
What we still build by hand
Vuetify covers ~70%. The remaining 30% is the surface that is the product:
key-value rowsgrid + checkbox + 2 inputs · custom · see Inputs
code editorCodeMirror · themed to our palette
protocol tagsour component · don't use VChip
status badgesours · VChip's pill shape is wrong for us
empty statescustom · Vuetify has no opinion here
command palettecustom · Vuetify's autocomplete is too form-shaped
Don't
- Don't use VChip for protocol tags. Pill shape, wrong typography. Build the tag (page 10).
- Don't enable Material Design ripples. They're not in our motion system.
- Don't import Vuetify's icon font. We use Phosphor — install
@phosphor-icons/vueand passiconcomponents explicitly. - Don't use density="compact" as default. Comfortable is our floor.