@fitfoculture/fleet-radio
v0.4.1
Published
The fleet's floating-mark music player — a curated YouTube playlist that rides any app's floating mark. Framework-agnostic React; no YouTube Data API, no key, no quota.
Readme
@fitfoculture/fleet-radio
The fleet's floating-mark music player — a curated YouTube playlist that rides any app's floating mark (Fitfo's Star, BOOF's Que Ball, …). Framework-agnostic React. No YouTube Data API, no key, no quota — the IFrame Player loads a playlist by id. Autoplay is impossible by browser rule; the tap on the mark is the required user gesture.
Extracted from BOOF's radio so every app in the fleet imports the identical player — a version bump propagates a design change to all of them at once.
Install
npm install @fitfoculture/fleet-radioPeer deps: react / react-dom >= 18 (built against 19).
Use
Import the stylesheet once (e.g. in the root layout), then render FleetRadio
in a persistent layout so a track survives client-side navigation:
import { FleetRadio, type RadioStation } from "@fitfoculture/fleet-radio";
import "@fitfoculture/fleet-radio/styles.css";Two modes
Anchored — ride an existing mark (Fitfo's Star). The host owns the position
and renders its own glyph; FleetRadio draws only the orbiting ring + the panel
at anchor, and the host controls open:
<FleetRadio
stations={stations}
anchor={{ x: starCenterX, y: starCenterY }}
open={radioOpen}
onOpenChange={setRadioOpen}
tokens={{ accent: "#e8c764", accentDeep: "#d4a843", ink: "#f0ece4", panel: "#141220" }}
onConnectPlaylist={openConnectDialog}
/>Standalone — a self-parking floating mark (BOOF). Provide the mark glyph;
the player manages its own drag/dismount/park:
<FleetRadio
stations={stations}
size={112}
persistKey="boof.queball.park"
mark={({ playing }) => <QueBall state={playing ? "working" : "rest"} />}
extra={<LiveCart />}
/>Branding
The whole player themes from CSS vars — set them via the tokens prop or your
own CSS. The ring, transport, hairlines and panel edge-glow all derive from
--radio-accent (via color-mix):
| var | what |
| --- | --- |
| --radio-accent | bright accent (ring on the mark, glow, hover) |
| --radio-accent-deep | deepened accent |
| --radio-ink | panel/body text |
| --radio-panel | panel ground |
| --radio-screen | the video letterbox (default black) |
| --radio-orbit-off-fill / --radio-orbit-halo | light-page apps: deep fill + an ink halo so the ring reads off the mark on bright paper |
Defaults suit a dark page (gold on midnight). A light-page app (BOOF's bone)
overrides --radio-panel, --radio-ink, --radio-orbit-off-fill and
--radio-orbit-halo.
Data
RadioStation = { slug, name, blurb?, playlistId }. Supply stations from your
own store. A station with no playlistId is not playable — in standalone mode
the mark won't mount; in anchored mode the panel still opens so a "connect a
playlist" flow is reachable. Validate a pasted playlist before saving it
(resolves + public + has videos + embeds) — a truncated paste looks identical
to a good id.
