A trackball that scrolls the page, made for fun.
Uses a bunch of cool CSS to appear 3D, and has some cool physics!
Used AI to improve my readme a bit, but not docs
Edit: To clarify, the ONLY use of AI was for the README, nothing else.
A trackball that scrolls the page, made for fun.
Uses a bunch of cool CSS to appear 3D, and has some cool physics!
Used AI to improve my readme a bit, but not docs
Edit: To clarify, the ONLY use of AI was for the README, nothing else.
I built Tamaru, a physics-driven virtual trackball widget for the web, and this ship is v0.1.1 with the Chrome extension!
Download the Chrome extension on the release page here!
The extension lets Tamaru haunt any website you visit, with a full interesant settings popup that themes itself to match your orb. It autosaves everything, has a floating orb header, themed section icons, sliders with live value displays, the works.
This ship also includes a handful of fixes and additions to the core library: audio now properly resumes on first interaction (browsers are rude about AudioContext and suspend it until a user gesture, so I added resumeIfNeeded() on every pointer event), a new startMinimized config option so the orb can boot as a tiny lil widget instead of slamming its full UI into your face, and the extensionâs dependency situation got untangled so it actually builds from source properly.
The hardest part was honestly wiring the extension together cleanly. Getting the Vite alias pointing at the right build output, Chrome storage syncing correctly, the popup theming matching the orb, and audio not being silent on first load all had their own little moments. But it works now and itâs so cool seeing Tamaru just⌠exist on every page.
I PUBLISHED V0.1.1!!!
ITâS ON NPM.
ITâS REAL.
THE EXTENSION EXISTS NOW.
As a .crx file đ but still
So uh.
I was supposed to just clean things up a bit.
Anyway.
THE EXTENSION IS NOW A REAL PROJECT.
And also the orb can make sounds again.
And also it can start already minimized.
And also dependencies are no longer lying about what version of Tamaru they use.
The math checks out. totally.
What I Did
Fixed audio!!
Browsers are incredibly rude about AudioContext. They suspend it until a user gesture happens, which means if you load the extension and havenât touched anything, the orb just silently judges you.
Fixed by adding resumeIfNeeded() that gets called on every pointerdown, on the trackball, on the widget handle, AND on the stick mode button.
The orb now makes sounds again. as it should. it was sad without them.
Added startMinimized!!!
New config option: startMinimized: boolean (defaults to false)
If you set it to true, Tamaru boots up as a tiny lil orb instead of the full widget.
Super useful for the extension so it doesnât slam its whole UI into your face the second you open a tab.
Added it to the demo config panel, the docs, and the types. it exists everywhere now.
The extensionâs popup even has a âStart Minimizedâ toggle defaulting to checked, because yes, unobtrusive is the vibe.
Fixed the extensionâs dependency situation (twice lol)
First I removed the broken "tamaru": "0.1.0" from dependencies because that was the old version and it was Lying
Then I wired up a Vite alias so the extension points directly at ../Build/dist/main.mjs
So it builds from source, properly, like a grown-up project
Then I bumped the npm package to v0.1.1 and updated the lock file to match
Also added @types/node, prettier, typecheck and make-pretty scripts to the extension because Past Me left it looking a little eeeh in there
Bugs Fixed
resumeIfNeeded on every pointer event)startMinimized)Log in to leave a comment
I was busyâŚ
Anyway.
THE POPUP HAS BEEN REVAMPED.
THE ORB CONTROL PANEL IS NOW A WHOLE APP.
The extension stole (with permission) Tamaruâs themes.
theme-aqua
theme-red
theme-glossy
theme-metal
theme-neon
theme-sunset
The popup now cosplays as your orb :D
Replaced with ⨠better ⨠things.
base: "./"
@types/chrome
src/ and styles/
Log in to leave a comment
SO I STARTED AN EXTENSION THINGY
VERY BROKEN
BUT STILL
Anyway.
THE ORB HAS ESCAPED THE DEMO.
IT CAN HAUNT ANY WEBSITE NOW.
uhh will make it better in upcoming devlogs
Log in to leave a comment
I built Tamaru, a physicsâdriven virtual trackball widget for the web!
It lets you scroll any page or container by flicking a little 3D orb, complete with inertia, audio, haptics, themes, and now⌠Stick Mode (pointerâlock scrolling), which nearly broke me (/silly) but was so worth it.
The hardest part was definitely Stick Mode. Pointer lock, scrollâtarget cycling, highlight logic, restoring state, and making it all feel like a real trackball was a whole boss fight. I figured it out by rewriting half the scroll engine, adding a targetâcycling system, and bribing the browser with sheer stubbornness (yes your browserâs now corrupt đ).
Iâm really proud of how polished it feels now, the physics, the audio, the theming, the demo, the docs, everything. It started as a tiny 6 AM experiment and somehow turned into a full npm package with real features and real users. Iâm honestly so happy with how it turned out.
So uh.
I DID IT.
I ACTUALLY SHIPPED TAMARU.
Itâs on npm.
Itâs real.
Itâs alive.
It has provenance logs and everything.
Iâm screaming.
(Iâm using the bookmarklet, by the way, in the first two images)
so uh. stick mode.
I finally did it.
I added stick to cursor mode.
And let me tell you:
this was
SO
HARD.
like âwhy am I doing this to myselfâ hard
like âpointer lock is a demonâ hard
like âscroll target cycling is a cursed ritualâ hard
BUT ALSO
SO
WORTH IT.
I had to fight the browser for custody of the mouse.
It did NOT want to give it to me.
I won.
with a smirk cause why not >:3
stick mode now forceâminimizes the orb
centers it
no more dragging the orb
no more âgo to the cornerâ
just pure raw mouse movement -> scroll velocity
like a REAL trackball
but digital!
hold Shift
scroll wheel (or two fingers on laptop)
Tamaru goes:
âoh you want to scroll THAT div?
okay let me highlight it for youâ
it even scrolls it into view configurably
because Iâm extra.
enter stick mode
exit stick mode
restore position
restore size
restore sanity (attempted, not guaranteed, often fails)
added a cute little â button
it mocks me
but it works
updated the demo again
because of course I did
stick mode works
itâs beautiful
itâs terrifying
I love it
Log in to leave a comment
So uhâŚ
I kinda want to ship this todayâŚ
Maybe a bit obsessed but hereâs another devlog haha.
I decided to try not to do like 10 things in one devlog.
And then IâŚ
did not do that.
Apparently I cannot touch this project without accidentally doing a full renovation.
Anyway.
Updated the demo again and it now is curvomorphic and prettyyy :3
Now with a working favicon.
Probably.
Confirmed now, yeah it works
I love it, itâs perfect :D
Log in to leave a comment
So uh.
I did⌠a lot of things.
Like, a silly amount of things for someone who allegedly âwas just fixing bugs.â
This commit arc is basically:
âIâm only going to clean my room a littleâ
proceeds to renovate the entire house, add two new rooms, repaint the walls, and fix a installed sound system
Anyway.
gradient, heheheheheheh
(I NEED MORE GIVE ME MOREEEEEEEEEE)
Orange, mic drop.
(but also it looks like mars sob)
Updated the demo again because if Iâm suffering, you get to see the results :3
Log in to leave a comment
So⌠I did a bunch of one thing:
This commit message best summarizes it:
I just wrote a manual audio engine
d6e51b1
¡
2 hours ago
this took ages
help
help me
someone
/j this is normal for me I made an *audio codec*
no it isn't why didn't i use audio files
WAIT
OH
OMG
AAAAAAAAAAAAAAAAAAA
So uh.
I sat down to âadd some sounds.â
Anyway, I guess I wrote a manual audio engine.
Like.
A whole one.
From scratch.
Why?
I donât know.
Ask the version of me who thought âhm yes, procedural rollingâbearing noise with dynamic playbackRate modulation sounds fun.â
Built a full WebAudio pipeline with:
Added perâevent sound design:
Implemented a rolling sound layer that:
Added speedâaware feedback everywhere so the widget feels alive and so realistic.
rollSoundLevel).Updated the demo to expose rollSoundLevel because if I suffered for this, you get to play with the dial.
DEVLOG TIMEEEEEEE
Hackatime is behaving much more nicely, kudos to the maintainers. XD
I did stuff.
Okay, actually, I turned the little trackball experiment into a proper, modular toolkit with theming, config, and haptics.
tactus package and added a simple haptic engine that calls triggerHaptic(duration)
tactus for native-feeling pulses.Log in to leave a comment
So first devlog for Tamaru!!!
I initially made this today at like 6 AM as a small JS experiment, then was like, this is actually so useful!!!
Then i decided to make this an npm module/library, for fun :3.
Stuff I did to the original JS module