fix(ui): heartbeat dialog layout tweaks + skills sort order

- Move checklist section to bottom of heartbeat dialog
- Reduce checklist textarea height (rows 8, min-h 120/200px)
- Widen interval input (w-24)
- Skills list: sort ungranted skills first
This commit is contained in:
viettranx committed 2026-03-18 23:26:24 +07:00
1 parent 5b349db7eb
commit 545941eeb4
2 files changed
+27 -27

No files matched your search

@@ -182,7 +182,7 @@ export function HeartbeatConfigDialog({
min={5}
value={intervalMin}
onChange={(e) => setIntervalMin(Math.max(5, Number(e.target.value) || 5))}
className="w-16 text-center text-base md:text-sm"
className="w-24 text-center text-base md:text-sm"
/>
<span className="text-xs text-muted-foreground">min</span>
</div>
@@ -333,31 +333,6 @@ export function HeartbeatConfigDialog({
<p className="text-xs text-muted-foreground">{t("heartbeat.scheduleHint")}</p>
</div>
{/* ── Checklist — WHAT the agent does ── */}
<div className="space-y-2">
<div className="flex items-center gap-2">
<FileText className="h-3.5 w-3.5 text-emerald-500" />
<h4 className="text-xs font-semibold uppercase tracking-wide text-muted-foreground">
{t("heartbeat.checklist")}
</h4>
</div>
<p className="text-xs text-muted-foreground">{t("heartbeat.checklistHint")}</p>
{checklistLoading ? (
<div className="flex items-center gap-2 text-xs text-muted-foreground py-4 justify-center">
<Loader2 className="h-3.5 w-3.5 animate-spin" />
{t("heartbeat.checklistLoading")}
</div>
) : (
<Textarea
value={checklist}
onChange={(e) => setChecklistState(e.target.value)}
placeholder={t("heartbeat.checklistPlaceholder")}
rows={15}
className="text-base md:text-sm font-mono resize-y min-h-[200px] sm:min-h-[400px]"
/>
)}
</div>
{/* ── Advanced (collapsible) ── */}
<div className="rounded-lg border">
<button
@@ -415,6 +390,31 @@ export function HeartbeatConfigDialog({
)}
</div>
{/* ── Checklist — WHAT the agent does ── */}
<div className="space-y-2">
<div className="flex items-center gap-2">
<FileText className="h-3.5 w-3.5 text-emerald-500" />
<h4 className="text-xs font-semibold uppercase tracking-wide text-muted-foreground">
{t("heartbeat.checklist")}
</h4>
</div>
<p className="text-xs text-muted-foreground">{t("heartbeat.checklistHint")}</p>
{checklistLoading ? (
<div className="flex items-center gap-2 text-xs text-muted-foreground py-4 justify-center">
<Loader2 className="h-3.5 w-3.5 animate-spin" />
{t("heartbeat.checklistLoading")}
</div>
) : (
<Textarea
value={checklist}
onChange={(e) => setChecklistState(e.target.value)}
placeholder={t("heartbeat.checklistPlaceholder")}
rows={8}
className="text-base md:text-sm font-mono resize-y min-h-[120px] sm:min-h-[200px]"
/>
)}
</div>
{/* Bottom padding for scroll */}
<div className="h-1" />
</div>
@@ -32,7 +32,7 @@ export function SkillsSection({ agentId }: SkillsSectionProps) {
s.description.toLowerCase().includes(search.toLowerCase()),
)
.sort((a, b) => {
const rank = (s: typeof a) => s.granted ? 0 : s.is_system ? 1 : 2;
const rank = (s: typeof a) => s.granted ? 2 : s.is_system ? 1 : 0;
return rank(a) - rank(b);
});