Mini Bar

A slim contextual strip above the safe area — perfect for a now-playing bar.

variant="mini"footerminiplayer
Open fullscreen
9:41

In this demo

Tempo — music player

What to try

  • Tap a track — the mini player appears
  • Play and skip without leaving the list

Code

app.tsx
import {
  AppShell, Header, Content, Footer, MotionProvider,
} from "appshell-react";
import { framerMotionAdapter } from "appshell-react/motion-framer";
import { Play, Pause, SkipForward } from "lucide-react";

export default function App() {
  const [track, setTrack] = useState(null); // set by tapping a row
  const [playing, setPlaying] = useState(false);

  return (
    <MotionProvider adapter={framerMotionAdapter}>
      <AppShell safeArea>
        <Header behavior="fixed" logo={<span className="font-bold">Tempo</span>} />

        <Content>{/* track list rows call setTrack */}</Content>

        {/* Mount the mini bar only when there is something to show —
            it animates in above the safe area on its own. */}
        {track && (
          <Footer variant="mini">
            <div className="flex w-full items-center gap-3">
              <div className="min-w-0 flex-1">
                <p className="truncate text-sm font-medium">{track.title}</p>
                <p className="truncate text-xs text-muted-foreground">{track.artist}</p>
              </div>
              <button aria-label={playing ? "Pause" : "Play"}
                onClick={() => setPlaying(!playing)}>
                {playing ? <Pause /> : <Play />}
              </button>
              <button aria-label="Next track"><SkipForward /></button>
            </div>
          </Footer>
        )}
      </AppShell>
    </MotionProvider>
  );
}