fix: replace Select/datalist with styled Combobox for event name inputs

Replace the conditional Select/Input pattern with a unified Combobox
(Input + Command dropdown) that always allows free-text input while
offering autocomplete suggestions from previously tracked events.

Applied to both workflow creation dialog and edit page (trigger event,
add WAIT_FOR_EVENT step, edit WAIT_FOR_EVENT step).

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
This commit is contained in:
Hana Chang
2026-03-24 16:44:45 +08:00
co-authored by Claude Opus 4.6
parent 200dfb1dbf
commit 3e3117e4a7
2 changed files with 163 additions and 96 deletions
+50 -27
View File
@@ -6,6 +6,11 @@ import {
CardDescription,
CardHeader,
CardTitle,
Command,
CommandEmpty,
CommandGroup,
CommandItem,
CommandList,
ConfirmDialog,
Dialog,
DialogContent,
@@ -14,11 +19,6 @@ import {
DialogTitle,
Input,
Label,
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from '@plunk/ui';
import type {Workflow} from '@plunk/db';
import type {PaginatedResponse} from '@plunk/types';
@@ -321,6 +321,7 @@ function CreateWorkflowDialog({open, onOpenChange, onSuccess}: CreateWorkflowDia
const [name, setName] = useState('');
const [description, setDescription] = useState('');
const [eventName, setEventName] = useState('');
const [eventPopoverOpen, setEventPopoverOpen] = useState(false);
const [allowReentry, setAllowReentry] = useState(false);
const [isSubmitting, setIsSubmitting] = useState(false);
@@ -391,34 +392,56 @@ function CreateWorkflowDialog({open, onOpenChange, onSuccess}: CreateWorkflowDia
</div>
<div>
<Label htmlFor="eventName">Trigger Event *</Label>
{eventNamesData?.eventNames && eventNamesData.eventNames.length > 0 ? (
<Select value={eventName} onValueChange={setEventName} required>
<SelectTrigger id="eventName">
<SelectValue placeholder="Select an event..." />
</SelectTrigger>
<SelectContent>
{eventNamesData.eventNames.map(name => (
<SelectItem key={name} value={name}>
{name}
</SelectItem>
))}
</SelectContent>
</Select>
) : (
<Label htmlFor="createEventName">Trigger Event *</Label>
{/* Combobox: 可自由輸入 event name,同時提供已追蹤 event 的下拉建議 */}
<div className="relative">
<Input
id="eventName"
id="createEventName"
type="text"
value={eventName}
onChange={e => setEventName(e.target.value)}
required
onChange={e => {
setEventName(e.target.value);
setEventPopoverOpen(true);
}}
onFocus={() => setEventPopoverOpen(true)}
onBlur={() => {
// 延遲關閉,讓 CommandItem 的 onSelect 有時間觸發
setTimeout(() => setEventPopoverOpen(false), 150);
}}
placeholder="e.g., contact.created, email.opened"
required
autoComplete="off"
/>
)}
{eventPopoverOpen && eventNamesData?.eventNames && eventNamesData.eventNames.length > 0 && (
<div className="absolute z-50 w-full mt-1 rounded-md border border-neutral-200 bg-white shadow-md">
<Command>
<CommandList>
<CommandEmpty className="py-3 text-center text-sm text-neutral-500">
No matching events
</CommandEmpty>
<CommandGroup>
{eventNamesData.eventNames
.filter(n => !eventName || n.toLowerCase().includes(eventName.toLowerCase()))
.map(n => (
<CommandItem
key={n}
value={n}
onSelect={() => {
setEventName(n);
setEventPopoverOpen(false);
}}
>
{n}
</CommandItem>
))}
</CommandGroup>
</CommandList>
</Command>
</div>
)}
</div>
<p className="text-xs text-neutral-500 mt-1">
{eventNamesData?.eventNames && eventNamesData.eventNames.length > 0
? 'Select from previously tracked events'
: 'No events tracked yet. Enter the event name that will trigger this workflow.'}
The event that triggers this workflow to start for a contact
</p>
</div>