mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Grafana/ui: Unify flex shorthand props (#77768)
* Update flex props * Make the story external * Add ResponsiveProp
This commit is contained in:
@@ -4,7 +4,7 @@ import React, { ElementType, forwardRef, PropsWithChildren } from 'react';
|
|||||||
import { GrafanaTheme2, ThemeSpacingTokens, ThemeShape, ThemeShadows } from '@grafana/data';
|
import { GrafanaTheme2, ThemeSpacingTokens, ThemeShape, ThemeShadows } from '@grafana/data';
|
||||||
|
|
||||||
import { useStyles2 } from '../../../themes';
|
import { useStyles2 } from '../../../themes';
|
||||||
import { AlignItems, JustifyContent } from '../Stack/Stack';
|
import { AlignItems, FlexProps, JustifyContent } from '../types';
|
||||||
import { ResponsiveProp, getResponsiveStyle } from '../utils/responsiveness';
|
import { ResponsiveProp, getResponsiveStyle } from '../utils/responsiveness';
|
||||||
|
|
||||||
type Display = 'flex' | 'block' | 'inline' | 'none';
|
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 BorderRadius = keyof ThemeShape['radius'];
|
||||||
export type BoxShadow = keyof ThemeShadows;
|
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
|
// Margin props
|
||||||
/** Sets the property `margin` */
|
/** Sets the property `margin` */
|
||||||
margin?: ResponsiveProp<ThemeSpacingTokens>;
|
margin?: ResponsiveProp<ThemeSpacingTokens>;
|
||||||
@@ -53,10 +53,6 @@ interface BoxProps extends Omit<React.HTMLAttributes<HTMLElement>, 'className' |
|
|||||||
borderRadius?: ResponsiveProp<BorderRadius>;
|
borderRadius?: ResponsiveProp<BorderRadius>;
|
||||||
|
|
||||||
// Flex Props
|
// Flex Props
|
||||||
/** Sets the property `flex` */
|
|
||||||
grow?: ResponsiveProp<number>;
|
|
||||||
/** Sets the property `flex-shrink` */
|
|
||||||
shrink?: ResponsiveProp<number>;
|
|
||||||
alignItems?: ResponsiveProp<AlignItems>;
|
alignItems?: ResponsiveProp<AlignItems>;
|
||||||
justifyContent?: ResponsiveProp<JustifyContent>;
|
justifyContent?: ResponsiveProp<JustifyContent>;
|
||||||
gap?: ResponsiveProp<ThemeSpacingTokens>;
|
gap?: ResponsiveProp<ThemeSpacingTokens>;
|
||||||
@@ -90,6 +86,8 @@ export const Box = forwardRef<HTMLElement, PropsWithChildren<BoxProps>>((props,
|
|||||||
backgroundColor,
|
backgroundColor,
|
||||||
grow,
|
grow,
|
||||||
shrink,
|
shrink,
|
||||||
|
basis,
|
||||||
|
flex,
|
||||||
borderColor,
|
borderColor,
|
||||||
borderStyle,
|
borderStyle,
|
||||||
borderRadius,
|
borderRadius,
|
||||||
@@ -120,6 +118,8 @@ export const Box = forwardRef<HTMLElement, PropsWithChildren<BoxProps>>((props,
|
|||||||
backgroundColor,
|
backgroundColor,
|
||||||
grow,
|
grow,
|
||||||
shrink,
|
shrink,
|
||||||
|
basis,
|
||||||
|
flex,
|
||||||
borderColor,
|
borderColor,
|
||||||
borderStyle,
|
borderStyle,
|
||||||
borderRadius,
|
borderRadius,
|
||||||
@@ -183,6 +183,8 @@ const getStyles = (
|
|||||||
backgroundColor: BoxProps['backgroundColor'],
|
backgroundColor: BoxProps['backgroundColor'],
|
||||||
grow: BoxProps['grow'],
|
grow: BoxProps['grow'],
|
||||||
shrink: BoxProps['shrink'],
|
shrink: BoxProps['shrink'],
|
||||||
|
basis: BoxProps['basis'],
|
||||||
|
flex: BoxProps['flex'],
|
||||||
borderColor: BoxProps['borderColor'],
|
borderColor: BoxProps['borderColor'],
|
||||||
borderStyle: BoxProps['borderStyle'],
|
borderStyle: BoxProps['borderStyle'],
|
||||||
borderRadius: BoxProps['borderRadius'],
|
borderRadius: BoxProps['borderRadius'],
|
||||||
@@ -246,11 +248,17 @@ const getStyles = (
|
|||||||
backgroundColor: customBackgroundColor(val, theme),
|
backgroundColor: customBackgroundColor(val, theme),
|
||||||
})),
|
})),
|
||||||
getResponsiveStyle(theme, grow, (val) => ({
|
getResponsiveStyle(theme, grow, (val) => ({
|
||||||
flex: val,
|
flexGrow: val,
|
||||||
})),
|
})),
|
||||||
getResponsiveStyle(theme, shrink, (val) => ({
|
getResponsiveStyle(theme, shrink, (val) => ({
|
||||||
flexShrink: val,
|
flexShrink: val,
|
||||||
})),
|
})),
|
||||||
|
getResponsiveStyle(theme, basis, (val) => ({
|
||||||
|
flexBasis: val,
|
||||||
|
})),
|
||||||
|
getResponsiveStyle(theme, flex, (val) => ({
|
||||||
|
flex: val,
|
||||||
|
})),
|
||||||
getResponsiveStyle(theme, borderStyle, (val) => ({
|
getResponsiveStyle(theme, borderStyle, (val) => ({
|
||||||
borderStyle: val,
|
borderStyle: val,
|
||||||
})),
|
})),
|
||||||
|
|||||||
@@ -5,8 +5,9 @@ import { ThemeSpacingTokens } from '@grafana/data';
|
|||||||
|
|
||||||
import { useTheme2 } from '../../../themes';
|
import { useTheme2 } from '../../../themes';
|
||||||
import { SpacingTokenControl } from '../../../utils/storybook/themeStorybookControls';
|
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';
|
import mdx from './Stack.mdx';
|
||||||
|
|
||||||
const Item = ({ color, text, height }: { color: string; text?: string | number; height?: string }) => {
|
const Item = ({ color, text, height }: { color: string; text?: string | number; height?: string }) => {
|
||||||
@@ -1,59 +1,31 @@
|
|||||||
import { css } from '@emotion/css';
|
import { css } from '@emotion/css';
|
||||||
import React, { CSSProperties } from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
import { GrafanaTheme2, ThemeSpacingTokens } from '@grafana/data';
|
import { GrafanaTheme2, ThemeSpacingTokens } from '@grafana/data';
|
||||||
|
|
||||||
import { useStyles2 } from '../../../themes';
|
import { useStyles2 } from '../../../themes';
|
||||||
|
import { AlignItems, Direction, FlexProps, JustifyContent, Wrap } from '../types';
|
||||||
import { ResponsiveProp, getResponsiveStyle } from '../utils/responsiveness';
|
import { ResponsiveProp, getResponsiveStyle } from '../utils/responsiveness';
|
||||||
|
|
||||||
export type AlignItems =
|
interface StackProps extends FlexProps, Omit<React.HTMLAttributes<HTMLElement>, 'className' | 'style'> {
|
||||||
| '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'> {
|
|
||||||
gap?: ResponsiveProp<ThemeSpacingTokens>;
|
gap?: ResponsiveProp<ThemeSpacingTokens>;
|
||||||
alignItems?: ResponsiveProp<AlignItems>;
|
alignItems?: ResponsiveProp<AlignItems>;
|
||||||
justifyContent?: ResponsiveProp<JustifyContent>;
|
justifyContent?: ResponsiveProp<JustifyContent>;
|
||||||
direction?: ResponsiveProp<Direction>;
|
direction?: ResponsiveProp<Direction>;
|
||||||
wrap?: ResponsiveProp<Wrap>;
|
wrap?: ResponsiveProp<Wrap>;
|
||||||
children?: React.ReactNode;
|
children?: React.ReactNode;
|
||||||
flexGrow?: ResponsiveProp<CSSProperties['flexGrow']>;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const Stack = React.forwardRef<HTMLDivElement, StackProps>(
|
export const Stack = React.forwardRef<HTMLDivElement, StackProps>((props, ref) => {
|
||||||
({ gap = 1, alignItems, justifyContent, direction, wrap, children, flexGrow, ...rest }, ref) => {
|
const { gap = 1, alignItems, justifyContent, direction, wrap, children, grow, shrink, basis, flex, ...rest } = props;
|
||||||
const styles = useStyles2(getStyles, gap, alignItems, justifyContent, direction, wrap, flexGrow);
|
const styles = useStyles2(getStyles, gap, alignItems, justifyContent, direction, wrap, grow, shrink, basis, flex);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div ref={ref} className={styles.flex} {...rest}>
|
<div ref={ref} className={styles.flex} {...rest}>
|
||||||
{children}
|
{children}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
});
|
||||||
);
|
|
||||||
|
|
||||||
Stack.displayName = 'Stack';
|
Stack.displayName = 'Stack';
|
||||||
|
|
||||||
@@ -64,7 +36,10 @@ const getStyles = (
|
|||||||
justifyContent: StackProps['justifyContent'],
|
justifyContent: StackProps['justifyContent'],
|
||||||
direction: StackProps['direction'],
|
direction: StackProps['direction'],
|
||||||
wrap: StackProps['wrap'],
|
wrap: StackProps['wrap'],
|
||||||
flexGrow: StackProps['flexGrow']
|
grow: StackProps['grow'],
|
||||||
|
shrink: StackProps['shrink'],
|
||||||
|
basis: StackProps['basis'],
|
||||||
|
flex: StackProps['flex']
|
||||||
) => {
|
) => {
|
||||||
return {
|
return {
|
||||||
flex: css([
|
flex: css([
|
||||||
@@ -86,9 +61,18 @@ const getStyles = (
|
|||||||
getResponsiveStyle(theme, gap, (val) => ({
|
getResponsiveStyle(theme, gap, (val) => ({
|
||||||
gap: theme.spacing(val),
|
gap: theme.spacing(val),
|
||||||
})),
|
})),
|
||||||
getResponsiveStyle(theme, flexGrow, (val) => ({
|
getResponsiveStyle(theme, grow, (val) => ({
|
||||||
flexGrow: val,
|
flexGrow: val,
|
||||||
})),
|
})),
|
||||||
|
getResponsiveStyle(theme, shrink, (val) => ({
|
||||||
|
flexShrink: val,
|
||||||
|
})),
|
||||||
|
getResponsiveStyle(theme, basis, (val) => ({
|
||||||
|
flexBasis: val,
|
||||||
|
})),
|
||||||
|
getResponsiveStyle(theme, flex, (val) => ({
|
||||||
|
flex: val,
|
||||||
|
})),
|
||||||
]),
|
]),
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
51
packages/grafana-ui/src/components/Layout/types.ts
Normal file
51
packages/grafana-ui/src/components/Layout/types.ts
Normal file
@@ -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>
|
</Box>
|
||||||
<Stack direction={{ xs: 'column', md: 'row' }} wrap="wrap" gap={4}>
|
<Stack direction={{ xs: 'column', md: 'row' }} wrap="wrap" gap={4}>
|
||||||
{config.featureToggles.vizAndWidgetSplit && (
|
{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}>
|
<Stack direction="column" alignItems="center" gap={1}>
|
||||||
<Text element="h3" textAlignment="center" weight="medium">
|
<Text element="h3" textAlignment="center" weight="medium">
|
||||||
<Trans i18nKey="dashboard.empty.add-widget-header">Add a widget</Trans>
|
<Trans i18nKey="dashboard.empty.add-widget-header">Add a widget</Trans>
|
||||||
@@ -84,7 +84,7 @@ const DashboardEmpty = ({ dashboard, canCreate }: Props) => {
|
|||||||
</Stack>
|
</Stack>
|
||||||
</Box>
|
</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}>
|
<Stack direction="column" alignItems="center" gap={1}>
|
||||||
<Text element="h3" textAlignment="center" weight="medium">
|
<Text element="h3" textAlignment="center" weight="medium">
|
||||||
<Trans i18nKey="dashboard.empty.add-library-panel-header">Import panel</Trans>
|
<Trans i18nKey="dashboard.empty.add-library-panel-header">Import panel</Trans>
|
||||||
@@ -110,7 +110,7 @@ const DashboardEmpty = ({ dashboard, canCreate }: Props) => {
|
|||||||
</Button>
|
</Button>
|
||||||
</Stack>
|
</Stack>
|
||||||
</Box>
|
</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}>
|
<Stack direction="column" alignItems="center" gap={1}>
|
||||||
<Text element="h3" textAlignment="center" weight="medium">
|
<Text element="h3" textAlignment="center" weight="medium">
|
||||||
<Trans i18nKey="dashboard.empty.import-a-dashboard-header">Import a dashboard</Trans>
|
<Trans i18nKey="dashboard.empty.import-a-dashboard-header">Import a dashboard</Trans>
|
||||||
|
|||||||
Reference in New Issue
Block a user