A collection of 38+ zero-dependency hooks for SolidJS forked directly from Mantine Hooks, with some improvements.
import { useCounter } from 'bagon-hooks'; export function UseCounterExample() { const [count, { decrement, increment, reset, set }] = useCounter(5, { min: 1, max: 10 }); return ( <div class="flex h-full w-full flex-col items-center justify-center gap-5 gap-x-1 rounded-md border p-3 py-10 text-center"> <span>{count()}</span> <div class="flex gap-x-2 text-sm"> <button class="rounded-md border p-1 px-1.5 transition active:scale-90" onClick={decrement}> - </button> <button class="rounded-md border p-1 px-1.5 transition active:scale-90" onClick={increment}> + </button> <button class="rounded-md border p-1 px-1.5 transition active:scale-90" onClick={reset}> Reset </button> <button class="rounded-md border p-1 px-1.5 transition active:scale-90" onClick={() => set(Math.floor(Math.random() * 10))} > Set (To Random) </button> </div> </div> ); }
import { useOs } from 'bagon-hooks'; export function UseOsExample() { const os = useOs(); return ( <div class="flex h-full w-full items-center justify-center rounded-md border p-3 py-10 text-center"> Current OS: {os()} </div> ); }
import { useClickOutside } from 'bagon-hooks'; import { createSignal, Show } from 'solid-js'; export function UseClickOutsideExample() { const ref = useClickOutside(() => { setClicked(true); setTimeout(() => { setClicked(false); }, 500); }); const [clicked, setClicked] = createSignal(false); return ( <div class="flex h-full w-full flex-1 items-center justify-center rounded-md border p-3 py-10"> <div class={`select-none rounded-full border bg-neutral-50 p-2 text-xs transition ${clicked() ? 'scale-95' : ''}`} ref={ref} > <Show when={clicked()} fallback={'No detections'}> You clicked outside! </Show> </div> </div> ); }
import { useHotkeys, useOs } from 'bagon-hooks'; import { createSignal, FlowProps, VoidProps } from 'solid-js'; export function UseHotkeysExample() { const [activatedHotkey, setActivatedHotkey] = createSignal<-1 | 0 | 1 | 2>(-1); let timeout: ReturnType<typeof window.setTimeout>; function handleKeyPress(index: ReturnType<typeof activatedHotkey>) { if (timeout) clearTimeout(timeout); setActivatedHotkey(index); timeout = setTimeout(() => { setActivatedHotkey(-1); }, 400); } useHotkeys([ ['mod+a', () => handleKeyPress(0)], ['mod+Enter', () => handleKeyPress(1)], ['shift+g', () => handleKeyPress(2)], ]); const os = useOs(); return ( <div class="flex h-full w-full flex-wrap items-center justify-center gap-3 rounded-md border p-3 py-10 text-center"> <Key activated={activatedHotkey() === 0}>{os() === 'macos' ? 'cmd' : 'ctrl'} + a</Key> <Key activated={activatedHotkey() === 1}>{os() === 'macos' ? 'cmd' : 'ctrl'} + Enter</Key> <Key activated={activatedHotkey() === 2}>shift + g</Key> </div> ); } function Key(props: FlowProps<{ activated: boolean }>) { return ( <div class="relative text-xs"> <div class="absolute inset-0 rounded-md bg-neutral-200 transition"></div> <div class="relative transform rounded-md border bg-neutral-50 px-2 py-1.5 transition-transform" style={{ transform: props.activated ? 'translateY(0px)' : 'translateY(-5px)', }} > {props.children} </div> </div> ); }
import { useKeyboard } from 'bagon-hooks'; import { createStore } from 'solid-js/store'; export function UseKeyboardExample() { const [store, setStore] = createStore({ a: false, b: false, c: false, d: false }); useKeyboard({ onKeyDown(event) { // Refactor this into if statements. if (event.key === 'a') { setStore('a', true); } else if (event.key === 'b') { setStore('b', true); } else if (event.key === 'c') { setStore('c', true); } else if (event.key === 'd') { setStore('d', true); } }, onKeyUp(event) { // Refactor this into if statements. if (event.key === 'a') { setStore('a', false); } else if (event.key === 'b') { setStore('b', false); } else if (event.key === 'c') { setStore('c', false); } else if (event.key === 'd') { setStore('d', false); } }, }); return ( <div class="flex h-full w-full items-center justify-center gap-x-1 rounded-md border p-3 py-10 text-center"> <Kbd activated={store.a}>a</Kbd> <Kbd activated={store.b}>b</Kbd> <Kbd activated={store.c}>c</Kbd> <Kbd activated={store.d}>d</Kbd> </div> ); }
import { useClickOutside, useHover } from 'bagon-hooks'; import { createSignal, Show } from 'solid-js'; export function UseHoverExample() { const { ref, hovered } = useHover(); return ( <div class="flex h-full w-full flex-1 items-center justify-center rounded-md border p-3 py-10"> <div class={`cursor-pointer select-none rounded-full border bg-neutral-50 p-2 text-xs transition ${hovered() ? 'scale-95' : ''}`} ref={ref} > <Show when={hovered()} fallback={'No detections'}> You hovered me! </Show> </div> </div> ); }
import { useIdle, useOs } from 'bagon-hooks'; import { Show } from 'solid-js'; export function UseIdleExample() { const idle = useIdle(1000); return ( <div class="flex h-full w-full items-center justify-center gap-x-1 rounded-md border p-3 py-10 text-center"> <span>Is Idle (1s):</span> <Show when={idle()} fallback={ <span> <span class="text-green-500">false</span> </span> } > <span class="text-red-500">true</span> </Show> </div> ); }
import { useId } from 'bagon-hooks'; export function UseIdExample() { const id = useId(); return ( <div class="flex h-full w-full items-center justify-center gap-x-1 rounded-md border p-3 py-10 text-center text-sm"> Random ID: <span class="rounded-md bg-neutral-300 px-1.5 py-0.5">{id()}</span> </div> ); }
import { useIdle, useMounted, useOs } from 'bagon-hooks'; import { Show } from 'solid-js'; export function UseMountedExample() { const mounted = useMounted(); return ( <div class="flex h-full w-full items-center justify-center gap-x-1 rounded-md border p-3 py-10 text-center"> <Show when={mounted()}>This only shows on the client.</Show> </div> ); }
{ "online": true }
import { useIdle, useNetwork, useOs } from 'bagon-hooks'; export function UseNetworkExample() { const networkStatus = useNetwork(); return ( <div class="flex h-full w-full items-center justify-center gap-x-1 rounded-md border p-3 py-10 text-start"> <pre class={`rounded-md border p-3 px-5 ${networkStatus().online ? 'bg-neutral-100' : 'border-red-500 bg-red-200'}`} > {JSON.stringify(networkStatus(), null, 2)} </pre> </div> ); }
{ "rect": { "x": 0, "y": 0, "width": 0, "height": 0, "top": 0, "left": 0, "bottom": 0, "right": 0 } }
import { useIdle, useNetwork, useOs, useResizeObserver } from 'bagon-hooks'; export function UseResizeObserverExample() { const [ref, rectStore] = useResizeObserver(); return ( <div class="flex h-full w-full items-center justify-center gap-x-3 rounded-md border p-3 py-10 text-start"> <pre class={`rounded-md border bg-neutral-100 p-3 px-5 text-xs`}> {JSON.stringify(rectStore, null, 2)} </pre> <div class="relative grid place-items-center overflow-hidden"> <textarea ref={ref} class="h-20 w-20 resize rounded-md border"></textarea> <div class="pointer-events-none absolute inset-0 grid place-items-center truncate text-xs text-neutral-400"> Resize Me </div> </div> </div> ); }
import { useElementSize, useIdle, useNetwork, useOs, useResizeObserver } from 'bagon-hooks'; export function UseElementSizeExample() { const { ref, height, width } = useElementSize(); return ( <div class="flex h-full w-full flex-col items-center justify-center gap-3 rounded-md border p-3 py-10 text-start"> <div class="flex flex-col items-center"> <span>Width: {width().toFixed(2)}</span> <span>Height: {height().toFixed(2)}</span> </div> <div class="relative grid flex-1 place-items-center overflow-hidden"> <textarea ref={ref} class="h-20 w-20 resize rounded-md border"></textarea> <div class="pointer-events-none absolute inset-0 grid place-items-center truncate text-center text-xs text-neutral-400"> Resize Me </div> </div> </div> ); }
import { useToggle } from 'bagon-hooks'; import { createMemo, FlowProps } from 'solid-js'; export function UseToggleExample() { const [value, toggle] = useToggle(['apple', 'orange', 'grape', 'kiwi'] as const); const color = createMemo(() => { if (value() === 'apple') return '#e5312f'; if (value() === 'orange') return '#fc8627'; if (value() === 'grape') return '#bc3d73'; if (value() === 'kiwi') return '#acc144'; return undefined; }); return ( <div class="flex h-full w-full flex-col items-center justify-center gap-3 rounded-md border p-3 py-10 text-center transition-colors" style={{ 'background-color': color(), }} > <div class="flex flex-wrap gap-3"> <Key activated={value() === 'apple'}>🍎 apple</Key> <Key activated={value() === 'orange'}>🍊 orange</Key> <Key activated={value() === 'grape'}>🍇 grape</Key> <Key activated={value() === 'kiwi'}>🥝 kiwi </Key> </div> <button onClick={() => toggle()} class="text-white transition active:scale-95"> Click me to Toggle </button> </div> ); } function Key(props: FlowProps<{ activated: boolean }>) { return ( <div class="relative text-xs"> <div class="absolute inset-0 rounded-md bg-neutral-200 transition"></div> <div class="relative transform rounded-md border bg-neutral-50 px-2 py-1.5 transition-transform" style={{ transform: props.activated ? 'translateY(0px)' : 'translateY(-5px)', }} > {props.children} </div> </div> ); }
import { useFavicon } from 'bagon-hooks'; import { createSignal } from 'solid-js'; /** Improved Bagon implementation - You can choose to set it when you want. */ export function UseFaviconExample() { const [_favicon, setFavicon] = useFavicon(); // The secret is: just don't pass an accessor in the hook. const setXFavicon = () => { setCurrentIcon('x'); setFavicon('https://x.com/favicon.ico'); }; const setSolidFavicon = () => { setCurrentIcon('solid'); setFavicon('https://docs.solidjs.com/favicon.svg'); }; return ( <div class="relative flex h-full w-full flex-col items-center justify-center gap-3 overflow-hidden rounded-md border p-3 py-10 text-center text-sm"> <IconSolidJS class="absolute -bottom-10 -right-10 h-48 w-48 rotate-45 transition" style={{ opacity: currentIcon() === 'solid' ? 1 : 0 }} /> <IconX class="absolute -bottom-10 -right-10 h-48 w-48 rotate-45 transition" style={{ opacity: currentIcon() === 'x' ? 1 : 0 }} /> <button onClick={() => { setXFavicon(); }} class="relative rounded-md border bg-white px-2 py-1.5 transition active:scale-95" > X favicon </button> <button onClick={() => { setSolidFavicon(); }} class="relative rounded-md border bg-white px-2 py-1.5 transition active:scale-95" > Solid favicon </button> </div> ); } /** Based on Mantine's implementation - it always runs onMount. */ export function UseFaviconExampleMantine() { const [favicon, setFavicon] = createSignal('https://docs.solidjs.com/favicon.svg'); const setXFavicon = () => setFavicon('https://x.com/favicon.ico'); const setSolidFavicon = () => setFavicon('https://docs.solidjs.com/favicon.svg'); useFavicon(favicon); // Will always run at the start. return ( <> <button onClick={setXFavicon}>Use X Favicon</button> <button onClick={setSolidFavicon}>Use SolidJS Favicon</button> </> ); }
import { useLocalStorage } from 'bagon-hooks'; import { FlowProps } from 'solid-js'; export function UseLocalStorageExample() { const [value, setValue] = useLocalStorage({ key: 'favorite-fruit', defaultValue: 'apple', }); return ( <div class="flex h-full w-full flex-col items-center justify-center gap-3 rounded-md border p-3 py-10 text-center transition-colors"> <div class="flex flex-wrap gap-3"> <Key activated={value() === 'apple'} onClick={() => setValue('apple')}> 🍎 apple </Key> <Key activated={value() === 'orange'} onClick={() => setValue('orange')}> 🍊 orange </Key> <Key activated={value() === 'grape'} onClick={() => setValue('grape')}> 🍇 grape </Key> <Key activated={value() === 'kiwi'} onClick={() => setValue('kiwi')}> 🥝 kiwi{' '} </Key> </div> <span class="text-sm text-neutral-500">Favorite Fruit: {value()}</span> </div> ); } function Key(props: FlowProps<{ activated: boolean; onClick: () => void }>) { return ( <button onClick={props.onClick} class="relative text-xs"> <div class="absolute inset-0 rounded-md bg-neutral-200 transition" /> <div class="relative transform rounded-md border bg-neutral-50 px-2 py-1.5 transition-transform" style={{ transform: props.activated ? 'translateY(0px)' : 'translateY(-5px)', }} > {props.children} </div> </button> ); }
import { useLocalStorageStore } from 'bagon-hooks'; import { For } from 'solid-js'; import { produce } from 'solid-js/store'; export function UseLocalStorageStoreExample() { const [value, setValue] = useLocalStorageStore<{ id: string; name: string }[]>({ key: 'todos-store', defaultValue: [], }); return ( <div class="flex h-full w-full flex-col items-center justify-center gap-3 rounded-md border p-3 py-10 text-center transition-colors"> <For each={value}> {(todo, index) => ( <div class="flex flex-wrap items-center gap-1 text-sm"> <input class="rounded-md border p-1" value={todo.name} onInput={event => { setValue( produce(_value => { if (!_value[index()]) return; _value[index()]!.name = event.target.value ?? ''; }), ); }} /> <button onClick={() => { setValue( produce(_value => { _value.splice(index(), 1); }), ); }} > <IconClose width={18} height={18} /> </button> </div> )} </For> <button class={`rounded-md bg-primary px-3 py-1.5 text-white transition active:scale-95`} onClick={() => { setValue( produce(_value => { _value.push({ id: Math.random().toString(), name: 'New Todo' }); }), ); }} > New Todo </button> </div> ); }
import { useEyeDropper } from 'bagon-hooks'; import { Show } from 'solid-js'; export function UseEyeDropperExample() { const { color, supported, pickColor } = useEyeDropper(); return ( <div class="flex h-full w-full flex-col items-center justify-center gap-5 rounded-md border p-3 py-10 text-center"> <div class="flex items-center gap-x-2"> <button class="transition active:scale-95" onClick={pickColor} disabled={!supported()}> <IconEyeDropper /> </button> <div class="flex items-center gap-x-2 text-sm"> Picked Color: {color()} <div class="h-8 w-8 rounded-full border" style={{ 'background-color': color() }} /> </div> </div> <Show when={supported() !== undefined && !supported()}> <span class="text-xs text-red-500">Your browser does not support EyeDropper.</span> </Show> </div> ); }
import { useFullscreen } from 'bagon-hooks'; import { Show } from 'solid-js'; export function UseFullScreenExample() { const { fullscreen, toggle } = useFullscreen(); return ( <div class="flex h-full w-full items-center justify-center gap-x-1 rounded-md border p-3 py-10 text-center"> <button class={`rounded-md px-3 py-1.5 text-white transition active:scale-95 ${fullscreen() ? 'bg-red-500' : 'bg-primary'}`} onClick={toggle} > <Show when={fullscreen()} children={'Exit Fullscreen'} fallback={'Enter Fullscreen'} /> </button> </div> ); }
import { randomId, useHash } from 'bagon-hooks'; export function UseHashExample() { const [hash, setHash] = useHash(); return ( <div class="flex h-full w-full flex-col items-center justify-center gap-3 rounded-md border p-3 py-10 text-center"> <button class="rounded-md border px-3 py-1.5 text-sm text-typography transition active:scale-95" onClick={() => setHash(randomId())} > Set hash </button> <span class="flex gap-x-1 text-sm"> Current hash: <code class="rounded-md bg-neutral-300 px-1.5 py-0.5">{hash()}</code> </span> </div> ); }
import { useClipboard } from 'bagon-hooks'; import { Show } from 'solid-js'; export function UseClipboardExample() { const { copied, copy, reset } = useClipboard(); return ( <div class="flex h-full w-full flex-col items-center justify-center gap-3 rounded-md border p-3 py-10 text-center text-sm"> <span class="text-center">Bagon is awesome!</span> <button class="transition active:scale-90" onClick={() => copy('Bagon is awesome!')}> <Show when={copied()} fallback={ <div class="flex items-center gap-x-1"> <IconCopy class="h-8 w-8" /> Copy </div> } children={ <div class="flex items-center gap-x-1 text-green-500"> <IconCheck class="h-8 w-8" /> Copied! </div> } /> </button> </div> ); }
{ "angle": 0, "type": "landscape-primary" }
import { useOrientation } from 'bagon-hooks'; export function UseOrientationExample() { const orientation = useOrientation(); return ( <div class="flex h-full w-full items-center justify-center gap-x-1 rounded-md border p-3 py-10 text-center text-sm"> <pre class={`rounded-md border bg-neutral-100 p-3 px-5 text-start text-xs`}> {JSON.stringify(orientation(), null, 2)} </pre> </div> ); }
import { useMediaQuery } from 'bagon-hooks'; import { Match, Switch } from 'solid-js'; export function UseMediaQueryExample() { const sm = useMediaQuery(() => '(min-width: 640px)'); const md = useMediaQuery(() => '(min-width: 768px)'); const lg = useMediaQuery(() => '(min-width: 1024px)'); const xl = useMediaQuery(() => '(min-width: 1280px)'); const xxl = useMediaQuery(() => '(min-width: 1536px)'); return ( <div class="flex h-full w-full flex-col items-center justify-center gap-x-1 rounded-md border p-3 py-10 text-center text-sm"> <Switch fallback="No match"> <Match when={xxl()}>2xl: (min-width: 1536px)</Match> <Match when={xl()}>xl: (min-width: 1280px)</Match> <Match when={lg()}>lg: (min-width: 1024px)</Match> <Match when={md()}>md: (min-width: 768px)</Match> <Match when={sm()}>sm: (min-width: 640px)</Match> </Switch> </div> ); }
{"x":0,"y":0}
import { useMouse } from 'bagon-hooks'; export function UseMouseExample() { const { ref, position } = useMouse(); return ( <div class="flex h-full w-full flex-col items-center justify-center gap-4 gap-x-1 rounded-md border p-3 py-10 text-center text-sm"> <div ref={ref} class="flex h-40 w-40 items-center justify-center rounded border bg-neutral-100 text-sm" > Track Here </div> Mouse coordinates{' '} <code class="rounded-md bg-neutral-300 px-1.5 py-0.5">{JSON.stringify(position())}</code> </div> ); }
{"x":"0.50","y":"0.50"}
import { useMove } from 'bagon-hooks'; import { createSignal } from 'solid-js'; export function UseMoveExample() { const [value, setValue] = createSignal({ x: 0.5, y: 0.5 }); const { ref, active } = useMove(({ x, y }) => { setValue({ x, y }); }, {}); return ( <div class="flex h-full w-full flex-col items-center justify-center gap-x-1 gap-y-3 rounded-md border p-3 py-10 text-center"> <div ref={ref} class="h-40 w-full rounded bg-blue-400/50" style={{ position: 'relative', }} > <div style={{ position: 'absolute', left: `calc(${value().x * 100}% - ${8}px)`, top: `calc(${value().y * 100}% - ${8}px)`, width: '16px', height: '16px', 'background-color': active() ? '#22c55e' : '#3b82f6', }} /> </div> <div class="flex justify-center"> Values:{' '} <code class="rounded-md bg-neutral-300 px-1.5 py-0.5"> {JSON.stringify({ x: value().x.toFixed(2), y: value().y.toFixed(2), })} </code> </div> </div> ); }
import { useDebouncedSignal } from 'bagon-hooks'; export function UseDebouncedSignalExample() { const [signal, setSignal] = useDebouncedSignal('', 500); return ( <div class="flex h-full w-full flex-col items-center justify-center gap-x-1 gap-y-2 rounded-md border p-3 py-10 text-center text-sm"> <input value={signal()} onInput={e => setSignal(e.currentTarget.value)} class="rounded-md border p-2" /> <span>State: {JSON.stringify(signal())}</span> </div> ); }
import { useDebouncedValue } from 'bagon-hooks'; import { createSignal } from 'solid-js'; export function UseDebouncedValueExample() { const [signal, setSignal] = createSignal(''); const [value, cancel] = useDebouncedValue(signal, 500); return ( <div class="flex h-full w-full flex-col items-center justify-center gap-x-1 gap-y-2 rounded-md border p-3 py-10 text-center text-sm"> <input value={signal()} onInput={e => setSignal(e.currentTarget.value)} class="rounded-md border p-2" /> <div class="flex items-center gap-x-2"> <span>State: {JSON.stringify(signal())}</span> <span>|</span> <span>Value: {JSON.stringify(value())}</span> </div> </div> ); }
import { useDocumentVisibility } from 'bagon-hooks'; export function UseDocumentVisibilityExample() { const visible = useDocumentVisibility(); return ( <div class="flex h-full w-full items-center justify-center gap-x-1 rounded-md border p-3 py-10 text-center text-sm"> <div class="flex items-center gap-x-1"> <div class="h-2 w-2 rounded-full" /> Tab is currently {visible()} </div> </div> ); }
import { useIntersection } from 'bagon-hooks'; import { Show } from 'solid-js'; export function UseIntersectionExample() { const { ref, entry } = useIntersection({ threshold: 0.75, // At least 75% of the element must "intersect" with the viewport }); return ( <div class="relative flex h-full min-h-32 w-full items-center justify-center gap-x-1 overflow-y-scroll rounded-md border p-3 text-center text-sm"> <div class="relative top-[calc(60%)] pb-5"> <div ref={ref} class={`rounded-md p-5 text-white ${entry()?.isIntersecting ? 'bg-green-500' : 'bg-red-500'}`} > <Show when={entry()?.isIntersecting} children={<>Fully Intersecting</>} fallback={<>Obscured</>} /> </div> </div> </div> ); }
import { useInViewport } from 'bagon-hooks'; import { Show } from 'solid-js'; export function UseInViewportExample() { const { ref, inViewport } = useInViewport(); return ( <div class="relative flex h-full min-h-32 w-full flex-col items-center justify-center gap-x-1 overflow-y-scroll rounded-md border p-3 text-center text-sm"> <div class="sticky left-0 right-0 top-0 text-center"> <Show when={inViewport()} fallback={<>Scroll to See Box</>} children={<>Box is visible</>} /> </div> <div class="relative top-[calc(60%)] pb-5 pt-20"> <div ref={ref} class={`rounded-md p-5 text-white ${inViewport() ? 'bg-green-500' : 'bg-red-500'}`} > <Show when={inViewport()} children={<>Fully Intersecting</>} fallback={<>Obscured</>} /> </div> </div> </div> ); }
{"input":"","checkbox":false}
import { useInputState } from 'bagon-hooks'; export function UseInputStateExample() { const [input, handleInput] = useInputState(''); const [checkbox, handleCheckbox] = useInputState(false); return ( <div class="flex h-full w-full flex-col items-center justify-center gap-x-1 gap-y-2 rounded-md border p-3 py-10 text-center text-sm"> <pre class="rounded bg-neutral-200 p-1 text-xs"> {JSON.stringify({ input: input(), checkbox: checkbox(), })} </pre> <input value={input()} onInput={handleInput} class="rounded-md border p-2" /> <input type="checkbox" checked={checkbox()} onChange={handleCheckbox} class="rounded-md border p-2" /> </div> ); }
import { useDebouncedCallback } from 'bagon-hooks'; import { createSignal, For, JSX, Show } from 'solid-js'; function getSearchResults(query: string): Promise<{ id: number; title: string }[]> { return new Promise(resolve => { setTimeout(() => { resolve( query.trim() === '' ? [] : Array(5) .fill(0) .map((_, index) => ({ id: index, title: `${query} ${index + 1}` })), ); }, 1000); }); } export function UseDebouncedCallbackExample() { const [search, setSearch] = createSignal(''); const [searchResults, setSearchResults] = createSignal<{ id: number; title: string }[]>([]); const [loading, setLoading] = createSignal(false); const debouncedSearch = useDebouncedCallback(async (query: string) => { setLoading(true); setSearchResults(await getSearchResults(query)); setLoading(false); }, 500); const handleInput: JSX.EventHandler<HTMLInputElement, InputEvent> = event => { setSearch(event.currentTarget.value); debouncedSearch(event.currentTarget.value); }; return ( <div class="flex h-full w-full flex-col items-center justify-center gap-x-1 gap-y-2 rounded-md border p-3 py-10 text-center text-sm"> <input value={search()} onInput={handleInput} class="rounded-md border p-2" placeholder="Search..." /> <Show when={loading()} children={<>Loading...</>} fallback={ <For each={searchResults()}>{result => <div class="text-xs">{result.title}</div>}</For> } /> </div> ); }
This logs "Did Update X" to the console. Notice that it doesn't log "Did Update 0" since it happens on mount.
import { useDidUpdate } from 'bagon-hooks'; import { createSignal } from 'solid-js'; export function UseDidUpdateExample() { const [signal, setSignal] = createSignal(0); useDidUpdate(() => { console.log('Did Update', signal()); }, signal); return ( <div class="flex h-full w-full flex-col items-center justify-center gap-x-1 gap-y-2 rounded-md border p-3 py-10 text-center text-sm"> <p class="max-w-xs text-center text-xs"> This logs "Did Update {signal() === 0 ? 'X' : signal()}" to the console. Notice that it doesn't log "Did Update 0" since it happens on mount. </p> <button class="rounded-md bg-primary p-2 text-white transition active:scale-95" onClick={() => { setSignal(signal() + 1); }} > Simulate an Update {signal()} </button> </div> ); }
import { useColorScheme } from 'bagon-hooks'; export function UseColorSchemeExample() { const colorScheme = useColorScheme(); return ( <div class="flex h-full w-full items-center justify-center gap-x-1 rounded-md border p-3 py-10 text-center text-sm"> <div class="rounded-md border px-4 py-2 text-sm" style={{ background: colorScheme() === 'dark' ? '#000' : '#fff', color: colorScheme() ? '#fff' : '#000', }} > Your system color scheme is: {colorScheme()} </div> </div> ); }
import { useDocumentTitle, useToggle } from 'bagon-hooks'; export function UseDocumentTitleExample() { const [title, setTitle] = useDocumentTitle(); const [_, cycle] = useToggle(['Home', 'About', 'Awesome']); function _cycle() { cycle(); setTitle(_() as any); } return ( <div class="flex h-full w-full flex-col items-center justify-center gap-x-1 rounded-md border p-3 py-10 text-center text-sm"> <div class="flex flex-col items-center gap-y-7"> <div class="flex items-center gap-x-2"> <Kbd activated={title() === 'Home'}>Home</Kbd> <Kbd activated={title() === 'About'}>About</Kbd> <Kbd activated={title() === 'Awesome'}>Awesome</Kbd> </div> <button onClick={_cycle}>Toggle</button> </div> </div> ); }
import { useDisclosure } from 'bagon-hooks'; import { Show } from 'solid-js'; export function UseDisclosureExample() { const [opened, handlers] = useDisclosure(false); return ( <div class="flex h-full w-full items-center justify-center gap-x-1 rounded-md border p-3 py-10 text-center text-sm"> <button onClick={handlers.open} class="rounded bg-blue-500 px-4 py-2 text-white"> Open Dialog </button> <Show when={opened()}> <div class="fixed inset-0 flex items-center justify-center bg-black bg-opacity-50"> <div class="rounded-lg bg-white p-6 shadow-lg"> <h2 class="mb-4 text-lg font-bold">Dialog Title</h2> <p class="mb-4">This is an example dialog using useDisclosure</p> <button onClick={handlers.close} class="rounded bg-gray-500 px-4 py-2 text-white"> Close </button> </div> </div> </Show> </div> ); }
import { useDisclosureData } from 'bagon-hooks'; import { For, Show } from 'solid-js'; export function UseDisclosureDataExample() { const items = [ { id: '1', title: 'Item 1' }, { id: '2', title: 'Item 2' }, ]; // If you have multiple modals, // I recommend prefixing `data`, `open`, `handlers` with the same name. // i.e. editModalData, editModalOpen, editModalHandlers const [data, open, handlers] = useDisclosureData<(typeof items)[number]>(null); return ( <div class="flex h-full w-full items-center justify-center gap-x-1 rounded-md border p-3 py-10 text-center text-sm"> <ul class="flex flex-col gap-2"> <For each={items}> {item => ( <li> <button onClick={() => { handlers.open(item); }} class="rounded bg-blue-500 px-4 py-2 text-white" > Open Dialog for {item.title} </button> </li> )} </For> </ul> <Show when={open()}> <div class="fixed inset-0 flex items-center justify-center bg-black bg-opacity-50"> <div class="rounded-lg bg-white p-6 shadow-lg"> <h2 class="mb-4 text-lg font-bold">{data()?.title || 'Dialog Title'}</h2> <p class="mb-4">This is an example dialog using useDisclosure and data: {data()?.id}</p> <button onClick={handlers.close} class="rounded bg-gray-500 px-4 py-2 text-white"> Close </button> </div> </div> </Show> </div> ); }
You: not awesome
You will become Awesome in 1 second after pressing 'Start'. You can also cancel.
import { useTimeout } from 'bagon-hooks'; import { createSignal } from 'solid-js'; export function UseTimeoutExample() { const [awesomeState, setAwesomeState] = createSignal('not awesome'); const { start, clear } = useTimeout(() => { setAwesomeState('awesome'); }, 1000); return ( <div class="flex h-full w-full flex-col items-center justify-center gap-x-3 gap-y-3 rounded-md border p-3 py-10 text-center"> <p class="text-xl font-medium">You: {awesomeState()}</p> <p class="max-w-xs text-sm"> You will become <b>Awesome</b> in 1 second after pressing 'Start'. You can also cancel. </p> <div class="flex gap-4"> <button class={`w-20 rounded-md bg-primary px-3 py-1.5 text-white transition active:scale-95`} onClick={() => { start(1000); }} > Start </button> <button class="w-20 rounded-md bg-gray-400 px-3 py-1.5 text-white transition active:scale-95" onClick={() => { clear(); setAwesomeState('not awesome'); }} > Cancel </button> </div> </div> ); }
Page loaded 0 seconds ago.
import { useInterval } from 'bagon-hooks'; import { createSignal } from 'solid-js'; export function UseIntervalExample() { const [seconds, setSeconds] = createSignal(0); const interval = useInterval( () => { setSeconds(s => s + 1); }, 1000, { autoInvoke: true }, ); return ( <div class="flex h-full w-full flex-col items-center justify-center gap-x-3 gap-y-3 rounded-md border p-3 py-10 text-center"> <p class="text-xl font-medium">Page loaded {seconds()} seconds ago.</p> <button class={`rounded-md ${ !interval.active() ? 'bg-primary' : 'bg-red-500' } px-3 py-1.5 text-white transition active:scale-95`} onClick={interval.toggle} > {interval.active() ? 'Stop' : 'Start'} counting </button> </div> ); }