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 80+ 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
useAsyncState Reactive async/promise state with loading/error

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
useAutoResetState State that auto-resets to default after delay
useDefaultState State with fallback for null/undefined
useLastChanged Timestamp of last reactive value change
useTrackHistory Undo/redo history for reactive values
useHistoryState State with built-in undo/redo history

Reactivity

Composable Description
useDebounce Debounce any reactive getter
useWatch Watch reactive values with current/previous args
useWhenever Watch that fires only when value becomes truthy

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
useDocumentVisibility Reactive document visibility state
useWindowFocus Track whether browser window is focused
useDeviceMotion Device acceleration and rotation data
useDeviceOrientation Device physical orientation (alpha/beta/gamma)
useDevicePixelRatio Reactive device pixel ratio for Retina detection
useScrollbarWidth Measure scrollbar width of an element

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
useActiveElement Track currently focused element globally
useLongPress Long press gesture detection
useStartTyping Detect typing on non-editable elements
useSwipe Touch swipe gesture detection

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
useEyeDropper EyeDropper API for color picking
useFileDialog Programmatic file input dialog
useShare Native Web Share API
useVibrate Vibration API
useWebNotification Desktop notifications API
usePermission Browser Permissions API
useWakeLock Screen Wake Lock API
useEventListener Generic event listener with cleanup
useTextDirection Track/set text directionality
useTextSelection Track text selection

Browser โ€“ Navigation

Composable Description
useNavigationGuard SvelteKit navigation guard with confirm/cancel

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