Recipe: commit detail drawer

Pass a renderDetail render-prop to <GitGraph> and a right-side drawer mounts alongside the graph. The drawer chrome (focus trap, ESC, scroll-lock, theme tokens) comes from shadcn's sheet, which installs transitively when you add git-graph.

Minimal — uncontrolled

With no other props, the drawer auto-opens on row click and closes on ESC or backdrop-click. The render-prop receives the currently selected commit.

import GitGraph from "@/components/git-graph/git-graph";

<GitGraph
  commits={commits}
  renderDetail={(c) =>
    c ? (
      <>
        <h3 className="font-semibold mb-2">{c.message}</h3>
        <pre className="text-xs">{c.sha}</pre>
      </>
    ) : null
  }
/>

Decoupled controlled

Selection and drawer-open are independent states. Pass detailOpen and ignore onDetailOpenChange's click-to-open signal to keep the drawer closed regardless of selection — useful when you want a separate affordance (a button, a keyboard shortcut) to open the drawer.

"use client";
import { useState } from "react";
import GitGraph from "@/components/git-graph/git-graph";

export default function DecoupledExample({ commits }) {
  const [sha, setSha] = useState<string | undefined>();
  const [open, setOpen] = useState(false);

  return (
    <>
      <GitGraph
        commits={commits}
        selectedSha={sha}
        onSelectChange={setSha}
        detailOpen={open}
        // Ignore GitGraph's default click-to-open signal —
        // only our button below opens the drawer.
        onDetailOpenChange={() => {}}
        renderDetail={(c) => (c ? <pre>{c.sha}</pre> : null)}
      />
      <button onClick={() => setOpen(true)}>Show detail</button>
    </>
  );
}