Skip to content

[Controls Anywhere] Add ControlsRenderer#234506

Merged
Heenawter merged 48 commits intoelastic:controlsAnywherefrom
Heenawter:controlsAnywhere_control-group-renderer_2025-09-02
Sep 24, 2025
Merged

[Controls Anywhere] Add ControlsRenderer#234506
Heenawter merged 48 commits intoelastic:controlsAnywherefrom
Heenawter:controlsAnywhere_control-group-renderer_2025-09-02

Conversation

@Heenawter
Copy link
Copy Markdown
Contributor

@Heenawter Heenawter commented Sep 9, 2025

Warning

This work is being merged into a feature branch, not main!
Because of this, we only need a review from @elastic/kibana-presentation for now.

Type failures are expected because the feature branch is currently in an incomplete state, where the controls that have not yet been converted (range slider, etc.) are dependent on things that no longer exist.

Closes #233115

Summary

This PR defines the ControlsRenderer component and adds it to the Dashboard sticky navigation in order to render the controlGroupInput.

Screen.Recording.2025-09-22.at.12.04.31.PM.mov

In order to unblock #233037, this work is incomplete - I will address the following in other PRs:

  1. You cannot add new controls to the controlGroupInput yet. This will be addressed with [Controls Anywhere] Allow control panels to be "pinned" to the top of the dashboard #221574
  2. You cannot modify the control's width or grow properties. This will be addressed with [Controls Anywhere] Add UI for grow and width settings to sticky controls #234681
  3. The ControlGroupRenderer component is still broken. This will be addressed with [Controls Anywhere] Convert ControlGroupRenderer to use ControlsRenderer #235866

As part of this work, I modified how the presentation panel wrapper handles errors due to the height restrictions that are on control embeddables. Previously, we weren't accounting for the panel size when rendering the error - which resulted in the error not being rendered properly for control embeddables. I fixed this with a resize observer, so now errors render differently depending on the size of the panel:

Panel size Error
Narrow image
Landscape Screenshot 2025-09-22 at 11 40 46 AM
Other Screenshot 2025-09-22 at 11 40 28 AM

Checklist

@Heenawter Heenawter added loe:medium Medium Level of Effort Project:Controls Team:Presentation Presentation Team for Dashboard, Input Controls, and Canvas t// impact:critical This issue should be addressed immediately due to a critical level of impact on the product. labels Sep 9, 2025
@Heenawter Heenawter force-pushed the controlsAnywhere_control-group-renderer_2025-09-02 branch from a9e412f to 0a02710 Compare September 11, 2025 20:26
@Heenawter Heenawter force-pushed the controlsAnywhere_control-group-renderer_2025-09-02 branch 2 times, most recently from 3657397 to e358cf5 Compare September 15, 2025 15:57
@Heenawter Heenawter changed the title [Controls Anywhere] Control group renderer [Controls Anywhere] Add new control group renderer to Dashboard Sep 18, 2025
<EuiFilterButton
badgeColor="success"
iconType={loading ? 'empty' : 'arrowDown'}
isLoading={loading}
Copy link
Copy Markdown
Contributor Author

@Heenawter Heenawter Sep 19, 2025

Choose a reason for hiding this comment

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

Loading state is no longer rendered by the control wrapper (since the wrapper doesn't exist when the control is a panel) - so each control should handle its own loading state.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I made some style changes so that it works better in the sticky wrapper. I also fixed the loading state a bit more:

Before After
Sep-19-2025 16-59-47 Sep-19-2025 17-00-42

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I don't know why the diff is showing this way 😆 This is a new file - not a moved file.

Copy link
Copy Markdown
Contributor Author

@Heenawter Heenawter Sep 22, 2025

Choose a reason for hiding this comment

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

<EuiEmptyPrompt> stopped working for smaller panels, so I decided to recreate the look with EuiFlexGroup so that I could get the desired responsive behaviour. Now, our error embeddable should look good regardless of the size of the panel.

Screen.Recording.2025-09-12.at.8.59.19.AM.mov

Comment on lines +160 to +161
layout$: BehaviorSubject<DashboardLayout>;
registerChildApi: (api: DefaultEmbeddableApi) => void;
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

These needed to be moved from the internal API because ControlsRenderer uses both layout$ (for its state management) and regIsterChildApi (so that the sticky controls count as regular children).

);
};

const NarrowError = ({ error }: { error: ErrorLike }) => {
Copy link
Copy Markdown
Contributor Author

@Heenawter Heenawter Sep 22, 2025

Choose a reason for hiding this comment

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

This is the error that small panels (including controls) will use:

Sep-22-2025 11-36-02

{isNarrow ? (
<NarrowError error={error} />
) : (
<EuiFlexGroup direction="column" gutterSize="l" css={styles.innerWrapperStyles}>
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This is the standard embeddable error:

Landscape Portrait
image image

@Heenawter Heenawter marked this pull request as ready for review September 22, 2025 18:07
@Heenawter Heenawter requested review from a team as code owners September 22, 2025 18:07

const [api, setApi] = useState<(DefaultEmbeddableApi & Partial<HasCustomPrepend>) | null>(null);
const initialState = useMemo(() => {
return parentApi.layout$.getValue().controls[uuid];
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.

Any reason we're not doing usePublishingSubject here?

Copy link
Copy Markdown
Contributor Author

@Heenawter Heenawter Sep 23, 2025

Choose a reason for hiding this comment

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

If I were to use usePublishingSubject, then every update to layout$ would trigger a re-render of each ControlPanel - even unrelated ones. We don't need ControlPanel to respond to changes to other panels and/or control order, for example - at this point in the rendering process, we only care about the grow and width properties of layout$ and so these are the only things we should respond to. So that is why I did it this way :)

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.

Got it, I don't want to block here but maybe there's something we can do to get the layout engine to automatically generate a more performant publishing subject for each control (something similar to the state manager?) so we can make code like this cleaner. We're already repeating this pattern twice in this PR so it's probably going to continue.

setPanelTitle(result);
})
);
if (api.defaultTitle$) {
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.

Oof this optional defaultTitle$ subject is becoming a code smell. Not sure it's in scope to do something about that in this PR but I don't love where this is going.

if (!apiPublishesTitle(api)) return; should be able to be the end of this.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

defaultTitle$ is necessary for the saved object title for all embeddables that can be saved to the library. It is optional because not all embeddables are by-reference - a lot are only by value. So I'm not really sure a better way of handling it 🤷

}

return (
<DndContext
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.

Curious why EUI drag and drop doesn't work here?

Copy link
Copy Markdown
Contributor Author

@Heenawter Heenawter Sep 23, 2025

Choose a reason for hiding this comment

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

It doesn't work once the controls wrap onto a new line :( The EUI library only works for single-dimension drag and drop (horizontal or vertical, but not both). We are stuck using dnd-kit until we can add to kbn-grid-layout to handle this type of layout.

getDisplayName: () =>
i18n.translate('controls.optionsList.displayName', {
defaultMessage: 'Options list',
defaultMessage: 'options list',
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.

This is going to get confusing if we make getDisplayName an available function, it'll end up used in other contexts where the lowercase looks like a bug. We should change this function to getEditActionTitle and include the entire Edit options list configuration in the i18n

@botelastic botelastic bot added the Feature:Embedding Embedding content via iFrame label Sep 23, 2025
Heenawter and others added 6 commits September 23, 2025 15:01
…github.com:heenawter/kibana into controlsAnywhere_control-group-renderer_2025-09-02
…trolsAnywhere_control-group-renderer_2025-09-02
…trolsAnywhere_control-group-renderer_2025-09-02
… src/core/server/integration_tests/ci_checks'
Copy link
Copy Markdown
Contributor

@Zacqary Zacqary left a comment

Choose a reason for hiding this comment

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

Overall LGTM, let's merge so we can push forward

@elasticmachine
Copy link
Copy Markdown
Contributor

elasticmachine commented Sep 24, 2025

💔 Build Failed

Failed CI Steps

History

cc @Heenawter

@Heenawter Heenawter merged commit 0c998c3 into elastic:controlsAnywhere Sep 24, 2025
10 of 12 checks passed
@Heenawter Heenawter deleted the controlsAnywhere_control-group-renderer_2025-09-02 branch September 24, 2025 16:57
Heenawter added a commit that referenced this pull request Oct 8, 2025
> [!WARNING]
> **_This work is being merged into a feature branch, not main!_**
> Because of this, we only need a review from
@elastic/kibana-presentation for now.
>
> Type failures are expected because the feature branch is currently in
an incomplete state, where the controls that have not yet been converted
(time slider, etc.) are dependent on things that no longer exist.


Closes #235866
Closes #236128


## Summary

This PR modifies the `ControlGroupRenderer` so that it wraps the
[`ControlsRenderer`
component](#234506) instead of the
old `ReactEmbeddableRenderer` (since `controlGroup` is no longer an
embeddable). To do this, we must create a parent API that matches the
expectations of `ControlsRenderer` from the props that the consumer
provides.

As part of this, I also added the `ignoreValidations` attribute back as
a data control setting (rather than a control group setting, like it
used to be), since some solutions relied on validations being turned
off. I also ensured that, for legacy dashboards where
`ignoreValidations` was turned on for the control group, I passed this
setting to the individual panels.

> [!IMPORTANT]
> The time slider has not been converted yet, which means that certain
uses of the `ControlGroupRenderer` (such as the one used in the maps
application) could not be tested. However, this is a large enough PR
that I don't want to delay merging this first big step. I will keep the
attached issue open until I can confirm that the time slider works as
expected.

### Checklist


- [x] Any text added follows [EUI's writing
guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses
sentence case text and includes [i18n
support](https://github.com/elastic/kibana/blob/main/src/platform/packages/shared/kbn-i18n/README.md)
- [x] [Unit or functional
tests](https://www.elastic.co/guide/en/kibana/mater/development-tests.html)
were updated or added to match the most common scenarios

---------

Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Feature:Embedding Embedding content via iFrame impact:critical This issue should be addressed immediately due to a critical level of impact on the product. loe:large Large Level of Effort Project:Controls Team:Presentation Presentation Team for Dashboard, Input Controls, and Canvas t//

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants