Grafana/ui: Unify flex shorthand props (#77768)

* Update flex props

* Make the story external

* Add ResponsiveProp
pull/77811/head
Alex Khomenko 2 years ago committed by GitHub
parent 0ae3cd6fa5
commit e286a3a652
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 22
      packages/grafana-ui/src/components/Layout/Box/Box.tsx
  2. 3
      packages/grafana-ui/src/components/Layout/Stack/Stack.story.tsx
  3. 68
      packages/grafana-ui/src/components/Layout/Stack/Stack.tsx
  4. 51
      packages/grafana-ui/src/components/Layout/types.ts
  5. 6
      public/app/features/dashboard/dashgrid/DashboardEmpty.tsx

@ -4,7 +4,7 @@ import React, { ElementType, forwardRef, PropsWithChildren } from 'react';
import { GrafanaTheme2, ThemeSpacingTokens, ThemeShape, ThemeShadows } from '@grafana/data';
import { useStyles2 } from '../../../themes';
import { AlignItems, JustifyContent } from '../Stack/Stack';
import { AlignItems, FlexProps, JustifyContent } from '../types';
import { ResponsiveProp, getResponsiveStyle } from '../utils/responsiveness';
type Display = 'flex' | 'block' | 'inline' | 'none';
@ -14,7 +14,7 @@ export type BorderColor = keyof GrafanaTheme2['colors']['border'] | 'error' | 's
export type BorderRadius = keyof ThemeShape['radius'];
export type BoxShadow = keyof ThemeShadows;
interface BoxProps extends Omit<React.HTMLAttributes<HTMLElement>, 'className' | 'style'> {
interface BoxProps extends FlexProps, Omit<React.HTMLAttributes<HTMLElement>, 'className' | 'style'> {
// Margin props
/** Sets the property `margin` */
margin?: ResponsiveProp<ThemeSpacingTokens>;
@ -53,10 +53,6 @@ interface BoxProps extends Omit<React.HTMLAttributes<HTMLElement>, 'className' |
borderRadius?: ResponsiveProp<BorderRadius>;
// Flex Props
/** Sets the property `flex` */
grow?: ResponsiveProp<number>;
/** Sets the property `flex-shrink` */
shrink?: ResponsiveProp<number>;
alignItems?: ResponsiveProp<AlignItems>;
justifyContent?: ResponsiveProp<JustifyContent>;
gap?: ResponsiveProp<ThemeSpacingTokens>;
@ -90,6 +86,8 @@ export const Box = forwardRef<HTMLElement, PropsWithChildren<BoxProps>>((props,
backgroundColor,
grow,
shrink,
basis,
flex,
borderColor,
borderStyle,
borderRadius,
@ -120,6 +118,8 @@ export const Box = forwardRef<HTMLElement, PropsWithChildren<BoxProps>>((props,
backgroundColor,
grow,
shrink,
basis,
flex,
borderColor,
borderStyle,
borderRadius,
@ -183,6 +183,8 @@ const getStyles = (
backgroundColor: BoxProps['backgroundColor'],
grow: BoxProps['grow'],
shrink: BoxProps['shrink'],
basis: BoxProps['basis'],
flex: BoxProps['flex'],
borderColor: BoxProps['borderColor'],
borderStyle: BoxProps['borderStyle'],
borderRadius: BoxProps['borderRadius'],
@ -246,11 +248,17 @@ const getStyles = (
backgroundColor: customBackgroundColor(val, theme),
})),
getResponsiveStyle(theme, grow, (val) => ({
flex: val,
flexGrow: val,
})),
getResponsiveStyle(theme, shrink, (val) => ({
flexShrink: val,
})),
getResponsiveStyle(theme, basis, (val) => ({
flexBasis: val,
})),
getResponsiveStyle(theme, flex, (val) => ({
flex: val,
})),
getResponsiveStyle(theme, borderStyle, (val) => ({
borderStyle: val,
})),

@ -5,8 +5,9 @@ import { ThemeSpacingTokens } from '@grafana/data';
import { useTheme2 } from '../../../themes';
import { SpacingTokenControl } from '../../../utils/storybook/themeStorybookControls';
import { JustifyContent, Wrap, Direction } from '../types';
import { Stack, JustifyContent, Wrap, Direction } from './Stack';
import { Stack } from './Stack';
import mdx from './Stack.mdx';
const Item = ({ color, text, height }: { color: string; text?: string | number; height?: string }) => {

@ -1,59 +1,31 @@
import { css } from '@emotion/css';
import React, { CSSProperties } from 'react';
import React from 'react';
import { GrafanaTheme2, ThemeSpacingTokens } from '@grafana/data';
import { useStyles2 } from '../../../themes';
import { AlignItems, Direction, FlexProps, JustifyContent, Wrap } from '../types';
import { ResponsiveProp, getResponsiveStyle } from '../utils/responsiveness';
export type AlignItems =
| 'stretch'
| 'flex-start'
| 'flex-end'
| 'center'
| 'baseline'
| 'start'
| 'end'
| 'self-start'
| 'self-end';
export type JustifyContent =
| 'flex-start'
| 'flex-end'
| 'center'
| 'space-between'
| 'space-around'
| 'space-evenly'
| 'start'
| 'end'
| 'left'
| 'right';
export type Direction = 'row' | 'row-reverse' | 'column' | 'column-reverse';
export type Wrap = 'nowrap' | 'wrap' | 'wrap-reverse';
interface StackProps extends Omit<React.HTMLAttributes<HTMLElement>, 'className' | 'style'> {
interface StackProps extends FlexProps, Omit<React.HTMLAttributes<HTMLElement>, 'className' | 'style'> {
gap?: ResponsiveProp<ThemeSpacingTokens>;
alignItems?: ResponsiveProp<AlignItems>;
justifyContent?: ResponsiveProp<JustifyContent>;
direction?: ResponsiveProp<Direction>;
wrap?: ResponsiveProp<Wrap>;
children?: React.ReactNode;
flexGrow?: ResponsiveProp<CSSProperties['flexGrow']>;
}
export const Stack = React.forwardRef<HTMLDivElement, StackProps>(
({ gap = 1, alignItems, justifyContent, direction, wrap, children, flexGrow, ...rest }, ref) => {
const styles = useStyles2(getStyles, gap, alignItems, justifyContent, direction, wrap, flexGrow);
export const Stack = React.forwardRef<HTMLDivElement, StackProps>((props, ref) => {
const { gap = 1, alignItems, justifyContent, direction, wrap, children, grow, shrink, basis, flex, ...rest } = props;
const styles = useStyles2(getStyles, gap, alignItems, justifyContent, direction, wrap, grow, shrink, basis, flex);
return (
<div ref={ref} className={styles.flex} {...rest}>
{children}
</div>
);
}
);
return (
<div ref={ref} className={styles.flex} {...rest}>
{children}
</div>
);
});
Stack.displayName = 'Stack';
@ -64,7 +36,10 @@ const getStyles = (
justifyContent: StackProps['justifyContent'],
direction: StackProps['direction'],
wrap: StackProps['wrap'],
flexGrow: StackProps['flexGrow']
grow: StackProps['grow'],
shrink: StackProps['shrink'],
basis: StackProps['basis'],
flex: StackProps['flex']
) => {
return {
flex: css([
@ -86,9 +61,18 @@ const getStyles = (
getResponsiveStyle(theme, gap, (val) => ({
gap: theme.spacing(val),
})),
getResponsiveStyle(theme, flexGrow, (val) => ({
getResponsiveStyle(theme, grow, (val) => ({
flexGrow: val,
})),
getResponsiveStyle(theme, shrink, (val) => ({
flexShrink: val,
})),
getResponsiveStyle(theme, basis, (val) => ({
flexBasis: val,
})),
getResponsiveStyle(theme, flex, (val) => ({
flex: val,
})),
]),
};
};

@ -0,0 +1,51 @@
import { ResponsiveProp } from './utils/responsiveness';
export type AlignItems =
| 'stretch'
| 'flex-start'
| 'flex-end'
| 'center'
| 'baseline'
| 'start'
| 'end'
| 'self-start'
| 'self-end';
export type JustifyContent =
| 'flex-start'
| 'flex-end'
| 'center'
| 'space-between'
| 'space-around'
| 'space-evenly'
| 'start'
| 'end'
| 'left'
| 'right';
export type Direction = 'row' | 'row-reverse' | 'column' | 'column-reverse';
export type Wrap = 'nowrap' | 'wrap' | 'wrap-reverse';
type FlexGrow = number;
type FlexShrink = number;
type FlexBasis = 'auto' | 'initial' | '0' | `${number}%` | `${number}px`;
// Support the following formats for the "flex" shorthand property:
// - 1
// - '1'
// - '1 1'
// - '1 1 0'
// - '1 1 0px'
// - '1 1 auto'
type Flex = FlexGrow | `${FlexGrow}` | `${FlexGrow} ${FlexShrink}` | `${FlexGrow} ${FlexShrink} ${FlexBasis}`;
export type FlexProps = {
/** Sets the property `flex-grow` */
grow?: ResponsiveProp<FlexGrow>;
/** Sets the property `flex-shrink` */
shrink?: ResponsiveProp<FlexShrink>;
/** Sets the property `flex-basis` */
basis?: ResponsiveProp<FlexBasis>;
/** Sets the property `flex` */
flex?: ResponsiveProp<Flex>;
};

@ -59,7 +59,7 @@ const DashboardEmpty = ({ dashboard, canCreate }: Props) => {
</Box>
<Stack direction={{ xs: 'column', md: 'row' }} wrap="wrap" gap={4}>
{config.featureToggles.vizAndWidgetSplit && (
<Box borderColor="strong" borderStyle="dashed" padding={3} grow={1}>
<Box borderColor="strong" borderStyle="dashed" padding={3} flex={1}>
<Stack direction="column" alignItems="center" gap={1}>
<Text element="h3" textAlignment="center" weight="medium">
<Trans i18nKey="dashboard.empty.add-widget-header">Add a widget</Trans>
@ -84,7 +84,7 @@ const DashboardEmpty = ({ dashboard, canCreate }: Props) => {
</Stack>
</Box>
)}
<Box borderColor="strong" borderStyle="dashed" padding={3} grow={1}>
<Box borderColor="strong" borderStyle="dashed" padding={3} flex={1}>
<Stack direction="column" alignItems="center" gap={1}>
<Text element="h3" textAlignment="center" weight="medium">
<Trans i18nKey="dashboard.empty.add-library-panel-header">Import panel</Trans>
@ -110,7 +110,7 @@ const DashboardEmpty = ({ dashboard, canCreate }: Props) => {
</Button>
</Stack>
</Box>
<Box borderColor="strong" borderStyle="dashed" padding={3} grow={1}>
<Box borderColor="strong" borderStyle="dashed" padding={3} flex={1}>
<Stack direction="column" alignItems="center" gap={1}>
<Text element="h3" textAlignment="center" weight="medium">
<Trans i18nKey="dashboard.empty.import-a-dashboard-header">Import a dashboard</Trans>

Loading…
Cancel
Save