Skip to main content
Svelte Fundamentals
CHAPTER 28 Beginner

Svelte Data Structures and Algorithms UI

Updated: May 18, 2026
5 min read

# CHAPTER 28

Svelte Data Structures and Algorithms UI

1. Chapter Introduction

Svelte's animations and reactivity make it perfect for building educational algorithm visualizations. In this chapter, we build animated visualizations for fundamental data structures — stack, queue, and sorting algorithms — demonstrating Svelte's rendering power.

2. Learning Objectives

  • Visualize Stack push/pop operations with animations.
  • Visualize Queue enqueue/dequeue.
  • Build a Bubble Sort animation.
  • Build an Array visualization with highlighting.

3. Stack Visualization

svelte
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960
<!-- StackVisualizer.svelte -->
<script>
  import { fly, fade } from &#039;svelte/transition';
  import { flip } from &#039;svelte/animate';

  let stack = [];
  let inputValue = &#039;';
  let maxSize = 6;

  $: isFull = stack.length >= maxSize;
  $: isEmpty = stack.length === 0;

  function push() {
    if (isFull || !inputValue.trim()) return;
    stack = [inputValue.trim(), ...stack]; // Top of stack = index 0
    inputValue = &#039;';
  }

  function pop() {
    if (isEmpty) return;
    stack = stack.slice(1);
  }
</script>

<div class="visualizer">
  <h2>📦 Stack (LIFO)</h2>

  <div class="controls">
    <input bind:value={inputValue} placeholder="Value to push" on:keydown={e => e.key===&#039;Enter' && push()} />
    <button on:click={push} disabled={isFull}>Push ↑</button>
    <button on:click={pop} disabled={isEmpty}>Pop ↓</button>
  </div>

  <div class="stack-container">
    {#if isEmpty}
      <div class="empty-state" transition:fade>Stack is empty</div>
    {:else}
      {#each stack as item, i (item + i)}
        <div
          class="stack-item"
          class:top={i === 0}
          animate:flip={{ duration: 250 }}
          transition:fly={{ y: -40, duration: 300 }}
        >
          {#if i === 0}<span class="label">TOP</span>{/if}
          {item}
        </div>
      {/each}
    {/if}
  </div>

  <p class="info">Size: {stack.length}/{maxSize} {isFull ? &#039;(FULL)' : ''}</p>
</div>

<style>
  .stack-container { display: flex; flex-direction: column; gap: 4px; min-height: 240px; width: 200px; border: 2px dashed #e2e8f0; padding: 1rem; border-radius: 12px; }
  .stack-item { background: #6366f1; color: white; padding: 0.75rem 1rem; border-radius: 8px; text-align: center; font-weight: 600; position: relative; }
  .top { background: #4f46e5; box-shadow: 0 4px 12px rgba(99,102,241,0.4); }
  .label { position: absolute; right: 8px; font-size: 10px; opacity: 0.8; }
</style>

4. Queue Visualization

svelte
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051
<!-- QueueVisualizer.svelte -->
<script>
  import { fly } from &#039;svelte/transition';
  import { flip } from &#039;svelte/animate';

  let queue = [];
  let inputValue = &#039;';

  function enqueue() {
    if (!inputValue.trim()) return;
    queue = [...queue, { id: Date.now(), value: inputValue.trim() }];
    inputValue = &#039;';
  }

  function dequeue() {
    if (queue.length === 0) return;
    queue = queue.slice(1);
  }

  $: front = queue[0];
  $: rear = queue[queue.length - 1];
</script>

<div class="visualizer">
  <h2>🚶 Queue (FIFO)</h2>
  <div class="controls">
    <input bind:value={inputValue} placeholder="Enqueue value" on:keydown={e => e.key===&#039;Enter' && enqueue()} />
    <button on:click={enqueue}>Enqueue →</button>
    <button on:click={dequeue} disabled={!queue.length}>← Dequeue</button>
  </div>

  <div class="queue-row">
    {#if queue.length === 0}
      <div class="empty">Queue is empty</div>
    {:else}
      {#each queue as item (item.id)}
        <div
          class="queue-item"
          class:front-item={item === front}
          class:rear-item={item === rear}
          animate:flip={{ duration: 250 }}
          transition:fly={{ x: 60, duration: 300 }}
        >
          {item.value}
          {#if item === front}<div class="pointer front-ptr">FRONT</div>{/if}
          {#if item === rear}<div class="pointer rear-ptr">REAR</div>{/if}
        </div>
      {/each}
    {/if}
  </div>
</div>

5. Bubble Sort Visualization

svelte
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
<!-- BubbleSortVisualizer.svelte -->
<script>
  let arr = [64, 34, 25, 12, 22, 11, 90];
  let comparing = [];
  let sorted = [];
  let isSorting = false;
  let delay = 400;

  function sleep(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
  }

  async function bubbleSort() {
    isSorting = true;
    let a = [...arr];
    const n = a.length;

    for (let i = 0; i < n - 1; i++) {
      for (let j = 0; j < n - i - 1; j++) {
        comparing = [j, j + 1];
        await sleep(delay);

        if (a[j] > a[j + 1]) {
          [a[j], a[j + 1]] = [a[j + 1], a[j]];
          arr = [...a];
          await sleep(delay);
        }
      }
      sorted = [n - 1 - i, ...sorted];
    }
    sorted = arr.map((_, i) => i);
    comparing = [];
    isSorting = false;
  }

  function reset() {
    arr = [64, 34, 25, 12, 22, 11, 90];
    comparing = [];
    sorted = [];
    isSorting = false;
  }

  $: maxVal = Math.max(...arr);
</script>

<div class="sort-visualizer">
  <h2>Bubble Sort</h2>

  <div class="controls">
    <label>Speed: <input type="range" bind:value={delay} min="100" max="1000" step="100" /></label>
    <button on:click={bubbleSort} disabled={isSorting}>▶ Sort</button>
    <button on:click={reset} disabled={isSorting}>⟳ Reset</button>
  </div>

  <div class="bars">
    {#each arr as value, i}
      <div class="bar-wrapper">
        <span class="bar-value">{value}</span>
        <div
          class="bar"
          class:comparing={comparing.includes(i)}
          class:sorted={sorted.includes(i)}
          style="height: {(value / maxVal) * 200}px"
        />
      </div>
    {/each}
  </div>

  <div class="legend">
    <span class="comparing-dot">Comparing</span>
    <span class="sorted-dot">Sorted</span>
  </div>
</div>

<style>
  .bars { display: flex; align-items: flex-end; gap: 6px; height: 220px; padding: 0 1rem; }
  .bar { width: 40px; border-radius: 4px 4px 0 0; background: #6366f1; transition: height 0.2s; }
  .bar.comparing { background: #f59e0b; }
  .bar.sorted { background: #10b981; }
</style>

6. Array Visualization with Highlighting

svelte
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556
<script>
  import { fade } from &#039;svelte/transition';

  let array = [3, 7, 1, 9, 4, 6, 2, 8, 5];
  let target = 6;
  let currentIndex = -1;
  let foundIndex = -1;
  let searching = false;

  async function linearSearch() {
    searching = true;
    foundIndex = -1;
    for (let i = 0; i < array.length; i++) {
      currentIndex = i;
      await new Promise(r => setTimeout(r, 500));
      if (array[i] === target) {
        foundIndex = i;
        break;
      }
    }
    searching = false;
  }

  function reset() {
    currentIndex = -1;
    foundIndex = -1;
  }
</script>

<div class="array-visualizer">
  <h2>Linear Search</h2>
  <div class="search-control">
    <label>Target: <input type="number" bind:value={target} min="1" max="9" /></label>
    <button on:click={linearSearch} disabled={searching}>Search</button>
    <button on:click={reset}>Reset</button>
  </div>

  <div class="array-display">
    {#each array as value, i}
      <div
        class="array-cell"
        class:current={i === currentIndex}
        class:found={i === foundIndex}
      >
        <div class="cell-value">{value}</div>
        <div class="cell-index">{i}</div>
      </div>
    {/each}
  </div>

  {#if foundIndex !== -1}
    <p class="result" transition:fade>✅ Found {target} at index {foundIndex}!</p>
  {:else if !searching && currentIndex >= 0}
    <p class="result" transition:fade>❌ {target} not found.</p>
  {/if}
</div>

7. MCQs

Question 1

What makes Svelte ideal for algorithm visualization?

Question 2

In a Stack, which end do push/pop operate on?

Question 3

In a Queue, where does dequeue happen?

Question 4

What Svelte animate directive smoothly repositions items in sort visualization?

Question 5

Why use sleep(ms) in sort animations?

Question 6

What Svelte transition shows new stack items flying in from above?

Question 7

What is the time complexity of Bubble Sort?

Question 8

How do you make sort visualization responsive to speed slider?

Question 9

What property controls bar height in the sort visualizer?

Question 10

How do you prevent multiple sort runs simultaneously?

8. Summary

Svelte's reactive state and built-in animation system make algorithm visualization both easy to build and beautiful to watch. These projects demonstrate advanced reactive patterns: async operations updating shared reactive state, conditional class bindings for highlighting, and flip animations for smooth visual feedback.

9. Next Chapter Recommendation

In Chapter 29: Deploying Svelte Applications, we build, optimize, and deploy Svelte apps to Vercel, Netlify, and Firebase Hosting with environment variables and production configurations.

Finish this Chapter

Save your progress on your learning path and prepare for coding interview challenges.

Discussion

Join the discussion

Log in or create a free account to participate.

Sort: ·