You are viewing Pre-Alpha documentation.
Vuetify0 Logo

Core

v0’s core architecture provides type-safe dependency injection and composable patterns. This page explains how v0 works. For creating plugins, see Plugins Guide→.

Edit this page
Report a Bug
Copy Page as Markdown

Architecture Overview

createContext ─── Type-safe provide/inject wrapper

      └──► createTrinity ─── [use, provide, context] tuple

                └──► createPlugin ─── Vue plugin factory

The Trinity Pattern

The signature pattern of v0. Every composable returns a readonly 3-tuple:

ts
const [useTheme, provideTheme, defaultTheme] = createThemeContext()

// 1. useTheme - Inject from ancestor
const theme = useTheme()

// 2. provideTheme - Provide to descendants
provideTheme()              // Use defaults
provideTheme(customTheme)   // Provide custom

// 3. defaultTheme - Direct access without DI
defaultTheme.toggle()

Why Three Elements?

ElementPurpose
useContextConsume in child components
provideContextProvide from parent (defaults to built-in context)
defaultContextStandalone access, testing, outside Vue

createContext

Type-safe wrapper around Vue’s provide/inject that throws on missing context (no silent undefined):

Static Key Mode

ts
const [useTheme, provideTheme] = createContext<ThemeContext>('v0:theme')

// Provider
provideTheme({ isDark: ref(false), toggle: () => {} })

// Consumer - throws if not provided
const theme = useTheme()

Dynamic Key Mode

For nested contexts (panels within panels):

ts
const [usePanel, providePanel] = createContext<PanelContext>()

// Provider with runtime key
providePanel('panel-1', context)

// Consumer with same key
const panel = usePanel('panel-1')

Suffix Pattern

For parent-child context hierarchies:

ts
const [useItem, provideItem] = createContext<ItemContext>({ suffix: 'item' })

provideItem('v0:panel', context)  // Provides to 'v0:panel:item'
useItem('v0:panel')               // Injects from 'v0:panel:item'

Registry System

useRegistry is the foundational data structure. All selection, forms, and token composables extend it.

ts
const registry = useRegistry()

// Register items
const ticket = registry.register({ id: 'item-1', value: 'First' })

// Lookup
registry.get('item-1')      // Get by ID
registry.browse('First')    // Get IDs by value
registry.lookup(0)          // Get ID by index

// Cleanup
registry.unregister('item-1')

Ticket Structure

Every registered item is a “ticket”:

ts
interface RegistryTicket {
  id: ID           // Unique identifier
  index: number    // Position in registry
  value: unknown   // Associated data
}

Extension Chain

useRegistry ─── Base collection management

      ├──► useSelection ─── + selectedIds Set
      │         │
      │         ├──► useSingle ─── Single selection
      │         │         │
      │         │         └──► useStep ─── + navigation
      │         │
      │         └──► useGroup ─── + tri-state, batch ops

      ├──► useTokens ─── + alias resolution

      └──► useForm ─── + validation

Selection System

useSelection

Base multi-selection with Set-based tracking:

ts
const selection = createSelection({ multiple: true })

selection.register({ id: 'a', value: 'Apple' })
selection.register({ id: 'b', value: 'Banana' })

selection.select('a')
selection.selectedIds  // Set { 'a' }

useSingle

Auto-clears previous selection:

ts
const tabs = createSingle({ mandatory: true })

tabs.select('tab-1')
tabs.select('tab-2')  // tab-1 auto-unselected
tabs.selectedId       // 'tab-2'

useGroup

Multi-select with tri-state:

ts
const checkboxes = createGroup()

checkboxes.select(['a', 'b'])
checkboxes.selectAll()
checkboxes.isMixed  // true when some (not all) selected

useStep

Sequential navigation:

ts
const wizard = createStep({ circular: false })

wizard.next()   // Move forward
wizard.prev()   // Move backward
wizard.first()  // Jump to start
wizard.last()   // Jump to end

Best Practices

Naming Conventions

PrefixPurposeExample
use*Inject from contextuseTheme()
create*Factory returning instancecreateSelection()
create*ContextFactory returning trinitycreateThemeContext()
create*PluginFactory returning Vue plugincreateThemePlugin()

When to Use Each

NeedUse
Share state in component treeprovideContext / useContext
App-wide singletoncreatePlugin with app.use()
Standalone logicDirect factory call
TestingTrinity’s third element

© 2016-2025 Vuetify, LLC
Ctrl+/