From e286a3a652a2e66240d15f320065a08f6a62aa9c Mon Sep 17 00:00:00 2001 From: Alex Khomenko Date: Tue, 7 Nov 2023 16:45:57 +0100 Subject: [PATCH] Grafana/ui: Unify flex shorthand props (#77768) * Update flex props * Make the story external * Add ResponsiveProp --- .../src/components/Layout/Box/Box.tsx | 22 ++++-- ...ack.internal.story.tsx => Stack.story.tsx} | 3 +- .../src/components/Layout/Stack/Stack.tsx | 68 +++++++------------ .../grafana-ui/src/components/Layout/types.ts | 51 ++++++++++++++ .../dashboard/dashgrid/DashboardEmpty.tsx | 6 +- 5 files changed, 97 insertions(+), 53 deletions(-) rename packages/grafana-ui/src/components/Layout/Stack/{Stack.internal.story.tsx => Stack.story.tsx} (98%) create mode 100644 packages/grafana-ui/src/components/Layout/types.ts diff --git a/packages/grafana-ui/src/components/Layout/Box/Box.tsx b/packages/grafana-ui/src/components/Layout/Box/Box.tsx index d6942711747..a590d41a0cd 100644 --- a/packages/grafana-ui/src/components/Layout/Box/Box.tsx +++ b/packages/grafana-ui/src/components/Layout/Box/Box.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, 'className' | 'style'> { +interface BoxProps extends FlexProps, Omit, 'className' | 'style'> { // Margin props /** Sets the property `margin` */ margin?: ResponsiveProp; @@ -53,10 +53,6 @@ interface BoxProps extends Omit, 'className' | borderRadius?: ResponsiveProp; // Flex Props - /** Sets the property `flex` */ - grow?: ResponsiveProp; - /** Sets the property `flex-shrink` */ - shrink?: ResponsiveProp; alignItems?: ResponsiveProp; justifyContent?: ResponsiveProp; gap?: ResponsiveProp; @@ -90,6 +86,8 @@ export const Box = forwardRef>((props, backgroundColor, grow, shrink, + basis, + flex, borderColor, borderStyle, borderRadius, @@ -120,6 +118,8 @@ export const Box = forwardRef>((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, })), diff --git a/packages/grafana-ui/src/components/Layout/Stack/Stack.internal.story.tsx b/packages/grafana-ui/src/components/Layout/Stack/Stack.story.tsx similarity index 98% rename from packages/grafana-ui/src/components/Layout/Stack/Stack.internal.story.tsx rename to packages/grafana-ui/src/components/Layout/Stack/Stack.story.tsx index eff686a4847..259c67e9132 100644 --- a/packages/grafana-ui/src/components/Layout/Stack/Stack.internal.story.tsx +++ b/packages/grafana-ui/src/components/Layout/Stack/Stack.story.tsx @@ -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 }) => { diff --git a/packages/grafana-ui/src/components/Layout/Stack/Stack.tsx b/packages/grafana-ui/src/components/Layout/Stack/Stack.tsx index d966ce2bf75..835282b8e17 100644 --- a/packages/grafana-ui/src/components/Layout/Stack/Stack.tsx +++ b/packages/grafana-ui/src/components/Layout/Stack/Stack.tsx @@ -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, 'className' | 'style'> { +interface StackProps extends FlexProps, Omit, 'className' | 'style'> { gap?: ResponsiveProp; alignItems?: ResponsiveProp; justifyContent?: ResponsiveProp; direction?: ResponsiveProp; wrap?: ResponsiveProp; children?: React.ReactNode; - flexGrow?: ResponsiveProp; } -export const Stack = React.forwardRef( - ({ 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((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 ( -
- {children} -
- ); - } -); + return ( +
+ {children} +
+ ); +}); 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, + })), ]), }; }; diff --git a/packages/grafana-ui/src/components/Layout/types.ts b/packages/grafana-ui/src/components/Layout/types.ts new file mode 100644 index 00000000000..b31f68c97ab --- /dev/null +++ b/packages/grafana-ui/src/components/Layout/types.ts @@ -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; + /** Sets the property `flex-shrink` */ + shrink?: ResponsiveProp; + /** Sets the property `flex-basis` */ + basis?: ResponsiveProp; + /** Sets the property `flex` */ + flex?: ResponsiveProp; +}; diff --git a/public/app/features/dashboard/dashgrid/DashboardEmpty.tsx b/public/app/features/dashboard/dashgrid/DashboardEmpty.tsx index 2d087b41b0c..e8e90d4e832 100644 --- a/public/app/features/dashboard/dashgrid/DashboardEmpty.tsx +++ b/public/app/features/dashboard/dashgrid/DashboardEmpty.tsx @@ -59,7 +59,7 @@ const DashboardEmpty = ({ dashboard, canCreate }: Props) => { {config.featureToggles.vizAndWidgetSplit && ( - + Add a widget @@ -84,7 +84,7 @@ const DashboardEmpty = ({ dashboard, canCreate }: Props) => { )} - + Import panel @@ -110,7 +110,7 @@ const DashboardEmpty = ({ dashboard, canCreate }: Props) => { - + Import a dashboard