From 70e69a64212653413479cb1279aa7c704a0a71c0 Mon Sep 17 00:00:00 2001 From: Paul Marbach Date: Tue, 2 Dec 2025 12:41:02 -0500 Subject: [PATCH] footer layout adjustments --- .../QueryOperationRow/QueryOperationRow.tsx | 7 ++- .../PanelDataPane/QueryDetailView.tsx | 54 +++++++++---------- 2 files changed, 32 insertions(+), 29 deletions(-) diff --git a/public/app/core/components/QueryOperationRow/QueryOperationRow.tsx b/public/app/core/components/QueryOperationRow/QueryOperationRow.tsx index 09717052c44..0f3ac7e6c13 100644 --- a/public/app/core/components/QueryOperationRow/QueryOperationRow.tsx +++ b/public/app/core/components/QueryOperationRow/QueryOperationRow.tsx @@ -1,5 +1,6 @@ import { css } from '@emotion/css'; import { Draggable } from '@hello-pangea/dnd'; +import { clsx } from 'clsx'; import { useCallback, useEffect, useState } from 'react'; import * as React from 'react'; import { useUpdateEffect } from 'react-use'; @@ -25,6 +26,7 @@ export interface QueryOperationRowProps { disabled?: boolean; expanderMessages?: ExpanderMessages; hideHeader?: boolean; + className?: string; } export type QueryOperationRowRenderProp = ((props: QueryOperationRowRenderProps) => React.ReactNode) | React.ReactNode; @@ -50,6 +52,7 @@ export function QueryOperationRow({ id, expanderMessages, hideHeader = false, + className, }: QueryOperationRowProps) { const [isContentVisible, setIsContentVisible] = useState(isOpen !== undefined ? isOpen : true); const styles = useStyles2(getQueryOperationRowStyles, hideHeader); @@ -114,7 +117,7 @@ export function QueryOperationRow({ {(provided) => { return ( <> -
+
{!hideHeader && (
+
{!hideHeader && (
- {renderQueryEditor()} {error && } + {renderQueryEditor()}
+
+ {renderCollapsedText()} + +
{showOptions && datasource && panelData && (
@@ -361,12 +373,6 @@ export function QueryDetailView({ panel, query, queryIndex }: QueryDetailViewPro
)}
-
- {renderCollapsedText()} - -
); } @@ -376,13 +382,12 @@ const getStyles = (theme: GrafanaTheme2) => { container: css({ width: '100%', height: '100%', - position: 'relative', }), contentWrapper: css({ display: 'grid', gridTemplateColumns: '1fr', width: '100%', - minHeight: 'calc(100% - 36px)', // 36px for footer + height: '100%', }), contentWrapperTwoColumn: css({ gridTemplateColumns: '1fr 0.5fr', @@ -390,19 +395,28 @@ const getStyles = (theme: GrafanaTheme2) => { mainContent: css({ display: 'flex', flexDirection: 'column', - gap: theme.spacing(1), + position: 'relative', overflow: 'scroll', - padding: theme.spacing(2, 2, 0, 2), }), queryContent: css({ display: 'flex', flexDirection: 'column', gap: theme.spacing(1), - minHeight: '100%', + padding: theme.spacing(2), + height: '100%', + overflow: 'scroll', + scrollbarWidth: 'thin', + scrollbarColor: theme.isDark ? '#fff5 #fff1' : '#0005 #0001', + }), + queryOperationRow: css({ + marginBottom: '0 !important', // need to beat specificty in the underling component + minHeight: 'calc(100% - 49px)', // 49px for the footer + overflow: 'scroll', }), footer: css({ display: 'flex', justifyContent: 'flex-end', + alignItems: 'center', borderTop: `1px solid ${theme.colors.border.weak}`, position: 'sticky', bottom: 0, @@ -410,23 +424,9 @@ const getStyles = (theme: GrafanaTheme2) => { padding: theme.spacing(1, 2), background: theme.colors.background.secondary, }), - optionsLink: css({ - background: 'none', - border: 'none', - color: theme.colors.text.link, - cursor: 'pointer', - fontSize: theme.typography.bodySmall.fontSize, - marginLeft: 'auto', - padding: 0, - textDecoration: 'none', - '&:hover': { - textDecoration: 'underline', - }, - }), optionsColumn: css({ display: 'flex', flexDirection: 'column', - paddingLeft: theme.spacing(2), borderLeft: `1px solid ${theme.colors.border.weak}`, background: theme.colors.background.secondary, padding: theme.spacing(2),