mirror of
https://github.com/grafana/grafana.git
synced 2025-07-31 04:02:30 +08:00
Grafana UI: Add columnGap
+ rowGap
to Stack
/Grid
(#102883)
add columnGap/rowGap to Stack/Grid
This commit is contained in:
@ -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<typeof Grid> = (args) => {
|
||||
const theme = useTheme2();
|
||||
return (
|
||||
<Grid gap={args.gap} minColumnWidth={args.minColumnWidth}>
|
||||
<Grid {...args}>
|
||||
{Array.from({ length: 9 }).map((_, i) => (
|
||||
<div key={i} style={{ background: theme.colors.background.secondary, textAlign: 'center' }}>
|
||||
N# {i}
|
||||
@ -61,6 +65,11 @@ export const ColumnsMinWidth: StoryFn<typeof Grid> = (args) => {
|
||||
</Grid>
|
||||
);
|
||||
};
|
||||
ColumnsMinWidth.argTypes = {
|
||||
gap: SpacingTokenControl,
|
||||
rowGap: SpacingTokenControl,
|
||||
columnGap: SpacingTokenControl,
|
||||
};
|
||||
ColumnsMinWidth.args = {
|
||||
minColumnWidth: 21,
|
||||
};
|
||||
|
@ -12,6 +12,8 @@ interface GridPropsBase extends Omit<HTMLAttributes<HTMLDivElement>, 'className'
|
||||
children: NonNullable<React.ReactNode>;
|
||||
/** Specifies the gutters between columns and rows. It is overwritten when a column or row gap has a value. */
|
||||
gap?: ResponsiveProp<ThemeSpacingTokens>;
|
||||
rowGap?: ResponsiveProp<ThemeSpacingTokens>;
|
||||
columnGap?: ResponsiveProp<ThemeSpacingTokens>;
|
||||
alignItems?: ResponsiveProp<AlignItems>;
|
||||
}
|
||||
|
||||
@ -33,8 +35,8 @@ interface PropsWithMinColumnWidth extends GridPropsBase {
|
||||
type GridProps = PropsWithColumns | PropsWithMinColumnWidth;
|
||||
|
||||
export const Grid = forwardRef<HTMLDivElement, GridProps>((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 (
|
||||
<div ref={ref} {...rest} className={styles.grid}>
|
||||
@ -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))`,
|
||||
|
@ -36,11 +36,11 @@ const meta: Meta<typeof Stack> = {
|
||||
},
|
||||
};
|
||||
|
||||
export const Basic: StoryFn<typeof Stack> = ({ direction, wrap, alignItems, justifyContent, gap }) => {
|
||||
export const Basic: StoryFn<typeof Stack> = (args) => {
|
||||
const theme = useTheme2();
|
||||
return (
|
||||
<div style={{ width: '600px', height: '600px', border: '1px solid grey' }}>
|
||||
<Stack direction={direction} wrap={wrap} alignItems={alignItems} justifyContent={justifyContent} gap={gap}>
|
||||
<Stack {...args}>
|
||||
{Array.from({ length: 5 }).map((_, i) => (
|
||||
<Item key={i} color={theme.colors.warning.main} text={i + 1} />
|
||||
))}
|
||||
@ -51,6 +51,8 @@ export const Basic: StoryFn<typeof Stack> = ({ 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: {
|
||||
|
@ -10,6 +10,8 @@ import { getSizeStyles, SizeProps } from '../utils/styles';
|
||||
|
||||
interface StackProps extends FlexProps, SizeProps, Omit<React.HTMLAttributes<HTMLElement>, 'className' | 'style'> {
|
||||
gap?: ResponsiveProp<ThemeSpacingTokens>;
|
||||
rowGap?: ResponsiveProp<ThemeSpacingTokens>;
|
||||
columnGap?: ResponsiveProp<ThemeSpacingTokens>;
|
||||
alignItems?: ResponsiveProp<AlignItems>;
|
||||
justifyContent?: ResponsiveProp<JustifyContent>;
|
||||
direction?: ResponsiveProp<Direction>;
|
||||
@ -20,6 +22,8 @@ interface StackProps extends FlexProps, SizeProps, Omit<React.HTMLAttributes<HTM
|
||||
export const Stack = React.forwardRef<HTMLDivElement, StackProps>((props, ref) => {
|
||||
const {
|
||||
gap = 1,
|
||||
rowGap,
|
||||
columnGap,
|
||||
alignItems,
|
||||
justifyContent,
|
||||
direction,
|
||||
@ -37,7 +41,20 @@ export const Stack = React.forwardRef<HTMLDivElement, StackProps>((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 (
|
||||
<div ref={ref} className={cx(styles.flex, sizeStyles)} {...rest}>
|
||||
@ -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,
|
||||
})),
|
||||
|
Reference in New Issue
Block a user