Skip to content

feat: group internal:connection, internal:trigger and internal:custom_variable dropdown fields by collections#3964

Merged
Julusian merged 5 commits intomainfrom
feat/group-internal-dropdowns-with-collections
Feb 13, 2026
Merged

feat: group internal:connection, internal:trigger and internal:custom_variable dropdown fields by collections#3964
Julusian merged 5 commits intomainfrom
feat/group-internal-dropdowns-with-collections

Conversation

@Julusian
Copy link
Member

@Julusian Julusian commented Feb 13, 2026

#3899

eg:

image

Summary by CodeRabbit

Release Notes

  • New Features

    • Dropdown fields now support grouped options organized by collection hierarchies, displaying full path labels (e.g., "Parent / Child") for improved navigation.
    • Added optional tooltip and regex validation properties to dropdown input fields.
  • Improvements

    • Collections and related items across various dropdowns now display with complete hierarchical paths for better clarity and organization.

@coderabbitai
Copy link

coderabbitai bot commented Feb 13, 2026

📝 Walkthrough

Walkthrough

This pull request refactors dropdown handling by introducing a centralized DropdownChoices module with typed utilities and a useDropdownChoicesForSelect hook. It centralizes the DropdownChoiceInt type, adds support for grouped dropdown options via a new groupItemsByCollection helper, and updates existing dropdown components and multiple imports to use these new abstractions.

Changes

Cohort / File(s) Summary
Core Dropdown Refactoring
webui/src/Components/DropdownChoices.tsx, webui/src/Components/DropdownInputField.tsx, webui/src/Components/MultiDropdownInputField.tsx
New DropdownChoices.tsx module exports types (DropdownChoiceGroup, DropdownChoicesOrGroups, DropdownChoiceInt, OptionsOrGroupsInt) and useDropdownChoicesForSelect hook. Both dropdown field components now use this hook instead of local option construction, and DropdownInputFieldProps.choices signature updated to accept DropdownChoicesOrGroups.
Type Export Updates
webui/src/Components/index.tsx, webui/src/Components/DropDownInputFancy.tsx
Type-only exports added for DropdownChoiceGroup and DropdownChoicesOrGroups in main index. DropdownChoiceInt type moved from DropDownInputFancy.tsx to DropdownChoices.tsx.
Import Path Consolidation
webui/src/Components/ExpressionInputField.tsx, webui/src/Components/TextInputField.tsx, webui/src/Controls/LocalVariablesStore.tsx, webui/src/Instances/useModuleVersionSelectOptions.tsx, webui/src/Resources/Expression.monarch.ts, webui/src/Surfaces/EditPanelConfigField.tsx, webui/src/Surfaces/Remote/RemoteSurfaces/AddRemoteSurfaceButton.tsx, webui/src/types/monaco-augmentations.d.ts
Updated import paths for DropdownChoiceInt type to use new DropdownChoices.js module instead of DropDownInputFancy.js.
Grouping & Collection Utilities
webui/src/Helpers/CollectionGrouping.tsx
New helper function groupItemsByCollection<TItem> groups items by collection hierarchy into react-select compatible groups, supporting optional filtering and ungrouped item handling.
Internal Module Field Enhancements
webui/src/Controls/InternalModuleField.tsx
Refactored dropdown choices across multiple internal dropdowns (connections, custom variables, triggers, pages, surfaces) to use grouped structures via groupItemsByCollection and updated useCollectionChoices to display full hierarchical collection paths.
Entity Connection Updates
webui/src/Controls/Components/EntityChangeConnection.tsx
Enhanced EntityCellLeftMainProps interface to include setConnectionId callback, and connection choices now use groupItemsByCollection for grouped presentation with filtering by moduleId.

Poem

📋 Dropdowns once scattered and loose,
Now grouped in collections with spruce,
Helpers refactored with care,
Organized, flattened, laid bare—
A cleaner hierarchy takes the deuce! 🎯

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and specifically describes the main change: grouping three internal dropdown fields by collections.
Merge Conflict Detection ✅ Passed ✅ No merge conflicts detected when merging into main

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


No actionable comments were generated in the recent review. 🎉

🧹 Recent nitpick comments
webui/src/Components/DropDownInputFancy.tsx (1)

3-3: Minor: Missing .js extension on the import path.

All other files in this PR use the .js extension when importing from DropdownChoices (e.g., ~/Components/DropdownChoices.js). This import omits it. Depending on your module resolution and bundler settings, this might work fine — but for consistency with the rest of the codebase, you might want to add it:

Suggested tweak
-import type { DropdownChoiceInt } from './DropdownChoices'
+import type { DropdownChoiceInt } from './DropdownChoices.js'
webui/src/Components/MultiDropdownInputField.tsx (1)

50-64: Nit: Redundant ternary on line 60.

In this else branch (line 59), we've already fallen through else if (allowCustom) on line 57, so allowCustom is guaranteed to be falsy here. The ternary allowCustom ? String(val) : \?? (${val})`will always evaluate to the??` fallback — making it equivalent to just using the string directly.

Not a bug at all, just a small readability thing you could simplify if you like:

Optional simplification
 			} else if (allowCustom) {
 				res.push({ value: val, label: String(val) })
 			} else {
-				res.push({ value: val, label: allowCustom ? String(val) : `?? (${val})` })
+				res.push({ value: val, label: `?? (${val})` })
 			}
webui/src/Components/DropdownChoices.tsx (1)

41-45: Tiny nit: duplicate object allocation for flat choices.

Lines 43 and 44 each construct an identical { value, label } object. You could stash it in a local to avoid the duplication — totally optional though, this is very minor! 😊

♻️ Optional tweak
 			} else {
 				// Flat choice
-				options.push({ value: item.id, label: item.label })
-				flatOptions.push({ value: item.id, label: item.label })
+				const entry: DropdownChoiceInt = { value: item.id, label: item.label }
+				options.push(entry)
+				flatOptions.push(entry)
 			}
webui/src/Components/DropdownInputField.tsx (1)

189-189: The as any cast here could be tightened up.

e.value is DropdownChoiceId (string | number) but setCustomInputValue expects string | undefined. If a numeric option ID gets through, the custom input state would hold a number silently. You could use String(e.value) instead to be explicit — but since this pattern seems pre-existing and connection IDs are strings in practice, this is really just a polish suggestion for whenever you're in the neighborhood. 🙂

♻️ Optional improvement
-			setCustomInputValue(e.value as any)
+			setCustomInputValue(String(e.value))

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (2)
webui/src/Helpers/CollectionGrouping.tsx (1)

44-64: The speculative child-check block (lines 44–61) is dead code.

Hey! Nice work on this grouping helper — the overall design is clean. 🎉

One thing I noticed: when groupOptions.length === 0 at line 45, the code checks whether any child collections have items (lines 47–59). But regardless of the result, the function reaches line 64 and returns null because groupOptions is still empty. Both the hasChildGroups = true and hasChildGroups = false paths lead to a null return.

The speculative buildGroupForCollection calls inside this block also add items to assignedItemIds as a side effect, but since collectAllGroups independently recurses into children anyway (line 82–88), those items get re-processed (Set.add is idempotent, so no corruption — just redundant work).

You could simplify by removing lines 44–61 entirely:

♻️ Suggested simplification
-		// If this collection has no direct items and no valid child collections, hide it
-		if (groupOptions.length === 0) {
-			// Check if any child collections will have items
-			let hasChildGroups = false
-			if (collection.children) {
-				for (const child of collection.children) {
-					const childGroup = buildGroupForCollection(child, [
-						...parentPath,
-						collection.label || `Collection #${collection.id}`,
-					])
-					if (childGroup) {
-						hasChildGroups = true
-						break
-					}
-				}
-			}
-			if (!hasChildGroups) return null
-		}
-
 		// Only return a group if this collection has direct items
 		if (groupOptions.length === 0) return null
webui/src/Controls/InternalModuleField.tsx (1)

262-267: Consider moving inline interfaces outside the useComputed callback.

Small style nit — MinimalCustomVariable (and similarly MinimalTrigger at line 465) is defined inside the useComputed callback. While this works fine at runtime, pulling these to module scope (or at least component scope) would improve readability and make them reusable if needed later. Totally optional though!

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
webui/src/DropDownInputFancy.tsx (1)

17-25: Pre-existing note: CustomSingleValue uses OptionProps instead of SingleValueProps

This isn't something introduced by your PR at all, so feel free to ignore — but just a friendly heads-up that CustomSingleValue is typed with OptionProps<DropdownChoiceInt> while it renders SelectComponents.SingleValue, which normally expects SingleValueProps. If it's working fine today, no rush, but it might be worth a small follow-up cleanup sometime. 🙂

@Julusian Julusian merged commit e1f47ea into main Feb 13, 2026
18 checks passed
@Julusian Julusian deleted the feat/group-internal-dropdowns-with-collections branch February 13, 2026 22:19
@Julusian Julusian added this to the v4.3 milestone Feb 13, 2026
@github-project-automation github-project-automation bot moved this from In Progress to Done in Companion Plan Feb 13, 2026
@github-project-automation github-project-automation bot moved this to In Progress in Companion Plan Feb 13, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

1 participant

Comments