Skip to content

Demos

// Turn any hook into a ✨ nook ✨
const mountInterval = nook(useInterval);
function GranularMount() {
// Animation state
const [walkIdx, incrementWalkIdx] = useModuloCounter(WALKING_FRAMES.length);
const [lookIdx, incrementLookIdx] = useModuloCounter(LOOKING_FRAMES.length);
const [walk, toggleWalk] = useToggle(true);
const [look, toggleLook] = useToggle(true);
// You can use nooks inside regular components via
// the `useNook` hook
useNook(() => {
walk && mountInterval``(incrementWalkIdx, 100);
look && mountInterval``(incrementLookIdx, 100);
});
return (
<div className="grid gap-2 max-w-sm place-items-center place-content-center mx-auto mt-12 grid-cols-2">
<pre className={walk ? '' : 'opacity-50'}>
<code>{WALKING_FRAMES[walkIdx]}</code>
</pre>
<pre className={look ? '' : 'opacity-50'}>
<code>{LOOKING_FRAMES[lookIdx]}</code>
</pre>
<Btn onClick={toggleWalk}>{walk ? 'Pause' : 'Play'}</Btn>
<Btn onClick={toggleLook}>{look ? 'Pause' : 'Play'}</Btn>
</div>
);
}
// Turn any hook into a ✨ nook ✨
const mountInterval = nook(useInterval);
// Nooks are just functions that can use other nooks, so they can also be components
const DeleteWithNevermind = nook(() => {
const [step, next] = useStep();
if (step === 0) {
// Not deleting...
return <Btn onClick={() => next()}>Delete</Btn>;
}
if (step < 3) {
// Mounting the interval nook conditionally, which
// will call `next` every second
mountInterval``(next, 1000);
return (
<>
<Btn onClick={() => next(0)} highlighted>
Bring it back!
</Btn>
<p>{step === 1 ? 'Deleting...' : 'You can still stop this...'}</p>
</>
);
}
return (
<>
<Btn onClick={() => next(0)}>Restore</Btn>
<p>Deleted</p>
</>
);
});
// Turn any hook into a ✨ nook ✨
const mountTimer = nook(useTimer);
// Nooks are just functions that can use other nooks, so they can also be components
const Timer = nook(() => {
const [active, setActive] = useState(false);
const toggle = () => setActive((prev) => !prev);
return (
<div className="grid gap-2 max-w-sm place-items-center place-content-center mx-auto grid-cols-2 m-12">
{/* Only using `mountTimer` when active, directly in markup */}
<p className="min-w-[5rem]">Time: {active ? mountTimer``(100) : 0}</p>
<Btn onClick={toggle} highlighted={active}>
{active ? 'Stop' : 'Start'}
</Btn>
</div>
);
});