mirror of
https://github.com/fabro-sh/fabro.git
synced 2026-09-06 08:18:58 +00:00
Add collapsible code blocks and run workflow button to workflow detail
Code blocks are now expandable/collapsible with a chevron toggle, line count, and LOC count in the header. TOML defaults collapsed, DOT expanded. Workflow detail header gets a circular play button and max-w-prose on the description for readability. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
0f9606e9e3
commit
d980b6de12
2 changed files with 50 additions and 18 deletions
|
|
@ -1,3 +1,4 @@
|
|||
import { ChevronRightIcon } from "@heroicons/react/20/solid";
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import { useParams } from "react-router";
|
||||
import { workflowData } from "./workflow-detail";
|
||||
|
|
@ -7,13 +8,16 @@ function CodeBlock({
|
|||
code,
|
||||
lang,
|
||||
filename,
|
||||
defaultOpen = true,
|
||||
}: {
|
||||
code: string;
|
||||
lang: string;
|
||||
filename: string;
|
||||
defaultOpen?: boolean;
|
||||
}) {
|
||||
const containerRef = useRef<HTMLDivElement>(null);
|
||||
const [ready, setReady] = useState(false);
|
||||
const [open, setOpen] = useState(defaultOpen);
|
||||
|
||||
useEffect(() => {
|
||||
let cancelled = false;
|
||||
|
|
@ -45,22 +49,39 @@ function CodeBlock({
|
|||
};
|
||||
}, [code, lang]);
|
||||
|
||||
const lines = code.split("\n");
|
||||
const lineCount = lines.length;
|
||||
const loc = lines.filter((l) => l.trim().length > 0).length;
|
||||
|
||||
return (
|
||||
<div className="rounded-lg border border-white/[0.06] bg-navy-800/50 overflow-hidden">
|
||||
<div className="flex items-center gap-2 border-b border-white/[0.06] px-4 py-2.5">
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setOpen((v) => !v)}
|
||||
className="flex w-full items-center gap-2 px-4 py-2.5 text-left hover:bg-white/[0.02] transition-colors"
|
||||
>
|
||||
<ChevronRightIcon
|
||||
className={`size-4 text-navy-600 transition-transform duration-150 ${open ? "rotate-90" : ""}`}
|
||||
/>
|
||||
<span className="font-mono text-xs text-navy-600">{filename}</span>
|
||||
<span className="ml-auto font-mono text-xs text-navy-600/60">
|
||||
{lineCount} lines ({loc} loc)
|
||||
</span>
|
||||
</button>
|
||||
|
||||
<div className={open ? "" : "hidden"}>
|
||||
<div className="border-t border-white/[0.06]" />
|
||||
<div
|
||||
ref={containerRef}
|
||||
className={`shiki-container overflow-x-auto transition-opacity duration-200 ${ready ? "opacity-100" : "opacity-0"}`}
|
||||
/>
|
||||
|
||||
{!ready && (
|
||||
<pre className="px-4 py-4 font-mono text-sm leading-relaxed text-navy-600">
|
||||
{code}
|
||||
</pre>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div
|
||||
ref={containerRef}
|
||||
className={`shiki-container overflow-x-auto transition-opacity duration-200 ${ready ? "opacity-100" : "opacity-0"}`}
|
||||
/>
|
||||
|
||||
{!ready && (
|
||||
<pre className="px-4 py-4 font-mono text-sm leading-relaxed text-navy-600">
|
||||
{code}
|
||||
</pre>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
@ -75,7 +96,7 @@ export default function WorkflowDefinition() {
|
|||
|
||||
return (
|
||||
<div className="flex flex-col gap-6">
|
||||
<CodeBlock code={workflow.config} lang="toml" filename="task.toml" />
|
||||
<CodeBlock code={workflow.config} lang="toml" filename="task.toml" defaultOpen={false} />
|
||||
<CodeBlock code={workflow.graph} lang="dot" filename={workflow.filename} />
|
||||
</div>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -275,12 +275,23 @@ export default function WorkflowDetail() {
|
|||
|
||||
return (
|
||||
<div>
|
||||
<div className="mb-6">
|
||||
<div className="flex items-center gap-3">
|
||||
<h2 className="text-xl font-semibold text-white">{workflow.title}</h2>
|
||||
<span className="font-mono text-xs text-navy-600">{workflow.filename}</span>
|
||||
<div className="mb-6 flex items-center gap-4">
|
||||
<div className="min-w-0 flex-1">
|
||||
<div className="flex items-center gap-3">
|
||||
<h2 className="text-xl font-semibold text-white">{workflow.title}</h2>
|
||||
<span className="font-mono text-xs text-navy-600">{workflow.filename}</span>
|
||||
</div>
|
||||
<p className="mt-2 max-w-prose text-sm leading-relaxed text-ice-300">{workflow.description}</p>
|
||||
</div>
|
||||
<p className="mt-2 text-sm leading-relaxed text-ice-300">{workflow.description}</p>
|
||||
<button
|
||||
type="button"
|
||||
title="Run workflow"
|
||||
className="flex size-9 shrink-0 items-center justify-center rounded-full border border-mint/20 text-mint transition-colors hover:border-mint/50 hover:bg-mint/10 hover:text-white"
|
||||
>
|
||||
<svg viewBox="0 0 24 24" fill="currentColor" className="size-4" aria-hidden="true">
|
||||
<path fillRule="evenodd" d="M4.5 5.653c0-1.427 1.529-2.33 2.779-1.643l11.54 6.347c1.295.712 1.295 2.573 0 3.286L7.28 19.99c-1.25.687-2.779-.217-2.779-1.643V5.653Z" clipRule="evenodd" />
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div className="border-b border-white/[0.06]">
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue