feat(widgets): redesign gate widgets — readable hierarchy, prominent select-all, styled controls
Titles + intro read as a clear prompt (comfortable line length), options as spaced choice rows, Other/Back/Exit as discreet secondary controls under a divider. Multiselect gets a prominent Select all/Deselect all at the head of the list with a live count. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -13,12 +13,12 @@ export function ReservedControls({
|
||||
const [text, setText] = useState("");
|
||||
if (!reserved?.length) return null;
|
||||
return (
|
||||
<div className="flex flex-col gap-2 pt-2">
|
||||
<div className="flex gap-2">
|
||||
<div className="flex flex-col gap-2 border-t border-border/60 pt-3">
|
||||
<div className="flex flex-wrap gap-2">
|
||||
{reserved.map((c) => (
|
||||
<button
|
||||
key={c}
|
||||
className="text-sm border rounded px-2 py-1"
|
||||
className="rounded-md border border-border/60 px-2.5 py-1 text-xs text-muted-foreground transition-colors hover:bg-muted hover:text-foreground"
|
||||
onClick={() => (c === "other" ? setOtherOpen(true) : onControl(c))}
|
||||
>
|
||||
{LABELS[c] ?? c}
|
||||
@@ -26,14 +26,15 @@ export function ReservedControls({
|
||||
))}
|
||||
</div>
|
||||
{otherOpen && (
|
||||
<div className="flex flex-col gap-1">
|
||||
<div className="flex flex-col gap-2">
|
||||
<textarea
|
||||
className="w-full border rounded p-2"
|
||||
className="min-h-20 w-full resize-y rounded-lg border border-input bg-card p-3 text-sm outline-none transition-colors focus:border-primary/40 focus:ring-2 focus:ring-ring/20"
|
||||
value={text}
|
||||
onChange={(e) => setText(e.target.value)}
|
||||
placeholder="Describe your alternative…"
|
||||
/>
|
||||
<button
|
||||
className="text-sm border rounded px-2 py-1 self-start disabled:opacity-50 disabled:cursor-not-allowed"
|
||||
className="self-start rounded-lg bg-primary px-3 py-1.5 text-sm font-medium text-primary-foreground transition-colors hover:bg-[oklch(var(--primary-hover))] disabled:cursor-not-allowed disabled:opacity-50"
|
||||
disabled={!text.trim()}
|
||||
onClick={() => onControl("freetext", text)}
|
||||
>
|
||||
|
||||
Reference in New Issue
Block a user