From 0f0519eae505caaa8a15bcf2da263b0929e22c4d Mon Sep 17 00:00:00 2001 From: Ashley Harrison Date: Wed, 26 Mar 2025 12:46:24 +0000 Subject: [PATCH] Grafana UI: Add `columnGap` + `rowGap` to `Stack`/`Grid` (#102883) add columnGap/rowGap to Stack/Grid --- .../src/components/Layout/Grid/Grid.story.tsx | 11 +++++++- .../src/components/Layout/Grid/Grid.tsx | 14 ++++++++-- .../components/Layout/Stack/Stack.story.tsx | 6 +++-- .../src/components/Layout/Stack/Stack.tsx | 27 ++++++++++++++++++- 4 files changed, 52 insertions(+), 6 deletions(-) diff --git a/packages/grafana-ui/src/components/Layout/Grid/Grid.story.tsx b/packages/grafana-ui/src/components/Layout/Grid/Grid.story.tsx index 5eb6d6aae2b..f69433d22eb 100644 --- a/packages/grafana-ui/src/components/Layout/Grid/Grid.story.tsx +++ b/packages/grafana-ui/src/components/Layout/Grid/Grid.story.tsx @@ -1,6 +1,7 @@ import { Meta, StoryFn } from '@storybook/react'; import { useTheme2 } from '../../../themes'; +import { SpacingTokenControl } from '../../../utils/storybook/themeStorybookControls'; import { Grid } from './Grid'; import mdx from './Grid.mdx'; @@ -39,6 +40,9 @@ ColumnsNumber.argTypes = { control: 'select', options: ['stretch', 'flex-start', 'flex-end', 'center', 'baseline', 'start', 'end', 'self-start', 'self-end'], }, + gap: SpacingTokenControl, + rowGap: SpacingTokenControl, + columnGap: SpacingTokenControl, }; ColumnsNumber.args = { columns: 3, @@ -52,7 +56,7 @@ ColumnsNumber.parameters = { export const ColumnsMinWidth: StoryFn = (args) => { const theme = useTheme2(); return ( - + {Array.from({ length: 9 }).map((_, i) => (
N# {i} @@ -61,6 +65,11 @@ export const ColumnsMinWidth: StoryFn = (args) => { ); }; +ColumnsMinWidth.argTypes = { + gap: SpacingTokenControl, + rowGap: SpacingTokenControl, + columnGap: SpacingTokenControl, +}; ColumnsMinWidth.args = { minColumnWidth: 21, }; diff --git a/packages/grafana-ui/src/components/Layout/Grid/Grid.tsx b/packages/grafana-ui/src/components/Layout/Grid/Grid.tsx index b85fdcafa4e..969d5fb1f06 100644 --- a/packages/grafana-ui/src/components/Layout/Grid/Grid.tsx +++ b/packages/grafana-ui/src/components/Layout/Grid/Grid.tsx @@ -12,6 +12,8 @@ interface GridPropsBase extends Omit, 'className' children: NonNullable; /** Specifies the gutters between columns and rows. It is overwritten when a column or row gap has a value. */ gap?: ResponsiveProp; + rowGap?: ResponsiveProp; + columnGap?: ResponsiveProp; alignItems?: ResponsiveProp; } @@ -33,8 +35,8 @@ interface PropsWithMinColumnWidth extends GridPropsBase { type GridProps = PropsWithColumns | PropsWithMinColumnWidth; export const Grid = forwardRef((props, ref) => { - const { alignItems, children, gap, columns, minColumnWidth, ...rest } = props; - const styles = useStyles2(getGridStyles, gap, columns, minColumnWidth, alignItems); + const { alignItems, children, gap, rowGap, columnGap, columns, minColumnWidth, ...rest } = props; + const styles = useStyles2(getGridStyles, gap, rowGap, columnGap, columns, minColumnWidth, alignItems); return (
@@ -48,6 +50,8 @@ Grid.displayName = 'Grid'; const getGridStyles = ( theme: GrafanaTheme2, gap: GridProps['gap'], + rowGap: GridProps['rowGap'], + columnGap: GridProps['columnGap'], columns: GridProps['columns'], minColumnWidth: GridProps['minColumnWidth'], alignItems: GridProps['alignItems'] @@ -58,6 +62,12 @@ const getGridStyles = ( getResponsiveStyle(theme, gap, (val) => ({ gap: theme.spacing(val), })), + getResponsiveStyle(theme, rowGap, (val) => ({ + rowGap: theme.spacing(val), + })), + getResponsiveStyle(theme, columnGap, (val) => ({ + columnGap: theme.spacing(val), + })), minColumnWidth && getResponsiveStyle(theme, minColumnWidth, (val) => ({ gridTemplateColumns: `repeat(auto-fill, minmax(${theme.spacing(val)}, 1fr))`, diff --git a/packages/grafana-ui/src/components/Layout/Stack/Stack.story.tsx b/packages/grafana-ui/src/components/Layout/Stack/Stack.story.tsx index 450cecb1eb0..4190e727f6b 100644 --- a/packages/grafana-ui/src/components/Layout/Stack/Stack.story.tsx +++ b/packages/grafana-ui/src/components/Layout/Stack/Stack.story.tsx @@ -36,11 +36,11 @@ const meta: Meta = { }, }; -export const Basic: StoryFn = ({ direction, wrap, alignItems, justifyContent, gap }) => { +export const Basic: StoryFn = (args) => { const theme = useTheme2(); return (
- + {Array.from({ length: 5 }).map((_, i) => ( ))} @@ -51,6 +51,8 @@ export const Basic: StoryFn = ({ direction, wrap, alignItems, just Basic.argTypes = { gap: SpacingTokenControl, + rowGap: SpacingTokenControl, + columnGap: SpacingTokenControl, direction: { control: 'select', options: ['row', 'row-reverse', 'column', 'column-reverse'] }, wrap: { control: 'select', options: ['nowrap', 'wrap', 'wrap-reverse'] }, alignItems: { diff --git a/packages/grafana-ui/src/components/Layout/Stack/Stack.tsx b/packages/grafana-ui/src/components/Layout/Stack/Stack.tsx index 05d544739f5..d73dfe4d1cf 100644 --- a/packages/grafana-ui/src/components/Layout/Stack/Stack.tsx +++ b/packages/grafana-ui/src/components/Layout/Stack/Stack.tsx @@ -10,6 +10,8 @@ import { getSizeStyles, SizeProps } from '../utils/styles'; interface StackProps extends FlexProps, SizeProps, Omit, 'className' | 'style'> { gap?: ResponsiveProp; + rowGap?: ResponsiveProp; + columnGap?: ResponsiveProp; alignItems?: ResponsiveProp; justifyContent?: ResponsiveProp; direction?: ResponsiveProp; @@ -20,6 +22,8 @@ interface StackProps extends FlexProps, SizeProps, Omit((props, ref) => { const { gap = 1, + rowGap, + columnGap, alignItems, justifyContent, direction, @@ -37,7 +41,20 @@ export const Stack = React.forwardRef((props, ref) = maxHeight, ...rest } = props; - const styles = useStyles2(getStyles, gap, alignItems, justifyContent, direction, wrap, grow, shrink, basis, flex); + const styles = useStyles2( + getStyles, + gap, + rowGap, + columnGap, + alignItems, + justifyContent, + direction, + wrap, + grow, + shrink, + basis, + flex + ); const sizeStyles = useStyles2(getSizeStyles, width, minWidth, maxWidth, height, minHeight, maxHeight); return (
@@ -51,6 +68,8 @@ Stack.displayName = 'Stack'; const getStyles = ( theme: GrafanaTheme2, gap: StackProps['gap'], + rowGap: StackProps['rowGap'], + columnGap: StackProps['columnGap'], alignItems: StackProps['alignItems'], justifyContent: StackProps['justifyContent'], direction: StackProps['direction'], @@ -80,6 +99,12 @@ const getStyles = ( getResponsiveStyle(theme, gap, (val) => ({ gap: theme.spacing(val), })), + getResponsiveStyle(theme, rowGap, (val) => ({ + rowGap: theme.spacing(val), + })), + getResponsiveStyle(theme, columnGap, (val) => ({ + columnGap: theme.spacing(val), + })), getResponsiveStyle(theme, grow, (val) => ({ flexGrow: val, })),