Drag across files to select. Hold Ctrl, ⌘, or Shift to add. Press Escape to cancel a drag.
<script setup lang="ts">
import { ref } from "vue";
import { DragSelection } from "@dicehub/kappa/components/drag-selection";
const selected = ref(["notes"]);
const items = [
{ value: "brand", label: "Brand guidelines.pdf" },
{ value: "landing", label: "Landing page.png" },
{ value: "notes", label: "Project notes.md" },
{ value: "photos", label: "Product photos.zip" },
{ value: "release", label: "Release checklist.md" },
{ value: "tokens", label: "Design tokens.json" },
];
</script>
<template>
<DragSelection v-model="selected" :items="items" label="Shared files" :columns="3" />
</template>Installation
import { DragSelection } from "@dicehub/kappa";
// Or: "@dicehub/kappa/components/drag-selection"Usage
Give each item a unique value and a readable label. Bind the selected identifiers with v-model, or use defaultValue for local state. The item slot changes presentation without changing selection.
A normal drag replaces the selection. Hold Control, Command, or Shift to add to the selection. Escape or a canceled pointer restores the selection from before the drag. Touch devices retain scrolling and tap selection.
Composition
Ark UI Listbox supplies selected state, keyboard navigation, typeahead, and listbox semantics. Its grid collection keeps arrow navigation aligned with the columns prop. Kappa adds rectangle hit testing and vertical edge scrolling.
Keep item content presentational and place actions outside the listbox. This component renders every item; use VirtualTree for very large hierarchies. Rectangle selection only applies to mounted items.
Kappa filters disabled items out of new keyboard selections. This corrects the installed Ark version's select-all behavior, which includes disabled values. A disabled value supplied by the parent remains valid.
Examples
List layout
Use one column for long names. The same selection model works for lists and grids.
Drag across files to select. Hold Ctrl, ⌘, or Shift to add. Press Escape to cancel a drag.
<DragSelection v-model="selected" :items="items" label="Shared files" :columns="1">
<template #item="{ item, selected }">
<span>{{ item.label }}</span>
<span v-if="selected" aria-hidden="true">✓</span>
</template>
</DragSelection>Edge scrolling
Keep the pointer near the top or bottom edge during a drag to select items outside the visible area.
Drag across files to select. Hold Ctrl, ⌘, or Shift to add. Press Escape to cancel a drag.
<DragSelection
v-model="selected"
:items="assets"
label="Asset library"
:columns="3"
style="--kappa-drag-selection-max-height: 18rem"
/>Disabled items and collection
A disabled item is excluded from pointer and keyboard selection. Disable the entire collection to lock selection.
Drag across files to select. Hold Ctrl, ⌘, or Shift to add. Press Escape to cancel a drag.
<script setup lang="ts">
const items = [
{ value: "notes", label: "Project notes.md" },
{ value: "landing", label: "Landing page.png", disabled: true },
];
</script>
<template>
<DragSelection :items="items" label="Shared files" :disabled="locked" />
</template>Click and keyboard only
Turn off rectangle gestures without removing the accessible selection behavior.
Click a file. Use Ctrl or ⌘ to add more, or Shift to select a range.
<DragSelection v-model="selected" :items="items" label="Shared files" drag-disabled />Accessibility
The required label names the multi-select listbox. Tab enters the list, arrow keys move focus, and Space selects. Shift extends a range; Control/Command+A selects enabled items. Visible focus, disabled states, and forced colors are supported. No animation is used.
API Reference
DragSelection accepts items: DragSelectionItem[], label: string, modelValue?: string[], defaultValue?: string[], columns?: number (3), disabled?: boolean, dragDisabled?: boolean, autoScroll?: boolean (true), threshold?: number (6 pixels), and emptyLabel?: string (“No items”). Native attributes reach the root.
An item has value: string, label: string, and optional disabled: boolean. The item slot receives { item, selected }. The empty slot replaces the empty message.
Events: update:modelValue emits the selected identifiers; valueChange emits { value }; dragStart starts a rectangle gesture; dragEnd emits { value, canceled }. Canceled gestures restore their initial selection.
Set --kappa-drag-selection-max-height to change the scroll height (22rem). Use columns for responsive layout changes so the keyboard grid changes with the visual grid.