Skip to content

Add Subform container for Enter handling, drop Combobox onEnter - #3422

Merged
david-crespo merged 4 commits into
mainfrom
subform-enter-handling
Oct 30, 2026
Merged

david-crespo merged 4 commits into
mainfrom
subform-enter-handling

Conversation

@david-crespo

@david-crespo david-crespo commented Oct 23, 2026 •

Copy link
Copy Markdown
Collaborator

The diff is unreadable unless you hide whitespace changes because it adds a wrapper to existing code.

This is an alternative to #3417 that deletes the sad logic inside Combobox instead of fixing it. We get rid of onEnter, and instead of having to keep track of whether the list is open with isOpenRef and decide when to preventDefault, Combobox never calls preventDefault (unless it's done for it by Headless UI when selecting an option).

But in subforms we still need to capture those enter keypresses before they hit the parent form, so we wrap subforms in a Subform component with an onSubmit prop. The advantage is we no longer have to remember to do this for every field we add to a subform (and we have messed this up before).

This approach fixes the same problem cases as #3417, all of which are noops on main. Enter in a closed combobox now:

  • Adds the protocol filter from the ICMP type combobox, like Enter in the ICMP code field next to it
  • Applies the alert class filter (Alert list class search #3393)
  • Submits standalone forms from their pickers, like link silo, link pool, attach disk, create snapshot, and instance create's boot disk and image pickers

Subform.browser.spec.tsx tests Enter in a combobox, text input, and button inside a subform, and in a combobox outside a subform. In the e2e tests, Enter adds a firewall rule target, port and ICMP type, a webhook secret, and a transit IP. Enter in a closed combobox applies the alert class filter, attaches a disk, and creates an instance from the image picker (these tests fail on main).

@vercel

vercel Bot commented Oct 23, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
console Ready Ready Preview Oct 30, 2026 3:48pm UTC

Request Review

@david-crespo

Copy link
Copy Markdown
Collaborator Author

@claude review

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I reviewed this PR and didn't find any bugs. Because it changes what Enter does in every Combobox across the app (Enter in a closed combobox now reaches and submits the enclosing form), a human should still confirm that is the intended UX for every form, beyond the pickers the e2e tests cover.

What was reviewed:

  • Subform's keydown guard (defaultPrevented, IME isComposing, and the target being an HTMLInputElement), and its reliance on Headless UI calling preventDefault/stopPropagation when the options list is open.
  • The Combobox refactor from a render prop to a plain child. No onEnter or isOpenRef references remain anywhere in app/.
  • The <Subform> wrapping in firewall-rules-common, network-interface-edit and webhook-create, plus the new browser spec and the e2e Enter cases.
Extended reasoning...

The change adds a Subform wrapper component, removes the per-field Enter handlers and the Combobox's onEnter and open-state tracking, and updates the firewall rule, webhook secret and transit IP subforms along with the e2e tests. It touches no security-sensitive surface: no auth, data exposure or injection. The code is coherent and has test coverage, but it changes Enter behavior in the shared Combobox for every form in the app, which is a UX decision rather than a mechanical change. That is the reason for deferring instead of approving.

Comment thread app/forms/firewall-rules-common.tsx Outdated
name="value"
{...getFilterValueProps(valueType)}
description="Select an option or enter a custom value"
<Subform onSubmit={submitSubform} className="space-y-6">

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what do you think of either explicitly using ox-form here or adding another selector for, idk ox-subform or ox-form-spacing?

diff --git a/app/ui/styles/components/form.css b/app/ui/styles/components/form.css
index 82d35e84..516d4140 100644
--- a/app/ui/styles/components/form.css
+++ b/app/ui/styles/components/form.css
@@ -18,7 +18,8 @@
 
 .ox-form,
 .ox-form .ox-tabs-panel,
-.ox-form .ox-accordion-content {
+.ox-form .ox-accordion-content,
+.ox-form .ox-subform {
   @apply space-y-6;
 }

if we ever adjust the ox-form spacing i assume we want that change propagated here

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, good idea. Turns out the different Subforms have slightly different spacing situations but I think I can make them all the same.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in 20c52c0 — diff is better with whitespace hidden. Had to get slightly more invasive by bringing the buttons inside the form, but it's a better end result. The layout changes are barely visible: buttons slightly closer to the last field in the first one, and like 4px more (lol) between fields in the second.

compare-all

onClear={() => subform.reset()}
onSubmit={submitSubform}
/>
</div>

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This feels pretty good overall. It makes subforms a lot harder to mess up.

@david-crespo
david-crespo enabled auto-merge (squash) October 30, 2026 15:59
@david-crespo
david-crespo merged commit 94f1e9e into main Oct 30, 2026
9 checks passed
@david-crespo
david-crespo deleted the subform-enter-handling branch October 30, 2026 16:04

This branch was successfully deployed

1 active deployment
Preview — 20c52c07 Deployed Oct 30, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants