Expand the Sortable demo and add default SortableJS drag styles (#3106)

This commit is contained in:
Bartosz-Do authored and GitHub committed 2026-09-21 14:13:22 +02:00
1 parent ce523643b2
commit bd60d5fd4c
11 files changed
+602 -11

No files matched your search

+87
View File
@@ -0,0 +1,87 @@
---
// Sortable on a kanban board, drawn in the middle of a drag. The card being
// moved has left the Upcoming column and shows twice, as SortableJS renders it:
// a dashed slot in In Progress where it will land, and the copy that follows the
// pointer, lifted with a shadow and an outline. Both carry the real state classes
// (`.sortable-ghost`, `.sortable-drag`), so the picture shows the shipped styles.
// The fake cursor rests on the floating card.
import ScreenshotLayout from '../layouts/ScreenshotLayout.astro'
import Avatar from '@ui/Avatar.astro'
import Card from '@ui/Card.astro'
import CardBody from '@ui/CardBody.astro'
import Signal from '@ui/Signal.astro'
import { personById } from '@shared/lib/people'
import tasks from '@data/tasks.json'
interface Task {
name: string
assigned_to: number
priority: string
}
interface Column {
name: string
tasks: Task[]
}
const [upcoming, progress, completed] = tasks.columns as Column[] as [Column, Column, Column]
const priorities: Record<string, { value: number; color: string }> = {
High: { value: 3, color: 'red' },
Medium: { value: 2, color: 'orange' },
Low: { value: 1, color: 'blue' },
}
const moving = upcoming.tasks[2]!
const columns = [
{ name: upcoming.name, cards: [upcoming.tasks[0]!, upcoming.tasks[1]!] },
{ name: progress.name, cards: [progress.tasks[0]!, moving, progress.tasks[1]!] },
{ name: completed.name, cards: [completed.tasks[0]!, completed.tasks[1]!, completed.tasks[2]!] },
]
---
<ScreenshotLayout title="Sortable" columns={3}>
<Card>
<CardBody class="p-4 position-relative">
<div class="row g-3">
{
columns.map((column) => (
<div class="col-4">
<h4 class="mb-2">{column.name}</h4>
<div class="d-flex flex-column gap-2">
{column.cards.map((task) => (
<Card size="sm" class:list={['cursor-move', task === moving && 'sortable-chosen sortable-ghost']}>
<CardBody>
<div class="mb-3">{task.name}</div>
<div class="d-flex align-items-center justify-content-between">
<span class="d-flex align-items-center gap-2 text-secondary">
<Signal value={priorities[task.priority]?.value ?? 0} color={priorities[task.priority]?.color} />
{task.priority}
</span>
<Avatar person={personById(task.assigned_to)} size="xs" />
</div>
</CardBody>
</Card>
))}
</div>
</div>
))
}
</div>
<div class="card card-sm sortable-chosen sortable-fallback sortable-drag" style="position: absolute; top: 11rem; left: 39.5%; width: 28.5%">
<div class="card-body">
<div class="mb-3">{moving.name}</div>
<div class="d-flex align-items-center justify-content-between">
<span class="d-flex align-items-center gap-2 text-secondary">
<Signal value={priorities[moving.priority]?.value ?? 0} color={priorities[moving.priority]?.color} />
{moving.priority}
</span>
<Avatar person={personById(moving.assigned_to)} size="xs" />
</div>
</div>
<span class="cursor" style="top: 55%; left: 55%"></span>
</div>
</CardBody>
</Card>
</ScreenshotLayout>