mirror of https://github.com/grafana/grafana
Grafana UI: create `Grid` component in the `unstable` package (#75299)
parent
1aa911dee6
commit
611df82259
@ -0,0 +1,64 @@ |
||||
import { Meta, StoryFn } from '@storybook/react'; |
||||
import React from 'react'; |
||||
|
||||
import { useTheme2 } from '../../../themes'; |
||||
|
||||
import { Grid } from './Grid'; |
||||
import mdx from './Grid.mdx'; |
||||
|
||||
const meta: Meta<typeof Grid> = { |
||||
title: 'General/Layout/Grid', |
||||
component: Grid, |
||||
parameters: { |
||||
docs: { |
||||
page: mdx, |
||||
}, |
||||
}, |
||||
args: { |
||||
gap: 1, |
||||
}, |
||||
}; |
||||
|
||||
export const ColumnsNumber: StoryFn<typeof Grid> = (args) => { |
||||
const theme = useTheme2(); |
||||
return ( |
||||
<Grid gap={args.gap} columns={args.columns}> |
||||
{Array.from({ length: 9 }).map((_, i) => ( |
||||
<div key={i} style={{ background: theme.colors.background.secondary, textAlign: 'center' }}> |
||||
N# {i} |
||||
</div> |
||||
))} |
||||
</Grid> |
||||
); |
||||
}; |
||||
ColumnsNumber.args = { |
||||
columns: 3, |
||||
}; |
||||
ColumnsNumber.parameters = { |
||||
controls: { |
||||
exclude: ['minColumnWidth'], |
||||
}, |
||||
}; |
||||
|
||||
export const ColumnsMinWidth: StoryFn<typeof Grid> = (args) => { |
||||
const theme = useTheme2(); |
||||
return ( |
||||
<Grid gap={args.gap} minColumnWidth={args.minColumnWidth}> |
||||
{Array.from({ length: 9 }).map((_, i) => ( |
||||
<div key={i} style={{ background: theme.colors.background.secondary, textAlign: 'center' }}> |
||||
N# {i} |
||||
</div> |
||||
))} |
||||
</Grid> |
||||
); |
||||
}; |
||||
ColumnsMinWidth.args = { |
||||
minColumnWidth: 21, |
||||
}; |
||||
ColumnsMinWidth.parameters = { |
||||
controls: { |
||||
exclude: ['columns'], |
||||
}, |
||||
}; |
||||
|
||||
export default meta; |
@ -0,0 +1,32 @@ |
||||
import { Meta, ArgTypes } from '@storybook/blocks'; |
||||
import { Grid } from './Grid'; |
||||
|
||||
<Meta title="MDX|Grid" component={Grid} /> |
||||
|
||||
# Grid |
||||
|
||||
The `Grid` component allows for the organized layout and alignment of content into a grid-based structure. |
||||
|
||||
## Usage |
||||
|
||||
### When to use |
||||
|
||||
Use the Grid component when you want to create structured and organized layouts where content or elements need to be aligned in rows and columns for clarity and consistency. |
||||
|
||||
### When not to use |
||||
|
||||
Use the `Stack` component instead for these use cases: |
||||
|
||||
- **Simple layouts:** When you need to arrange elements in a linear format, either vertically or horizontally. |
||||
- **Regular flow:** When you want a "regular" site flow but with standardized spacing between the elements. |
||||
|
||||
Use the `Flex` component instead for these use cases: |
||||
|
||||
- **Alignment:** More options for item alignment. |
||||
- **Flex items:** Custom flex basis or configure how items stretch and wrap. |
||||
|
||||
## Properties |
||||
|
||||
_Note: There is no support for using `columns` and `minColumnWidth` props at the same time. The correct behaviour is working just with one of them not both._ |
||||
|
||||
<ArgTypes of={Grid} /> |
@ -0,0 +1,56 @@ |
||||
import { css } from '@emotion/css'; |
||||
import React, { forwardRef, HTMLAttributes } from 'react'; |
||||
|
||||
import { GrafanaTheme2, ThemeSpacingTokens } from '@grafana/data'; |
||||
|
||||
import { useStyles2 } from '../../../themes'; |
||||
|
||||
interface GridProps 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?: ThemeSpacingTokens; |
||||
|
||||
/** Number of columns */ |
||||
columns?: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12; |
||||
|
||||
/** For a responsive layout, fit as many columns while maintaining this minimum column width. |
||||
* The real width will be calculated based on the theme spacing tokens: `theme.spacing(minColumnWidth)` |
||||
*/ |
||||
minColumnWidth?: 1 | 2 | 3 | 5 | 8 | 13 | 21 | 34 | 44 | 55 | 72 | 89 | 144; |
||||
} |
||||
|
||||
export const Grid = forwardRef<HTMLDivElement, GridProps>((props, ref) => { |
||||
const { children, gap, columns, minColumnWidth, ...rest } = props; |
||||
const styles = useStyles2(getGridStyles, gap, columns, minColumnWidth); |
||||
|
||||
return ( |
||||
<div ref={ref} {...rest} className={styles.grid}> |
||||
{children} |
||||
</div> |
||||
); |
||||
}); |
||||
|
||||
Grid.displayName = 'Grid'; |
||||
|
||||
const getGridStyles = ( |
||||
theme: GrafanaTheme2, |
||||
gap: GridProps['gap'], |
||||
columns: GridProps['columns'], |
||||
minColumnWidth: GridProps['minColumnWidth'] |
||||
) => { |
||||
return { |
||||
grid: css([ |
||||
{ |
||||
display: 'grid', |
||||
gap: gap ? theme.spacing(gap) : undefined, |
||||
}, |
||||
minColumnWidth && { |
||||
gridTemplateColumns: `repeat(auto-fill, minmax(${theme.spacing(minColumnWidth)}, 1fr))`, |
||||
}, |
||||
columns && { |
||||
gridTemplateColumns: `repeat(${columns}, 1fr)`, |
||||
}, |
||||
]), |
||||
}; |
||||
}; |
Loading…
Reference in new issue