[SIP] Proposal for Modernizing Control Panel Architecture using React Components
Motivation
The current control panel architecture in Apache Superset relies on a configuration-driven design, where controlPanelSections define controlSetRows as arrays of strings or configuration objects in superset-frontend/plugins/plugin-chart-word-cloud/src/plugin/controlPanel.ts. While this approach is functional, it has become increasingly rigid, difficult to maintain, and misaligned with modern frontend development practices.
String-based controls (e.g., ['color_scheme']) are indirectly mapped to React components through control registries, creating unnecessary indirection and making the code harder to trace and refactor. Similarly, object-based configurations define control metadata but are not React components, which limits composability, reusability, and dynamic interactions.
By moving to a React component-based approach, Superset can modernize its control panel architecture to be more modular, testable, and maintainable. This change will improve developer experience, streamline debugging, and enable richer interactions using React’s state management features such as hooks and context.
Proposed Change
We propose to modernize the control panel architecture by incrementally replacing configuration objects and strings with React components.
The first step will be a proof of concept (POC) for the Word Cloud control panel, where each control (e.g., rotation, color scheme) will be defined directly as a React component such as <RotationControl /> or <ColorSchemeControl />.
The rendering logic in superset-frontend/src/explore/components/ControlPanelsContainer.tsx will be extended to detect and render both legacy configuration objects and React components. This ensures backward compatibility and allows for a gradual migration without breaking existing visualizations.
Example transformation:
Before:
[
{
name: 'rotation',
config: {
type: 'SelectControl',
label: t('Word Rotation'),
choices: [
['random', t('random')],
['flat', t('flat')],
['square', t('square')],
],
renderTrigger: true,
default: 'square',
clearable: false,
description: t('Rotation to apply to words in the cloud'),
},
},
]
After:
[
<SelectControl name="rotation" ...{everything as props} />
]
New or Changed Public Interfaces
Frontend (React):
- controlPanel.ts files will gradually transition from static configuration objects to React components.
- ControlPanelsContainer.tsx will include updated logic to handle both legacy configurations and React component entries.
- New reusable control components (e.g., RotationControl, ColorSchemeControl) will be implemented under src/explore/components/controls/.
- No REST API or CLI-level changes are expected.
- UI and user behavior will remain identical during migration.
Backward Compatibility: - Both configuration-based and component-based controls will coexist during the transition. - Older dashboards and visualizations will continue to render correctly.
Migration Plan and Compatibility
- No database schema changes or migrations are required.
- No updates to stored URLs or metadata will be needed.
- Migration will begin with the Word Cloud control panel as a proof of concept.
- Once validated, the same approach will be extended incrementally to other control panels.
- The hybrid rendering system ensures full backward compatibility until all panels are migrated.
Additional Context
This proposal originated from discussions in the Apache Superset Slack community. Our team selected this task from a list of available backlog items for contribution. We then reached out to @rusackas who provided additional details and guidance on the implementation approach. Evan recommended beginning with a small proof of concept and progressing incrementally to ensure maintainability and alignment with Superset’s ongoing frontend modernization efforts.
Comment From: Yatin-Malhotra
This proposal’s incremental migration approach is smart, especially since Superset has a large set of plugin-specific control panels. One idea worth discussing is whether we can introduce a thin compatibility layer or adapter that converts legacy config objects into temporary React wrappers. This could accelerate adoption while reducing the risk of partial migrations introducing inconsistencies.
Comment From: GursimarSingh1
Curious how you'll verify that behaviour stays consistent after swapping controls to React components. Maybe you could set up a few Playwright or Cypress tests that capture basic interactions to ensure no regressions?
Comment From: AshwinM1523
While moving to component-based controls increases modularity, it might also increase rendering overhead in panels with many controls. Has there been any discussion about memoization or lazy loading strategies to maintain performance parity with the current configuration-based approach? Exploring this early might prevent regressions later during the migration.
Comment From: meliadamian17
This sounds like a great modernization move overall. My only small concern is whether having each control as a React component could cause too many re-renders when props update, maybe React.memo or a centralized state context could smooth that out?
Comment From: rusackas
I think the proposal is great (not that I'm biased or anything hehehe) but it probably doesn't need a SIP. We'll number it and follow the process, but there's nothing stopping you from opening a POC pull request (which we might merge). Writing any level of tests to make sure the control panel works as intended before and after the migration would be wonderful.
I would advise starting quite small... just pick ONE control as a react compnet that could be implemented and tested, then we can look at the pattern and start implementing across additional control panels and controls.
I'd rather review a thousand small PRs than have one gigantic PR that we'll never feel safe merging, so let's just take a whole lot of cuts at it and call it a roadmap :)
Comment From: rusackas
...even something like a "Show Legend" checkbox (quite simple) would be a great test to start with here.
Comment From: rusackas
Agreed, memoization is key.
While I don't personally know if this step requires a SIP, per se, since it's essentially a foundational step toward making our frontend codebase just actually USE React like it should have for years :) That said it's a great place to discuss this for now, so maybe I'll take a moment to say where I think this effort probably leads (with a SIP along the way, when we get to the point of adopting new packages/architecture).
So where I believe this ought to go in future steps is as follows: 1) Get rid of all the sting-based controls in favor of components with props wherever needed 2) Get rid of the config object controls in favor of props based on the current config options 3) Get rid of this array-of-arrays layout method in favor of something like JSONForms (this would need a SIP) 4) Add a proper state management layer around these JSONForms-driven control panels 5) Make sure that all control panels use standardized sections/layouts, so they're all consistent 6) Add proper linting/testing to make sure people stick to the pattern 7) Update developer docs so people know how to build these things going forward 8) Consider this pattern for adoption in other forms throughout Superset (Alerts & Reports, database connection modals, etc)
Somewhere along that roadmap, there's a very intricate step: we should also standardized FormData so that control panels don't have their current misaligned contols/keys (metric, metrics, secondaryMetric, etc... there are lots) so that our schemas used to build charts and queries are all consistent for both DevEx and AIEx.
Long ramble, but what you're up to here is VERY important. Just... start small... hammer on bits and pieces in small PRs to make sure our patterns don't run into unexpected roadblocks or snowball to any giant PRs that are hard to merge :D
Comment From: rusackas
I think since this is a non-breaking change, and we already use React, and want our app to be a proper React app, so this is just "using React as React" - I'll close it and consider it done, since a first PR is already merged