a6bd33bcff
Workspace sessions (docs/plans/desktop-parity, phases 1-5 and 7): - sessions.lane_id: a workspace lists only the sessions its panes held, stamped by bindRunSession (first writer wins, nested `claude -p` excluded); GET /api/sessions?lane=&archived= - session row state dot, double-click rename, archive (sessions.archived_at, hides only); the activity bar's duplicate Sessions tab removed - Fork beside Resume (--fork-session, Claude only), Ctrl/Cmd+click a live session opens it in a second pane, a diff line's comment is pasted into the workspace's last-focused pane (lib/panePaste.ts) dashboard_runs stability: - a pane's previous run is archived as <pane>@<started_at> instead of being overwritten by INSERT OR REPLACE - a run is flagged abandoned only once its tmux session is gone, at boot and on the run-heal beat (panes outlive a server restart) UI: - sidebar: no footer, language or theme block; small collapse button in the brand corner; version + update check in the connection details modal, a status-bar dot while a release is out; language in Settings -> General - one Switch component for every switch, the themed Checkbox for every checkbox (no native checkboxes) Also: AI Tools catalog trimmed to 10 built-ins (custom-file prompt modes tested through fixtures), and the workspace plans under docs/plans/ (the multi-user server plan lives in the AgentHub-Server repo).
46 lines
1.4 KiB
TypeScript
46 lines
1.4 KiB
TypeScript
/**
|
|
* @file Switch.tsx
|
|
* @description The app's ONE on/off switch (`role="switch"`): an accent track
|
|
* with a white knob, the same size everywhere. Settings rows, webhook targets
|
|
* and the AI Tools list all draw this — do not hand-roll another one; a
|
|
* yes/no choice inside a form or list is a `Checkbox` instead.
|
|
* @author Nguyễn Ngọc Trí Vĩ <vinnt@smartgift.vn>
|
|
*/
|
|
|
|
export function Switch({
|
|
checked,
|
|
onChange,
|
|
label,
|
|
title,
|
|
disabled = false,
|
|
}: {
|
|
checked: boolean;
|
|
onChange: (v: boolean) => void;
|
|
/** Accessible name — a switch usually sits beside its visible label. */
|
|
label?: string;
|
|
title?: string;
|
|
disabled?: boolean;
|
|
}) {
|
|
return (
|
|
<button
|
|
type="button"
|
|
role="switch"
|
|
aria-checked={checked}
|
|
aria-label={label}
|
|
title={title}
|
|
disabled={disabled}
|
|
onClick={() => onChange(!checked)}
|
|
className={`relative inline-flex h-5 w-9 shrink-0 items-center rounded-full transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent/40 disabled:cursor-not-allowed disabled:opacity-50 ${
|
|
checked ? "bg-accent" : "bg-surface-4"
|
|
}`}
|
|
>
|
|
<span
|
|
aria-hidden
|
|
className={`inline-block h-4 w-4 rounded-full bg-white shadow transition-transform ${
|
|
checked ? "translate-x-[18px]" : "translate-x-0.5"
|
|
}`}
|
|
/>
|
|
</button>
|
|
);
|
|
}
|