A true Svelte 5 renderer for terminal user interfaces, inspired by Ink for React.
SvelTUI allows you to build beautiful terminal user interfaces using Svelte 5 components. Unlike wrapper libraries, SvelTUI implements a custom Svelte compiler plugin that renders Svelte components directly to the terminal, bringing the full power of Svelte to terminal applications.
# Install dependencies
bun install
# Run the example application
bun run example
<!-- App.svelte -->
<script>
// Svelte 5 runes for reactivity
let count = $state(0);
let items = $state(["Item 1", "Item 2", "Item 3"]);
let selected = $state(0);
// Reactivity with $derived
$derived selectedItem = items[selected];
$derived hasItems = items.length > 0;
function increment() {
count++;
}
function handleSelect(event) {
selected = event.detail.index;
}
// Effects for side effects
$effect(() => {
console.log(`Selection changed: ${selectedItem}`);
});
</script>
<box border label="SvelTUI Demo">
<text>Count: {count}</text>
<button on:press={increment}>Increment</button>
<list
items={items}
selected={selected}
on:select={handleSelect}
/>
<text>Selected: {selectedItem}</text>
</box>
// main.ts
import { render } from 'sveltui';
import App from './App.svelte';
render(App, {
// Optional configuration
title: 'My Terminal App',
fullscreen: true,
debug: false,
theme: 'dark'
});
SvelTUI implements a custom Svelte 5 renderer for the terminal, with direct integration via Svelte 5's mount/unmount APIs.
The architecture consists of:
For more details, see the Architecture Documentation.
SvelTUI components are built using Svelte 5's component model and runes system:
<script>
// Import theme
import { getTheme } from '../theme/currentTheme.svelte';
// Props with defaults
let {
value = '',
width = 20,
height = 1,
border = true,
} = $props();
// Local state
let focused = $state(false);
// Get theme
const theme = getTheme();
// Event handlers
function handleFocus() {
focused = true;
}
function handleBlur() {
focused = false;
}
</script>
<input
value={value}
width={width}
height={height}
border={border}
style={{
bg: focused ? theme.colors.focusBg : theme.colors.bg,
fg: theme.colors.fg,
border: {
fg: focused ? theme.colors.focusBorder : theme.colors.border
}
}}
on:focus={handleFocus}
on:blur={handleBlur}
/>
For more details, see the Component Implementation Strategy.
SvelTUI includes a set of built-in components for common terminal UI elements:
Component | Description |
---|---|
<box> |
Container component with borders and title support |
<text> |
Text display with styling options |
<list> |
Interactive, selectable list |
<input> |
Text input field |
<checkbox> |
Checkbox for boolean selection |
<button> |
Pressable button |
<progress> |
Progress bar |
SvelTUI supports a flexible theming system:
// Apply a theme
import { setTheme } from 'sveltui';
setTheme('dark');
// Use theme in components
import { getTheme } from 'sveltui';
const theme = getTheme();
<text style={{ fg: theme.colors.primary }}>Themed Text</text>
SvelTUI is under active development. Contributions are welcome!
# Run development server
bun run dev
# Build the library
bun run build
# Run tests
bun run test
MIT © RLabs Inc.