Grid: Make props responsive (#78214)

* Grid: Make props responsive

* Make 'columns' and 'minColumnWidth' mutually exclusive

* Cleanup
This commit is contained in:
Alex Khomenko 2023-11-15 18:49:27 +02:00 committed by GitHub
parent 2c73f15839
commit 441403729f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 28 additions and 17 deletions

View File

@ -4,22 +4,31 @@ import React, { forwardRef, HTMLAttributes } from 'react';
import { GrafanaTheme2, ThemeSpacingTokens } from '@grafana/data';
import { useStyles2 } from '../../../themes';
import { getResponsiveStyle, ResponsiveProp } from '../utils/responsiveness';
interface GridProps extends Omit<HTMLAttributes<HTMLDivElement>, 'className' | 'style'> {
interface GridPropsBase extends Omit<HTMLAttributes<HTMLDivElement>, 'className' | 'style'> {
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>;
}
/** Specifies the gutters between columns and rows. It is overwritten when a column or row gap has a value */
gap?: ThemeSpacingTokens;
interface PropsWithColumns extends GridPropsBase {
/** Number of columns */
columns?: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12;
columns?: ResponsiveProp<1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12>;
minColumnWidth?: never;
}
interface PropsWithMinColumnWidth extends GridPropsBase {
columns?: never;
/** 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;
minColumnWidth?: ResponsiveProp<1 | 2 | 3 | 5 | 8 | 13 | 21 | 34 | 44 | 55 | 72 | 89 | 144>;
}
/** 'columns' and 'minColumnWidth' are mutually exclusive */
type GridProps = PropsWithColumns | PropsWithMinColumnWidth;
export const Grid = forwardRef<HTMLDivElement, GridProps>((props, ref) => {
const { children, gap, columns, minColumnWidth, ...rest } = props;
const styles = useStyles2(getGridStyles, gap, columns, minColumnWidth);
@ -41,16 +50,18 @@ const getGridStyles = (
) => {
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)`,
},
{ display: 'grid' },
getResponsiveStyle(theme, gap, (val) => ({
gap: theme.spacing(val),
})),
minColumnWidth &&
getResponsiveStyle(theme, minColumnWidth, (val) => ({
gridTemplateColumns: `repeat(auto-fill, minmax(${theme.spacing(val)}, 1fr))`,
})),
columns &&
getResponsiveStyle(theme, columns, (val) => ({
gridTemplateColumns: `repeat(${val}, 1fr)`,
})),
]),
};
};

View File

@ -19,7 +19,7 @@ export const PluginList = ({ plugins, displayMode }: Props) => {
const pathName = config.appSubUrl + (pathname.endsWith('/') ? pathname.slice(0, -1) : pathname);
return (
<Grid gap={3} columns={isList ? 1 : undefined} minColumnWidth={isList ? undefined : 34} data-testid="plugin-list">
<Grid gap={3} {...(isList ? { columns: 1 } : { minColumnWidth: 34 })} data-testid="plugin-list">
{plugins.map((plugin) => (
<PluginListItem key={plugin.id} plugin={plugin} pathName={pathName} displayMode={displayMode} />
))}