diff --git a/docusaurus/docs/scene-layout.md b/docusaurus/docs/scene-layout.md index ccd63e0ba..c15509748 100644 --- a/docusaurus/docs/scene-layout.md +++ b/docusaurus/docs/scene-layout.md @@ -162,9 +162,76 @@ new SceneFlexLayout({ In the preceding example, we use the `md` property to override the default responsive behavior that changes a row layout to a column layout. We also apply a tighter `minHeight` constraint. +## CSS grid layout + +As an alternative to `SceneFlexLayout`, `SceneCSSGridLayout` is available to wrap scene items in a CSS Grid. + +```ts +const scene = new EmbeddedScene({ + body: new SceneCSSGridLayout({ + templateColumns: `repeat(auto-fit, minmax(400px, 1fr))`, + children: [ + PanelBuilders.timeseries().setTitle('Graph 1').build(), + PanelBuilders.timeseries().setTitle('Graph 2').build(), + ], + }), +}); +``` + +`SceneCSSGridLayout` accepts `children` the same as `SceneFlexLayout`, and has the following properties for applying CSS grid styles: + +```ts +autoRows?: CSSProperties['gridAutoRows']; +templateRows?: CSSProperties['gridTemplateRows']; +templateColumns: CSSProperties['gridTemplateColumns']; +/** In Grafana design system grid units (8px) */ +rowGap: number; +/** In Grafana design system grid units (8px) */ +columnGap: number; +justifyItems?: CSSProperties['justifyItems']; +alignItems?: CSSProperties['alignItems']; +justifyContent?: CSSProperties['justifyContent']; +// For sizing constaints on smaller screens +md?: SceneCSSGridLayoutState; +``` + +With CSS Grid it's easy to build a dynamic grid of panels where panel size constraints can be specific on the grid itself instead of each panel. Very useful +for building grids of equally sized panels. + +The grid layout below is configured to have child elements with a minimum size of 400px and if there is more space available split it equally. The height +is set using autoRows. This configuration will enable a very responsive layout of equally sized panels. + +```ts +const scene = new EmbeddedScene({ + body: new SceneCSSGridLayout({ + templateColumns: `repeat(auto-fit, minmax(400px, 1fr))`, + autoRows: '150px', + rowGap: 2, + columnGap: 2, + children: [ + new SceneCSSGridItem({ + body: PanelBuilders.timeseries().setTitle('Time series').build(), + }), + new SceneCSSGridItem({ + body: PanelBuilders.table().setTitle('Table').build(), + }), + new SceneCSSGridItem({ + body: PanelBuilders.timeseries().setTitle('Time series').build(), + }), + new SceneCSSGridItem({ + body: PanelBuilders.table().setTitle('Table').build(), + }), + ], + }), +}); +``` + +The SceneCSSGridItem wrapper around each child is optional. + ## Grid layout -`SceneGridLayout` allows you to build scenes as grids. This is the default behavior of Dashboards in Grafana, and grid layout lets you add a similar experience to your scene. +`SceneGridLayout` allows you to build scenes as grids of elements that can be dragged and moved around. This is the default layout used by the core Dashboard experiance in Grafana. It is +not recommended for scene app plugins unless you need users to be able to move panels around. ### Step 1. Create a scene diff --git a/docusaurus/docs/scene-layout.tsx b/docusaurus/docs/scene-layout.tsx index c4b0d2a10..8b67da8cb 100644 --- a/docusaurus/docs/scene-layout.tsx +++ b/docusaurus/docs/scene-layout.tsx @@ -1,6 +1,8 @@ import { EmbeddedScene, PanelBuilders, + SceneCSSGridItem, + SceneCSSGridLayout, SceneFlexItem, SceneFlexLayout, SceneGridItem, @@ -41,6 +43,53 @@ export function getFlexBoxLayoutScene() { return scene; } +export function getCSSGridLayoutScene() { + const queryRunner = new SceneQueryRunner({ + datasource: { + type: 'prometheus', + uid: 'gdev-prometheus', + }, + queries: [ + { + refId: 'A', + expr: 'rate(prometheus_http_requests_total{}[5m])', + }, + ], + }); + + const scene = new EmbeddedScene({ + $data: queryRunner, + body: new SceneCSSGridLayout({ + templateColumns: `repeat(auto-fit, minmax(400px, 1fr))`, + autoRows: '150px', + rowGap: 2, + columnGap: 2, + children: [ + new SceneCSSGridItem({ + body: PanelBuilders.timeseries().setTitle('Time series').build(), + }), + new SceneCSSGridItem({ + body: PanelBuilders.table().setTitle('Time series').build(), + }), + new SceneCSSGridItem({ + body: PanelBuilders.timeseries().setTitle('Time series').build(), + }), + new SceneCSSGridItem({ + body: PanelBuilders.table().setTitle('Time series').build(), + }), + new SceneCSSGridItem({ + body: PanelBuilders.timeseries().setTitle('Table').build(), + }), + new SceneCSSGridItem({ + body: PanelBuilders.table().setTitle('Table').build(), + }), + ], + }), + }); + + return scene; +} + export function getGridLayoutScene() { const queryRunner = new SceneQueryRunner({ datasource: { diff --git a/packages/scenes-app/src/demos/docs-examples.tsx b/packages/scenes-app/src/demos/docs-examples.tsx index d626a6cef..ef80f419c 100644 --- a/packages/scenes-app/src/demos/docs-examples.tsx +++ b/packages/scenes-app/src/demos/docs-examples.tsx @@ -5,6 +5,7 @@ import { getAdvancedCustomObjectScene } from '../../../../docusaurus/docs/advanc import { getCustomObjectScene, getDataAndTimeRangeScene } from '../../../../docusaurus/docs/core-concepts'; import { getHelloWorldScene } from '../../../../docusaurus/docs/getting-started'; import { + getCSSGridLayoutScene, getFlexBoxLayoutScene, getGridLayoutScene, getSplitLayoutScene, @@ -38,6 +39,11 @@ const docs = [ url: 'scene-layout-flexbox', getScene: getFlexBoxLayoutScene, }, + { + title: 'CSS grid layout', + url: 'scene-layout-css-grid', + getScene: getCSSGridLayoutScene, + }, { title: 'Grid layout', url: 'scene-layout-grid',