Nexus UI

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

PropTypeDefaultWhat it does
state—Controlled activity shown in the island.
defaultState"timer"Starting activity when uncontrolled.
onStateChange—Called when the island changes activity (stop, decline, or a cycle step).
timerSeconds300Length of the countdown in seconds. It really ticks.
accent"#ff9f0a"Accent colour for the timer and the music bars.
cycle0Uncontrolled only: step through `states` every this many ms. 0 stays put.
states["timer", "music", "call"]Activities visited by `cycle`.
track{ title: "Midnight Drive", artist: "Neon Harbor" }Track shown in the music state.
caller"Ava Lin"Name shown in the call state.
className—Classes for the outer wrapper.

Add it to your project

  1. 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 (the registries key 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. 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. 3

    Check what was added

    With the standard aliases, these files land in your project:

    components/
    dynamic-island/
    dynamic-island.tsx
    index.ts
  4. 4

    Copying by hand? Install the packages

    Skip this if you used the command above.

    npm install framer-motion lucide-react
  5. 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>
      );
    }