# Collapsible sidebar

> A Linear‑style sidebar that folds down to icons with the [ key, with a sliding active marker and tooltips when folded.

- Category: [Navigation](https://library.aimran.es/components/navigation)
- Built with: React + Motion
- Live editor: https://library.aimran.es/blocks/linear-collapsible-sidebar
- Library: AIMRAN Library (https://library.aimran.es), free, no sign-up, by Aimran Oukham

## Where to use it

This collapsible sidebar in React is made for tools people spend the whole day in: a project tracker, a CRM, the admin panel of a SaaS. Folded, it leaves just the icons and gives the content room; the unread badge turns into a small dot and every entry shows its name in a tooltip.

The [ shortcut listens on the whole page, so check your app does not already use that key. Start folded if your users mostly work on laptops. On phones a sidebar is rarely the answer; a bottom bar or a drawer usually works better.

## Code

### React (Motion)

```tsx
import { useEffect, useState } from "react";
import { AnimatePresence, motion } from "framer-motion";
import { Box, CircleCheck, CircleDashed, CircleDot, Inbox, Layers, PanelLeft } from "lucide-react";
import type { LucideIcon } from "lucide-react";

const SIDEBAR_NAV: { label: string; icon: LucideIcon; badge?: number }[] = [
  { label: "Inbox", icon: Inbox, badge: 3 },
  { label: "My tasks", icon: CircleDot },
  { label: "Projects", icon: Box },
  { label: "Views", icon: Layers },
];

const SIDEBAR_TEAMS = [
  { label: "Design", color: "#f2994a" },
  { label: "Engineering", color: "#26b5ce" },
];

const SIDEBAR_ISSUES = [
  { id: "AIM-142", title: "Review onboarding", status: "progress" },
  { id: "AIM-139", title: "New app icon", status: "todo" },
  { id: "AIM-131", title: "Migrate payments to v2", status: "done" },
  { id: "AIM-128", title: "Dark mode in settings", status: "progress" },
  { id: "AIM-120", title: "Clean up color tokens", status: "todo" },
  { id: "AIM-117", title: "Keyboard shortcuts", status: "done" },
];

const SIDEBAR_SPRING = { type: "spring", stiffness: 420, damping: 38 } as const;

interface SidebarItemProps {
  label: string;
  icon?: LucideIcon;
  dot?: string;
  badge?: number;
  active: boolean;
  collapsed: boolean;
  accent: string;
  onSelect: () => void;
}

function SidebarItem({
  label,
  icon: Icon,
  dot,
  badge,
  active,
  collapsed,
  accent,
  onSelect,
}: SidebarItemProps) {
  const [tip, setTip] = useState(false);
  return (
    <div
      className="relative"
      onPointerEnter={() => setTip(true)}
      onPointerLeave={() => setTip(false)}
    >
      <button
        type="button"
        onClick={onSelect}
        onFocus={() => setTip(true)}
        onBlur={() => setTip(false)}
        aria-label={collapsed ? label : undefined}
        aria-current={active ? "page" : undefined}
        className={
          "relative flex h-8 w-full items-center gap-2.5 rounded-lg px-2.5 text-[13px] outline-none transition-colors duration-150 focus-visible:ring-2 focus-visible:ring-black/15 active:scale-[0.98] dark:focus-visible:ring-white/20 " +
          (active
            ? "font-medium text-[#1d1d1f] dark:text-[#f5f5f7]"
            : "text-[#5f5f66] hover:bg-black/[0.04] hover:text-[#1d1d1f] dark:text-[#a1a1aa] dark:hover:bg-white/[0.05] dark:hover:text-[#f5f5f7]")
        }
      >
        {active && (
          <motion.span
            layoutId="linear-sidebar-active"
            className="absolute inset-0 rounded-lg bg-white shadow-[0_1px_2px_rgba(0,0,0,0.06),0_0_0_1px_rgba(0,0,0,0.04)] dark:bg-white/[0.08] dark:shadow-none"
            transition={SIDEBAR_SPRING}
          />
        )}
        {Icon ? (
          <Icon
            className="relative h-4 w-4 shrink-0"
            strokeWidth={1.5}
            style={{ color: active ? accent : undefined }}
          />
        ) : (
          <span
            className="relative mx-[3px] h-2.5 w-2.5 shrink-0 rounded-[3px]"
            style={{ backgroundColor: dot }}
          />
        )}
        <motion.span
          initial={false}
          animate={{ opacity: collapsed ? 0 : 1 }}
          transition={{ duration: 0.15 }}
          className="relative flex-1 truncate whitespace-nowrap text-left"
        >
          {label}
        </motion.span>
        {badge ? (
          <>
            <motion.span
              initial={false}
              animate={{ opacity: collapsed ? 0 : 1, scale: collapsed ? 0.5 : 1 }}
              transition={SIDEBAR_SPRING}
              className="relative grid h-[18px] min-w-[18px] place-items-center rounded-full px-1 text-[10px] font-semibold tabular-nums text-white"
              style={{ backgroundColor: accent }}
            >
              {badge}
            </motion.span>
            <motion.span
              aria-hidden
              initial={false}
              animate={{ opacity: collapsed ? 1 : 0, scale: collapsed ? 1 : 0 }}
              transition={SIDEBAR_SPRING}
              className="absolute left-[23px] top-[5px] h-2 w-2 rounded-full ring-2 ring-[#f4f4f5] dark:ring-[#0e0e10]"
              style={{ backgroundColor: accent }}
            />
          </>
        ) : null}
      </button>
      <AnimatePresence>
        {collapsed && tip && (
          <motion.span
            role="tooltip"
            initial={{ opacity: 0, x: -4, y: "-50%", scale: 0.96 }}
            animate={{ opacity: 1, x: 0, y: "-50%", scale: 1 }}
            exit={{ opacity: 0, x: -4, y: "-50%", scale: 0.96 }}
            transition={{ type: "spring", stiffness: 600, damping: 36 }}
            className="pointer-events-none absolute left-full top-1/2 z-30 ml-3 flex items-center gap-1.5 whitespace-nowrap rounded-lg bg-[#1d1d1f] px-2.5 py-1.5 text-[12px] font-medium text-white shadow-[0_8px_24px_rgba(0,0,0,0.18)] dark:bg-[#f5f5f7] dark:text-[#1d1d1f]"
          >
            {label}
            {badge ? <span className="opacity-50">{badge}</span> : null}
          </motion.span>
        )}
      </AnimatePresence>
    </div>
  );
}

function IssueStatus({ status, accent }: { status: string; accent: string }) {
  if (status === "done")
    return <CircleCheck className="h-4 w-4 shrink-0" strokeWidth={1.5} style={{ color: accent }} />;
  if (status === "progress")
    return <CircleDot className="h-4 w-4 shrink-0 text-[#e2a93b]" strokeWidth={1.5} />;
  return <CircleDashed className="h-4 w-4 shrink-0 text-[#aeaeb2]" strokeWidth={1.5} />;
}

interface LinearSidebarProps {
  accent?: string;
  startCollapsed?: boolean;
}

export default function LinearSidebar({
  accent = "#5e6ad2",
  startCollapsed = false,
}: LinearSidebarProps) {
  const [collapsed, setCollapsed] = useState(startCollapsed);
  const [active, setActive] = useState("Inbox");

  useEffect(() => setCollapsed(startCollapsed), [startCollapsed]);

  useEffect(() => {
    const onKey = (e: KeyboardEvent) => {
      const t = e.target as HTMLElement | null;
      if (t && (t.tagName === "INPUT" || t.tagName === "TEXTAREA" || t.isContentEditable)) return;
      if (e.key === "[") setCollapsed((c) => !c);
    };
    window.addEventListener("keydown", onKey);
    return () => window.removeEventListener("keydown", onKey);
  }, []);

  const all = [...SIDEBAR_NAV.map((n) => n.label), ...SIDEBAR_TEAMS.map((t) => t.label)];
  const offset = Math.max(0, all.indexOf(active)) % 3;
  const issues = SIDEBAR_ISSUES.slice(offset, offset + 4);

  return (
    <div className="flex h-full w-full overflow-hidden bg-[#f4f4f5] text-[#1d1d1f] dark:bg-[#0e0e10] dark:text-[#f5f5f7]">
      <motion.aside
        initial={false}
        animate={{ width: collapsed ? 52 : 172 }}
        transition={SIDEBAR_SPRING}
        className="relative z-10 flex h-full shrink-0 flex-col gap-0.5 p-2"
      >
        <div className="mb-3 flex h-9 items-center gap-2 overflow-hidden px-1.5">
          <span
            className="grid h-6 w-6 shrink-0 place-items-center rounded-[7px] text-[12px] font-semibold text-white shadow-[inset_0_1px_0_rgba(255,255,255,0.25)]"
            style={{ backgroundColor: accent }}
          >
            A
          </span>
          <motion.span
            initial={false}
            animate={{ opacity: collapsed ? 0 : 1 }}
            transition={{ duration: 0.15 }}
            className="whitespace-nowrap text-[13px] font-semibold tracking-[-0.01em]"
          >
            Aimran
          </motion.span>
        </div>

        <nav aria-label="Workspace" className="flex flex-col gap-0.5">
          {SIDEBAR_NAV.map((item) => (
            <SidebarItem
              key={item.label}
              label={item.label}
              icon={item.icon}
              {...(item.badge ? { badge: item.badge } : {})}
              active={active === item.label}
              collapsed={collapsed}
              accent={accent}
              onSelect={() => setActive(item.label)}
            />
          ))}
          <div className="relative mb-1 mt-4 h-4 px-2.5">
            <motion.p
              initial={false}
              animate={{ opacity: collapsed ? 0 : 1 }}
              className="whitespace-nowrap text-[11px] font-medium text-[#8e8e93]"
            >
              Teams
            </motion.p>
            <motion.div
              initial={false}
              animate={{ opacity: collapsed ? 1 : 0 }}
              className="absolute inset-x-2.5 top-2 h-px bg-black/[0.08] dark:bg-white/[0.08]"
            />
          </div>
          {SIDEBAR_TEAMS.map((team) => (
            <SidebarItem
              key={team.label}
              label={team.label}
              dot={team.color}
              active={active === team.label}
              collapsed={collapsed}
              accent={accent}
              onSelect={() => setActive(team.label)}
            />
          ))}
        </nav>

        <button
          type="button"
          onClick={() => setCollapsed((c) => !c)}
          aria-label={collapsed ? "Expand sidebar" : "Collapse sidebar"}
          aria-expanded={!collapsed}
          className="mt-auto flex h-8 items-center gap-2.5 overflow-hidden rounded-lg px-2.5 text-[12px] text-[#8e8e93] outline-none transition-colors hover:bg-black/[0.04] hover:text-[#1d1d1f] focus-visible:ring-2 focus-visible:ring-black/15 dark:hover:bg-white/[0.05] dark:hover:text-[#f5f5f7] dark:focus-visible:ring-white/20"
        >
          <PanelLeft className="h-4 w-4 shrink-0" strokeWidth={1.5} />
          <motion.span
            initial={false}
            animate={{ opacity: collapsed ? 0 : 1 }}
            transition={{ duration: 0.15 }}
            className="flex flex-1 items-center justify-between whitespace-nowrap"
          >
            Collapse
            <kbd className="rounded-[5px] border border-black/10 bg-white px-1.5 font-mono text-[10px] leading-4 dark:border-white/10 dark:bg-white/5">
              [
            </kbd>
          </motion.span>
        </button>
      </motion.aside>

      <main className="my-2 mr-2 flex min-w-0 flex-1 flex-col overflow-hidden rounded-xl bg-white shadow-[0_1px_2px_rgba(0,0,0,0.05),0_0_0_1px_rgba(0,0,0,0.04)] dark:bg-[#18181b] dark:shadow-[0_0_0_1px_rgba(255,255,255,0.06)]">
        <header className="flex h-11 shrink-0 items-center gap-2 border-b border-black/[0.06] px-4 text-[13px] font-medium dark:border-white/[0.06]">
          <span className="truncate">{active}</span>
          <span className="rounded-md bg-black/[0.05] px-1.5 text-[11px] tabular-nums text-[#8e8e93] dark:bg-white/10">
            {issues.length}
          </span>
        </header>
        <AnimatePresence mode="wait" initial={false}>
          <motion.ul
            key={active}
            initial={{ opacity: 0, y: 6 }}
            animate={{ opacity: 1, y: 0 }}
            exit={{ opacity: 0, y: -4 }}
            transition={{ duration: 0.18 }}
            className="flex-1 overflow-y-auto"
          >
            {issues.map((issue) => (
              <li
                key={issue.id}
                className="flex items-center gap-3 border-b border-black/[0.04] px-4 py-2.5 text-[13px] transition-colors hover:bg-black/[0.02] dark:border-white/[0.04] dark:hover:bg-white/[0.02]"
              >
                <IssueStatus status={issue.status} accent={accent} />
                <span className="truncate">{issue.title}</span>
              </li>
            ))}
          </motion.ul>
        </AnimatePresence>
      </main>
    </div>
  );
}
```

## Prompt for AI assistants

Paste this into ChatGPT, Claude, Cursor, v0 or Lovable to adapt the block to your stack (Tailwind, Vue, Svelte…):

````text
I want to add the “Collapsible sidebar” block (Navigation) from AIMRAN Library to my project.

## What it is
A Linear‑style sidebar that folds down to icons with the [ key, with a sliding active marker and tooltips when folded.

## Chosen settings
- Accent: #5e6ad2
- Start collapsed: no

## What I need
1. Add it to my project with the same look and animation as the reference code: same sizes, colours, radii, shadows, timings and easing.
2. It is built with React + TypeScript, with framer-motion for the animation and lucide-react for the icons. If my project uses something else (Vue, Svelte, Astro, plain HTML…), translate it without losing any behaviour. If I use Tailwind, turn the styles into classes; if not, keep the CSS in its own file.
3. Expose the settings above as props (or CSS variables) with those values as defaults.
4. Make it work well on phones: nothing that depends only on hover, touch targets of at least 44 px and no overflow on 320 px screens.
5. Make it look right in light and dark mode.
6. Keep it accessible: semantic HTML, roles and aria-* where needed, visible focus and keyboard support.
7. Respect prefers-reduced-motion: with reduced motion, no big animations but the same end result.

## Reference code
```tsx
import { useEffect, useState } from "react";
import { AnimatePresence, motion } from "framer-motion";
import { Box, CircleCheck, CircleDashed, CircleDot, Inbox, Layers, PanelLeft } from "lucide-react";
import type { LucideIcon } from "lucide-react";

const SIDEBAR_NAV: { label: string; icon: LucideIcon; badge?: number }[] = [
  { label: "Inbox", icon: Inbox, badge: 3 },
  { label: "My tasks", icon: CircleDot },
  { label: "Projects", icon: Box },
  { label: "Views", icon: Layers },
];

const SIDEBAR_TEAMS = [
  { label: "Design", color: "#f2994a" },
  { label: "Engineering", color: "#26b5ce" },
];

const SIDEBAR_ISSUES = [
  { id: "AIM-142", title: "Review onboarding", status: "progress" },
  { id: "AIM-139", title: "New app icon", status: "todo" },
  { id: "AIM-131", title: "Migrate payments to v2", status: "done" },
  { id: "AIM-128", title: "Dark mode in settings", status: "progress" },
  { id: "AIM-120", title: "Clean up color tokens", status: "todo" },
  { id: "AIM-117", title: "Keyboard shortcuts", status: "done" },
];

const SIDEBAR_SPRING = { type: "spring", stiffness: 420, damping: 38 } as const;

interface SidebarItemProps {
  label: string;
  icon?: LucideIcon;
  dot?: string;
  badge?: number;
  active: boolean;
  collapsed: boolean;
  accent: string;
  onSelect: () => void;
}

function SidebarItem({
  label,
  icon: Icon,
  dot,
  badge,
  active,
  collapsed,
  accent,
  onSelect,
}: SidebarItemProps) {
  const [tip, setTip] = useState(false);
  return (
    <div
      className="relative"
      onPointerEnter={() => setTip(true)}
      onPointerLeave={() => setTip(false)}
    >
      <button
        type="button"
        onClick={onSelect}
        onFocus={() => setTip(true)}
        onBlur={() => setTip(false)}
        aria-label={collapsed ? label : undefined}
        aria-current={active ? "page" : undefined}
        className={
          "relative flex h-8 w-full items-center gap-2.5 rounded-lg px-2.5 text-[13px] outline-none transition-colors duration-150 focus-visible:ring-2 focus-visible:ring-black/15 active:scale-[0.98] dark:focus-visible:ring-white/20 " +
          (active
            ? "font-medium text-[#1d1d1f] dark:text-[#f5f5f7]"
            : "text-[#5f5f66] hover:bg-black/[0.04] hover:text-[#1d1d1f] dark:text-[#a1a1aa] dark:hover:bg-white/[0.05] dark:hover:text-[#f5f5f7]")
        }
      >
        {active && (
          <motion.span
            layoutId="linear-sidebar-active"
            className="absolute inset-0 rounded-lg bg-white shadow-[0_1px_2px_rgba(0,0,0,0.06),0_0_0_1px_rgba(0,0,0,0.04)] dark:bg-white/[0.08] dark:shadow-none"
            transition={SIDEBAR_SPRING}
          />
        )}
        {Icon ? (
          <Icon
            className="relative h-4 w-4 shrink-0"
            strokeWidth={1.5}
            style={{ color: active ? accent : undefined }}
          />
        ) : (
          <span
            className="relative mx-[3px] h-2.5 w-2.5 shrink-0 rounded-[3px]"
            style={{ backgroundColor: dot }}
          />
        )}
        <motion.span
          initial={false}
          animate={{ opacity: collapsed ? 0 : 1 }}
          transition={{ duration: 0.15 }}
          className="relative flex-1 truncate whitespace-nowrap text-left"
        >
          {label}
        </motion.span>
        {badge ? (
          <>
            <motion.span
              initial={false}
              animate={{ opacity: collapsed ? 0 : 1, scale: collapsed ? 0.5 : 1 }}
              transition={SIDEBAR_SPRING}
              className="relative grid h-[18px] min-w-[18px] place-items-center rounded-full px-1 text-[10px] font-semibold tabular-nums text-white"
              style={{ backgroundColor: accent }}
            >
              {badge}
            </motion.span>
            <motion.span
              aria-hidden
              initial={false}
              animate={{ opacity: collapsed ? 1 : 0, scale: collapsed ? 1 : 0 }}
              transition={SIDEBAR_SPRING}
              className="absolute left-[23px] top-[5px] h-2 w-2 rounded-full ring-2 ring-[#f4f4f5] dark:ring-[#0e0e10]"
              style={{ backgroundColor: accent }}
            />
          </>
        ) : null}
      </button>
      <AnimatePresence>
        {collapsed && tip && (
          <motion.span
            role="tooltip"
            initial={{ opacity: 0, x: -4, y: "-50%", scale: 0.96 }}
            animate={{ opacity: 1, x: 0, y: "-50%", scale: 1 }}
            exit={{ opacity: 0, x: -4, y: "-50%", scale: 0.96 }}
            transition={{ type: "spring", stiffness: 600, damping: 36 }}
            className="pointer-events-none absolute left-full top-1/2 z-30 ml-3 flex items-center gap-1.5 whitespace-nowrap rounded-lg bg-[#1d1d1f] px-2.5 py-1.5 text-[12px] font-medium text-white shadow-[0_8px_24px_rgba(0,0,0,0.18)] dark:bg-[#f5f5f7] dark:text-[#1d1d1f]"
          >
            {label}
            {badge ? <span className="opacity-50">{badge}</span> : null}
          </motion.span>
        )}
      </AnimatePresence>
    </div>
  );
}

function IssueStatus({ status, accent }: { status: string; accent: string }) {
  if (status === "done")
    return <CircleCheck className="h-4 w-4 shrink-0" strokeWidth={1.5} style={{ color: accent }} />;
  if (status === "progress")
    return <CircleDot className="h-4 w-4 shrink-0 text-[#e2a93b]" strokeWidth={1.5} />;
  return <CircleDashed className="h-4 w-4 shrink-0 text-[#aeaeb2]" strokeWidth={1.5} />;
}

interface LinearSidebarProps {
  accent?: string;
  startCollapsed?: boolean;
}

export default function LinearSidebar({
  accent = "#5e6ad2",
  startCollapsed = false,
}: LinearSidebarProps) {
  const [collapsed, setCollapsed] = useState(startCollapsed);
  const [active, setActive] = useState("Inbox");

  useEffect(() => setCollapsed(startCollapsed), [startCollapsed]);

  useEffect(() => {
    const onKey = (e: KeyboardEvent) => {
      const t = e.target as HTMLElement | null;
      if (t && (t.tagName === "INPUT" || t.tagName === "TEXTAREA" || t.isContentEditable)) return;
      if (e.key === "[") setCollapsed((c) => !c);
    };
    window.addEventListener("keydown", onKey);
    return () => window.removeEventListener("keydown", onKey);
  }, []);

  const all = [...SIDEBAR_NAV.map((n) => n.label), ...SIDEBAR_TEAMS.map((t) => t.label)];
  const offset = Math.max(0, all.indexOf(active)) % 3;
  const issues = SIDEBAR_ISSUES.slice(offset, offset + 4);

  return (
    <div className="flex h-full w-full overflow-hidden bg-[#f4f4f5] text-[#1d1d1f] dark:bg-[#0e0e10] dark:text-[#f5f5f7]">
      <motion.aside
        initial={false}
        animate={{ width: collapsed ? 52 : 172 }}
        transition={SIDEBAR_SPRING}
        className="relative z-10 flex h-full shrink-0 flex-col gap-0.5 p-2"
      >
        <div className="mb-3 flex h-9 items-center gap-2 overflow-hidden px-1.5">
          <span
            className="grid h-6 w-6 shrink-0 place-items-center rounded-[7px] text-[12px] font-semibold text-white shadow-[inset_0_1px_0_rgba(255,255,255,0.25)]"
            style={{ backgroundColor: accent }}
          >
            A
          </span>
          <motion.span
            initial={false}
            animate={{ opacity: collapsed ? 0 : 1 }}
            transition={{ duration: 0.15 }}
            className="whitespace-nowrap text-[13px] font-semibold tracking-[-0.01em]"
          >
            Aimran
          </motion.span>
        </div>

        <nav aria-label="Workspace" className="flex flex-col gap-0.5">
          {SIDEBAR_NAV.map((item) => (
            <SidebarItem
              key={item.label}
              label={item.label}
              icon={item.icon}
              {...(item.badge ? { badge: item.badge } : {})}
              active={active === item.label}
              collapsed={collapsed}
              accent={accent}
              onSelect={() => setActive(item.label)}
            />
          ))}
          <div className="relative mb-1 mt-4 h-4 px-2.5">
            <motion.p
              initial={false}
              animate={{ opacity: collapsed ? 0 : 1 }}
              className="whitespace-nowrap text-[11px] font-medium text-[#8e8e93]"
            >
              Teams
            </motion.p>
            <motion.div
              initial={false}
              animate={{ opacity: collapsed ? 1 : 0 }}
              className="absolute inset-x-2.5 top-2 h-px bg-black/[0.08] dark:bg-white/[0.08]"
            />
          </div>
          {SIDEBAR_TEAMS.map((team) => (
            <SidebarItem
              key={team.label}
              label={team.label}
              dot={team.color}
              active={active === team.label}
              collapsed={collapsed}
              accent={accent}
              onSelect={() => setActive(team.label)}
            />
          ))}
        </nav>

        <button
          type="button"
          onClick={() => setCollapsed((c) => !c)}
          aria-label={collapsed ? "Expand sidebar" : "Collapse sidebar"}
          aria-expanded={!collapsed}
          className="mt-auto flex h-8 items-center gap-2.5 overflow-hidden rounded-lg px-2.5 text-[12px] text-[#8e8e93] outline-none transition-colors hover:bg-black/[0.04] hover:text-[#1d1d1f] focus-visible:ring-2 focus-visible:ring-black/15 dark:hover:bg-white/[0.05] dark:hover:text-[#f5f5f7] dark:focus-visible:ring-white/20"
        >
          <PanelLeft className="h-4 w-4 shrink-0" strokeWidth={1.5} />
          <motion.span
            initial={false}
            animate={{ opacity: collapsed ? 0 : 1 }}
            transition={{ duration: 0.15 }}
            className="flex flex-1 items-center justify-between whitespace-nowrap"
          >
            Collapse
            <kbd className="rounded-[5px] border border-black/10 bg-white px-1.5 font-mono text-[10px] leading-4 dark:border-white/10 dark:bg-white/5">
              [
            </kbd>
          </motion.span>
        </button>
      </motion.aside>

      <main className="my-2 mr-2 flex min-w-0 flex-1 flex-col overflow-hidden rounded-xl bg-white shadow-[0_1px_2px_rgba(0,0,0,0.05),0_0_0_1px_rgba(0,0,0,0.04)] dark:bg-[#18181b] dark:shadow-[0_0_0_1px_rgba(255,255,255,0.06)]">
        <header className="flex h-11 shrink-0 items-center gap-2 border-b border-black/[0.06] px-4 text-[13px] font-medium dark:border-white/[0.06]">
          <span className="truncate">{active}</span>
          <span className="rounded-md bg-black/[0.05] px-1.5 text-[11px] tabular-nums text-[#8e8e93] dark:bg-white/10">
            {issues.length}
          </span>
        </header>
        <AnimatePresence mode="wait" initial={false}>
          <motion.ul
            key={active}
            initial={{ opacity: 0, y: 6 }}
            animate={{ opacity: 1, y: 0 }}
            exit={{ opacity: 0, y: -4 }}
            transition={{ duration: 0.18 }}
            className="flex-1 overflow-y-auto"
          >
            {issues.map((issue) => (
              <li
                key={issue.id}
                className="flex items-center gap-3 border-b border-black/[0.04] px-4 py-2.5 text-[13px] transition-colors hover:bg-black/[0.02] dark:border-white/[0.04] dark:hover:bg-white/[0.02]"
              >
                <IssueStatus status={issue.status} accent={accent} />
                <span className="truncate">{issue.title}</span>
              </li>
            ))}
          </motion.ul>
        </AnimatePresence>
      </main>
    </div>
  );
}
```

Give me the complete final code, ready to paste, and tell me in one line where to put it in my project.
````
