svelte-dnd-timeline Svelte Themes

Svelte Dnd Timeline

svelte-dnd-timeline

A powerful drag-and-drop timeline component for Svelte 5, built with @atlaskit/pragmatic-drag-and-drop.

This is a conceptual port of dnd-timeline to Svelte, featuring precise pixel manipulation and layout control for timeline-based interfaces.

Features

  • Drag items horizontally to move them in time
  • Drag items vertically to move them between rows
  • Resize items by dragging the left or right edges
  • Grid snapping for precise alignment
  • Real-time visual feedback during drag operations
  • Type-safe with full TypeScript support
  • Headless & Composable - You control the layout and styling
  • Built with Svelte 5 and modern runes API

Installation

npm install svelte-dnd-timeline @atlaskit/pragmatic-drag-and-drop @atlaskit/pragmatic-drag-and-drop-auto-scroll

Usage

This library provides a headless, composable set of components. You are responsible for iterating over your rows and items, which gives you full control over the markup and styling.

<script lang="ts">
    import { Timeline, TimelineRow, TimelineItem } from 'svelte-dnd-timeline';
    import type { Item, Row, TimelineOptions } from 'svelte-dnd-timeline';

    const rows: Row[] = [
        { id: 'row-1', label: 'Team A' },
        { id: 'row-2', label: 'Team B' }
    ];

    // Items must be reactive (using $state) if you want the UI to update
    const items = $state<Item[]>([
        { id: '1', rowId: 'row-1', span: { start: 100, end: 300 }, title: 'Task 1' },
        { id: '2', rowId: 'row-2', span: { start: 400, end: 600 }, title: 'Task 2' }
    ]);

    const options: TimelineOptions = {
        items,
        rows,
        range: { start: 0, end: 1000 },
        gridSize: 50
    };
</script>

<!-- You can pass any class to style the container -->
<Timeline {options} class="timeline-container">
    <!-- You can build your own header here -->
    <div class="header">...</div>

    <!-- Render Rows -->
    {#each rows as row (row.id)}
        <div class="row-wrapper">
            <div class="sidebar">{row.label}</div>

            <!-- The Droppable Row Area -->
            <TimelineRow id={row.id} class="row-track">
                {#each items.filter((i) => i.rowId === row.id) as item (item.id)}
                    <!-- The Draggable Item -->
                    <TimelineItem {item} class="item-style">
                        <!-- Custom Content Snippet -->
                        {#snippet children({ item })}
                            <span>{item.title}</span>
                        {/snippet}
                    </TimelineItem>
                {/each}
            </TimelineRow>
        </div>
    {/each}
</Timeline>

<style>
    .timeline-container {
        border: 1px solid #ccc;
        width: 100%;
    }
    .row-wrapper {
        display: flex;
        height: 50px;
        border-bottom: 1px solid #eee;
    }
    .sidebar {
        width: 100px;
        border-right: 1px solid #eee;
    }
    /* TimelineRow needs relative positioning usually handled by the lib, 
     but you can add background colors etc */
    :global(.row-track) {
        flex: 1;
        background: #f9f9f9;
    }
    /* TimelineItem handles positioning, you handle the look */
    :global(.item-style) {
        background: #e0f2fe;
        border: 1px solid #7dd3fc;
        border-radius: 4px;
    }
</style>

API

Components

<Timeline>

The root container.

  • options: TimelineOptions - Configuration object.
  • class: string - CSS class for the wrapper.

<TimelineRow>

A droppable zone for items.

  • id: string - The row ID (must match row.id).
  • class: string - CSS class.

<TimelineItem>

A draggable and resizable item.

  • item: Item - The item data object.
  • class: string - CSS class.
  • children: Snippet - Render prop for item content. Receives { item, isDragging }.

Types

interface TimelineOptions {
    items: Item[];
    rows: Row[];
    range?: { start: number; end: number };
    gridSize?: number;
    magnetism?: number;
    minWidth?: number;
    collision?: boolean;
}

interface Item {
    id: string;
    rowId: string;
    span: { start: number; end: number };
    title?: string;
    [key: string]: any;
}

Developing

pnpm install
pnpm run dev

License

MIT

Top categories

Loading Svelte Themes