[Dashboard] Focus on a single panel (#165417)

This commit is contained in:
Catherine Liu 2023-09-25 15:37:30 -07:00 committed by GitHub
parent d4bb52b8b2
commit 1066eb3d59
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
18 changed files with 250 additions and 43 deletions

View file

@ -20,7 +20,7 @@ type ToolbarButtonTypes = 'primary' | 'empty';
export interface Props
extends Pick<
EuiButtonPropsForButton,
'onClick' | 'iconType' | 'iconSide' | 'size' | 'data-test-subj'
'onClick' | 'iconType' | 'iconSide' | 'size' | 'data-test-subj' | 'isDisabled'
> {
label: string;
type?: ToolbarButtonTypes;
@ -31,16 +31,23 @@ export const ToolbarButton: React.FunctionComponent<Props> = ({
type = 'empty',
iconSide = 'left',
size = 'm',
isDisabled,
...rest
}) => {
const euiTheme = useEuiTheme();
const toolbarButtonStyleProps: EuiButtonPropsForButton =
type === 'primary'
const toolbarButtonStyleProps: EuiButtonPropsForButton = !isDisabled
? type === 'primary'
? { color: 'primary', fill: true }
: { color: 'text', css: ToolbarButtonStyles(euiTheme).emptyButton };
: { color: 'text', css: ToolbarButtonStyles(euiTheme).emptyButton }
: {};
return (
<EuiButton size={size} {...toolbarButtonStyleProps} {...{ iconSide, ...rest }}>
<EuiButton
size={size}
isDisabled={isDisabled}
{...toolbarButtonStyleProps}
{...{ iconSide, ...rest }}
>
{label}
</EuiButton>
);

View file

@ -35,6 +35,7 @@ export const ToolbarPopover = ({
iconType,
size = 'm',
children,
isDisabled,
...popover
}: Props) => {
const [isOpen, setIsOpen] = useState(false);
@ -46,6 +47,7 @@ export const ToolbarPopover = ({
<ToolbarButton
onClick={onButtonClick}
size={size}
isDisabled={isDisabled}
{...{ type, label, iconType: iconType || 'arrowDown', iconSide: iconType ? 'left' : 'right' }}
/>
);

View file

@ -17,7 +17,13 @@ import { AddDataControlButton } from './add_data_control_button';
import { AddTimeSliderControlButton } from './add_time_slider_control_button';
import { EditControlGroupButton } from './edit_control_group_button';
export function ControlsToolbarButton({ controlGroup }: { controlGroup: ControlGroupContainer }) {
export function ControlsToolbarButton({
controlGroup,
isDisabled,
}: {
controlGroup: ControlGroupContainer;
isDisabled?: boolean;
}) {
const { euiTheme } = useEuiTheme();
return (
@ -30,6 +36,7 @@ export function ControlsToolbarButton({ controlGroup }: { controlGroup: ControlG
size="s"
iconType="controlsHorizontal"
data-test-subj="dashboard-controls-menu-button"
isDisabled={isDisabled}
>
{({ closePopover }: { closePopover: () => void }) => (
<EuiContextMenuPanel

View file

@ -23,7 +23,7 @@ import { ControlsToolbarButton } from './controls_toolbar_button';
import { DASHBOARD_APP_ID, DASHBOARD_UI_METRIC_ID } from '../../dashboard_constants';
import { dashboardReplacePanelActionStrings } from '../../dashboard_actions/_dashboard_actions_strings';
export function DashboardEditingToolbar() {
export function DashboardEditingToolbar({ isDisabled }: { isDisabled?: boolean }) {
const {
usageCollection,
data: { search },
@ -106,15 +106,22 @@ export function DashboardEditingToolbar() {
);
const extraButtons = [
<EditorMenu createNewVisType={createNewVisType} createNewEmbeddable={createNewEmbeddable} />,
<EditorMenu
createNewVisType={createNewVisType}
createNewEmbeddable={createNewEmbeddable}
isDisabled={isDisabled}
/>,
<AddFromLibraryButton
onClick={() => dashboard.addFromLibrary()}
size="s"
data-test-subj="dashboardAddFromLibraryButton"
isDisabled={isDisabled}
/>,
];
if (dashboard.controlGroup) {
extraButtons.push(<ControlsToolbarButton controlGroup={dashboard.controlGroup} />);
extraButtons.push(
<ControlsToolbarButton isDisabled={isDisabled} controlGroup={dashboard.controlGroup} />
);
}
return (
@ -128,6 +135,7 @@ export function DashboardEditingToolbar() {
primaryButton: (
<ToolbarButton
type="primary"
isDisabled={isDisabled}
iconType="lensApp"
size="s"
onClick={createNewVisType(lensAlias)}

View file

@ -83,6 +83,7 @@ export function DashboardTopNav({ embedSettings, redirectTo }: DashboardTopNavPr
const fullScreenMode = dashboard.select((state) => state.componentState.fullScreenMode);
const savedQueryId = dashboard.select((state) => state.componentState.savedQueryId);
const lastSavedId = dashboard.select((state) => state.componentState.lastSavedId);
const focusedPanelId = dashboard.select((state) => state.componentState.focusedPanelId);
const managed = dashboard.select((state) => state.componentState.managed);
const viewMode = dashboard.select((state) => state.explicitInput.viewMode);
@ -323,7 +324,9 @@ export function DashboardTopNav({ embedSettings, redirectTo }: DashboardTopNavPr
<LabsFlyout solutions={['dashboard']} onClose={() => setIsLabsShown(false)} />
</PresentationUtilContextProvider>
) : null}
{viewMode === ViewMode.EDIT ? <DashboardEditingToolbar /> : null}
{viewMode === ViewMode.EDIT ? (
<DashboardEditingToolbar isDisabled={!!focusedPanelId} />
) : null}
<EuiHorizontalRule margin="none" />
</div>
);

View file

@ -24,6 +24,7 @@ import { pluginServices } from '../../services/plugin_services';
import { DASHBOARD_APP_ID } from '../../dashboard_constants';
interface Props {
isDisabled?: boolean;
/** Handler for creating new visualization of a specified type */
createNewVisType: (visType: BaseVisType | VisTypeAlias) => () => void;
/** Handler for creating a new embeddable of a specified type */
@ -43,7 +44,7 @@ interface UnwrappedEmbeddableFactory {
isEditable: boolean;
}
export const EditorMenu = ({ createNewVisType, createNewEmbeddable }: Props) => {
export const EditorMenu = ({ createNewVisType, createNewEmbeddable, isDisabled }: Props) => {
const {
embeddable,
visualizations: {
@ -273,6 +274,7 @@ export const EditorMenu = ({ createNewVisType, createNewEmbeddable }: Props) =>
label={i18n.translate('dashboard.solutionToolbar.editorMenuButtonLabel', {
defaultMessage: 'Add panel',
})}
isDisabled={isDisabled}
size="s"
iconType="plusInCircle"
panelPaddingSize="none"

View file

@ -21,12 +21,19 @@ jest.mock('./dashboard_grid_item', () => {
// eslint-disable-next-line @typescript-eslint/no-var-requires
DashboardGridItem: require('react').forwardRef(
(props: DashboardGridItemProps, ref: HTMLDivElement) => {
const className =
const className = `${
props.expandedPanelId === undefined
? 'regularPanel'
: props.expandedPanelId === props.id
? 'expandedPanel'
: 'hiddenPanel';
: 'hiddenPanel'
} ${
props.focusedPanelId
? props.focusedPanelId === props.id
? 'focusedPanel'
: 'blurredPanel'
: ''
}`;
return (
<div className={className} id={`mockDashboardGridItem_${props.id}`}>
mockDashboardGridItem
@ -101,3 +108,21 @@ test('DashboardGrid renders expanded panel', async () => {
expect(component.find('#mockDashboardGridItem_1').hasClass('regularPanel')).toBe(true);
expect(component.find('#mockDashboardGridItem_2').hasClass('regularPanel')).toBe(true);
});
test('DashboardGrid renders focused panel', async () => {
const { dashboardContainer, component } = createAndMountDashboardGrid();
dashboardContainer.setFocusedPanelId('2');
component.update();
// Both panels should still exist in the dom, so nothing needs to be re-fetched once minimized.
expect(component.find('GridItem').length).toBe(2);
expect(component.find('#mockDashboardGridItem_1').hasClass('blurredPanel')).toBe(true);
expect(component.find('#mockDashboardGridItem_2').hasClass('focusedPanel')).toBe(true);
dashboardContainer.setFocusedPanelId(undefined);
component.update();
expect(component.find('GridItem').length).toBe(2);
expect(component.find('#mockDashboardGridItem_1').hasClass('blurredPanel')).toBe(false);
expect(component.find('#mockDashboardGridItem_2').hasClass('focusedPanel')).toBe(false);
});

View file

@ -30,6 +30,7 @@ export const DashboardGrid = ({ viewportWidth }: { viewportWidth: number }) => {
const viewMode = dashboard.select((state) => state.explicitInput.viewMode);
const useMargins = dashboard.select((state) => state.explicitInput.useMargins);
const expandedPanelId = dashboard.select((state) => state.componentState.expandedPanelId);
const focusedPanelId = dashboard.select((state) => state.componentState.focusedPanelId);
const animatePanelTransforms = dashboard.select(
(state) => state.componentState.animatePanelTransforms
);
@ -78,11 +79,12 @@ export const DashboardGrid = ({ viewportWidth }: { viewportWidth: number }) => {
index={index + 1}
type={type}
expandedPanelId={expandedPanelId}
focusedPanelId={focusedPanelId}
onPanelStatusChange={onPanelStatusChange}
/>
);
});
}, [expandedPanelId, onPanelStatusChange, panels, panelsInOrder]);
}, [expandedPanelId, onPanelStatusChange, panels, panelsInOrder, focusedPanelId]);
const onLayoutChange = useCallback(
(newLayout: Array<Layout & { i: string }>) => {
@ -127,8 +129,8 @@ export const DashboardGrid = ({ viewportWidth }: { viewportWidth: number }) => {
breakpoints={breakpoints}
onDragStop={onLayoutChange}
onResizeStop={onLayoutChange}
isResizable={!expandedPanelId}
isDraggable={!expandedPanelId}
isResizable={!expandedPanelId && !focusedPanelId}
isDraggable={!expandedPanelId && !focusedPanelId}
rowHeight={DASHBOARD_GRID_HEIGHT}
margin={useMargins ? [DASHBOARD_MARGIN_SIZE, DASHBOARD_MARGIN_SIZE] : [0, 0]}
draggableHandle={'.embPanel--dragHandle'}

View file

@ -0,0 +1,116 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import React from 'react';
import { mountWithIntl } from '@kbn/test-jest-helpers';
import { CONTACT_CARD_EMBEDDABLE } from '@kbn/embeddable-plugin/public/lib/test_samples/embeddables';
import { buildMockDashboard } from '../../../mocks';
import { Item, Props as DashboardGridItemProps } from './dashboard_grid_item';
import { DashboardContainerContext } from '../../embeddable/dashboard_container';
jest.mock('@kbn/embeddable-plugin/public', () => {
const original = jest.requireActual('@kbn/embeddable-plugin/public');
return {
...original,
EmbeddablePanel: (props: DashboardGridItemProps) => {
return (
<div className="embedPanel" id={`mockEmbedPanel_${props.id}`}>
mockEmbeddablePanel
</div>
);
},
};
});
const createAndMountDashboardGridItem = (props: DashboardGridItemProps) => {
const panels = {
'1': {
gridData: { x: 0, y: 0, w: 6, h: 6, i: '1' },
type: CONTACT_CARD_EMBEDDABLE,
explicitInput: { id: '1' },
},
'2': {
gridData: { x: 6, y: 6, w: 6, h: 6, i: '2' },
type: CONTACT_CARD_EMBEDDABLE,
explicitInput: { id: '2' },
},
};
const dashboardContainer = buildMockDashboard({ panels });
const component = mountWithIntl(
<DashboardContainerContext.Provider value={dashboardContainer}>
<Item {...props} />
</DashboardContainerContext.Provider>
);
return { dashboardContainer, component };
};
test('renders Item', async () => {
const { component } = createAndMountDashboardGridItem({
id: '1',
key: '1',
type: CONTACT_CARD_EMBEDDABLE,
});
const panelElements = component.find('.embedPanel');
expect(panelElements.length).toBe(1);
expect(component.find('#panel-1').hasClass('dshDashboardGrid__item--expanded')).toBe(false);
expect(component.find('#panel-1').hasClass('dshDashboardGrid__item--hidden')).toBe(false);
expect(component.find('#panel-1').hasClass('dshDashboardGrid__item--focused')).toBe(false);
expect(component.find('#panel-1').hasClass('dshDashboardGrid__item--blurred')).toBe(false);
});
test('renders expanded panel', async () => {
const { component } = createAndMountDashboardGridItem({
id: '1',
key: '1',
type: CONTACT_CARD_EMBEDDABLE,
expandedPanelId: '1',
});
expect(component.find('#panel-1').hasClass('dshDashboardGrid__item--expanded')).toBe(true);
expect(component.find('#panel-1').hasClass('dshDashboardGrid__item--hidden')).toBe(false);
});
test('renders hidden panel', async () => {
const { component } = createAndMountDashboardGridItem({
id: '1',
key: '1',
type: CONTACT_CARD_EMBEDDABLE,
expandedPanelId: '2',
});
expect(component.find('#panel-1').hasClass('dshDashboardGrid__item--expanded')).toBe(false);
expect(component.find('#panel-1').hasClass('dshDashboardGrid__item--hidden')).toBe(true);
});
test('renders focused panel', async () => {
const { component } = createAndMountDashboardGridItem({
id: '1',
key: '1',
type: CONTACT_CARD_EMBEDDABLE,
focusedPanelId: '1',
});
expect(component.find('#panel-1').hasClass('dshDashboardGrid__item--focused')).toBe(true);
expect(component.find('#panel-1').hasClass('dshDashboardGrid__item--blurred')).toBe(false);
});
test('renders blurred panel', async () => {
const { component } = createAndMountDashboardGridItem({
id: '1',
key: '1',
type: CONTACT_CARD_EMBEDDABLE,
focusedPanelId: '2',
});
expect(component.find('#panel-1').hasClass('dshDashboardGrid__item--focused')).toBe(false);
expect(component.find('#panel-1').hasClass('dshDashboardGrid__item--blurred')).toBe(true);
});

View file

@ -12,6 +12,7 @@ import classNames from 'classnames';
import { EmbeddablePhaseEvent, EmbeddablePanel, ViewMode } from '@kbn/embeddable-plugin/public';
import { css } from '@emotion/react';
import { DashboardPanelState } from '../../../../common';
import { pluginServices } from '../../../services/plugin_services';
import { useDashboardContainer } from '../../embeddable/dashboard_container';
@ -22,14 +23,14 @@ export interface Props extends DivProps {
id: DashboardPanelState['explicitInput']['id'];
index?: number;
type: DashboardPanelState['type'];
focusedPanelId?: string;
expandedPanelId?: string;
focusedPanelId?: string;
key: string;
isRenderable?: boolean;
onPanelStatusChange?: (info: EmbeddablePhaseEvent) => void;
}
const Item = React.forwardRef<HTMLDivElement, Props>(
export const Item = React.forwardRef<HTMLDivElement, Props>(
(
{
expandedPanelId,
@ -43,7 +44,6 @@ const Item = React.forwardRef<HTMLDivElement, Props>(
// https://github.com/react-grid-layout/react-grid-layout/issues/1241#issuecomment-658306889
children,
className,
style,
...rest
},
ref
@ -54,9 +54,13 @@ const Item = React.forwardRef<HTMLDivElement, Props>(
const expandPanel = expandedPanelId !== undefined && expandedPanelId === id;
const hidePanel = expandedPanelId !== undefined && expandedPanelId !== id;
const focusPanel = focusedPanelId !== undefined && focusedPanelId === id;
const blurPanel = focusedPanelId !== undefined && focusedPanelId !== id;
const classes = classNames({
'dshDashboardGrid__item--expanded': expandPanel,
'dshDashboardGrid__item--hidden': hidePanel,
'dshDashboardGrid__item--focused': focusPanel,
'dshDashboardGrid__item--blurred': blurPanel,
// eslint-disable-next-line @typescript-eslint/naming-convention
printViewport__vis: container.getInput().viewMode === ViewMode.PRINT,
});
@ -69,12 +73,29 @@ const Item = React.forwardRef<HTMLDivElement, Props>(
if (highlightPanelId === id) {
container.highlightPanel(ref.current);
}
ref.current.querySelectorAll('*').forEach((e) => {
if (blurPanel) {
// remove blurred panels and nested elements from tab order
e.setAttribute('tabindex', '-1');
} else {
// restore tab order
e.removeAttribute('tabindex');
}
});
}
}, [id, container, scrollToPanelId, highlightPanelId, ref]);
}, [id, container, scrollToPanelId, highlightPanelId, ref, blurPanel]);
const focusStyles = blurPanel
? css`
pointer-events: none;
opacity: 0.25;
`
: css``;
return (
<div
style={{ ...style, zIndex: focusedPanelId === id ? 2 : 'auto' }}
css={focusStyles}
className={[classes, className].join(' ')}
data-test-subj="dashboardPanel"
id={`panel-${id}`}
@ -140,11 +161,16 @@ export const DashboardGridItem = React.forwardRef<HTMLDivElement, Props>((props,
const {
settings: { isProjectEnabledInLabs },
} = pluginServices.getServices();
const container = useDashboardContainer();
const focusedPanelId = container.select((state) => state.componentState.focusedPanelId);
const dashboard = useDashboardContainer();
const isPrintMode = dashboard.select((state) => state.explicitInput.viewMode) === ViewMode.PRINT;
const isEnabled = !isPrintMode && isProjectEnabledInLabs('labs:dashboard:deferBelowFold');
const isEnabled =
!isPrintMode &&
isProjectEnabledInLabs('labs:dashboard:deferBelowFold') &&
(!focusedPanelId || focusedPanelId === props.id);
return isEnabled ? <ObservedItem ref={ref} {...props} /> : <Item ref={ref} {...props} />;
});

View file

@ -23,7 +23,9 @@
// Remove border color unless in editing mode
.dshLayout-withoutMargins:not(.dshLayout--editing),
.dshDashboardGrid__item--expanded {
.dshDashboardGrid__item--expanded,
.dshDashboardGrid__item--blurred,
.dshDashboardGrid__item--focused {
.embPanel {
border-color: transparent;
}

View file

@ -20,13 +20,13 @@ import { pluginServices } from '../../../services/plugin_services';
import { useDashboardContainer } from '../../embeddable/dashboard_container';
import { DashboardEmptyScreen } from '../empty_screen/dashboard_empty_screen';
export const useDebouncedWidthObserver = (wait = 250) => {
export const useDebouncedWidthObserver = (skipDebounce = false, wait = 100) => {
const [width, setWidth] = useState<number>(0);
const onWidthChange = useMemo(() => debounce(setWidth, wait), [wait]);
const { ref } = useResizeObserver<HTMLDivElement>({
onResize: (dimensions) => {
if (dimensions.width) {
if (width === 0) setWidth(dimensions.width);
if (width === 0 || skipDebounce) setWidth(dimensions.width);
if (dimensions.width !== width) onWidthChange(dimensions.width);
}
},
@ -58,10 +58,11 @@ export const DashboardViewportComponent = () => {
const viewMode = dashboard.select((state) => state.explicitInput.viewMode);
const dashboardTitle = dashboard.select((state) => state.explicitInput.title);
const description = dashboard.select((state) => state.explicitInput.description);
const focusedPanelId = dashboard.select((state) => state.componentState.focusedPanelId);
const expandedPanelId = dashboard.select((state) => state.componentState.expandedPanelId);
const controlsEnabled = isProjectEnabledInLabs('labs:dashboard:dashboardControls');
const { ref: resizeRef, width: viewportWidth } = useDebouncedWidthObserver();
const { ref: resizeRef, width: viewportWidth } = useDebouncedWidthObserver(!!focusedPanelId);
const classes = classNames({
dshDashboardViewport: true,

View file

@ -434,14 +434,18 @@ export class DashboardContainer extends Container<InheritedChildInput, Dashboard
this.dispatch.setExpandedPanelId(newId);
};
public openOverlay = (ref: OverlayRef) => {
public openOverlay = (ref: OverlayRef, options?: { focusedPanelId?: string }) => {
this.clearOverlays();
this.dispatch.setHasOverlays(true);
this.overlayRef = ref;
if (options?.focusedPanelId) {
this.setFocusedPanelId(options?.focusedPanelId);
}
};
public clearOverlays = () => {
this.dispatch.setHasOverlays(false);
this.dispatch.setFocusedPanelId(undefined);
this.controlGroup?.closeAllFlyouts();
this.overlayRef?.close();
};
@ -500,4 +504,8 @@ export class DashboardContainer extends Container<InheritedChildInput, Dashboard
}
this.setHighlightPanelId(undefined);
};
public setFocusedPanelId = (id: string | undefined) => {
this.dispatch.setFocusedPanelId(id);
};
}

View file

@ -239,6 +239,9 @@ export const dashboardContainerReducers = {
setHighlightPanelId: (state: DashboardReduxState, action: PayloadAction<string | undefined>) => {
state.componentState.highlightPanelId = action.payload;
},
setFocusedPanelId: (state: DashboardReduxState, action: PayloadAction<string | undefined>) => {
state.componentState.focusedPanelId = action.payload;
},
setAnimatePanelTransforms: (
state: DashboardReduxState,

View file

@ -43,6 +43,7 @@ export interface DashboardPublicState {
managed?: boolean;
scrollToPanelId?: string;
highlightPanelId?: string;
focusedPanelId?: string;
}
export interface DashboardRenderPerformanceStats {

View file

@ -8,8 +8,12 @@
import { OverlayRef } from '@kbn/core-mount-utils-browser';
interface TracksOverlaysOptions {
focusedPanelId?: string;
}
interface TracksOverlays {
openOverlay: (ref: OverlayRef) => void;
openOverlay: (ref: OverlayRef, options?: TracksOverlaysOptions) => void;
clearOverlays: () => void;
}

View file

@ -25,7 +25,7 @@ import { uiActions } from '../../kibana_services';
import { EmbeddablePanelProps, PanelUniversalActions } from '../types';
import { getContextMenuAriaLabel } from '../embeddable_panel_strings';
import { useSelectFromEmbeddableInput } from '../use_select_from_embeddable';
import { IEmbeddable, contextMenuTrigger, CONTEXT_MENU_TRIGGER, ViewMode } from '../..';
import { IEmbeddable, contextMenuTrigger, CONTEXT_MENU_TRIGGER } from '../..';
const sortByOrderField = (
{ order: orderA }: { order?: number },
@ -56,7 +56,6 @@ export const EmbeddablePanelContextMenu = ({
const [contextMenuPanels, setContextMenuPanels] = useState<EuiContextMenuPanelDescriptor[]>([]);
const title = useSelectFromEmbeddableInput('title', embeddable);
const viewMode = useSelectFromEmbeddableInput('viewMode', embeddable);
useEffect(() => {
/**
@ -135,7 +134,7 @@ export const EmbeddablePanelContextMenu = ({
data-test-subj="embeddablePanelToggleMenuIcon"
aria-label={getContextMenuAriaLabel(title, index)}
onClick={() => setIsContextMenuOpen((isOpen) => !isOpen)}
iconType={viewMode === ViewMode.VIEW ? 'boxesHorizontal' : 'gear'}
iconType={'boxesHorizontal'}
/>
);

View file

@ -6,8 +6,8 @@
*/
import React from 'react';
import './helpers.scss';
import type { IEmbeddable } from '@kbn/embeddable-plugin/public';
import type { OverlayRef, OverlayStart, ThemeServiceStart } from '@kbn/core/public';
import { IEmbeddable, tracksOverlays } from '@kbn/embeddable-plugin/public';
import type { OverlayStart, ThemeServiceStart } from '@kbn/core/public';
import { toMountPoint } from '@kbn/kibana-react-plugin/public';
import { IncompatibleActionError } from '@kbn/ui-actions-plugin/public';
import { isLensEmbeddable } from '../utils';
@ -20,15 +20,6 @@ interface Context {
theme: ThemeServiceStart;
}
interface TracksOverlays {
openOverlay: (ref: OverlayRef) => void;
clearOverlays: () => void;
}
function tracksOverlays(root: unknown): root is TracksOverlays {
return Boolean((root as TracksOverlays).openOverlay && (root as TracksOverlays).clearOverlays);
}
export async function isActionCompatible(embeddable: IEmbeddable) {
return Boolean(isLensEmbeddable(embeddable) && embeddable.isTextBasedLanguage());
}
@ -67,6 +58,6 @@ export async function executeAction({ embeddable, startDependencies, overlays, t
outsideClickCloses: true,
}
);
overlayTracker?.openOverlay(handle);
overlayTracker?.openOverlay(handle, { focusedPanelId: embeddable.id });
}
}