Dynamic Island, animated React component
A black pill that morphs on a spring into whatever is happening, a running timer, the track that is playing or an incoming call, and opens into live controls when tapped.
- Free
- Cards
- Spring
Play with it
Move the controls and watch it change. Copy code gives you a snippet with only the props you changed.
Props
| Prop | Type | Default | What it does |
|---|---|---|---|
| state | "idle" | "timer" | "music" | "call" | — | Controlled activity shown in the island. |
| defaultState | "idle" | "timer" | "music" | "call" | "timer" | Starting activity when uncontrolled. |
| onStateChange | (state: IslandState) => void | — | Called when the island changes activity (stop, decline, or a cycle step). |
| timerSeconds | number | 300 | Length of the countdown in seconds. It really ticks. |
| accent | string | "#ff9f0a" | Accent colour for the timer and the music bars. |
| cycle | number | 0 | Uncontrolled only: step through `states` every this many ms. 0 stays put. |
| states | IslandState[] | ["timer", "music", "call"] | Activities visited by `cycle`. |
| track | { title: string; artist: string } | { title: "Midnight Drive", artist: "Neon Harbor" } | Track shown in the music state. |
| caller | string | "Ava Lin" | Name shown in the call state. |
| className | string | — | Classes for the outer wrapper. |
Add it to your project
- 1
Prepare your project
You need Tailwind CSS and the
@/import alias. If shadcn isn't set up yet, initialise it once:npx shadcn@latest init
Then add the Nexus registry to your
components.json(theregistrieskey is the part that matters):{ "$schema": "https://ui.shadcn.com/schema.json", "style": "default", "rsc": true, "tsx": true, "tailwind": { "css": "src/app/globals.css", "baseColor": "neutral", "cssVariables": true, "prefix": "" }, "aliases": { "components": "@/components", "utils": "@/lib/utils", "ui": "@/components/ui", "lib": "@/lib", "hooks": "@/hooks" }, "registries": { "@nexus-labs": "https://www.nexus-ui.com/api/registry/{name}" } } - 2
Add the component
Run this from your project root. It adds the component, the utilities it uses and its packages.
npx shadcn@latest add @nexus-labs/dynamic-island
- 3
Check what was added
With the standard aliases, these files land in your project:
components/dynamic-island/dynamic-island.tsxindex.ts - 4
Copying by hand? Install the packages
Skip this if you used the command above.
npm install framer-motion lucide-react
- 5
Use it in a page
Import it and render it. The Code tab above has the full example.
// app/page.tsx import { DynamicIsland, type IslandState } from "@/components/dynamic-island"; export default function Page() { return ( <main> <DynamicIsland /> </main> ); }