Vue Native provides 40 built-in components that map directly to native views on iOS, Android, and macOS.
All components are globally registered — no import needed in templates.
The three platform columns name the native view (or views) that backs the component on each OS.
- "JS-composed" means the component has no native factory of its own — it is assembled in TypeScript out of other components (and, for animation,
useAnimation), so it behaves identically on all three platforms. - "No-op" means the component is registered for API compatibility but renders nothing (or a hidden, zero-size placeholder). Your app will not crash or warn in production; it just gets no UI from that component on that platform.
VToolbar, VSplitView, and VOutlineView are macOS-only — in development builds they log a console warning on iOS/Android and render nothing there.
| Component | iOS | Android | macOS | Description |
|---|
<VView> | UIView | FlexboxLayout | FlippedView (NSView) | Container view. Supports all Flexbox props |
<VScrollView> | UIScrollView | ScrollView | NSScrollView | Scrollable container |
<VSafeArea> | UIView + safeAreaInsets | View + WindowInsetsCompat | Pass-through NSView (no insets) | Respects device safe areas |
<VKeyboardAvoiding> | Custom VC logic | AdjustResize / manual offset | Pass-through NSView (no avoidance) | Shifts content when keyboard appears |
<VSplitView> | No-op | No-op | NSSplitView | Resizable split pane. macOS only |
| Component | iOS | Android | macOS | Description |
|---|
<VText> | UILabel | TextView | NSTextField | Text display |
<VInput> | UITextField / UITextView | EditText | NSTextField | Text input with v-model |
<VCheckbox> | Custom checkbox view | CheckBox | NSButton (checkbox) | Boolean checkbox with optional label, v-model |
<VRadio> | UIStackView + radio circles | RadioGroup + RadioButton | NSStackView + NSButton (radio) | Radio button group, v-model |
<VDropdown> | UIMenu (iOS 14+) / UIPickerView | Spinner | NSPopUpButton | Dropdown selection, v-model |
<VPicker> | UIDatePicker | DatePickerDialog / NumberPicker | NSDatePicker | Date/time and value picker |
| Component | iOS | Android | macOS | Description |
|---|
<VButton> | UIButton / UIControl | Custom TouchDelegate | ClickableView (NSView) | Pressable container with :onPress |
<VPressable> | Custom TouchableView | Custom TouchableView | PressableView (ClickableView subclass) | Generic pressable wrapper with press-in/out events |
<VSwitch> | UISwitch | Switch | NSSwitch | Toggle with v-model |
<VSlider> | UISlider | SeekBar | NSSlider | Range slider with v-model |
<VSegmentedControl> | UISegmentedControl | TabLayout | NSSegmentedControl | Tab strip selector |
<VToolbar> | No-op | No-op | NSToolbar | Window toolbar with items. macOS only |
| Component | iOS | Android | macOS | Description |
|---|
<VImage> | UIImageView + URLSession | ImageView + Coil | NSImageView | Async image loading with caching |
<VSVG> | SVGKit | AndroidSVG (custom SVGView) | SVGKit + NSImageView | Native SVG rendering (inline, asset, or URI) |
<VVideo> | AVPlayer | MediaPlayer | AVPlayer + AVPlayerLayer | Inline video playback with progress events |
<VWebView> | WKWebView | WebView | WKWebView | Embedded web view |
| Component | iOS | Android | macOS | Description |
|---|
<VList> | UITableView | RecyclerView | NSScrollView + NSTableView | Virtualized list for large datasets. Rows come from the #item slot |
<VSectionList> | UITableView (sections) | RecyclerView | NSScrollView + NSTableView (group rows) | Sectioned list with headers |
<VFlatList> | JS-composed (VScrollView + VView) | JS-composed | JS-composed | React Native-compatible list. Takes a renderItem prop, unlike VList |
<VOutlineView> | No-op | No-op | NSOutlineView | Hierarchical outline / source list. macOS only |
| Component | iOS | Android | macOS | Description |
|---|
<VActivityIndicator> | UIActivityIndicatorView | ProgressBar (circular) | NSProgressIndicator (spinner) | Loading spinner |
<VProgressBar> | UIProgressView | ProgressBar (horizontal) | NSProgressIndicator (bar) | Progress bar |
<VAlertDialog> | UIAlertController | AlertDialog | NSAlert | Native alert |
<VActionSheet> | UIAlertController (.actionSheet) | BottomSheetDialog | NSMenu | Action sheet |
<VModal> | UIViewController presentation | Dialog | NSPanel | Full-screen overlay modal |
<VRefreshControl> | UIRefreshControl | SwipeRefreshLayout | No-op placeholder | Pull-to-refresh. Mobile pattern — inert on macOS |
| Component | iOS | Android | macOS | Description |
|---|
<VTabBar> | JS-composed (VView + VPressable) | JS-composed | JS-composed | Tab bar with labels, icons, and badges |
<VDrawer> | JS-composed (VPressable + VView) | JS-composed | JS-composed | Side-menu drawer container |
<VDrawerItem> | JS-composed | JS-composed | JS-composed | Row inside a VDrawer |
<VDrawerSection> | JS-composed | JS-composed | JS-composed | Labelled group of VDrawerItems |
| Component | iOS | Android | macOS | Description |
|---|
<VStatusBar> | UIStatusBarStyle (via the root view controller) | WindowInsetsController | No-op | Control status bar style. Props: barStyle, hidden, animated |
These are Vue's own components, re-exported so they cooperate with the custom renderer. They have no native view of their own and work identically on all three platforms.
| Component | iOS | Android | macOS | Description |
|---|
<VTransition> | JS-composed (useAnimation) | JS-composed | JS-composed | Enter/leave transitions driven by native animations |
<VTransitionGroup> | JS-composed (useAnimation) | JS-composed | JS-composed | Same, for lists |
<KeepAlive> | Renderer-level | Renderer-level | Renderer-level | Caches inactive component instances |
<VSuspense> | Renderer-level | Renderer-level | Renderer-level | Async component boundary (Vue's Suspense) |
createApp() registers the 40 components above plus a few extras, so these need no import either:
| Global name | Notes |
|---|
ErrorBoundary / VErrorBoundary | Two names for the same component. Both are registered and both are in the GlobalComponents type augmentation, so editors resolve either tag. |
VDrawer.Item / VDrawer.Section | Dotted aliases for VDrawerItem / VDrawerSection. Registered at runtime, but a dotted name cannot be a key in GlobalComponents, so it gets no editor typing. Prefer <VDrawerItem> / <VDrawerSection> in lang="ts" SFCs. |
KeepAlive is deliberately absent from Vue Native's own augmentation because @vue/runtime-core already declares it — the runtime re-exports Vue's KeepAlive unchanged.
<VNavigationBar> is the one documented component that is not globally registered: it lives in @thelacanians/vue-native-navigation, so import it from that package.
Three components exist for macOS window chrome and render nothing elsewhere. Guard them with usePlatform() if you share screens across targets:
<script setup>
import { usePlatform } from '@thelacanians/vue-native-runtime'
const { isMacOS } = usePlatform()
</script>
<template>
<VToolbar v-if="isMacOS" :items="toolbarItems" @itemClick="onToolbarItem" />
<VView v-else :style="{ flex: 1 }">
</VView>
</template>
In development builds, mounting VToolbar, VSplitView, or VOutlineView on iOS or Android logs a console warning telling you the component renders nothing on that platform.