diff --git a/.betterer.results b/.betterer.results index d1b8ef95b28..7f01a7c90a5 100644 --- a/.betterer.results +++ b/.betterer.results @@ -1750,9 +1750,6 @@ exports[`better eslint`] = { "public/app/features/dashboard-scene/panel-edit/PanelOptionsPane.test.tsx:5381": [ [0, 0, 0, "Unexpected any. Specify a different type.", "0"] ], - "public/app/features/dashboard-scene/panel-edit/PanelOptionsPane.tsx:5381": [ - [0, 0, 0, "Add noMargin prop to Field components to remove built-in margins. Use layout components like Stack or Grid with the gap prop instead for consistent spacing.", "0"] - ], "public/app/features/dashboard-scene/panel-edit/PanelVizTypePicker.tsx:5381": [ [0, 0, 0, "Add noMargin prop to Field components to remove built-in margins. Use layout components like Stack or Grid with the gap prop instead for consistent spacing.", "0"] ], diff --git a/public/app/features/dashboard-scene/panel-edit/PanelEditorRenderer.tsx b/public/app/features/dashboard-scene/panel-edit/PanelEditorRenderer.tsx index 9aee611d4f0..ee2d74b3513 100644 --- a/public/app/features/dashboard-scene/panel-edit/PanelEditorRenderer.tsx +++ b/public/app/features/dashboard-scene/panel-edit/PanelEditorRenderer.tsx @@ -15,12 +15,15 @@ import { getDashboardSceneFor, getLibraryPanelBehavior } from '../utils/utils'; import { PanelEditor } from './PanelEditor'; import { SaveLibraryVizPanelModal } from './SaveLibraryVizPanelModal'; import { useSnappingSplitter } from './splitter/useSnappingSplitter'; +import { scrollReflowMediaCondition, useScrollReflowLimit } from './useScrollReflowLimit'; export function PanelEditorRenderer({ model }: SceneComponentProps) { const dashboard = getDashboardSceneFor(model); const { optionsPane } = model.useState(); const styles = useStyles2(getStyles); - const [isCollapsed, setIsCollapsed] = useEditPaneCollapsed(); + const [isInitiallyCollapsed, setIsCollapsed] = useEditPaneCollapsed(); + + const isScrollingLayout = useScrollReflowLimit(); const { containerProps, primaryProps, secondaryProps, splitterProps, splitterState, onToggleCollapse } = useSnappingSplitter({ @@ -28,8 +31,9 @@ export function PanelEditorRenderer({ model }: SceneComponentProps) dragPosition: 'end', initialSize: 330, usePixels: true, - collapsed: isCollapsed, + collapsed: isInitiallyCollapsed, collapseBelowPixels: 250, + disabled: isScrollingLayout, }); useEffect(() => { @@ -80,17 +84,20 @@ function VizAndDataPane({ model }: SceneComponentProps) { const { controls } = dashboard.useState(); const styles = useStyles2(getStyles); + const isScrollingLayout = useScrollReflowLimit(); + const { containerProps, primaryProps, secondaryProps, splitterProps, splitterState, onToggleCollapse } = useSnappingSplitter({ direction: 'column', dragPosition: 'start', initialSize: 0.5, collapseBelowPixels: 150, + disabled: isScrollingLayout, }); containerProps.className = cx(containerProps.className, styles.container); - if (!dataPane) { + if (!dataPane && !isScrollingLayout) { primaryProps.style.flexGrow = 1; } @@ -102,7 +109,7 @@ function VizAndDataPane({ model }: SceneComponentProps) { )}
-
+
{showLibraryPanelSaveModal && libraryPanel && ( @@ -123,7 +130,10 @@ function VizAndDataPane({ model }: SceneComponentProps) { {dataPane && ( <>
-
+
{splitterState.collapsed && (
- + @@ -209,9 +208,6 @@ function getStyles(theme: GrafanaTheme2) { searchWrapper: css({ padding: theme.spacing(2, 2, 2, 0), }), - vizField: css({ - marginBottom: theme.spacing(0), - }), rotateIcon: css({ rotate: '180deg', }), diff --git a/public/app/features/dashboard-scene/panel-edit/splitter/useSnappingSplitter.ts b/public/app/features/dashboard-scene/panel-edit/splitter/useSnappingSplitter.ts index 67e97e9dac9..f5579074804 100644 --- a/public/app/features/dashboard-scene/panel-edit/splitter/useSnappingSplitter.ts +++ b/public/app/features/dashboard-scene/panel-edit/splitter/useSnappingSplitter.ts @@ -16,6 +16,9 @@ export interface UseSnappingSplitterOptions { handleSize?: ComponentSize; usePixels?: boolean; collapseBelowPixels: number; + + /* Disables the splitter, hiding all of its styles */ + disabled?: boolean; } interface PaneState { @@ -31,6 +34,7 @@ export function useSnappingSplitter({ collapsed, handleSize, usePixels, + disabled, }: UseSnappingSplitterOptions) { const [state, setState] = useState({ collapsed: collapsed ?? false, @@ -91,6 +95,26 @@ export function useSnappingSplitter({ onSizeChanged, }); + // This does cause the loss of the adjustment position when toggling disabled on and off again. + // Fixing this properly would require changing how useSplitter works to not both pass and + // adjust styles directly on the element by ref. That causes a React conflict. + if (disabled) { + containerProps.className = ''; + primaryProps.className = ''; + primaryProps.style = {}; + secondaryProps.className = ''; + secondaryProps.style = {}; + splitterProps.style.display = 'none'; + return { + containerProps, + primaryProps, + secondaryProps, + splitterProps, + splitterState: { collapsed: false }, + onToggleCollapse, + }; + } + // This is to allow resizing it beyond the content dimensions secondaryProps.style.overflow = 'hidden'; secondaryProps.style.minWidth = 'unset'; diff --git a/public/app/features/dashboard-scene/panel-edit/useScrollReflowLimit.ts b/public/app/features/dashboard-scene/panel-edit/useScrollReflowLimit.ts new file mode 100644 index 00000000000..3f8285fa366 --- /dev/null +++ b/public/app/features/dashboard-scene/panel-edit/useScrollReflowLimit.ts @@ -0,0 +1,15 @@ +import { useMedia } from 'react-use'; + +/** + * Media query body "(max-height: 540px)" which matches screens small enough we have zoom reflow + * problems. + * 540px is one of the round screen size numbers that's about what we want. + */ +export const scrollReflowMediaCondition = '(max-height: 540px)'; + +/** + * @returns {boolean} true when the screen is small enough to need zoom reflow handling + */ +export function useScrollReflowLimit(): boolean { + return useMedia(scrollReflowMediaCondition); +} diff --git a/public/app/features/dashboard-scene/scene/DashboardControls.tsx b/public/app/features/dashboard-scene/scene/DashboardControls.tsx index f5099ba1b95..5bbe9733755 100644 --- a/public/app/features/dashboard-scene/scene/DashboardControls.tsx +++ b/public/app/features/dashboard-scene/scene/DashboardControls.tsx @@ -147,10 +147,10 @@ function DashboardControlsRenderer({ model }: SceneComponentProps} {!hideTimeControls && ( - +
- +
)} @@ -181,7 +181,7 @@ function getStyles(theme: GrafanaTheme2) { gap: theme.spacing(1), padding: theme.spacing(2), flexDirection: 'row', - flexWrap: 'nowrap', + flexWrap: 'wrap-reverse', position: 'relative', width: '100%', marginLeft: 'auto', @@ -198,5 +198,12 @@ function getStyles(theme: GrafanaTheme2) { background: 'unset', position: 'unset', }), + timeControlStack: css({ + display: 'flex', + flexWrap: 'wrap', + justifyContent: 'flex-end', + gap: theme.spacing(1), + marginLeft: 'auto', + }), }; }