Interactive Elements with Svelte 5
Markdown files on this site are Svelte components, which means you can add interactivity using Svelte 5's runes system.
Note: You don't need do use .md files only. If you only want a page to be html... you can use a .svelte file. However, if you're making a component that should be reusable, then put it in the src/lib/components/ directory.
Important Note
This project uses Svelte 5 with the runes system.
Resources:
Quick Start
Step 1: Add Script Tag
Add a <script> tag at the top of your markdown file (after frontmatter):
<script>
let count = $state(0)
</script>
Note: Only one <script> tag allowed per file!
Step 2: Use in Content
Reference your variables in markdown:
# Interactive Counter
The count is: {count}
<button onclick={() => count++}>Increment</button>
Svelte 5 - The tip of the iceberg
Runes are special functions that begin with $. They're Svelte 5's way of handling reactivity.
$state() - Reactive Variables
Use $state() for values that should trigger updates when changed:
let count = $state(0)
let name = $state('Alice')
let isVisible = $state(true)
Live example:
Current count: 0
Code:
<script>
let count = $state(0)
</script>
Current count: {count}
<button onclick={() => count++}>Increment</button>
<button onclick={() => count--}>Decrement</button>
<button onclick={() => count = 0}>Reset</button>
$derived() - Computed Values
Use $derived() for values that depend on other state:
let count = $state(0)
let doubled = $derived(count * 2)
let isEven = $derived(count % 2 === 0)
Live example:
Count: 0 | Doubled: 0 | Even: Yes
Code:
<script>
let count = $state(0)
let doubled = $derived(count * 2)
</script>
Count: {count}
Doubled: {doubled}
Even: {count % 2 === 0 ? 'Yes' : 'No'}
<button onclick={() => count++}>Increment</button>
$effect() - Side Effects
Use $effect() for actions that should run when state changes:
let count = $state(0)
$effect(() => {
console.log(`Count changed to: ${count}`)
})
Common use cases:
- Logging for debugging
- Updating browser APIs (localStorage, etc.)
- Triggering animations
- Syncing with external systems
Practical Examples
Example 1: Input Field
Enter your name:
Code:
<script>
let name = $state('')
</script>
Enter your name: <input
type="text"
bind:value={name}
placeholder="Your name"
/>
{#if name}
<p>Hello, <strong>{name}</strong>!</p>
{/if}
Example 2: Toggle Visibility
Code:
<script>
let isVisible = $state(false)
</script>
<button onclick={() => isVisible = !isVisible}>
Toggle Content
</button>
{#if isVisible}
<p>This content can be toggled on and off!</p>
{/if}
Example 3: Conditional Styling
Code:
<script>
let isActive = $state(false)
</script>
<button
class="btn"
class:preset-filled-success-500={isActive}
class:preset-outlined-surface-500={!isActive}
onclick={() => isActive = !isActive}
>
{isActive ? 'Active' : 'Inactive'}
</button>
Example 4: List Iteration
Code:
<script>
const topics = ['Quantum Mechanics', 'Superposition', 'Entanglement']
</script>
<ul>
{#each topics as topic}
<li>{topic}</li>
{/each}
</ul>
Result:
- Quantum Mechanics
- Superposition
- Entanglement
Quantum Computing Example
Here's a practical example for lessons:
<script>
import { Slider } from '@skeletonlabs/skeleton-svelte'
let theta = $state(Math.PI / 4)
let phi = $state(0)
// Compute probability of measuring |0>
let prob0 = $derived(Math.cos(theta / 2) ** 2)
let prob1 = $derived(Math.sin(theta / 2) ** 2)
</script>
## Qubit State Explorer
Adjust the angles to explore different qubit states:
**theta:** <Slider
name="theta"
min="0"
max={Math.PI}
step="0.01"
onValueChange={(e) => (theta = e.value)}
/>
**phi:** <Slider
name="phi"
min={0}
max={2 * Math.PI}
step={0.01}
onValueChange={(e) => (phi = e.value)}
/>
### Measurement Probabilities
- **P(|0>):** {(prob0 * 100).toFixed(1)}%
- **P(|1>):** {(prob1 * 100).toFixed(1)}%
### State Vector
$$
|\psi\rangle = \cos(\theta/2)|0\rangle + e^{i\phi}\sin(\theta/2)|1\rangle
$$
Result:
Qubit State Explorer
Adjust the angles to explore different qubit states:
theta:
phi:
Measurement Probabilities
- P(|0>): 85.4%
- P(|1>): 14.6%
State Vector
Accessing Frontmatter
Frontmatter variables are automatically available:
---
title: My Lesson
author: Dr. Jane Smith
---
# {title}
By {author}
Control Flow
Conditional Rendering
{#if condition}
<p>Shown when true</p>
{:else if otherCondition}
<p>Shown when other condition true</p>
{:else}
<p>Shown otherwise</p>
{/if}
Loops
{#each items as item}
<p>{item}</p>
{/each}
{#each items as item, index}
<p>{index + 1}. {item}</p>
{/each}
Event Handlers
Common event handlers:
<button onclick={() => count++}>Click</button>
<input oninput={(e) => name = e.target.value} />
<div onmouseenter={() => hover = true}>Hover</div>
<form onsubmit={(e) => { e.preventDefault(); handleSubmit() }}>
Resources
- Official Svelte 5 Docs
- Tutorial
- Svelte REPL - Try code online