Transfer / Dual List
The VdTransfer component renders a dual-panel picker — users move items from a "Source" list to a "Target" list using arrow buttons. Search filtering is built into both panels automatically, and selected items are accessible programmatically at any time.
Transfer
Source0/15
- HTML
- CSS
- JavaScript
- TypeScript
- Python
- Ruby
- Go
- Rust
- Java
- C#
- PHP
- Swift
- Kotlin
- Dart
- Scala
Target0/0
<script setup lang="ts">
import { VdTransfer } from "@vanduo-oss/vd3";
const items = [
{ id: "html", label: "HTML" },
{ id: "css", label: "CSS" },
{ id: "javascript", label: "JavaScript" },
{ id: "typescript", label: "TypeScript" },
{ id: "python", label: "Python" },
];
</script>
<template>
<VdTransfer :items="items" />
</template>import { ref } from 'vue';
const transferRef = ref();
// Read the current Target-panel ids via the exposed method:
const selected = transferRef.value?.getSelected();
console.log(selected); // ["javascript", "python"]
// VdTransfer also dispatches a native transfer:change event
// ({ selected, available }) on its root — listen via a template ref.API Reference
Usage
<script setup lang="ts">
import { VdTransfer } from "@vanduo-oss/vd3";
const items = [
{ id: 'html', label: 'HTML' },
{ id: 'css', label: 'CSS' },
];
</script>
<template>
<VdTransfer :items="items" />
</template>CSS Classes
| Class | Description |
|---|---|
.vd-transfer | Auto-generated root container (flex layout with two panels) |
.vd-transfer-panel | Each side panel (Available / Selected) |
.vd-transfer-header | Panel header showing title and item count |
.vd-transfer-search | Search input inside each panel for filtering items |
.vd-transfer-list | Scrollable list container holding items |
.vd-transfer-item | Individual item row with a checkbox |
.vd-transfer-item.is-selected | Selected state on an item (ready to move) |
.vd-transfer-actions | Center column holding the move buttons |
.vd-transfer-btn | Arrow button to move checked items between panels |
Component API
| Prop / event / method | Description |
|---|---|
:items | Array of { id, label } objects; all start in the Source panel. |
transfer:change | Native event on the root; detail = { selected, available } (id arrays). |
ref.getSelected() | Exposed method — returns the current Target-panel id array. |
Events
| Event | Description |
|---|---|
transfer:change | Fired on the element when items are moved. event.detail contains { selected: string[], available: string[] } |
Accessibility
- Each panel list has
role="listbox"witharia-multiselectable="true" - Items use
role="option"witharia-selectedreflecting checked state - Move buttons have descriptive
aria-labels (e.g. "Move selected to right") - Space toggles item selection; ↑/↓ navigate the list
- Ctrl+A selects all visible items in the focused panel
- Search inputs are labelled with
aria-label="Search source"/"Search target" - Panel headers use
aria-live="polite"to announce count changes