svelte-use Svelte Themes

Svelte Use

Collection of reactive utility composables for Svelte 5 inspired by VueUse

svelte-use logo

@ariefsn/svelte-use

A collection of 50+ Svelte 5 runes-first utility composables.
No stores. No external dependencies. SSR-safe. Fully typed.

GitHub npm version npm downloads Svelte 5 TypeScript


Features

โšก Svelte 5 Runes Built for $state, $derived, $effect โ€” no stores
๐ŸŒฒ Tree-shakable Import only what you use
๐Ÿ”’ Fully typed First-class TypeScript, no any
๐ŸŒ SSR safe All browser APIs are guarded
๐Ÿ“ฆ Zero deps No runtime dependencies
๐Ÿงน Auto cleanup Listeners removed on component destroy

Installation

npm install @ariefsn/svelte-use
# or
pnpm add @ariefsn/svelte-use
# or
bun add @ariefsn/svelte-use

Requires Svelte 5 as a peer dependency.


Utilities

Animation

Composable Description
useAnimate Reactive Web Animations API wrapper
useParallax Parallax effect based on pointer or device tilt
useTransition Animated numeric transitions with easing

Async

Composable Description
useFetch Reactive fetch with loading/error state
useWebSocket Reactive WebSocket with auto-reconnect

Time

Composable Description
useInterval Reactive interval counter
useIntervalFn Run a callback on an interval
useNow Reactive current Date
useTimeout Reactive timeout flag
useTimeoutFn Run a callback after a delay
useTimeoutPoll Poll a callback with timeout-based intervals
useTimestamp Reactive current timestamp (ms)

State

Composable Description
useToggle Reactive boolean toggle
useCounter Reactive counter with inc/dec/reset
usePrevious Track previous value of any reactive getter
useSorted Reactive sorted copy of an array
useCycleList Cycle through a list reactively
useCountdown Countdown timer with start/stop/reset
useTimeAgo Human-readable relative time string

Reactivity

Composable Description
useDebounce Debounce any reactive getter

Browser โ€“ Keyboard & Scroll

Composable Description
useMagicKeys Reactive keyboard state via Proxy โ€” single keys or combos
useKeyModifier Track Ctrl/Shift/Alt/Meta state
useScroll Scroll position, direction, edge arrival
useScrollLock Lock/unlock body scroll

Browser โ€“ Pointer & Drag

Composable Description
useMouse Viewport-relative pointer position
useMousePressed Detect mouse button press state
useDraggable Full-featured draggable with axis, bounds, handles

Browser โ€“ Observers

Composable Description
useElementSize Reactive element dimensions via ResizeObserver
useIntersectionObserver Visibility detection via IntersectionObserver
useResizeObserver Raw ResizeObserver with callback
useMutationObserver DOM mutation observation

Browser โ€“ Sensors

Composable Description
useIdle Detect user idle state
useNetwork Network Information API (downlink, RTT, effectiveType)
useGeolocation Reactive geolocation via watchPosition
useBreakpoints Reactive responsive breakpoints
useBrowserLocation Reactive browser location (URL, hash, search)
useNavigatorLanguage Reactive navigator language
useOnline Reactive online/offline status
usePageLeave Detect when user leaves the page

Browser โ€“ Storage

Composable Description
useLocalStorage Reactive localStorage with SSR safety
useIndexedDB Reactive IndexedDB with CRUD & querying
useBase64 Reactive Base64 encode/decode
useObjectUrl Reactive object URL from Blob/File
useSessionStorage Reactive sessionStorage with SSR safety

Browser โ€“ Interaction

Composable Description
useClickOutside Detect clicks outside an element
useDropZone Drag-and-drop zone with file/data support
useElementHover Detect hover state of an element
useFocus Reactive focus state of an element

Performance

Composable Description
useFps Reactive frames-per-second counter
useThrottleFn Throttle any function
useDebounceFn Debounce any function

Virtualization

Composable Description
useVirtualList Efficient virtual list rendering

Web APIs

Composable Description
useClipboard Reactive clipboard read/write
useBattery Reactive Battery Status API
useSpeechRecognition Reactive Web Speech Recognition API

Composable Reference

useToggle

Reactive boolean toggle.

import { useToggle } from '@ariefsn/svelte-use';

const { value, toggle, set } = useToggle();
// value โ†’ false
toggle(); // value โ†’ true
set(false); // value โ†’ false
Return Type Description
value boolean (reactive) Current boolean state
toggle () => void Flips the value
set (v: boolean) => void Sets the value explicitly

useCounter

Reactive counter with increment, decrement, and reset.

import { useCounter } from '@ariefsn/svelte-use';

const { value, inc, dec, reset } = useCounter(0);
inc(); // value โ†’ 1
inc(5); // value โ†’ 6
dec(3); // value โ†’ 3
reset(); // value โ†’ 0
Return Type Description
value number (reactive) Current counter value
inc (delta?: number) => void Increment by delta (default 1)
dec (delta?: number) => void Decrement by delta (default 1)
reset () => void Reset to initial value

usePrevious

Tracks the previous value of any reactive getter. Returns undefined until the tracked value changes for the first time.

import { usePrevious } from '@ariefsn/svelte-use';

let count = $state(0);
const prev = usePrevious(() => count);
// prev() โ†’ undefined
count = 1;
// prev() โ†’ 0
count = 2;
// prev() โ†’ 1
Parameter Type Description
getter () => T Reactive getter function to observe

Returns a () => T | undefined getter.


useDebounce

Delays a reactive value until the source stops changing for the specified duration.

import { useDebounce } from '@ariefsn/svelte-use';

let query = $state('');
const debounced = useDebounce(() => query, 500);
// debounced() updates only after 500 ms of inactivity
Parameter Type Default Description
getter () => T โ€” Reactive getter to debounce
delay number 300 Delay in milliseconds

Returns a () => T getter.


useLocalStorage

Reactive localStorage with SSR safety. Values are serialised with JSON.stringify / JSON.parse. Falls back to initial in non-browser environments or on parse errors.

import { useLocalStorage } from '@ariefsn/svelte-use';

const theme = useLocalStorage<'light' | 'dark'>('theme', 'light');
theme.set('dark'); // persists to localStorage
theme.value; // 'dark'
Parameter Type Description
key string localStorage key
initial T Fallback when key is absent or in SSR
Return Type Description
value T (reactive) Current stored value
set (v: T) => void Update and persist the value

useIndexedDB

Reactive IndexedDB utility with full CRUD, querying, and filtering. SSR-safe โ€” all operations are no-ops on the server. Values survive page refreshes and browser restarts.

import { useIndexedDB } from '@ariefsn/svelte-use';

interface Note {
    id?: number;
    text: string;
    done: boolean;
}

const db = useIndexedDB<Note>('my-app', 'notes');

// CRUD
await db.add({ text: 'Buy milk', done: false }); // returns generated key
await db.get(1); // Note | undefined
await db.getAll(); // Note[]
await db.update({ id: 1, text: 'Buy milk', done: true });
await db.remove(1);
await db.clear(); // delete all records

// Reactive state (updated automatically after every mutation)
db.items; // Note[]   โ€” all records
db.loading; // boolean
db.error; // Error | null

// Filtering
const pending = await db.query((n) => !n.done); // Note[]

Options

Parameter Type Default Description
dbName string โ€” IndexedDB database name
storeName string โ€” Object store name
options.version number 1 Schema version (increment to migrate)
options.keyPath string 'id' Primary key field name
options.autoIncrement boolean true Auto-generate numeric keys

Returns

Property / Method Type Description
items T[] (reactive) All stored records; refreshed after every mutation
loading boolean (reactive) true while an async operation is in flight
error Error | null (reactive) Last error, or null
add(record) Promise<IDBValidKey | undefined> Insert record; returns generated key
get(key) Promise<T | undefined> Fetch single record by primary key
getAll() Promise<T[]> Fetch all records and sync items
update(record) Promise<void> Replace record (must include key field)
remove(key) Promise<void> Delete record by primary key
query(filter) Promise<T[]> Return records matching a predicate (doesn't modify items)
clear() Promise<void> Delete all records

useSorted

Returns a reactive sorted copy of an array. Never mutates the source.

import { useSorted } from '@ariefsn/svelte-use';

let items = $state([3, 1, 4, 1, 5]);
const sorted = useSorted(() => items);
// sorted() โ†’ [1, 1, 3, 4, 5]

const desc = useSorted(
    () => items,
    (a, b) => b - a
);

useCycleList

Cycle through a list reactively. Wraps around at both ends.

import { useCycleList } from '@ariefsn/svelte-use';

const cycle = useCycleList(['light', 'dark', 'system']);
cycle.state(); // โ†’ 'light'
cycle.next(); // โ†’ 'dark'
cycle.prev(); // โ†’ 'light'
cycle.setIndex(2);

useCountdown

Countdown timer with start/stop/reset.

import { useCountdown } from '@ariefsn/svelte-use';

const timer = useCountdown(60); // 60s at 1s intervals
timer.start();
timer.count(); // โ†’ 60, 59, โ€ฆ, 0
timer.isActive(); // โ†’ true
timer.stop();
timer.reset();

useTimeAgo

Reactive human-readable relative time string.

import { useTimeAgo } from '@ariefsn/svelte-use';

const ago = useTimeAgo(() => new Date('2024-01-01'));
ago(); // โ†’ "1 year ago"

useMagicKeys

Track any key or combination via a Proxy.

import { useMagicKeys } from '@ariefsn/svelte-use';

const keys = useMagicKeys();
keys['ctrl+s'](); // โ†’ true while Ctrl+S is held
keys['shift'](); // โ†’ true while Shift is held

useKeyModifier

Track a specific modifier key state.

import { useKeyModifier } from '@ariefsn/svelte-use';

const ctrl = useKeyModifier('ctrl'); // 'ctrl' | 'shift' | 'alt' | 'meta'
ctrl(); // โ†’ true while Ctrl is held

useScroll

Scroll position, direction flags, edge detection for any scrollable element or window.

import { useScroll } from '@ariefsn/svelte-use';

const scroll = useScroll(); // window
const elScroll = useScroll(() => myEl, { offset: { bottom: 20 } });

scroll.y(); // โ†’ number
scroll.isScrolling(); // โ†’ boolean
scroll.arrivedState.bottom(); // โ†’ boolean
scroll.directions.down(); // โ†’ boolean
scroll.scrollTo({ top: 0 });

useMouse

Tracks viewport-relative pointer position.

import { useMouse } from '@ariefsn/svelte-use';

const mouse = useMouse();
mouse.x(); // โ†’ number
mouse.y(); // โ†’ number
mouse.sourceType(); // โ†’ 'mouse' | 'touch' | null

useMousePressed

Detects whether any mouse button is held.

import { useMousePressed } from '@ariefsn/svelte-use';

const pressed = useMousePressed();
pressed(); // โ†’ boolean

useDraggable

Full-featured draggable with axis constraints, bounds, handles, and callbacks.

import { useDraggable } from '@ariefsn/svelte-use';

const drag = useDraggable(() => el, {
    axis: 'x',
    initialValue: { x: 100, y: 100 },
    onEnd: (pos) => console.log(pos)
});

drag.x(); // โ†’ number
drag.isDragging(); // โ†’ boolean
drag.style(); // โ†’ "transform: translate(100px, 0px);"

useElementSize

Reactively tracks element dimensions via ResizeObserver.

import { useElementSize } from '@ariefsn/svelte-use';

const size = useElementSize(() => el);
size.width(); // โ†’ number
size.height(); // โ†’ number

useIntersectionObserver

Viewport visibility detection.

import { useIntersectionObserver } from '@ariefsn/svelte-use';

const { isIntersecting, stop } = useIntersectionObserver(() => el, { threshold: 0.5 });
isIntersecting(); // โ†’ boolean

useResizeObserver

Raw ResizeObserver wrapper with automatic cleanup.

import { useResizeObserver } from '@ariefsn/svelte-use';

const { stop } = useResizeObserver(
    () => el,
    (entry) => {
        console.log(entry.contentRect.width);
    }
);

useMutationObserver

Observes DOM mutations on any node.

import { useMutationObserver } from '@ariefsn/svelte-use';

const { stop } = useMutationObserver(
    () => el,
    (mutations) => {
        for (const m of mutations) console.log(m.type);
    },
    { childList: true, subtree: true }
);

useIdle

Detect user inactivity.

import { useIdle } from '@ariefsn/svelte-use';

const { isIdle, reset } = useIdle(5000); // idle after 5s
isIdle(); // โ†’ boolean

useNetwork

Reactive Network Information API.

import { useNetwork } from '@ariefsn/svelte-use';

const net = useNetwork();
net.effectiveType(); // โ†’ '4g' | '3g' | undefined
net.downlink(); // โ†’ Mbps | undefined
net.saveData(); // โ†’ boolean | undefined

useGeolocation

Reactive geolocation via watchPosition.

import { useGeolocation } from '@ariefsn/svelte-use';

const geo = useGeolocation({ enableHighAccuracy: true });
geo.coords()?.latitude; // โ†’ number | null
geo.error(); // โ†’ GeolocationPositionError | null
geo.isSupported(); // โ†’ boolean

useFetch

Reactive fetch wrapper with loading/error state.

import { useFetch } from '@ariefsn/svelte-use';

const { data, loading, error, execute } = useFetch<User[]>('/api/users');
// data() โ†’ User[] | null
// loading() โ†’ boolean
// error() โ†’ Error | null

useWebSocket

Reactive WebSocket with auto-reconnect.

import { useWebSocket } from '@ariefsn/svelte-use';

const ws = useWebSocket('wss://echo.example.com');
ws.send('hello');
ws.data(); // โ†’ last received message
ws.status(); // โ†’ 'OPEN' | 'CLOSED' | 'CONNECTING'

useAnimate

Reactive Web Animations API wrapper.

import { useAnimate } from '@ariefsn/svelte-use';

const { animate, stop } = useAnimate(() => el);
animate([{ opacity: 0 }, { opacity: 1 }], { duration: 300 });

useParallax

Parallax effect based on pointer position or device tilt.

import { useParallax } from '@ariefsn/svelte-use';

const { tilt, roll } = useParallax(() => containerEl);
// tilt() โ†’ number  (โˆ’0.5 to 0.5)
// roll() โ†’ number  (โˆ’0.5 to 0.5)

useTransition

Animated numeric transitions with easing.

import { useTransition } from '@ariefsn/svelte-use';

let target = $state(0);
const animated = useTransition(() => target, { duration: 500 });
// animated() smoothly interpolates to target

useInterval

Reactive interval counter.

import { useInterval } from '@ariefsn/svelte-use';

const { counter, pause, resume } = useInterval(1000);
counter(); // โ†’ increments every second

useNow

Reactive current Date.

import { useNow } from '@ariefsn/svelte-use';

const now = useNow();
now(); // โ†’ Date (updated every second by default)

useTimestamp

Reactive current timestamp in milliseconds.

import { useTimestamp } from '@ariefsn/svelte-use';

const ts = useTimestamp();
ts(); // โ†’ number (ms since epoch)

useBreakpoints

Reactive responsive breakpoints.

import { useBreakpoints } from '@ariefsn/svelte-use';

const bp = useBreakpoints({ sm: 640, md: 768, lg: 1024 });
bp.lg(); // โ†’ true if viewport โ‰ฅ 1024px
bp.between('sm', 'lg')(); // โ†’ boolean

useClipboard

Reactive clipboard read/write.

import { useClipboard } from '@ariefsn/svelte-use';

const { text, copy, copied } = useClipboard();
copy('Hello!');
copied(); // โ†’ true for 1.5s after copy

useBattery

Reactive Battery Status API.

import { useBattery } from '@ariefsn/svelte-use';

const battery = useBattery();
battery.level(); // โ†’ 0โ€“1
battery.charging(); // โ†’ boolean

useVirtualList

Efficient virtual list rendering for large datasets.

import { useVirtualList } from '@ariefsn/svelte-use';

const { list, containerProps, wrapperProps } = useVirtualList(items, { itemHeight: 40 });
// list() โ†’ only the visible slice of items

Developing

bun install
bun run dev

To run tests:

bun run test

Building & Publishing

# build the library
bun run build

# publish to npm
npm publish --access public

License

MIT

Top categories

Loading Svelte Themes