diff options
| author | soryu <soryu@soryu.co> | 2026-02-09 00:11:51 +0000 |
|---|---|---|
| committer | soryu <soryu@soryu.co> | 2026-02-09 00:11:51 +0000 |
| commit | 8c23b3ab6f7fabca01b0468911bae073aa5ced32 (patch) | |
| tree | f50159aee13b13f0b55618ac09e9be1f89a41bb2 /makima/frontend/src/components/directives/DirectiveList.tsx | |
| parent | 3662b334dfd68cfdf00ed44ae88927c2e1b2aabe (diff) | |
| download | soryu-8c23b3ab6f7fabca01b0468911bae073aa5ced32.tar.gz soryu-8c23b3ab6f7fabca01b0468911bae073aa5ced32.zip | |
Add new directive mechanism v3
Diffstat (limited to 'makima/frontend/src/components/directives/DirectiveList.tsx')
| -rw-r--r-- | makima/frontend/src/components/directives/DirectiveList.tsx | 87 |
1 files changed, 87 insertions, 0 deletions
diff --git a/makima/frontend/src/components/directives/DirectiveList.tsx b/makima/frontend/src/components/directives/DirectiveList.tsx new file mode 100644 index 0000000..6393ea7 --- /dev/null +++ b/makima/frontend/src/components/directives/DirectiveList.tsx @@ -0,0 +1,87 @@ +import type { DirectiveSummary, DirectiveStatus } from "../../lib/api"; + +const STATUS_BADGE: Record<DirectiveStatus, { color: string; label: string }> = { + draft: { color: "text-[#7788aa] border-[#2a3a5a]", label: "DRAFT" }, + active: { color: "text-green-400 border-green-800", label: "ACTIVE" }, + idle: { color: "text-yellow-400 border-yellow-800", label: "IDLE" }, + paused: { color: "text-orange-400 border-orange-800", label: "PAUSED" }, + archived: { color: "text-[#556677] border-[#2a3a5a]", label: "ARCHIVED" }, +}; + +interface DirectiveListProps { + directives: DirectiveSummary[]; + selectedId: string | null; + onSelect: (id: string) => void; + onCreate: () => void; +} + +export function DirectiveList({ directives, selectedId, onSelect, onCreate }: DirectiveListProps) { + return ( + <div className="flex flex-col h-full"> + <div className="flex items-center justify-between px-3 py-2 border-b border-dashed border-[rgba(117,170,252,0.2)]"> + <span className="text-[11px] font-mono text-[#9bc3ff] uppercase tracking-wide"> + Directives + </span> + <button + type="button" + onClick={onCreate} + className="text-[11px] font-mono text-[#75aafc] hover:text-white bg-transparent border border-[rgba(117,170,252,0.3)] rounded px-2 py-0.5 hover:border-[rgba(117,170,252,0.6)] transition-colors" + > + + New + </button> + </div> + <div className="flex-1 overflow-y-auto"> + {directives.length === 0 ? ( + <div className="px-3 py-6 text-center text-[#556677] font-mono text-[11px]"> + No directives yet + </div> + ) : ( + directives.map((d) => { + const badge = STATUS_BADGE[d.status] || STATUS_BADGE.draft; + const progress = d.totalSteps > 0 + ? Math.round((d.completedSteps / d.totalSteps) * 100) + : 0; + + return ( + <button + key={d.id} + type="button" + onClick={() => onSelect(d.id)} + className={`w-full text-left px-3 py-2.5 border-b border-[rgba(117,170,252,0.1)] hover:bg-[rgba(117,170,252,0.05)] transition-colors ${ + selectedId === d.id ? "bg-[rgba(117,170,252,0.1)]" : "" + }`} + > + <div className="flex items-center justify-between mb-1"> + <span className="text-[12px] font-mono text-white truncate pr-2"> + {d.title} + </span> + <span + className={`text-[9px] font-mono ${badge.color} border rounded px-1.5 py-0.5 shrink-0`} + > + {badge.label} + </span> + </div> + <p className="text-[10px] text-[#7788aa] font-mono truncate mb-1.5"> + {d.goal} + </p> + {d.totalSteps > 0 && ( + <div className="flex items-center gap-2"> + <div className="flex-1 h-1 bg-[#1a2540] rounded overflow-hidden"> + <div + className="h-full bg-emerald-600 rounded transition-all" + style={{ width: `${progress}%` }} + /> + </div> + <span className="text-[9px] font-mono text-[#556677] shrink-0"> + {d.completedSteps}/{d.totalSteps} + </span> + </div> + )} + </button> + ); + }) + )} + </div> + </div> + ); +} |
