From d7be68ab3cf9a2e014fc2f75690d1896d98158d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Thu, 27 Mar 2025 16:16:30 +0100 Subject: [PATCH] Dashboard: Only auto focus new objects (#102931) * Dashboard: Only auto focus new objects * fix outline issue * Also set isNew when adding row below/above and tab before/after --------- Co-authored-by: oscarkilhed --- .../dashboard-scene/edit-pane/DashboardEditPane.tsx | 2 +- .../dashboard-scene/edit-pane/DashboardOutline.tsx | 2 +- .../dashboard-scene/panel-edit/getPanelFrameOptions.tsx | 8 +++++++- .../dashboard-scene/scene/layout-rows/RowItem.tsx | 3 ++- .../dashboard-scene/scene/layout-rows/RowItemEditor.tsx | 4 ++-- .../scene/layout-rows/RowsLayoutManager.tsx | 6 +++--- .../dashboard-scene/scene/layout-tabs/TabItem.tsx | 6 +++++- .../dashboard-scene/scene/layout-tabs/TabItemEditor.tsx | 4 ++-- .../scene/layout-tabs/TabsLayoutManager.tsx | 6 +++--- .../dashboard-scene/scene/layouts-shared/utils.ts | 8 ++++---- 10 files changed, 30 insertions(+), 19 deletions(-) diff --git a/public/app/features/dashboard-scene/edit-pane/DashboardEditPane.tsx b/public/app/features/dashboard-scene/edit-pane/DashboardEditPane.tsx index b6fc29882fd..b07791ff607 100644 --- a/public/app/features/dashboard-scene/edit-pane/DashboardEditPane.tsx +++ b/public/app/features/dashboard-scene/edit-pane/DashboardEditPane.tsx @@ -210,7 +210,7 @@ export function DashboardEditPaneRenderer({ editPane, isCollapsed, onToggleColla const selectedObject = selection?.getFirstObject(); const [outlineCollapsed, setOutlineCollapsed] = useLocalStorage( 'grafana.dashboard.edit-pane.outline.collapsed', - false + true ); const [outlinePaneSize = 0.4, setOutlinePaneSize] = useLocalStorage('grafana.dashboard.edit-pane.outline.size', 0.4); diff --git a/public/app/features/dashboard-scene/edit-pane/DashboardOutline.tsx b/public/app/features/dashboard-scene/edit-pane/DashboardOutline.tsx index 67a7ba72c14..63ad898edb5 100644 --- a/public/app/features/dashboard-scene/edit-pane/DashboardOutline.tsx +++ b/public/app/features/dashboard-scene/edit-pane/DashboardOutline.tsx @@ -88,7 +88,7 @@ function getStyles(theme: GrafanaTheme2) { boxShadow: 'none', border: 'none', background: 'transparent', - padding: theme.spacing(0.25, 1), + padding: theme.spacing(0.25, 1, 0.25, 0), borderRadius: theme.shape.radius.default, color: theme.colors.text.secondary, display: 'flex', diff --git a/public/app/features/dashboard-scene/panel-edit/getPanelFrameOptions.tsx b/public/app/features/dashboard-scene/panel-edit/getPanelFrameOptions.tsx index 26def57f9d7..31037a28413 100644 --- a/public/app/features/dashboard-scene/panel-edit/getPanelFrameOptions.tsx +++ b/public/app/features/dashboard-scene/panel-edit/getPanelFrameOptions.tsx @@ -3,6 +3,7 @@ import { selectors } from '@grafana/e2e-selectors'; import { config } from '@grafana/runtime'; import { SceneTimeRangeLike, VizPanel } from '@grafana/scenes'; import { DataLinksInlineEditor, Input, TextArea, Switch } from '@grafana/ui'; +import { t } from 'app/core/internationalization'; import { GenAIPanelDescriptionButton } from 'app/features/dashboard/components/GenAI/GenAIPanelDescriptionButton'; import { GenAIPanelTitleButton } from 'app/features/dashboard/components/GenAI/GenAIPanelTitleButton'; import { OptionsPaneCategoryDescriptor } from 'app/features/dashboard/components/PanelEditor/OptionsPaneCategoryDescriptor'; @@ -110,7 +111,12 @@ function ScenePanelLinksEditor({ panelLinks }: ScenePanelLinksEditorProps) { export function PanelFrameTitleInput({ panel }: { panel: VizPanel }) { const { title } = panel.useState(); - let ref = useEditPaneInputAutoFocus({ noAutoFocus: panel.getPanelContext().app === CoreApp.PanelEditor }); + const notInPanelEdit = panel.getPanelContext().app !== CoreApp.PanelEditor; + const newPanelTitle = t('dashboard.new-panel-title', 'New panel'); + + let ref = useEditPaneInputAutoFocus({ + autoFocus: notInPanelEdit && title === newPanelTitle, + }); return ( i } public addNewRow(): RowItem { - const row = new RowItem(); + const row = new RowItem({ isNew: true }); this.setState({ rows: [...this.state.rows, row] }); this.publishEvent(new NewObjectAddedToCanvasEvent(row), true); return row; @@ -115,7 +115,7 @@ export class RowsLayoutManager extends SceneObjectBase i public addRowAbove(row: RowItem): RowItem { const index = this.state.rows.indexOf(row); - const newRow = new RowItem(); + const newRow = new RowItem({ isNew: true }); const newRows = [...this.state.rows]; newRows.splice(index, 0, newRow); @@ -135,7 +135,7 @@ export class RowsLayoutManager extends SceneObjectBase i index = index + 1; } - const newRow = new RowItem(); + const newRow = new RowItem({ isNew: true }); const newRows = [...this.state.rows]; newRows.splice(index + 1, 0, newRow); diff --git a/public/app/features/dashboard-scene/scene/layout-tabs/TabItem.tsx b/public/app/features/dashboard-scene/scene/layout-tabs/TabItem.tsx index d92461f43af..e29fe6cd7d7 100644 --- a/public/app/features/dashboard-scene/scene/layout-tabs/TabItem.tsx +++ b/public/app/features/dashboard-scene/scene/layout-tabs/TabItem.tsx @@ -27,6 +27,10 @@ import { TabsLayoutManager } from './TabsLayoutManager'; export interface TabItemState extends SceneObjectState { layout: DashboardLayoutManager; title?: string; + /** + * Used to auto focus the title input + */ + isNew?: boolean; isDropTarget?: boolean; } @@ -123,7 +127,7 @@ export class TabItem } public onChangeTitle(title: string) { - this.setState({ title }); + this.setState({ title, isNew: false }); } public setIsDropTarget(isDropTarget: boolean) { diff --git a/public/app/features/dashboard-scene/scene/layout-tabs/TabItemEditor.tsx b/public/app/features/dashboard-scene/scene/layout-tabs/TabItemEditor.tsx index 13ae006ab43..8d4528022c6 100644 --- a/public/app/features/dashboard-scene/scene/layout-tabs/TabItemEditor.tsx +++ b/public/app/features/dashboard-scene/scene/layout-tabs/TabItemEditor.tsx @@ -30,8 +30,8 @@ export function getEditOptions(model: TabItem): OptionsPaneCategoryDescriptor[] } function TabTitleInput({ tab }: { tab: TabItem }) { - const { title } = tab.useState(); - const ref = useEditPaneInputAutoFocus(); + const { title, isNew } = tab.useState(); + const ref = useEditPaneInputAutoFocus({ autoFocus: isNew }); return tab.onChangeTitle(e.currentTarget.value)} />; } diff --git a/public/app/features/dashboard-scene/scene/layout-tabs/TabsLayoutManager.tsx b/public/app/features/dashboard-scene/scene/layout-tabs/TabsLayoutManager.tsx index e8477e002b4..c7b51462e7a 100644 --- a/public/app/features/dashboard-scene/scene/layout-tabs/TabsLayoutManager.tsx +++ b/public/app/features/dashboard-scene/scene/layout-tabs/TabsLayoutManager.tsx @@ -113,7 +113,7 @@ export class TabsLayoutManager extends SceneObjectBase i } public addNewTab() { - const newTab = new TabItem(); + const newTab = new TabItem({ isNew: true }); this.setState({ tabs: [...this.state.tabs, newTab], currentTabIndex: this.state.tabs.length }); this.publishEvent(new NewObjectAddedToCanvasEvent(newTab), true); return newTab; @@ -150,7 +150,7 @@ export class TabsLayoutManager extends SceneObjectBase i } public addTabBefore(tab: TabItem): TabItem { - const newTab = new TabItem(); + const newTab = new TabItem({ isNew: true }); const tabs = this.state.tabs.slice(); tabs.splice(tabs.indexOf(tab), 0, newTab); this.setState({ tabs, currentTabIndex: this.state.currentTabIndex }); @@ -160,7 +160,7 @@ export class TabsLayoutManager extends SceneObjectBase i } public addTabAfter(tab: TabItem): TabItem { - const newTab = new TabItem(); + const newTab = new TabItem({ isNew: true }); const tabs = this.state.tabs.slice(); tabs.splice(tabs.indexOf(tab) + 1, 0, newTab); this.setState({ tabs, currentTabIndex: this.state.currentTabIndex + 1 }); diff --git a/public/app/features/dashboard-scene/scene/layouts-shared/utils.ts b/public/app/features/dashboard-scene/scene/layouts-shared/utils.ts index 9d4dbc3b2ce..e704e108c04 100644 --- a/public/app/features/dashboard-scene/scene/layouts-shared/utils.ts +++ b/public/app/features/dashboard-scene/scene/layouts-shared/utils.ts @@ -19,18 +19,18 @@ export function findParentLayout(sceneObject: SceneObject): DashboardLayoutManag } export interface EditPaneInputAutoFocusProps { - noAutoFocus?: boolean; + autoFocus?: boolean; } -export function useEditPaneInputAutoFocus({ noAutoFocus }: EditPaneInputAutoFocusProps = {}) { +export function useEditPaneInputAutoFocus({ autoFocus }: EditPaneInputAutoFocusProps = {}) { const ref = useRef(null); useEffect(() => { - if (ref.current && !noAutoFocus) { + if (ref.current && autoFocus) { // Need the setTimeout here for some reason setTimeout(() => ref.current?.focus(), 200); } - }, [noAutoFocus]); + }, [autoFocus]); return ref; }