mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-11-05 03:41:32 +01:00
Keep diff renderer dependency in plugin
This commit is contained in:
1 parent
d9a59827fd
commit
8baca513c0
3 files changed
+56
-530
No files matched your search
@@ -45,7 +45,6 @@
|
||||
"@paperclipai/adapter-pi-local": "workspace:*",
|
||||
"@paperclipai/adapter-utils": "workspace:*",
|
||||
"@paperclipai/shared": "workspace:*",
|
||||
"@pierre/diffs": "^1.1.22",
|
||||
"@radix-ui/react-slot": "^1.2.4",
|
||||
"@tailwindcss/typography": "^0.5.19",
|
||||
"@tanstack/react-query": "^5.90.21",
|
||||
|
||||
@@ -1,276 +0,0 @@
|
||||
import { parsePatchFiles } from "@pierre/diffs";
|
||||
import type { FileDiffMetadata } from "@pierre/diffs";
|
||||
|
||||
const smallDiffPatch = `diff --git a/src/pagination.ts b/src/pagination.ts
|
||||
index 6c2a1f4..e91d2ac 100644
|
||||
--- a/src/pagination.ts
|
||||
+++ b/src/pagination.ts
|
||||
@@ -1,8 +1,12 @@
|
||||
export type PageRequest = {
|
||||
limit: number;
|
||||
+ cursor?: string;
|
||||
offset: number;
|
||||
};
|
||||
|
||||
export function buildOffset(offset: number, limit: number) {
|
||||
- return { offset, limit };
|
||||
+ return {
|
||||
+ offset,
|
||||
+ limit,
|
||||
+ hasMore: limit > 0,
|
||||
+ };
|
||||
}
|
||||
`;
|
||||
|
||||
const largeDiffPatch = `diff --git a/tmp/pierre-large-old.ts b/tmp/pierre-large-new.ts
|
||||
index 6ea4ef1..9449233 100644
|
||||
--- a/tmp/pierre-large-old.ts
|
||||
+++ b/tmp/pierre-large-new.ts
|
||||
@@ -1,160 +1,163 @@
|
||||
export const value_001 = '1';
|
||||
export const value_002 = '2';
|
||||
-export const value_003 = '3';
|
||||
+export const value_003 = '6';
|
||||
export const value_004 = '4';
|
||||
export const value_005 = '5';
|
||||
-export const value_006 = '6';
|
||||
+export const value_006 = '12';
|
||||
export const value_007 = '7';
|
||||
export const value_008 = '8';
|
||||
-export const value_009 = '9';
|
||||
+export const value_009 = '18';
|
||||
export const value_010 = '10';
|
||||
export const value_011 = '11';
|
||||
-export const value_012 = '12';
|
||||
+export const value_012 = '24';
|
||||
export const value_013 = '13';
|
||||
export const value_014 = '14';
|
||||
-export const value_015 = '15';
|
||||
+export const value_015 = '30';
|
||||
export const value_016 = '16';
|
||||
export const value_017 = '17';
|
||||
-export const value_018 = '18';
|
||||
+export const value_018 = '36';
|
||||
export const value_019 = '19';
|
||||
export const value_020 = '20';
|
||||
+export function isEven(n: number) {
|
||||
+ return n % 2 === 0;
|
||||
+}
|
||||
|
||||
-export const value_021 = '21';
|
||||
+export const value_021 = '42';
|
||||
export const value_022 = '22';
|
||||
export const value_023 = '23';
|
||||
-export const value_024 = '24';
|
||||
+export const value_024 = '48';
|
||||
export const value_025 = '25';
|
||||
export const value_026 = '26';
|
||||
-export const value_027 = '27';
|
||||
+export const value_027 = '54';
|
||||
export const value_028 = '28';
|
||||
export const value_029 = '29';
|
||||
-export const value_030 = '30';
|
||||
+export const value_030 = '60';
|
||||
export const value_031 = '31';
|
||||
export const value_032 = '32';
|
||||
-export const value_033 = '33';
|
||||
+export const value_033 = '66';
|
||||
export const value_034 = '34';
|
||||
export const value_035 = '35';
|
||||
-export const value_036 = '36';
|
||||
+export const value_036 = '72';
|
||||
export const value_037 = '37';
|
||||
export const value_038 = '38';
|
||||
-export const value_039 = '39';
|
||||
+export const value_039 = '78';
|
||||
export const value_040 = '40';
|
||||
export const value_041 = '41';
|
||||
-export const value_042 = '42';
|
||||
+export const value_042 = '84';
|
||||
export const value_043 = '43';
|
||||
export const value_044 = '44';
|
||||
-export const value_045 = '45';
|
||||
+export const value_045 = '90';
|
||||
export const value_046 = '46';
|
||||
export const value_047 = '47';
|
||||
-export const value_048 = '48';
|
||||
+export const value_048 = '96';
|
||||
export const value_049 = '49';
|
||||
export const value_050 = '50';
|
||||
-export const value_051 = '51';
|
||||
+export const value_051 = '102';
|
||||
export const value_052 = '52';
|
||||
export const value_053 = '53';
|
||||
-export const value_054 = '54';
|
||||
+export const value_054 = '108';
|
||||
export const value_055 = '55';
|
||||
export const value_056 = '56';
|
||||
-export const value_057 = '57';
|
||||
+export const value_057 = '114';
|
||||
export const value_058 = '58';
|
||||
export const value_059 = '59';
|
||||
-export const value_060 = '60';
|
||||
+export const value_060 = '120';
|
||||
export const value_061 = '61';
|
||||
export const value_062 = '62';
|
||||
-export const value_063 = '63';
|
||||
+export const value_063 = '126';
|
||||
export const value_064 = '64';
|
||||
export const value_065 = '65';
|
||||
-export const value_066 = '66';
|
||||
+export const value_066 = '132';
|
||||
export const value_067 = '67';
|
||||
export const value_068 = '68';
|
||||
-export const value_069 = '69';
|
||||
+export const value_069 = '138';
|
||||
export const value_070 = '70';
|
||||
export const value_071 = '71';
|
||||
-export const value_072 = '72';
|
||||
+export const value_072 = '144';
|
||||
export const value_073 = '73';
|
||||
export const value_074 = '74';
|
||||
-export const value_075 = '75';
|
||||
+export const value_075 = '150';
|
||||
export const value_076 = '76';
|
||||
export const value_077 = '77';
|
||||
-export const value_078 = '78';
|
||||
+export const value_078 = '156';
|
||||
export const value_079 = '79';
|
||||
export const value_080 = '80';
|
||||
-export const value_081 = '81';
|
||||
+export const value_081 = '162';
|
||||
export const value_082 = '82';
|
||||
export const value_083 = '83';
|
||||
-export const value_084 = '84';
|
||||
+export const value_084 = '168';
|
||||
export const value_085 = '85';
|
||||
export const value_086 = '86';
|
||||
-export const value_087 = '87';
|
||||
+export const value_087 = '174';
|
||||
export const value_088 = '88';
|
||||
export const value_089 = '89';
|
||||
-export const value_090 = '90';
|
||||
+export const value_090 = '180';
|
||||
export const value_091 = '91';
|
||||
export const value_092 = '92';
|
||||
-export const value_093 = '93';
|
||||
+export const value_093 = '186';
|
||||
export const value_094 = '94';
|
||||
export const value_095 = '95';
|
||||
-export const value_096 = '96';
|
||||
+export const value_096 = '192';
|
||||
export const value_097 = '97';
|
||||
export const value_098 = '98';
|
||||
-export const value_099 = '99';
|
||||
+export const value_099 = '198';
|
||||
export const value_100 = '100';
|
||||
export const value_101 = '101';
|
||||
-export const value_102 = '102';
|
||||
+export const value_102 = '204';
|
||||
export const value_103 = '103';
|
||||
export const value_104 = '104';
|
||||
-export const value_105 = '105';
|
||||
+export const value_105 = '210';
|
||||
export const value_106 = '106';
|
||||
export const value_107 = '107';
|
||||
-export const value_108 = '108';
|
||||
+export const value_108 = '216';
|
||||
export const value_109 = '109';
|
||||
export const value_110 = '110';
|
||||
-export const value_111 = '111';
|
||||
+export const value_111 = '222';
|
||||
export const value_112 = '112';
|
||||
export const value_113 = '113';
|
||||
-export const value_114 = '114';
|
||||
+export const value_114 = '228';
|
||||
export const value_115 = '115';
|
||||
export const value_116 = '116';
|
||||
-export const value_117 = '117';
|
||||
+export const value_117 = '234';
|
||||
export const value_118 = '118';
|
||||
export const value_119 = '119';
|
||||
-export const value_120 = '120';
|
||||
+export const value_120 = '240';
|
||||
export const value_121 = '121';
|
||||
export const value_122 = '122';
|
||||
-export const value_123 = '123';
|
||||
+export const value_123 = '246';
|
||||
export const value_124 = '124';
|
||||
export const value_125 = '125';
|
||||
-export const value_126 = '126';
|
||||
+export const value_126 = '252';
|
||||
export const value_127 = '127';
|
||||
export const value_128 = '128';
|
||||
-export const value_129 = '129';
|
||||
+export const value_129 = '258';
|
||||
export const value_130 = '130';
|
||||
export const value_131 = '131';
|
||||
-export const value_132 = '132';
|
||||
+export const value_132 = '264';
|
||||
export const value_133 = '133';
|
||||
export const value_134 = '134';
|
||||
-export const value_135 = '135';
|
||||
+export const value_135 = '270';
|
||||
export const value_136 = '136';
|
||||
export const value_137 = '137';
|
||||
-export const value_138 = '138';
|
||||
+export const value_138 = '276';
|
||||
export const value_139 = '139';
|
||||
export const value_140 = '140';
|
||||
-export const value_141 = '141';
|
||||
+export const value_141 = '282';
|
||||
export const value_142 = '142';
|
||||
export const value_143 = '143';
|
||||
-export const value_144 = '144';
|
||||
+export const value_144 = '288';
|
||||
export const value_145 = '145';
|
||||
export const value_146 = '146';
|
||||
-export const value_147 = '147';
|
||||
+export const value_147 = '294';
|
||||
export const value_148 = '148';
|
||||
export const value_149 = '149';
|
||||
-export const value_150 = '150';
|
||||
+export const value_150 = '300';
|
||||
export const value_151 = '151';
|
||||
export const value_152 = '152';
|
||||
-export const value_153 = '153';
|
||||
+export const value_153 = '306';
|
||||
export const value_154 = '154';
|
||||
export const value_155 = '155';
|
||||
-export const value_156 = '156';
|
||||
+export const value_156 = '312';
|
||||
export const value_157 = '157';
|
||||
export const value_158 = '158';
|
||||
-export const value_159 = '159';
|
||||
+export const value_159 = '318';
|
||||
export const value_160 = '160';
|
||||
`;
|
||||
|
||||
function parsePatchFilesOrEmpty(patch: string): FileDiffMetadata[] {
|
||||
return parsePatchFiles(patch).flatMap((entry) => entry.files);
|
||||
}
|
||||
|
||||
export type DiffRendererFixtureId = "small" | "large";
|
||||
|
||||
export interface DiffRendererFixture {
|
||||
id: DiffRendererFixtureId;
|
||||
label: string;
|
||||
patch: string;
|
||||
fileDiffs: FileDiffMetadata[];
|
||||
}
|
||||
|
||||
export const DIFF_RENDERER_FIXTURES: DiffRendererFixture[] = [
|
||||
{
|
||||
id: "small",
|
||||
label: "Small mixed edit fixture",
|
||||
patch: smallDiffPatch,
|
||||
fileDiffs: parsePatchFilesOrEmpty(smallDiffPatch),
|
||||
},
|
||||
{
|
||||
id: "large",
|
||||
label: "Large 160-line patch fixture",
|
||||
patch: largeDiffPatch,
|
||||
fileDiffs: parsePatchFilesOrEmpty(largeDiffPatch),
|
||||
},
|
||||
];
|
||||
|
||||
@@ -1,30 +1,22 @@
|
||||
import { useState } from "react";
|
||||
import { FileDiff, PatchDiff } from "@pierre/diffs/react";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
import { cn, formatDateTime } from "../lib/utils";
|
||||
import { DIFF_RENDERER_FIXTURES, type DiffRendererFixtureId } from "../fixtures/diffRendererFixtures";
|
||||
import { Identity } from "../components/Identity";
|
||||
import { StatusBadge } from "../components/StatusBadge";
|
||||
import { RunTranscriptView, type TranscriptDensity, type TranscriptMode } from "../components/transcript/RunTranscriptView";
|
||||
import { runTranscriptFixtureEntries, runTranscriptFixtureMeta } from "../fixtures/runTranscriptFixtures";
|
||||
import { ExternalLink, FlaskConical, LayoutPanelLeft, MonitorCog, PanelsTopLeft, RadioTower, GitCompare } from "lucide-react";
|
||||
import { ExternalLink, FlaskConical, LayoutPanelLeft, MonitorCog, PanelsTopLeft, RadioTower } from "lucide-react";
|
||||
|
||||
type SurfaceId = "detail" | "live" | "dashboard" | "diffs";
|
||||
type DiffComponentMode = "patch" | "file";
|
||||
type DiffStyle = "unified" | "split";
|
||||
type DiffOverflow = "scroll" | "wrap";
|
||||
type DiffThemeType = "system" | "light" | "dark";
|
||||
type SurfaceId = "detail" | "live" | "dashboard";
|
||||
|
||||
type SurfaceOption = {
|
||||
const surfaceOptions: Array<{
|
||||
id: SurfaceId;
|
||||
label: string;
|
||||
eyebrow: string;
|
||||
description: string;
|
||||
icon: typeof LayoutPanelLeft;
|
||||
};
|
||||
|
||||
const surfaceOptions: SurfaceOption[] = [
|
||||
}> = [
|
||||
{
|
||||
id: "detail",
|
||||
label: "Run Detail",
|
||||
@@ -46,13 +38,6 @@ const surfaceOptions: SurfaceOption[] = [
|
||||
description: "The active-agents dashboard card, tuned for compact scanning while keeping the same transcript language.",
|
||||
icon: PanelsTopLeft,
|
||||
},
|
||||
{
|
||||
id: "diffs",
|
||||
label: "Diff Renderer",
|
||||
eyebrow: "@pierre/diffs",
|
||||
description: "A spike harness for `PatchDiff` and `FileDiff` with realistic fixtures and rendering options.",
|
||||
icon: GitCompare,
|
||||
},
|
||||
];
|
||||
|
||||
function previewEntries(surface: SurfaceId) {
|
||||
@@ -175,9 +160,7 @@ function DashboardPreview({
|
||||
<div className="flex items-center gap-2">
|
||||
<span className={cn(
|
||||
"inline-flex h-2.5 w-2.5 rounded-full",
|
||||
streaming
|
||||
? "bg-cyan-500 shadow-[0_0_0_6px_rgba(34,211,238,0.12)]"
|
||||
: "bg-muted-foreground/35",
|
||||
streaming ? "bg-cyan-500 shadow-[0_0_0_6px_rgba(34,211,238,0.12)]" : "bg-muted-foreground/35",
|
||||
)} />
|
||||
<Identity name={runTranscriptFixtureMeta.agentName} size="sm" />
|
||||
</div>
|
||||
@@ -207,111 +190,12 @@ function DashboardPreview({
|
||||
);
|
||||
}
|
||||
|
||||
function DiffRendererPreview({
|
||||
fixtureId,
|
||||
componentMode,
|
||||
diffStyle,
|
||||
overflow,
|
||||
showLineNumbers,
|
||||
disableBackground,
|
||||
themeType,
|
||||
}: {
|
||||
fixtureId: DiffRendererFixtureId;
|
||||
componentMode: DiffComponentMode;
|
||||
diffStyle: DiffStyle;
|
||||
overflow: DiffOverflow;
|
||||
showLineNumbers: boolean;
|
||||
disableBackground: boolean;
|
||||
themeType: DiffThemeType;
|
||||
}) {
|
||||
const fixture = DIFF_RENDERER_FIXTURES.find((item) => item.id === fixtureId) ?? DIFF_RENDERER_FIXTURES[0];
|
||||
const firstFileDiff = fixture.fileDiffs[0];
|
||||
|
||||
const options = {
|
||||
diffStyle,
|
||||
overflow,
|
||||
disableLineNumbers: !showLineNumbers,
|
||||
disableBackground,
|
||||
themeType,
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="overflow-hidden rounded-xl border border-border/70 bg-background/75 shadow-[0_24px_60px_rgba(15,23,42,0.08)]">
|
||||
<div className="border-b border-border/60 bg-background/90 px-5 py-4">
|
||||
<div className="flex flex-wrap items-center gap-2">
|
||||
<Badge variant="outline" className="uppercase tracking-[0.18em] text-[10px]">
|
||||
Diff Render
|
||||
</Badge>
|
||||
<span className="rounded-full border border-border/70 bg-background/70 px-2 py-1 text-[10px] text-muted-foreground">
|
||||
{fixture.label}
|
||||
</span>
|
||||
</div>
|
||||
<div className="mt-2 text-sm font-medium">
|
||||
{componentMode === "patch" ? "PatchDiff" : "FileDiff"} • {diffStyle.toUpperCase()} • {fixture.fileDiffs.length} file(s)
|
||||
</div>
|
||||
</div>
|
||||
<div className="max-h-[720px] overflow-hidden bg-[radial-gradient(circle_at_top_left,rgba(8,145,178,0.08),transparent_36%),radial-gradient(circle_at_bottom_right,rgba(245,158,11,0.10),transparent_28%)] p-5">
|
||||
<div className="rounded-lg border border-border/70 bg-background/80 p-3">
|
||||
{componentMode === "file" && !firstFileDiff ? (
|
||||
<div className="rounded-lg border border-destructive/35 bg-destructive/10 px-3 py-2 text-sm text-destructive">
|
||||
Parsed fixture did not produce a file diff payload for `FileDiff`.
|
||||
</div>
|
||||
) : componentMode === "patch" ? (
|
||||
<PatchDiff patch={fixture.patch} options={options} />
|
||||
) : (
|
||||
<FileDiff fileDiff={firstFileDiff} options={options} />
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function ToggleButtonGroup<T extends string>({
|
||||
selected,
|
||||
options,
|
||||
onSelect,
|
||||
}: {
|
||||
selected: T;
|
||||
options: Array<{
|
||||
id: T;
|
||||
label: string;
|
||||
}>;
|
||||
onSelect: (next: T) => void;
|
||||
}) {
|
||||
return (
|
||||
<div className="inline-flex rounded-full border border-border/70 bg-background/80 p-1">
|
||||
{options.map((option) => (
|
||||
<button
|
||||
key={option.id}
|
||||
type="button"
|
||||
className={cn(
|
||||
"rounded-full px-3 py-1 text-xs font-medium capitalize transition-colors",
|
||||
selected === option.id ? "bg-accent text-foreground" : "text-muted-foreground hover:text-foreground",
|
||||
)}
|
||||
onClick={() => onSelect(option.id)}
|
||||
>
|
||||
{option.label}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export function RunTranscriptUxLab() {
|
||||
const [selectedSurface, setSelectedSurface] = useState<SurfaceId>("detail");
|
||||
const [detailMode, setDetailMode] = useState<TranscriptMode>("nice");
|
||||
const [streaming, setStreaming] = useState(true);
|
||||
const [density, setDensity] = useState<TranscriptDensity>("comfortable");
|
||||
|
||||
const [diffComponentMode, setDiffComponentMode] = useState<DiffComponentMode>("file");
|
||||
const [diffFixture, setDiffFixture] = useState<DiffRendererFixtureId>(DIFF_RENDERER_FIXTURES[0]?.id ?? "small");
|
||||
const [diffStyle, setDiffStyle] = useState<DiffStyle>("unified");
|
||||
const [diffOverflow, setDiffOverflow] = useState<DiffOverflow>("scroll");
|
||||
const [diffShowLineNumbers, setDiffShowLineNumbers] = useState(true);
|
||||
const [diffDisableBackground, setDiffDisableBackground] = useState(false);
|
||||
const [diffThemeType, setDiffThemeType] = useState<DiffThemeType>("system");
|
||||
|
||||
const selected = surfaceOptions.find((option) => option.id === selectedSurface) ?? surfaceOptions[0];
|
||||
|
||||
return (
|
||||
@@ -326,7 +210,7 @@ export function RunTranscriptUxLab() {
|
||||
</div>
|
||||
<h1 className="mt-4 text-2xl font-semibold tracking-tight">Run Transcript Fixtures</h1>
|
||||
<p className="mt-2 text-sm text-muted-foreground">
|
||||
Built from real Paperclip development data, with a focused spike surface for diff rendering controls.
|
||||
Built from a real Paperclip development run, then sanitized so no secrets, local paths, or environment details survive into the fixture.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -377,129 +261,58 @@ export function RunTranscriptUxLab() {
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="mb-5 flex flex-wrap items-center gap-2">
|
||||
{selectedSurface === "diffs" ? (
|
||||
<>
|
||||
<span className="text-[11px] font-semibold uppercase tracking-[0.18em] text-muted-foreground">
|
||||
Controls
|
||||
</span>
|
||||
<ToggleButtonGroup<DiffComponentMode>
|
||||
selected={diffComponentMode}
|
||||
options={[
|
||||
{ id: "patch", label: "PatchDiff" },
|
||||
{ id: "file", label: "FileDiff" },
|
||||
]}
|
||||
onSelect={setDiffComponentMode}
|
||||
/>
|
||||
<ToggleButtonGroup<DiffRendererFixtureId>
|
||||
selected={diffFixture}
|
||||
options={DIFF_RENDERER_FIXTURES.map((fixture) => ({
|
||||
id: fixture.id,
|
||||
label: fixture.label,
|
||||
}))}
|
||||
onSelect={setDiffFixture}
|
||||
/>
|
||||
<ToggleButtonGroup<DiffStyle>
|
||||
selected={diffStyle}
|
||||
options={[
|
||||
{ id: "unified", label: "Unified" },
|
||||
{ id: "split", label: "Split" },
|
||||
]}
|
||||
onSelect={setDiffStyle}
|
||||
/>
|
||||
<ToggleButtonGroup<DiffOverflow>
|
||||
selected={diffOverflow}
|
||||
options={[{ id: "scroll", label: "Scroll" }, { id: "wrap", label: "Wrap" }]}
|
||||
onSelect={setDiffOverflow}
|
||||
/>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
className="rounded-full"
|
||||
onClick={() => setDiffShowLineNumbers((value) => !value)}
|
||||
>
|
||||
{diffShowLineNumbers ? "Hide" : "Show"} line numbers
|
||||
</Button>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
className="rounded-full"
|
||||
onClick={() => setDiffDisableBackground((value) => !value)}
|
||||
>
|
||||
{diffDisableBackground ? "Enable" : "Disable"} background
|
||||
</Button>
|
||||
<ToggleButtonGroup<DiffThemeType>
|
||||
selected={diffThemeType}
|
||||
options={[
|
||||
{ id: "system", label: "Auto" },
|
||||
{ id: "light", label: "Light" },
|
||||
{ id: "dark", label: "Dark" },
|
||||
]}
|
||||
onSelect={setDiffThemeType}
|
||||
/>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<span className="text-[11px] font-semibold uppercase tracking-[0.18em] text-muted-foreground">
|
||||
Controls
|
||||
</span>
|
||||
<div className="inline-flex rounded-full border border-border/70 bg-background/80 p-1">
|
||||
{(["nice", "raw"] as const).map((mode) => (
|
||||
<button
|
||||
key={mode}
|
||||
type="button"
|
||||
className={cn(
|
||||
"rounded-full px-3 py-1 text-xs font-medium capitalize transition-colors",
|
||||
detailMode === mode
|
||||
? "bg-accent text-foreground"
|
||||
: "text-muted-foreground hover:text-foreground",
|
||||
)}
|
||||
onClick={() => setDetailMode(mode)}
|
||||
>
|
||||
{mode}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
<div className="inline-flex rounded-full border border-border/70 bg-background/80 p-1">
|
||||
{(["comfortable", "compact"] as const).map((nextDensity) => (
|
||||
<button
|
||||
key={nextDensity}
|
||||
type="button"
|
||||
className={cn(
|
||||
"rounded-full px-3 py-1 text-xs font-medium capitalize transition-colors",
|
||||
density === nextDensity
|
||||
? "bg-accent text-foreground"
|
||||
: "text-muted-foreground hover:text-foreground",
|
||||
)}
|
||||
onClick={() => setDensity(nextDensity)}
|
||||
>
|
||||
{nextDensity}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
className="rounded-full"
|
||||
onClick={() => setStreaming((value) => !value)}
|
||||
>
|
||||
{streaming ? "Show settled state" : "Show streaming state"}
|
||||
</Button>
|
||||
</>
|
||||
)}
|
||||
<div className="flex flex-wrap items-center gap-2">
|
||||
<Badge variant="outline" className="rounded-full px-3 py-1 text-[10px] uppercase tracking-[0.18em]">
|
||||
Source run {runTranscriptFixtureMeta.sourceRunId.slice(0, 8)}
|
||||
</Badge>
|
||||
<Badge variant="outline" className="rounded-full px-3 py-1 text-[10px] uppercase tracking-[0.18em]">
|
||||
{runTranscriptFixtureMeta.issueIdentifier}
|
||||
</Badge>
|
||||
</div>
|
||||
<Badge
|
||||
</div>
|
||||
|
||||
<div className="mb-5 flex flex-wrap items-center gap-2">
|
||||
<span className="text-[11px] font-semibold uppercase tracking-[0.18em] text-muted-foreground">
|
||||
Controls
|
||||
</span>
|
||||
<div className="inline-flex rounded-full border border-border/70 bg-background/80 p-1">
|
||||
{(["nice", "raw"] as const).map((mode) => (
|
||||
<button
|
||||
key={mode}
|
||||
type="button"
|
||||
className={cn(
|
||||
"rounded-full px-3 py-1 text-xs font-medium capitalize transition-colors",
|
||||
detailMode === mode ? "bg-accent text-foreground" : "text-muted-foreground hover:text-foreground",
|
||||
)}
|
||||
onClick={() => setDetailMode(mode)}
|
||||
>
|
||||
{mode}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
<div className="inline-flex rounded-full border border-border/70 bg-background/80 p-1">
|
||||
{(["comfortable", "compact"] as const).map((nextDensity) => (
|
||||
<button
|
||||
key={nextDensity}
|
||||
type="button"
|
||||
className={cn(
|
||||
"rounded-full px-3 py-1 text-xs font-medium capitalize transition-colors",
|
||||
density === nextDensity ? "bg-accent text-foreground" : "text-muted-foreground hover:text-foreground",
|
||||
)}
|
||||
onClick={() => setDensity(nextDensity)}
|
||||
>
|
||||
{nextDensity}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
<Button
|
||||
variant="outline"
|
||||
className="mb-0.5 flex rounded-full px-3 py-1 text-[10px] uppercase tracking-[0.18em]"
|
||||
size="sm"
|
||||
className="rounded-full"
|
||||
onClick={() => setStreaming((value) => !value)}
|
||||
>
|
||||
Source run {runTranscriptFixtureMeta.sourceRunId.slice(0, 8)}
|
||||
</Badge>
|
||||
<Badge
|
||||
variant="outline"
|
||||
className="mb-0.5 rounded-full px-3 py-1 text-[10px] uppercase tracking-[0.18em]"
|
||||
>
|
||||
{runTranscriptFixtureMeta.issueIdentifier}
|
||||
</Badge>
|
||||
{streaming ? "Show settled state" : "Show streaming state"}
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
{selectedSurface === "detail" ? (
|
||||
@@ -510,18 +323,8 @@ export function RunTranscriptUxLab() {
|
||||
<div className={cn(density === "compact" && "max-w-4xl")}>
|
||||
<LiveWidgetPreview streaming={streaming} mode={detailMode} density={density} />
|
||||
</div>
|
||||
) : selectedSurface === "dashboard" ? (
|
||||
<DashboardPreview streaming={streaming} mode={detailMode} density={density} />
|
||||
) : (
|
||||
<DiffRendererPreview
|
||||
fixtureId={diffFixture}
|
||||
componentMode={diffComponentMode}
|
||||
diffStyle={diffStyle}
|
||||
overflow={diffOverflow}
|
||||
showLineNumbers={diffShowLineNumbers}
|
||||
disableBackground={diffDisableBackground}
|
||||
themeType={diffThemeType}
|
||||
/>
|
||||
<DashboardPreview streaming={streaming} mode={detailMode} density={density} />
|
||||
)}
|
||||
</main>
|
||||
</div>
|
||||
|
||||
Reference in new issue
Block a user