The tray
Sound
The tray plays a shake while the dice tumble and a knock as each lands, from recordings of real dice. Ten dice landing are five knocks, not ten.
- It starts with the sound on, or off where the device asks for reduced motion. The speaker button on the felt mutes it, and the choice is remembered on the device.
- The recordings (36 kB) are fetched the first time a roll needs them and not before: a muted tray, or one mounted with
sound: false, never downloads them. If they cannot be fetched or decoded, the tray plays a short knock it makes itself. - A browser only lets a page make sound after somebody has touched it, so a roll started by code before any tap is silent.
- Nothing throws where there is no audio, as on a server or in a test.
mountRoller(el, { sound: false }); // silent, no button
mountRoller(el, { playSound: ({ dice }) => myClack(dice) }); // your own soundDice sounds from Kenney's Casino Audio, CC0, kenney.nl. SOUNDS.md names the files and what was done to them.
Theming
Every colour is a CSS variable on .kk-root. Pass them as theme, which sets them on the tray itself and so wins in light and dark alike:
mountRoller(el, { theme: { "--kk-felt": "#23405a", "--kk-felt-deep": "#162a3c", "--kk-accent": "#d4a017" } });--kk-surface, --kk-ink, --kk-muted, --kk-rule, --kk-felt, --kk-felt-deep, --kk-felt-ink, --kk-accent, --kk-accent-ink, --kk-good, --kk-bad, --kk-die, --kk-die-edge, --kk-die-ink, --kk-pip-one, --kk-radius, --kk-font.
Browser support
Any browser from the last few years: it needs ES2020 with BigInt, crypto.getRandomValues and CSS color-mix (Chrome and Edge 111, Firefox 113, Safari 16.2). The sound needs the Web Audio API and AAC decoding, which those browsers have; without them the tray is silent or plays its own knock. It is tested in Chromium and in WebKit, Safari's engine, at phone size with touch. The core also runs in Node 20 and later, Deno and Bun.
Languages
English and Japanese, chosen by locale or the page's lang, or by the reader where a page turns on languageChooser. The demo has a chooser of its own, follows the browser's language on a first visit, and takes ?lang=ja or ?lang=en in the address. Japanese: included; not yet reviewed by a native reader. Corrections welcome. Every Japanese string is listed beside its English in docs/strings-ja.md, and there is an issue template for fixing one. Any other language is a table of your own passed as strings.