feat: Add Expand all / Collapse all controls to Configuration Builder#508
Conversation
✅ Deploy Preview for otel-ecosystem-explorer ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
|
Hey @lucacavenaghi97 , just pushed a PR! The initial implementation used Both "Expand all" and "Collapse all" still work correctly on the SDK and Instrumentation tabs, Let me know if you'd like any changes! |
There was a problem hiding this comment.
Pull request overview
Adds bulk “Expand all” / “Collapse all” controls to the Java Agent Configuration Builder UI (SDK + Instrumentation tabs) by introducing a shared expansion context and wiring section cards to respond to it.
Changes:
- Added a
SectionExpansionProvider+useSectionExpansion()context to broadcast bulk expand/collapse signals. - Added an
ExpandCollapseToolbarto both tab bodies and wrapped each tab body with the provider. - Updated top-level group sections and the general settings section to subscribe to the expansion signal.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| ecosystem-explorer/src/features/java-agent/configuration/configuration-builder-page.tsx | Adds toolbar + provider wrappers for SDK/Instrumentation tab bodies. |
| ecosystem-explorer/src/features/java-agent/configuration/components/section-expansion-context.tsx | Introduces context + signal mechanism for bulk expand/collapse. |
| ecosystem-explorer/src/features/java-agent/configuration/components/group-renderer.tsx | Makes top-level group sections respond to bulk expand/collapse. |
| ecosystem-explorer/src/features/java-agent/configuration/components/general-section-card.tsx | Makes the general section card respond to bulk expand/collapse via controlled open state. |
Comments suppressed due to low confidence (1)
ecosystem-explorer/src/features/java-agent/configuration/configuration-builder-page.tsx:303
- In the Instrumentation tab, the toolbar actions only publish a
SectionExpansionContextsignal, but the instrumentation module rows manage expansion viaexpandedSetinsideInstrumentationBrowserand do not subscribe to this signal. As a result, "Expand all"/"Collapse all" here will only affectGeneralSectionCard, not the instrumentation module details. Either wire the toolbar intoInstrumentationBrowserexpansion state (e.g., expand all filtered modules / clear set) or adjust scope/UX so the buttons only appear where they actually control visible collapsibles.
<div className="space-y-4">
<div className="flex justify-end">
<ExpandCollapseToolbar />
</div>
<div ref={sectionsContainerRef} className="space-y-4">
<GeneralSectionCard
label={GENERAL_SETTINGS_LABEL}
sectionKey={GENERAL_SECTION_KEY}
children={generalNode?.children ?? []}
pathPrefix={`${INSTRUMENTATION_DEV_KEY}.${GENERAL_SUBKEY}`}
defaultExpanded={true}
emptyMessage="The schema for this version does not expose general instrumentation settings."
/>
<InstrumentationBrowser
instrumentations={instrumentationsState.data}
loading={instrumentationsState.loading}
error={instrumentationsState.error}
search={search}
statusFilter={statusFilter}
onJumpToGeneral={scrollToSection}
/>
| const { signal } = useSectionExpansion(); | ||
| const signalExpanded = useMemo(() => { | ||
| if (!signal || !isTopLevel) return null; | ||
| if (signal.action === "expand") return enabled ? true : null; | ||
| if (signal.action === "collapse") return false; | ||
| return null; | ||
| }, [signal, isTopLevel, enabled]); | ||
| const resolvedExpanded = signalExpanded !== null ? signalExpanded : expanded; | ||
|
|
| const [expanded, setExpanded] = useState(defaultExpanded); | ||
| const { signal } = useSectionExpansion(); | ||
| const signalExpanded = useMemo(() => { | ||
| if (!signal) return null; | ||
| if (signal.action === "expand") return true; | ||
| if (signal.action === "collapse") return false; | ||
| return null; | ||
| }, [signal]); | ||
| const resolvedExpanded = signalExpanded !== null ? signalExpanded : expanded; |
| function ExpandCollapseToolbar() { | ||
| const { expandAll, collapseAll } = useSectionExpansion(); | ||
| return ( | ||
| <div className="flex items-center gap-2"> | ||
| <button | ||
| type="button" | ||
| onClick={expandAll} | ||
| className="text-muted-foreground hover:text-foreground text-xs font-medium underline-offset-2 hover:underline" | ||
| > | ||
| Expand all | ||
| </button> | ||
| <span className="text-border" aria-hidden="true"> | ||
| | | ||
| </span> | ||
| <button | ||
| type="button" | ||
| onClick={collapseAll} | ||
| className="text-muted-foreground hover:text-foreground text-xs font-medium underline-offset-2 hover:underline" | ||
| > | ||
| Collapse all | ||
| </button> | ||
| </div> | ||
| ); |
|
Hey @lucacavenaghi97 , I have pushed another update addressing the Copilot feedback! The previous Regarding the integration test suggestion, happy to add that as a follow-up, or I can include it in this PR if you'd prefer it here. Just let me know! Also, I'd love to have your review on this... |
| const { signal } = useSectionExpansion(); | ||
| const [lastNonce, setLastNonce] = useState<number | null>(null); | ||
| if (signal && isTopLevel && signal.nonce !== lastNonce) { | ||
| setLastNonce(signal.nonce); | ||
| if (signal.action === "expand" && enabled) setExpanded(true); | ||
| if (signal.action === "collapse") setExpanded(false); | ||
| } |
| const [expanded, setExpanded] = useState(defaultExpanded); | ||
| const { signal } = useSectionExpansion(); | ||
| const [lastNonce, setLastNonce] = useState<number | null>(null); | ||
| if (signal && signal.nonce !== lastNonce) { | ||
| setLastNonce(signal.nonce); | ||
| if (signal.action === "expand") setExpanded(true); | ||
| if (signal.action === "collapse") setExpanded(false); | ||
| } |
| return { | ||
| expandAll: () => {}, | ||
| collapseAll: () => {}, | ||
| signal: null, | ||
| }; |
|
Hey @lucacavenaghi97 , I have pushed another update! The previous approach of deriving I've rearchitected the context to own an I'd love you you had look on it... |
|
Honestly testing this locally I don't find it very useful in the current shape. On the SDK tab "Expand all" still leaves all the sub-sections (Schedule Delay, Export Timeout, Sampler...) closed, so you still end up clicking through them one by one. On the Instrumentation tab it only opens the General settings card and leaves the 179 module rows untouched, which is probably where users would expect the biggest payoff. I think we should iterate on this and treat the two tabs separately, since the right behavior is pretty different:
@jaydeluca what do you think? @MeloveGupta the original issue was too narrow on my side, let's wait for Jay's input and then realign. |
|
Thanks for the feedback @lucacavenaghi97 ! Happy to wait for @jaydeluca for the input before iterating. Once we align on the right direction for each tab I'll pick it back up... |
|
i agree with @lucacavenaghi97's idea of recursively opening the leafs, and that for the instrumentation tab we should be opening all the instrumentation modules as well |
|
Hey @lucacavenaghi97 and @jaydeluca , I just pushed an update addressing both your feedback! Here's what I changed: SDK tab - "Expand all" now recursively opens all nested sections down to the leaf fields (Schedule Delay, Export Timeout, Sampler, Readers, Detectors, etc.), not just the top-level cards. "Collapse all" collapses everything recursively too. Individual section toggles still work independently after a bulk action. Instrumentation tab - "Expand all" now also drives the 178 module rows in the instrumentation list, opening each row to show its configurable options. "Collapse all" closes them all. Individual row toggles still work independently. Also resolved a few merge conflicts with upstream changes ( Let me know if this is closer to what you had in mind, or if you'd like any further adjustments! |
|
Tested on the deploy preview (SDK tab): "Expand all" still doesn't open the leaf fields. It only expands the top couple of levels, the actual leaves (Schedule Delay, Export Timeout, Exporter, Limits, etc.) stay collapsed. "Collapse all" works fine. |
|
@lucacavenaghi97 , I'll have a look into it, and update the PR shortly... |
|
Hi @MeloveGupta ! I noticed this PR has been inactive for about a week. Do you plan to continue working on it in the next few days, or would you prefer that I take over and finish it? I'd be happy to help move it forward and get it merged. Let me know what works best for you. Thanks! |
|
Hey @lucacavenaghi97 , Sorry for the delay, actually for the last few days I have been caught up with my End Sems and some travelling, I do wish to continue on this issue but I am still travelling so I would atleast require a week or so to continue the work and update the PR. But, if the issue is important and is getting held back then I'd be more than happy for you to take it up... |
|
No problem at all! Thanks. There's no rush on this one, so take your time and continue whenever you're back and have some bandwidth. Good luck with your exams, and enjoy your travels! 🙂 |
bdedfed to
80d0c5f
Compare
…nd Instrumentation tabs
…al-driven expansion
…lk expand/collapse
…est provider wrapping
…in Instrumentation tab
c673538 to
a2dd654
Compare
Hi @lucacavenaghi97 , what I found out was that the root cause was in two places:
Also made Both Expand all and Collapse all are now fully working across all levels - groups, nested groups, and leaf fields. Tested locally across all SDK sections. Could you review all the changes and tell me if any further changes are required from my side. |
Resolve conflicts in instrumentation-browser, schema-renderer and configuration-builder-page: keep the SectionExpansionProvider/toolbar wiring while adopting the i18n labels introduced on main.
Wire the union, list and plugin-select renderers into the section expansion context so Expand all and Collapse all drive every collapsible at any depth, on both the SDK and Instrumentation tabs. Extract the open-state resolution into a shared resolveBulkOpen helper and a useCollapsibleExpansion hook, keyed by path so repeated node keys (processors, exporter, attributes) no longer collide when toggling a single section. Add an integration test covering both tabs and restyle the toolbar buttons to match the existing toolbar.
|
Thanks a lot @MeloveGupta for the work here! I pushed a small update on top: merged main to clear the conflicts and made Expand/Collapse all reach every nested section on both tabs, plus an integration test. Hope that's ok with you! |
|
Thank you for your contribution @MeloveGupta! 🎉 We would like to hear from you about your experience contributing to OpenTelemetry by taking a few minutes to fill out this survey. |
What
Added "Expand all" and "Collapse all" buttons to both the SDK and Instrumentation tabs of the Configuration Builder. Previously users had to click each section individually to expand or collapse it.
Changes
src/features/java-agent/configuration/components/section-expansion-context.tsx(new file)SectionExpansionProvidercontext that exposesexpandAll()andcollapseAll()actions and broadcasts a signal with a nonce so subscriber components re-render on every call, even repeated ones of the same actionsrc/features/java-agent/configuration/components/group-renderer.tsxuseSectionExpansion()src/features/java-agent/configuration/components/general-section-card.tsxdefaultExpandedprop to controlleduseStatesrc/features/java-agent/configuration/configuration-builder-page.tsxSdkTabContentandInstrumentationTabBodywithSectionExpansionProviderExpandCollapseToolbarcomponent rendering "Expand all | Collapse all" above the section list in both tabsBefore / After
Expand all

Collapse all

Verified By
npx tsc --noEmit- no TypeScript errorsType of Change
Closes #476