Automations and webhooks for the AT Protocol airglow.run

fix(form): replace the dry-run paragraph over the create buttons with a compact, designed choice #88

Closed tyb.there-hugo.dev
Closed opened by tyb.there-hugo.dev

Follow-up to #27.

Problem #

#27 fixed the understanding gap, but the way it shows is poor. The create form now ends with a three-line, right-aligned, muted paragraph floating above "Create in dry run" / "Create automation". It takes more room than the buttons, reads like a disclaimer rather than part of the choice, and isn't built from anything else in the UI. Ragged right-aligned body text is hard to read, and the two most important controls on the page sit under it.

Evidence #

  • app/islands/AutomationForm.tsx:3427: <p id="create-dry-run-hint" class={s.createSubmitHint}> with three sentences, above the buttons.
  • app/islands/AutomationForm.css.ts:306-319: createSubmitBlock / createSubmitHint, one-off styles (textAlign: "end", maxInlineSize: 36rem).
  • app/islands/AutomationToolbar.tsx:254: the automation page has the same explanation as a full-width paragraph on its own row under the toolbar.

Expected #

The choice between dry run and live reads as one designed control, with the explanation attached to the option it explains, in no more than one short line each. A direction to start from (the owner can pick another):

  • Make "how it starts" part of the form: a small "Start in" choice with two options, Dry run ("Logs what each action would do. Nothing is written, posted or sent.") and Live ("Runs the actions for real as soon as it's created."), using the form's existing checkbox/label and hint styles, and a single primary "Create automation" button.
  • Or keep the two buttons, and put one short line under each one instead of a paragraph over both.

Either way:

  • No right-aligned paragraph; the submit row is no taller than the buttons plus one line.
  • "You can switch dry run on or off later" stays, in at most a few words.
  • The toolbar on the automation page gets the same treatment, so the two read alike: a short description attached to the toggle, not a full-width paragraph.

Acceptance criteria #

Out of scope #

What dry run does, and the default mode a new automation starts in.

Queued: the loop will work on this version of the issue.

loop:queued cid=bafyreidgmyzzre3dagvn2eu2kvn564r37ssgdtuom3ch5wnjuwdjutwja4

Working on this, attempt 1.

loop:claim run=contribute-20261102-190017-88 branch=loop/88 attempt=1 issue=88

fix(form): replace the dry-run paragraph with a "Start in" choice and attach the toolbar hint to its toggle

The create form no longer ends with a right-aligned three-sentence paragraph over two create buttons. Choosing dry run or live is now a "Start in" choice with two radio options, Dry run and Live. Each option has one hint line under it, and a single primary "Create automation" button follows, as docs/design.md asks ("If two options need explaining, they are a choice ... not two buttons and a paragraph"). On the automation page, the dry-run explanation is no longer a full-width row under the toolbar. It is one short hint line directly under the "Enable/Disable Dry Run" toggle, with the same wording as the form's Dry run option.

What changed #

  • app/islands/AutomationForm.tsx: new startDryRun state, preselected to dry run. It decides the dryRun field of the create POST, so the code no longer reads e.submitter. The two buttons and submitKind are gone. The create button's aria-describedby points at the chosen option's hint, plus submit-blockers while the form is invalid. The choice is also kept in the scope-upgrade stash (optional dryRun on FormDraft), so after the re-auth round trip "Create again" still creates in the mode the user picked. Autosave drafts do not store it.
  • app/islands/AutomationForm.css.ts: removed createSubmitHint and the two-button createSubmit grid. createSubmitBlock is now only the column that holds the button and its blockers. The existing checkbox style gets a [type="radio"] selector (radii.full) so a radio option uses the same control, but round. No new colour, spacing or text style.
  • app/islands/AutomationToolbar.tsx / .css.ts: the toggle and its hint sit in a small column wrapper (withHint, gap: space[1]). hint is now the form hint style (fontSize.xs, textMuted) and no longer a full-width fontSize.sm paragraph. The toolbar aligns its items to the top (flex-start), so the hint hangs under the toggle without pushing the other buttons down.
  • Tests in AutomationForm.test.tsx and AutomationToolbar.test.tsx are updated for the new markup.

What each state shows #

  • Create form, empty or invalid: the "Start in" fieldset is always there in create mode, with Dry run checked. Under it come the existing "Before you can create this automation:" list and the disabled "Create automation" button. The button is described by start-dry-run-hint submit-blockers.
  • Create form, filled: the same fieldset, then only the enabled "Create automation" button. The submit row is the button alone.
  • Live chosen: the Live radio is checked and the button is described by start-live-hint. The POST sends dryRun: false.
  • Submitting (loading): the outer fieldset disables both radios and the button, and the button reads "Creating..." with aria-busy.
  • Error from the server: the existing error alert shows above the submit row, and the choice keeps its value.
  • Edit form: unchanged: no "Start in" choice, and the sticky "Update automation" bar.
  • Toolbar: "Enable Dry Run" / "Disable Dry Run", with "Logs what each action would do. Nothing is written, posted or sent." under it in hint style. The flash tooltip after a toggle overlays that hint briefly, as it overlaid the next row before.

Markup of the choice: <fieldset aria-describedby="start-mode-hint"><legend>Start in</legend>. Each option is a label (checkbox label style) holding a radio (name="startMode", with aria-describedby set to its hint), followed by its hint line. The fieldset ends with "You can switch later on the automation's page." in hint style.

Verified #

  • pnpm run check: passes (format, lint, types).
  • pnpm run test: 185 files, 2849 tests pass.
  • Keyboard, checked from the markup (I could not open the page): Tab reaches the checked radio, the arrow keys move between Dry run and Live (a native radio group), and Tab goes on to "Create automation". Changing the choice only updates the checked and aria-describedby attributes, so no node is replaced and focus stays on the radio. The global :focus-visible ring applies to the radios.

Acceptance criteria #

Decisions the owner can reverse #

  • I took the issue's first direction: a radio choice and one button. The other direction, two buttons with a line under each, would contradict the design rule quoted above.
  • Dry run is preselected. The server's default is unchanged, and before this branch the form had no preselection: the user picked by clicking a button.
  • The "switch later" note is one fieldset-level hint line, "You can switch later on the automation's page.", and not part of either option.
  • Radio options reuse the checkbox style made round, and keep its checkmark rather than showing a dot, so no new size values are needed.
  • docs/design.md (owner-only) still lists createSubmitHint under Known debt. That entry can be dropped now that the style is gone.

Review: https://tangled.org/exosphere.site/airglow/compare/main...loop/88

loop:pushed run=contribute-20261102-190017-88 sha=762dc93699f4509967596b016daa2377422bef26

Verdict: merge. The branch swaps the right-aligned three-sentence paragraph and the two create buttons for a "Start in" radio choice (Dry run / Live). Each option has one hint line, and a single primary "Create automation" button follows, as the issue's first direction and docs/design.md ("Explaining a control") ask. The toolbar's full-width paragraph is now one hint line attached to the dry-run toggle. pnpm run check and pnpm run test (185 files, 2849 tests) both pass.

What I checked:

  • Acceptance criteria against the code. createSubmitHint, createSubmit and the #create-dry-run-hint paragraph are gone, and nothing else in the repo uses them (rg across app/, docs/, lib/). The new markup reuses Button, Layout/Stack and the form's groupFieldset/groupLegend/fieldGroup/checkboxLabel/checkbox/hint styles. The only style additions are a radii.full selector for radios and the toolbar's withHint column (space[1]). The toolbar's existing hint now has the same values as the form's hint. No new colour, spacing or radius value.
  • Accessible descriptions. Each radio is described by its own hint and the fieldset by the "switch later" line. The create button's aria-describedby follows the chosen mode, plus submit-blockers while the form is invalid. The toolbar toggle keeps aria-describedby="dry-run-hint".
  • Flows. With no choice made, the POST sends dryRun: true, the same as the server's default (body.dryRun !== false); choosing Live sends false. The scope-upgrade stash keeps the choice, so "Create again" after the re-auth trip uses the mode the user picked (a test covers this). Edit mode is unchanged and its payload still leaves dryRun out. The double-submit guard is still tested.
  • A throwaway test in /work, since removed. Focus the Live radio, click it, re-render: focus stays on the same radio node, the node is not replaced, and the POST sends dryRun: false. On a blank create form (no seed), Dry run is checked.
  • Toolbar layout. The page container is 72rem, so the hint under the toggle plus the right-hand link group fit on one row on desktop. On narrow screens the hint wraps inside its column. All toolbar buttons are size.sm, so switching to flex-start alignment does not shift anything.

Notes for the owner, nothing blocking:

  • Radios reuse the checkbox style made round, so a checked radio shows a checkmark rather than a dot. The PR lists this as reversible.
  • docs/design.md (owner-only) still lists createSubmitHint under Known debt. That half of the entry can go now. submitBlockers stays debt for #89.

loop:verdict run=review-20261102-212202-88 sha=762dc93699f4509967596b016daa2377422bef26 verdict=merge

Merged onto main as 51a528a5c39792431bf49bf24cc91059d884d5a1.

loop:merged sha=51a528a5c39792431bf49bf24cc91059d884d5a1 head=762dc93699f4509967596b016daa2377422bef26

Sign up or Sign in to add to the discussion.