Improve trigger inspector UX#4854
Conversation
Rework the webhook trigger flow (#4787) across the show panel and the Choose/Configure wizard: - Add a flat ghost button variant; move shadow out of the shared base so ghost buttons have no raised outline. - Picker: drop the "Popular" badge, add a trailing chevron per row. - Choose: show the trigger type as a chip with a "Change" button that opens the picker. - Configure: replace the native Response Type select with a Listbox carrying per-option descriptions; collapse Authentication and Response Options by default; let users type any Success/Error status code (default 201); drop the header back arrow for a clickable breadcrumb; label the commit button "Finish". - Show panel: use a secondary Edit button, drop the section separators, and summarise the response in one line with a link to the docs. Authentication still uses the existing modal and is unchanged here.
Resting panel:
- Make Authentication and Response collapsible, with an at-a-glance
auth count in the header ("none configured" / "N configured")
- Show the response type description and, when responding on
completion, the default success/error statuses as read-only inputs
with a note that job code can override them
- Replace prominent buttons with inline links ("Add authentication",
"Configure default response status") that deep-link straight into
the relevant Configure section
Edit wizard:
- Replace the multi-select credential dropdown with a row-per-method
picker: "Add" appends a row, each row dedupes against the others,
and a "Create a new authentication method" link opens the form
- Hide Response Options unless the webhook responds on completion
- Relay the create-auth modal's close event so Cancel works in the
new flow
Bring the cron trigger onto the redesigned inspector flow, matching the webhook pattern: a read-only show panel (humanized schedule + cron input source) and a Choose -> Configure edit wizard over a local draft that commits on Finish. Configure reuses the CronFieldBuilder dropdown for the schedule, which now auto-opens the raw cron expression field when Custom is selected and shows a plain-English description of the expression beneath it. Extract the shared TriggerTypeStep so the webhook and cron wizards no longer duplicate the picker step wiring.
Replace the per-type WebhookEditWizard and CronEditWizard with a single TriggerEditWizard that owns the draft and step machine and dispatches the Choose and Configure steps by trigger type. The initial step is `type ? 'choose' : 'picker'`, so supporting a nullable type later is a one-line change. Port kafka onto the new flow (KafkaConfigureStep + KafkaShowPanel, generalized TriggerChooseStep) so the legacy TriggerForm — and its now-orphaned WebhookAuthMethodModal — can be deleted. Kafka drops the Enabled toggle and Run button to match the webhook and cron panels. Guard useWebhookTrigger so it only requests trigger auth methods for webhook triggers, avoiding needless channel calls for cron and kafka.
Fold TriggerTypeStep back into TriggerPicker and route all three trigger types through the draft path, so picking a type holds until Finish — Cancel now reverts a kafka type switch instead of committing it immediately. Commit only the trigger fields that actually changed so a concurrent canvas edit to an untouched field is no longer clobbered, and stop a type change from silently re-enabling a disabled trigger. Resync the webhook auth-method rows when the selection resolves asynchronously. Extract shared EditFooter, ReadOnlyField, WizardFinishFooter and useCanEditWorkflow used across the show panels and configure steps, and add a trigger/ barrel for external consumers. Share the trigger test harness across the inspector test files, add a WebhookConfigureStep test, and collapse the repetitive cron and inspector suites with test.each.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #4854 +/- ##
=======================================
- Coverage 90.5% 90.5% -0.0%
=======================================
Files 445 445
Lines 22721 22721
=======================================
- Hits 20561 20555 -6
- Misses 2160 2166 +6 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
|
Confirmed: no backend changes. The PR is a pure frontend refactor of the trigger inspector that calls pre-existing, already-secured Phoenix channel handlers ( Security Review ✅
|
lmac-1
left a comment
There was a problem hiding this comment.
This is looking great, Frank! I have left some comments in the code re organisation and permissions. I do think some of these things need cleaning up before merging, so that we are in a great place for further design system work.
As a side conversation, as we are moving into a newer design system, I am wondering whether we should have some of these newer 'primitive' components in one place? e.g. breadcrumbs, buttons, badges. Then, as new epics come in, we can start to use these components rather than the legacy ones. Thoughts @theroinaochieng @stuartc ? Not for this PR, but something to clean up in future work or as a follow-on PR.
Some design niggles (not to block approval - perhaps something for Tyrell to review later in UAT, but just noting for reference):
1. "On webhook call" vs "On a Schedule" - I feel like "Schedule" should be lower case so that it's consistent casing.
2. This lighter purple for "Change" gave me a feeling that it was inactive or disabled because of the lighter colour.
There was a problem hiding this comment.
Can we move this inside /trigger too? Or is this shared with other inspector components?
| border-gray-200 p-2" | ||
| > | ||
| <span | ||
| className="shrink-0 rounded bg-[#eafaf3] px-2 py-1 font-mono |
There was a problem hiding this comment.
Can we avoid hardcoded hex tailwind classes? As we're moving to a design system, please put these in tailwind.config.ts for easy reference
Something like this under theme.extend.colors:
extend: {
colors: {
'brand-green': {
light: '#eafaf3',
DEFAULT: '#006840',
},
},
}
Don't worry too much about the naming, we can always rename when Tyrell confirms the design system/colours, but good to have in one place. Then you can swap the hardcoded values for bg-brand-green and bg-brand-green-light
| > | ||
| <span | ||
| className="shrink-0 rounded bg-[#eafaf3] px-2 py-1 font-mono | ||
| text-[10px] font-medium leading-none text-[#006840]" |
There was a problem hiding this comment.
same here re hardcoded hex
| createDefaultTrigger('kafka') as Extract<Workflow.Trigger, { type: 'kafka' }> | ||
| ).kafka_configuration; | ||
|
|
||
| const inputClass = cn( |
There was a problem hiding this comment.
Same pattern exists in WebhookConfigureStep and WebhookShowPanel but with slight inconsistencies — this file uses rounded-md and border-slate-300 while the webhook files use rounded-lg and border-gray-200. Should these be consistent and aligned?
(Not necessary for approval, just a bit of housekeeping)
| import { WebhookAuthMethodSelect } from './WebhookAuthMethodSelect'; | ||
| import { WizardBreadcrumb } from './WizardBreadcrumb'; | ||
|
|
||
| const codeInputClass = cn( |
There was a problem hiding this comment.
See comment on KafkaConfigureStep
| } | ||
|
|
||
| /** Order-independent comparison of two id sets. */ | ||
| function sameIdSet(a: string[], b: string[]): boolean { |
There was a problem hiding this comment.
This function is also in WebhookAuthMethodSelect, can we move it out to a shared utils or somewhere where both reference the same function?
| } | ||
|
|
||
| /** Order-independent comparison of two id sets. */ | ||
| function sameIdSet(a: string[], b: string[]): boolean { |
There was a problem hiding this comment.
See comment in useTriggerDraft
| : 'Enable or disable this trigger'; | ||
| // A typeless trigger has no show panel; route it straight to the wizard, | ||
| // which starts at its picker so the user can choose a type. | ||
| if (view === 'edit' || !trigger.type) { |
There was a problem hiding this comment.
If !trigger.type is ever true for a read-only user (e.g. starting from a blank canvas later on), they'll land in the edit wizard with no permission check. WebhookConfigureStep also doesn't call useWorkflowReadOnly unlike its cron/kafka siblings. Worth keeping in mind as the trigger system evolves.
There was a problem hiding this comment.
This is an example of a primitive component from the new design system that could sit outside of /trigger. Not sure where though, and could be in a follow-up PR.
| }); | ||
| // Each row: [description, triggerType, extra trigger fields, expected heading] | ||
| test.each<[string, string, Record<string, unknown>, string]>([ | ||
| [ |
There was a problem hiding this comment.
No read-only scenario tested here — worth adding a case with can_edit_workflow: false to cover the !trigger.type path mentioned in TriggerInspector comment.
Description
This PR redesigns the trigger inspector, replacing the old edit-in-place form with a read-only resting panel and a guided edit wizard, for webhook, cron, and kafka triggers.
Closes #4787
Closes #4797
Closes #4798
What changed for users:
Previously, selecting a trigger node dropped you straight into an editable form that wrote every change live, field by field. Now selecting a trigger shows a read-only "resting" panel that summarises its configuration, with an Edit button. Editing opens a wizard — Choose → (optionally Change the type via a picker) → Configure → Finish — and changes are held in a local draft, only persisted when you click Finish. Cancel discards them. So editing a trigger is now a deliberate, reviewable action rather than a live mutation.
The same flow applies to every trigger type:
The resting panels are read-only by design and drop the Enabled toggle and Run button — enabling/disabling lives on the canvas, and running lives in the header.
No backend changes — trigger schema and persistence are unchanged; this is a frontend/UX redesign in the collaborative editor.
Validation steps
kafka_triggers_enabled, repeat for a kafka trigger (connection/security/advanced config, validation messages).Additional notes for the reviewer
kafka_triggers_enabledis set; kafka is covered by unit tests and was browser-verified by temporarily forcing the flag on.TriggerFormandWebhookAuthMethodModal(and their tests). The unified wizard lives inassets/js/collaborative-editor/components/inspector/trigger/.AI Usage
Please disclose whether you've used AI anywhere in this PR (it's cool, we just
want to know!):
You can read more details in our
Responsible AI Policy
Pre-submission checklist
/reviewwith Claude Code)
(e.g.,
:owner,:admin,:editor,:viewer)