Dashboard Controls: Display dashboard links on the right side of the toolbar (#114378)

* have dashboard links on the right side

* Lets try a compromise (#114389)

Try to compromise on white space. Having a lot of links will create unessecary empty space under the time controls, but it is necessary if we want to be able to have the links on the right

---------

Co-authored-by: Oscar Kilhed <oscar.kilhed@grafana.com>
Co-authored-by: Sergej-Vlasov <sergej.s.vlasov@gmail.com>
This commit is contained in:
Haris Rozajac
2025-11-28 13:17:59 +00:00
committed by GitHub
co-authored by Oscar Kilhed Sergej-Vlasov
parent d3d294c99e
commit 8227ecb499
2 changed files with 39 additions and 7 deletions
@@ -176,8 +176,13 @@ function DashboardControlsRenderer({ model }: SceneComponentProps<DashboardContr
<refreshPicker.Component model={refreshPicker} />
</div>
)}
{!hideDashboardControls && model.hasDashboardControls() && <DashboardControlsButton dashboard={dashboard} />}
{!hideDashboardControls && model.hasDashboardControls() && (
<div className={styles.dashboardControlsButton}>
<DashboardControlsButton dashboard={dashboard} />
</div>
)}
{config.featureToggles.dashboardNewLayouts && <DashboardControlActions dashboard={dashboard} />}
{!hideLinksControls && !editPanel && <DashboardLinksControls links={links} dashboard={dashboard} />}
</div>
{!hideVariableControls && (
<>
@@ -185,7 +190,6 @@ function DashboardControlsRenderer({ model }: SceneComponentProps<DashboardContr
<DashboardDataLayerControls dashboard={dashboard} />
</>
)}
{!hideLinksControls && !editPanel && <DashboardLinksControls links={links} dashboard={dashboard} />}
{editPanel && <PanelEditControls panelEditor={editPanel} />}
{showDebugger && <SceneDebugger scene={model} key={'scene-debugger'} />}
</div>
@@ -268,17 +272,26 @@ function getStyles(theme: GrafanaTheme2) {
}),
rightControls: css({
display: 'flex',
justifyContent: 'flex-end',
gap: theme.spacing(1),
marginBottom: theme.spacing(1),
float: 'right',
alignItems: 'flex-start',
alignItems: 'center',
flexWrap: 'wrap',
maxWidth: '100%',
minWidth: 0,
}),
timeControls: css({
display: 'flex',
justifyContent: 'flex-end',
gap: theme.spacing(1),
marginBottom: theme.spacing(1),
order: 2,
marginLeft: 'auto',
flexShrink: 0,
alignSelf: 'flex-start',
}),
dashboardControlsButton: css({
order: 2,
marginLeft: 'auto',
}),
rightControlsWrap: css({
flexWrap: 'wrap',
@@ -1,5 +1,9 @@
import { css } from '@emotion/css';
import { GrafanaTheme2 } from '@grafana/data';
import { sceneGraph } from '@grafana/scenes';
import { DashboardLink } from '@grafana/schema';
import { useStyles2 } from '@grafana/ui';
import { DashboardLinkRenderer } from './DashboardLinkRenderer';
import { DashboardScene } from './DashboardScene';
@@ -12,18 +16,33 @@ export interface Props {
export function DashboardLinksControls({ links, dashboard }: Props) {
sceneGraph.getTimeRange(dashboard).useState();
const uid = dashboard.state.uid;
const styles = useStyles2(getStyles);
if (!links || !uid) {
return null;
}
return (
<>
<div className={styles.linksContainer}>
{links
.filter((link) => link.placement === undefined)
.map((link: DashboardLink, index: number) => (
<DashboardLinkRenderer link={link} dashboardUID={uid} key={`${link.title}-$${index}`} />
))}
</>
</div>
);
}
function getStyles(theme: GrafanaTheme2) {
return {
linksContainer: css({
display: 'flex',
flexWrap: 'wrap',
gap: theme.spacing(1),
maxWidth: '100%',
minWidth: 0,
order: 1,
flex: '1 1 0%',
}),
};
}