sortable
Sortable settings priority with frame
Sortable settings priority with frame
Загрузка превью…
src/sortable/c-sortable-5.vue
<!--
Расхождение с апстримом: `IconPlaceholder` заменена инлайновым `<svg>`
(lucide-react v0.545.0 "grip-vertical") — см. docs/PORTING.md §5.
-->
<script setup lang="ts">
import { ref } from "vue"
import { Frame, FrameDescription, FrameHeader, FramePanel, FrameTitle } from "@/components/reui/frame"
import { Sortable, SortableItem, SortableItemHandle } from "@/components/reui/sortable"
import { Switch } from "@/components/ui/switch"
interface NotificationChannel {
id: string
name: string
description: string
enabled: boolean
}
const channels = ref<NotificationChannel[]>([
{ id: "1", name: "Email", description: "Send notifications via email", enabled: true },
{ id: "2", name: "Push Notifications", description: "Browser and mobile push", enabled: true },
{ id: "3", name: "SMS", description: "Text message alerts", enabled: false },
{ id: "4", name: "Slack", description: "Post to Slack channels", enabled: true },
{ id: "5", name: "Webhook", description: "Send to custom endpoint", enabled: false },
])
function getItemValue(item: NotificationChannel) {
return item.id
}
function toggleChannel(id: string) {
const channel = channels.value.find((ch) => ch.id === id)
if (channel) channel.enabled = !channel.enabled
}
</script>
<template>
<div class="mx-auto w-full max-w-md">
<Frame spacing="sm">
<FrameHeader>
<FrameTitle>Notification Priority</FrameTitle>
<FrameDescription>
Drag to reorder by priority. Top channels are tried first.
</FrameDescription>
</FrameHeader>
<Sortable
v-model:value="channels"
:get-item-value="getItemValue"
strategy="vertical"
class="space-y-1"
>
<SortableItem v-for="channel in channels" :key="channel.id" :value="channel.id">
<FramePanel class="p-0!">
<div class="flex items-center gap-3 px-3 py-2.5">
<SortableItemHandle class="text-muted-foreground hover:text-foreground">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-grip-vertical size-4">
<circle cx="9" cy="12" r="1" />
<circle cx="9" cy="5" r="1" />
<circle cx="9" cy="19" r="1" />
<circle cx="15" cy="12" r="1" />
<circle cx="15" cy="5" r="1" />
<circle cx="15" cy="19" r="1" />
</svg>
</SortableItemHandle>
<div class="min-w-0 flex-1">
<p class="text-sm font-medium">{{ channel.name }}</p>
<p class="text-muted-foreground text-xs">{{ channel.description }}</p>
</div>
<Switch :default-value="channel.enabled" @update:model-value="() => toggleChannel(channel.id)" />
</div>
</FramePanel>
</SortableItem>
</Sortable>
</Frame>
</div>
</template>