Dynamic Island

One shape, many states. The pill expands and reveals its content.

"use client"

import { ViewTransition, type ReactNode } from "react"

export function DynamicIsland({ children }: { children: ReactNode }) {
  return (
    <ViewTransition update="vt-move vt-slow vt-spring vt-shell vt-inverse vt-clip">
      <div className="overflow-hidden rounded-[32px] bg-foreground text-background [view-transition-group:contain]">
        <ViewTransition update="vt-move vt-slow vt-spring vt-reveal vt-top">
          <div>{children}</div>
        </ViewTransition>
      </div>
    </ViewTransition>
  )
}

Installation

  1. 1Copy the Component tab into components/dynamic-island.tsx.
  2. 2Paste the CSS tab into globals.css, after Tailwind.

How it works

An outer boundary animates the pill’s size and paints its surface. Both boundaries use the same spring easing; content scales gently into view through the expanding shell. The example pins the island to the top of a fixed-height stage so it expands down and out without moving the controls. Nested clipping keeps content inside the changing pill.

Uses
nested boundaries, vt-shell, vt-inverse, vt-top
Theme
--background, --foreground, --card, --radius