Dashboards: Make variables selectable in controls menu (#115092)

* Dashboard: Make variables selectable in controls menu and improve spacing

- Add selection support for variables in controls menu (onPointerDown handler and selection classes)
- Add padding to variables and annotations in controls menu (theme.spacing(1))
- Reduce menu container padding from 1.5 to 1
- Remove margins between menu items

* fix: remove unused imports in DashboardControlsMenu
This commit is contained in:
Oscar Kilhed
2025-12-11 13:55:03 +01:00
committed by GitHub
parent 350c3578c7
commit b6ba8a0fd4
3 changed files with 32 additions and 14 deletions
@@ -64,6 +64,7 @@ const getStyles = (theme: GrafanaTheme2) => ({
display: 'flex',
alignItems: 'center',
gap: theme.spacing(1),
padding: theme.spacing(1),
}),
controlWrapper: css({
height: theme.spacing(2),
@@ -82,19 +82,39 @@ export function VariableValueSelectWrapper({ variable, inMenu }: VariableSelectP
// For switch variables in menu, we want to show the switch on the left and the label on the right
if (inMenu && sceneUtils.isSwitchVariable(variable)) {
return (
<div className={styles.switchMenuContainer} data-testid={selectors.pages.Dashboard.SubMenu.submenuItem}>
<div
className={cx(
styles.switchMenuContainer,
isSelected && 'dashboard-selected-element',
isSelectable && !isSelected && 'dashboard-selectable-element'
)}
onPointerDown={onPointerDown}
data-testid={selectors.pages.Dashboard.SubMenu.submenuItem}
>
<div className={styles.switchControl}>
<variable.Component model={variable} />
</div>
<VariableLabel variable={variable} layout={'vertical'} className={styles.switchLabel} />
<VariableLabel
variable={variable}
layout={'vertical'}
className={cx(isSelectable && styles.labelSelectable, styles.switchLabel)}
/>
</div>
);
}
if (inMenu) {
return (
<div className={styles.verticalContainer} data-testid={selectors.pages.Dashboard.SubMenu.submenuItem}>
<VariableLabel variable={variable} layout={'vertical'} />
<div
className={cx(
styles.verticalContainer,
isSelected && 'dashboard-selected-element',
isSelectable && !isSelected && 'dashboard-selectable-element'
)}
onPointerDown={onPointerDown}
data-testid={selectors.pages.Dashboard.SubMenu.submenuItem}
>
<VariableLabel variable={variable} layout={'vertical'} className={cx(isSelectable && styles.labelSelectable)} />
<variable.Component model={variable} />
</div>
);
@@ -164,11 +184,13 @@ const getStyles = (theme: GrafanaTheme2) => ({
verticalContainer: css({
display: 'flex',
flexDirection: 'column',
padding: theme.spacing(1),
}),
switchMenuContainer: css({
display: 'flex',
alignItems: 'center',
gap: theme.spacing(1),
padding: theme.spacing(1),
}),
switchControl: css({
'& > div': {
@@ -1,4 +1,4 @@
import { css, cx } from '@emotion/css';
import { css } from '@emotion/css';
import { GrafanaTheme2 } from '@grafana/data';
import { SceneDataLayerProvider, SceneVariable } from '@grafana/scenes';
@@ -17,8 +17,6 @@ interface DashboardControlsMenuProps {
}
export function DashboardControlsMenu({ variables, links, annotations, dashboardUID }: DashboardControlsMenuProps) {
const styles = useStyles2(getStyles);
return (
<Box
minWidth={32}
@@ -29,7 +27,7 @@ export function DashboardControlsMenu({ variables, links, annotations, dashboard
direction={'column'}
borderRadius={'default'}
backgroundColor={'primary'}
padding={1.5}
padding={1}
gap={0.5}
onClick={(e) => {
// Normally, clicking the overlay closes the dropdown.
@@ -39,7 +37,7 @@ export function DashboardControlsMenu({ variables, links, annotations, dashboard
>
{/* Variables */}
{variables.map((variable, index) => (
<div className={cx({ [styles.menuItem]: index > 0 })} key={variable.state.key}>
<div key={variable.state.key}>
<VariableValueSelectWrapper variable={variable} inMenu />
</div>
))}
@@ -47,7 +45,7 @@ export function DashboardControlsMenu({ variables, links, annotations, dashboard
{/* Annotation layers */}
{annotations.length > 0 &&
annotations.map((layer, index) => (
<div className={cx({ [styles.menuItem]: variables.length > 0 || index > 0 })} key={layer.state.key}>
<div key={layer.state.key}>
<DataLayerControl layer={layer} inMenu />
</div>
))}
@@ -79,10 +77,7 @@ function MenuDivider() {
const getStyles = (theme: GrafanaTheme2) => ({
divider: css({
marginTop: theme.spacing(2),
marginTop: theme.spacing(1),
padding: theme.spacing(0, 0.5),
}),
menuItem: css({
marginTop: theme.spacing(2),
}),
});