open-swe/ui/src/components/agents/ScheduleTriggerPicker.tsx
Johannes du Plessis 876836bdfe
Normalize frontend typography + enable font smoothing (#1546)
Lighter, more consistent type across the dashboard and agent UI:
unify title sizes, drop semibold/bold in chrome to medium, harmonize
stray text-sm to text-xs, normalize chat markdown headings, and enable
antialiased font smoothing (fixes heavy text on dark backgrounds).

Co-authored-by: open-swe[bot] <open-swe@users.noreply.github.com>
2026-06-16 14:56:11 -07:00

78 lines
2.7 KiB
TypeScript

import { useEffect, useRef, useState } from "react"
import { CaretRightIcon, ClockIcon, PlusIcon } from "@phosphor-icons/react"
import { CRON_PRESETS } from "@/lib/agents/cron"
import { cn } from "@/lib/utils"
interface ScheduleTriggerPickerProps {
/** Called with a cron value for a preset, or null when the user picks Custom. */
onSelect: (cron: string | null) => void
triggerLabel?: string
}
const OPTIONS: Array<{ id: string; label: string; cron: string | null }> = [
...CRON_PRESETS.map((preset) => ({
id: preset.id,
label: preset.label,
cron: preset.value,
})),
{ id: "custom", label: "Custom (cron)", cron: null },
]
export function ScheduleTriggerPicker({
onSelect,
triggerLabel = "Add Trigger",
}: ScheduleTriggerPickerProps) {
const [open, setOpen] = useState(false)
const ref = useRef<HTMLDivElement>(null)
useEffect(() => {
function handleClickOutside(e: MouseEvent) {
if (ref.current && !ref.current.contains(e.target as Node)) {
setOpen(false)
}
}
document.addEventListener("mousedown", handleClickOutside)
return () => document.removeEventListener("mousedown", handleClickOutside)
}, [])
return (
<div ref={ref} className="relative">
<button
type="button"
onClick={() => setOpen((value) => !value)}
className="flex w-full items-center gap-2 rounded-lg px-3 py-2.5 text-xs text-[var(--ui-text-muted)] transition-colors hover:bg-[var(--ui-panel-2)] hover:text-[var(--ui-text)]"
>
<PlusIcon className="size-4" />
{triggerLabel}
</button>
{open && (
<div className="absolute top-full left-0 z-50 mt-1 w-72 overflow-hidden rounded-xl border border-[var(--ui-border)] bg-[var(--ui-surface)] py-1 shadow-lg">
<div className="flex items-center gap-2 px-3 py-1.5 text-[11px] font-medium tracking-wide text-[var(--ui-text-dim)] uppercase">
<ClockIcon className="size-3.5" />
Scheduled
</div>
{OPTIONS.map((option) => (
<button
key={option.id}
type="button"
onClick={() => {
onSelect(option.cron)
setOpen(false)
}}
className={cn(
"flex w-full items-center gap-2 px-3 py-2 text-left text-xs text-[var(--ui-text-muted)] transition-colors hover:bg-[var(--ui-panel-2)] hover:text-[var(--ui-text)]"
)}
>
<span className="flex-1">{option.label}</span>
{option.cron === null && (
<CaretRightIcon className="size-3.5 opacity-50" />
)}
</button>
))}
</div>
)}
</div>
)
}