DesignX
IDE@paxeer/ide/terminal-panelimplemented

Terminal panel

Multi-session terminal chrome on Card + Tabs + ScrollArea.

Install

$pnpm exec designx add @paxeer/ide/terminal-panel

Preview

Loading preview...

Source code

components/designx/ide/terminal-panel.tsxtsx
"use client";

import { useState } from "react";
import {
  Badge,
  Card,
  CardContent,
  CardHeader,
  CardTitle,
  ScrollRegion,
  Tabs,
  TabsContent,
  TabsList,
  TabsTrigger,
} from "@paxeer/core";

export interface TerminalSession {
  id: string;
  title: string;
  lines: string[];
  cwd?: string;
}

export function TerminalPanel({
  sessions = [
    {
      id: "bash",
      title: "bash",
      cwd: "~/designx",
      lines: [
        "designx@workspace:~/designx$ pnpm exec designx add @paxeer/ide/terminal-panel",
        "copied @paxeer/ide/terminal-panel → components/designx/ide/terminal-panel.tsx",
        "designx@workspace:~/designx$ _",
      ],
    },
    {
      id: "test",
      title: "pnpm test",
      cwd: "~/designx",
      lines: ["✓ registry lists 32+ items", "✓ demo typecheck"],
    },
  ],
}: {
  sessions?: TerminalSession[];
}) {
  const [active, setActive] = useState(sessions[0]?.id ?? "");

  return (
    <Card className="gap-0 py-0" data-slot="terminal-panel">
      <CardHeader className="border-b border-outline-variant px-3 py-2">
        <CardTitle className="text-[length:var(--md-sys-typescale-label-large-size)]">
          Terminal
        </CardTitle>
      </CardHeader>
      <CardContent className="p-0">
        <Tabs value={active} onValueChange={setActive}>
          <TabsList variant="line" className="w-full justify-start rounded-none border-b border-outline-variant px-2">
            {sessions.map((session) => (
              <TabsTrigger key={session.id} value={session.id}>
                {session.title}
              </TabsTrigger>
            ))}
          </TabsList>
          {sessions.map((session) => (
            <TabsContent key={session.id} value={session.id}>
              <ScrollRegion label={`${session.title} output`} className="h-40">
                <pre className="p-3 font-[family-name:var(--md-ref-typeface-mono)] text-[length:var(--md-sys-typescale-body-small-size)] text-on-surface">
                  {session.cwd ? <Badge variant="ghost">{session.cwd}</Badge> : null}
                  {"\n"}
                  {session.lines.join("\n")}
                </pre>
              </ScrollRegion>
            </TabsContent>
          ))}
        </Tabs>
      </CardContent>
    </Card>
  );
}