diff --git a/packages/grafana-ui/src/components/Layout/Box/Box.mdx b/packages/grafana-ui/src/components/Layout/Box/Box.mdx index b789bead6d1..e9ec57ed812 100644 --- a/packages/grafana-ui/src/components/Layout/Box/Box.mdx +++ b/packages/grafana-ui/src/components/Layout/Box/Box.mdx @@ -16,7 +16,7 @@ Use it whenever you would use custom CSS. #### When not to use -If you need layout styles, use the Stack, Flex or Grid components instead. +If you need layout styles, use the Stack or Grid components instead. ### How to add a prop to Box diff --git a/packages/grafana-ui/src/components/Layout/Box/Box.story.tsx b/packages/grafana-ui/src/components/Layout/Box/Box.story.tsx index 42d0b7f759e..203f9f13108 100644 --- a/packages/grafana-ui/src/components/Layout/Box/Box.story.tsx +++ b/packages/grafana-ui/src/components/Layout/Box/Box.story.tsx @@ -3,7 +3,7 @@ import React from 'react'; import { SpacingTokenControl } from '../../../utils/storybook/themeStorybookControls'; import { Text } from '../../Text/Text'; -import { Flex } from '../Flex/Flex'; +import { Stack } from '../Stack/Stack'; import { Box, BackgroundColor, BorderColor, BorderStyle, BorderRadius, BoxShadow } from './Box'; import mdx from './Box.mdx'; @@ -48,11 +48,11 @@ const Item = ({ background }: { background?: string }) => { export const Basic: StoryFn = (args) => { return ( - + Box - + ); }; @@ -88,64 +88,64 @@ Basic.args = { export const Background: StoryFn = () => { return ( - + {backgroundOptions.map((background) => ( - + {background} - + ))} - + ); }; export const Border: StoryFn = () => { return ( - +
Border Color - + {borderColorOptions.map((border) => ( - + {border} - + ))} - +
Border Style - + {borderStyleOptions.map((border) => ( - + {border} - + ))} - +
-
+ ); }; export const Shadow: StoryFn = () => { return ( - + {boxShadowOptions.map((shadow) => ( - + {shadow} - + ))} - + ); }; diff --git a/packages/grafana-ui/src/components/Layout/Box/Box.tsx b/packages/grafana-ui/src/components/Layout/Box/Box.tsx index 4a5a7e52e2f..d6942711747 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 '../Flex/Flex'; +import { AlignItems, JustifyContent } from '../Stack/Stack'; import { ResponsiveProp, getResponsiveStyle } from '../utils/responsiveness'; type Display = 'flex' | 'block' | 'inline' | 'none'; diff --git a/packages/grafana-ui/src/components/Layout/Flex/Flex.internal.story.tsx b/packages/grafana-ui/src/components/Layout/Flex/Flex.internal.story.tsx deleted file mode 100644 index 4bada87b32b..00000000000 --- a/packages/grafana-ui/src/components/Layout/Flex/Flex.internal.story.tsx +++ /dev/null @@ -1,202 +0,0 @@ -import { Meta, StoryFn } from '@storybook/react'; -import React from 'react'; - -import { ThemeSpacingTokens } from '@grafana/data'; - -import { useTheme2 } from '../../../themes'; -import { SpacingTokenControl } from '../../../utils/storybook/themeStorybookControls'; - -import { Flex, JustifyContent, Wrap, Direction } from './Flex'; -import mdx from './Flex.mdx'; - -const Item = ({ color, text, height }: { color: string; text?: string | number; height?: string }) => { - return ( -
- {text &&

{text}

} -
- ); -}; - -const meta: Meta = { - title: 'General/Layout/Flex', - component: Flex, - parameters: { - docs: { - page: mdx, - }, - }, -}; - -export const Basic: StoryFn = ({ direction, wrap, alignItems, justifyContent, gap }) => { - const theme = useTheme2(); - return ( -
- - {Array.from({ length: 5 }).map((_, i) => ( - - ))} - -
- ); -}; - -Basic.argTypes = { - gap: SpacingTokenControl, - direction: { control: 'select', options: ['row', 'row-reverse', 'column', 'column-reverse'] }, - wrap: { control: 'select', options: ['nowrap', 'wrap', 'wrap-reverse'] }, - alignItems: { - control: 'select', - options: ['stretch', 'flex-start', 'flex-end', 'center', 'baseline', 'start', 'end', 'self-start', 'self-end'], - }, - justifyContent: { - control: 'select', - options: [ - 'flex-start', - 'flex-end', - 'center', - 'space-between', - 'space-around', - 'space-evenly', - 'start', - 'end', - 'left', - 'right', - ], - }, -}; - -export const AlignItemsExamples: StoryFn = () => { - const theme = useTheme2(); - - return ( -
-

Align items flex-start

- - {Array.from({ length: 5 }).map((_, i) => ( - - ))} - -

Align items flex-end

- - {Array.from({ length: 5 }).map((_, i) => ( - - ))} - -

Align items baseline

- - {Array.from({ length: 5 }).map((_, i) => ( - - ))} - -

Align items center

- - {Array.from({ length: 5 }).map((_, i) => ( - - ))} - -

Align items stretch

- - - - - - - -
- ); -}; - -export const JustifyContentExamples: StoryFn = () => { - const theme = useTheme2(); - const justifyContentOptions: JustifyContent[] = [ - 'space-between', - 'space-around', - 'space-evenly', - 'flex-start', - 'flex-end', - 'center', - ]; - - return ( -
- {justifyContentOptions.map((justifyContent) => ( - <> -

Justify Content {justifyContent}

- - {Array.from({ length: 5 }).map((_, i) => ( - - ))} - - - ))} -
- ); -}; - -export const GapExamples: StoryFn = () => { - const theme = useTheme2(); - const gapOptions: ThemeSpacingTokens[] = [2, 8, 10]; - return ( -
- {gapOptions.map((gap) => ( - <> -

Gap with spacingToken set to {gap}

- - {Array.from({ length: 5 }).map((_, i) => ( - - ))} - - - ))} -
- ); -}; - -export const WrapExamples: StoryFn = () => { - const theme = useTheme2(); - const wrapOptions: Wrap[] = ['nowrap', 'wrap', 'wrap-reverse']; - return ( -
- {wrapOptions.map((wrap) => ( - <> -

Wrap examples with {wrap} and gap set to spacingToken 2 (16px)

- - {Array.from({ length: 10 }).map((_, i) => ( - - ))} - - - ))} -
- ); -}; - -export const DirectionExamples: StoryFn = () => { - const theme = useTheme2(); - const directionOptions: Direction[] = ['row', 'row-reverse', 'column', 'column-reverse']; - return ( -
- {directionOptions.map((direction) => ( - <> -

Direction {direction}

- - {Array.from({ length: 5 }).map((_, i) => ( - - ))} - - - ))} -
- ); -}; - -export default meta; diff --git a/packages/grafana-ui/src/components/Layout/Flex/Flex.mdx b/packages/grafana-ui/src/components/Layout/Flex/Flex.mdx deleted file mode 100644 index a8dd4a58777..00000000000 --- a/packages/grafana-ui/src/components/Layout/Flex/Flex.mdx +++ /dev/null @@ -1,138 +0,0 @@ -import { Meta, ArgTypes } from '@storybook/blocks'; -import { Flex } from './Flex'; - - - -# Flex - -The Flex Component aims at providing a more efficient way to lay out, align and distribute space among items in a container and -the decision to create it is to ensure consistency in design across Grafana. - -### Usage - -#### When to use - -Use when in need to align components and small parts of the application. Use as parent container to wrap elements that you wish to align in a certain way. - -Also: - - * when working with one dimension layout - * to display the direction of the elements - * to set the elements to wrap - * to align items (vertically or horizontally) - -#### When not to use - -When you need to lay out bigger parts of the application or when you want to create page lay out. - -Also: - - * for complex grid layouts with various rows and columns - * bidirectional layouts - * complex nesting - * equal height columns - -### Variants - -Flex component has few variants that can be used based on the desired alignment you need for your case. - -Some examples of how to use the Flex component can be seen below: - -- AlignItems stretch - -```ts -import { Flex } from '@grafana/ui' -import { useTheme2 } from '../../themes'; - -const theme = useTheme2(); - -
-

Using Flex component to align-items stretch and justify-content to be center

-
- - - - - - -``` - -- Wrap items wrap-reverse - -```ts -import { Flex } from '@grafana/ui' -import { useTheme2 } from '../../themes'; - -const theme = useTheme2(); - -
-

Using Flex component to align-items with wrap-reverse property

-
- - - - - - -``` - -- JustifyContent flex-start - -```ts -import { Flex } from '@grafana/ui' -import { useTheme2 } from '../../themes'; - -const theme = useTheme2(); - -
-

Using Flex component to align-items with justify-content property

-
- - - - - - -``` - -- Gap of 16px using the ThemeSpacingTokens - -```ts -import { Flex } from '@grafana/ui' -import { useTheme2 } from '../../themes'; - -const theme = useTheme2(); - -
-

Using Flex component to align-items with gap of 16px

-
- - - - - - -``` - -- Direction column - -```ts -import { Flex } from '@grafana/ui' -import { useTheme2 } from '../../themes'; - -const theme = useTheme2(); - -
-

Using Flex component to align-items with direction column

-
- - - - - - -``` - -### Props - - diff --git a/packages/grafana-ui/src/components/Layout/Flex/Flex.tsx b/packages/grafana-ui/src/components/Layout/Flex/Flex.tsx deleted file mode 100644 index b54bce575b4..00000000000 --- a/packages/grafana-ui/src/components/Layout/Flex/Flex.tsx +++ /dev/null @@ -1,89 +0,0 @@ -import { css } from '@emotion/css'; -import React from 'react'; - -import { GrafanaTheme2, ThemeSpacingTokens } from '@grafana/data'; - -import { useStyles2 } from '../../../themes'; -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 FlexProps extends Omit, 'className' | 'style'> { - gap?: ResponsiveProp; - alignItems?: ResponsiveProp; - justifyContent?: ResponsiveProp; - direction?: ResponsiveProp; - wrap?: ResponsiveProp; - children?: React.ReactNode; -} - -export const Flex = React.forwardRef( - ({ gap = 1, alignItems, justifyContent, direction, wrap, children, ...rest }, ref) => { - const styles = useStyles2(getStyles, gap, alignItems, justifyContent, direction, wrap); - - return ( -
- {children} -
- ); - } -); - -Flex.displayName = 'Flex'; - -const getStyles = ( - theme: GrafanaTheme2, - gap: FlexProps['gap'], - alignItems: FlexProps['alignItems'], - justifyContent: FlexProps['justifyContent'], - direction: FlexProps['direction'], - wrap: FlexProps['wrap'] -) => { - return { - flex: css([ - { - display: 'flex', - }, - getResponsiveStyle(theme, direction, (val) => ({ - flexDirection: val, - })), - getResponsiveStyle(theme, wrap, (val) => ({ - flexWrap: val, - })), - getResponsiveStyle(theme, alignItems, (val) => ({ - alignItems: val, - })), - getResponsiveStyle(theme, justifyContent, (val) => ({ - justifyContent: val, - })), - getResponsiveStyle(theme, gap, (val) => ({ - gap: theme.spacing(val), - })), - ]), - }; -}; diff --git a/packages/grafana-ui/src/components/Layout/Grid/Grid.mdx b/packages/grafana-ui/src/components/Layout/Grid/Grid.mdx index 34acd4b15f1..7dd7f95f630 100644 --- a/packages/grafana-ui/src/components/Layout/Grid/Grid.mdx +++ b/packages/grafana-ui/src/components/Layout/Grid/Grid.mdx @@ -17,11 +17,6 @@ Use the Grid component when you want to create structured and organized layouts 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. diff --git a/packages/grafana-ui/src/components/Layout/Stack/HorizontalStack.tsx b/packages/grafana-ui/src/components/Layout/Stack/HorizontalStack.tsx deleted file mode 100644 index 57944ad2946..00000000000 --- a/packages/grafana-ui/src/components/Layout/Stack/HorizontalStack.tsx +++ /dev/null @@ -1,20 +0,0 @@ -import React from 'react'; - -import { ThemeSpacingTokens } from '@grafana/data'; - -import { ResponsiveProp } from '../utils/responsiveness'; - -import { Stack } from './Stack'; - -interface HorizontalStackProps extends Omit, 'className' | 'style'> { - gap?: ResponsiveProp; -} - -export const HorizontalStack = React.forwardRef>( - ({ children, gap = 1, ...rest }, ref) => ( - - {children} - - ) -); -HorizontalStack.displayName = 'HorizontalStack'; diff --git a/packages/grafana-ui/src/components/Layout/Stack/Stack.internal.story.tsx b/packages/grafana-ui/src/components/Layout/Stack/Stack.internal.story.tsx index 53ab64778fd..eff686a4847 100644 --- a/packages/grafana-ui/src/components/Layout/Stack/Stack.internal.story.tsx +++ b/packages/grafana-ui/src/components/Layout/Stack/Stack.internal.story.tsx @@ -1,16 +1,31 @@ import { Meta, StoryFn } from '@storybook/react'; -import React, { ReactNode } from 'react'; +import React from 'react'; +import { ThemeSpacingTokens } from '@grafana/data'; + +import { useTheme2 } from '../../../themes'; import { SpacingTokenControl } from '../../../utils/storybook/themeStorybookControls'; -import { Alert } from '../../Alert/Alert'; -import { Button } from '../../Button'; -import { Card } from '../../Card/Card'; -import { Text } from '../../Text/Text'; -import { HorizontalStack } from './HorizontalStack'; -import { Stack } from './Stack'; +import { Stack, JustifyContent, Wrap, Direction } from './Stack'; import mdx from './Stack.mdx'; +const Item = ({ color, text, height }: { color: string; text?: string | number; height?: string }) => { + return ( +
+ {text &&

{text}

} +
+ ); +}; + const meta: Meta = { title: 'General/Layout/Stack', component: Stack, @@ -19,204 +34,169 @@ const meta: Meta = { page: mdx, }, }, - argTypes: { - gap: SpacingTokenControl, - direction: { control: 'select', options: ['row', 'column'] }, - }, }; -const Item = ({ children }: { children: ReactNode }) => ( -
{children}
-); - -export const Basic: StoryFn = ({ direction = 'column', gap = 2 }) => { +export const Basic: StoryFn = ({ direction, wrap, alignItems, justifyContent, gap }) => { + const theme = useTheme2(); return ( - - Item 1 - Item 2 - Item 3 - +
+ + {Array.from({ length: 5 }).map((_, i) => ( + + ))} + +
); }; -export const TestCases: StoryFn = () => { - return ( -
- -

Comparisons Stack vs No stack

- - - - - - - - - - - - - - - - - - - - - - - - - I am a card heading - - - - I am a card heading - Ohhhhh - and now a description and some actions - - - - - - - - I am a card heading - Ohhhhh - and now a description! - - - - - - - I am a card heading - - - - I am a card heading - Ohhhhh - and now a description and some actions - - - - - - - - I am a card heading - Ohhhhh - and now a description! - - - - - - -
- - - - - - - - - - - - - - - - - -
- -

Child alignment

- -
- - - -
- - -
- - - -
- - - - - I am a card heading - - - - I am a card heading - Ohhhhh - and now a description and some actions - - - - - - - - I am a card heading - Ohhhhh - and now a description! - - - +Basic.argTypes = { + gap: SpacingTokenControl, + direction: { control: 'select', options: ['row', 'row-reverse', 'column', 'column-reverse'] }, + wrap: { control: 'select', options: ['nowrap', 'wrap', 'wrap-reverse'] }, + alignItems: { + control: 'select', + options: ['stretch', 'flex-start', 'flex-end', 'center', 'baseline', 'start', 'end', 'self-start', 'self-end'], + }, + justifyContent: { + control: 'select', + options: [ + 'flex-start', + 'flex-end', + 'center', + 'space-between', + 'space-around', + 'space-evenly', + 'start', + 'end', + 'left', + 'right', + ], + }, +}; - - - - I am a card heading - +export const AlignItemsExamples: StoryFn = () => { + const theme = useTheme2(); - - I am a card heading - Ohhhhh - and now a description! - + return ( +
+

Align items flex-start

+ + {Array.from({ length: 5 }).map((_, i) => ( + + ))} + +

Align items flex-end

+ + {Array.from({ length: 5 }).map((_, i) => ( + + ))} + +

Align items baseline

+ + {Array.from({ length: 5 }).map((_, i) => ( + + ))} + +

Align items center

+ + {Array.from({ length: 5 }).map((_, i) => ( + + ))} + +

Align items stretch

+ + + + + + + +
+ ); +}; - -
-
+export const JustifyContentExamples: StoryFn = () => { + const theme = useTheme2(); + const justifyContentOptions: JustifyContent[] = [ + 'space-between', + 'space-around', + 'space-evenly', + 'flex-start', + 'flex-end', + 'center', + ]; - - - - - - - - + return ( +
+ {justifyContentOptions.map((justifyContent) => ( + <> +

Justify Content {justifyContent}

+ + {Array.from({ length: 5 }).map((_, i) => ( + + ))} + + + ))} +
+ ); +}; - - - - - - Surprise - a description! What will happen to the height of all the other alerts? - - - - - +export const GapExamples: StoryFn = () => { + const theme = useTheme2(); + const gapOptions: ThemeSpacingTokens[] = [2, 8, 10]; + return ( +
+ {gapOptions.map((gap) => ( + <> +

Gap with spacingToken set to {gap}

+ + {Array.from({ length: 5 }).map((_, i) => ( + + ))} + + + ))}
); }; -function Example({ title, children }: { title: string; children: React.ReactNode }) { +export const WrapExamples: StoryFn = () => { + const theme = useTheme2(); + const wrapOptions: Wrap[] = ['nowrap', 'wrap', 'wrap-reverse']; return ( -
- {title} -
{children}
+
+ {wrapOptions.map((wrap) => ( + <> +

Wrap examples with {wrap} and gap set to spacingToken 2 (16px)

+ + {Array.from({ length: 10 }).map((_, i) => ( + + ))} + + + ))}
); -} +}; -function MyComponent({ children }: { children: React.ReactNode }) { - return
{children}
; -} +export const DirectionExamples: StoryFn = () => { + const theme = useTheme2(); + const directionOptions: Direction[] = ['row', 'row-reverse', 'column', 'column-reverse']; + return ( +
+ {directionOptions.map((direction) => ( + <> +

Direction {direction}

+ + {Array.from({ length: 5 }).map((_, i) => ( + + ))} + + + ))} +
+ ); +}; export default meta; diff --git a/packages/grafana-ui/src/components/Layout/Stack/Stack.mdx b/packages/grafana-ui/src/components/Layout/Stack/Stack.mdx index b21e7652f8f..046f414b697 100644 --- a/packages/grafana-ui/src/components/Layout/Stack/Stack.mdx +++ b/packages/grafana-ui/src/components/Layout/Stack/Stack.mdx @@ -1,44 +1,27 @@ -import { Meta, ArgTypes, Canvas } from '@storybook/blocks'; -import { Stack, HorizontalStack } from './index'; -import * as Stories from './Stack.internal.story'; +import { Meta, ArgTypes } from '@storybook/blocks'; +import { Stack } from './Stack'; # Stack -The `Stack` component is designed to assist with layout and positioning of elements within a container, offering a simple and flexible way to stack elements vertically or horizontally. This documentation outlines the proper usage of the Stack component and provides guidance on when to use it over the Grid or Flex components. - -There is also a `HorizontalStack` component, which is a thin wrapper around Stack, equivalent to ``. +The Stack component is a simple wrapper around the flexbox layout model that allows to easily create responsive and flexible layouts. It provides a simple and intuitive way to align and distribute items within a container either horizontally or vertically. ### Usage #### When to use -Use the Stack component when you need to arrange elements in a linear format, either vertically or horizontally. It's particularly useful when you want to maintain consistent spacing between items. - -Use the Stack component when: - -- You need a simple way to stack elements with predictable spacing. -- You want to ensure consistent alignment. +- For creating responsive and flexible layouts that can adapt to different screen sizes and orientations. +- When needing a simple and intuitive way to align and distribute items within a container either horizontally or vertically. +- To easily reorder and rearrange elements without changing the HTML structure. +- When aiming to create equal height columns. +- To create a grid-like structure with automatic wrapping and sizing of items based on the available space. #### When not to use -Use the `Grid` component instead for these use cases: - -- **Intricate Layouts:** Grids are ideal for complex dashboard and magazine-style designs with rows and columns. -- **Structured Grid:** Use Grids when items need to span multiple rows/columns, creating structured layouts. - -Use the `Flex` component instead for these use cases: +- For complex multi-dimensional layouts with intricate requirements that are better suited for CSS frameworks or grid systems. +- When precise control over spacing and positioning of elements is necessary. -- **Alignment:** More options for item alignment. -- **Flex items:** Custom flex basis or configure how items stretch and wrap. - -## Props - -### Stack +### Props - -### HorizontalStack - - diff --git a/packages/grafana-ui/src/components/Layout/Stack/Stack.tsx b/packages/grafana-ui/src/components/Layout/Stack/Stack.tsx index 2e24f2332f9..27baa49dfc5 100644 --- a/packages/grafana-ui/src/components/Layout/Stack/Stack.tsx +++ b/packages/grafana-ui/src/components/Layout/Stack/Stack.tsx @@ -1,26 +1,89 @@ +import { css } from '@emotion/css'; import React from 'react'; -import { ThemeSpacingTokens } from '@grafana/data'; +import { GrafanaTheme2, ThemeSpacingTokens } from '@grafana/data'; + +import { useStyles2 } from '../../../themes'; +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'; -import { Flex } from '../Flex/Flex'; -import { ResponsiveProp } from '../utils/responsiveness'; interface StackProps extends Omit, 'className' | 'style'> { - direction?: ResponsiveProp<'column' | 'row'>; gap?: ResponsiveProp; + alignItems?: ResponsiveProp; + justifyContent?: ResponsiveProp; + direction?: ResponsiveProp; + wrap?: ResponsiveProp; + children?: React.ReactNode; } -export const Stack = React.forwardRef>( - ({ gap = 1, direction = 'column', children, ...rest }, ref) => { +export const Stack = React.forwardRef( + ({ gap = 1, alignItems, justifyContent, direction, wrap, children, ...rest }, ref) => { + const styles = useStyles2(getStyles, gap, alignItems, justifyContent, direction, wrap); + return ( - - {React.Children.toArray(children) - .filter(Boolean) - .map((child, index) => ( -
{child}
- ))} -
+
+ {children} +
); } ); Stack.displayName = 'Stack'; + +const getStyles = ( + theme: GrafanaTheme2, + gap: StackProps['gap'], + alignItems: StackProps['alignItems'], + justifyContent: StackProps['justifyContent'], + direction: StackProps['direction'], + wrap: StackProps['wrap'] +) => { + return { + flex: css([ + { + display: 'flex', + }, + getResponsiveStyle(theme, direction, (val) => ({ + flexDirection: val, + })), + getResponsiveStyle(theme, wrap, (val) => ({ + flexWrap: val, + })), + getResponsiveStyle(theme, alignItems, (val) => ({ + alignItems: val, + })), + getResponsiveStyle(theme, justifyContent, (val) => ({ + justifyContent: val, + })), + getResponsiveStyle(theme, gap, (val) => ({ + gap: theme.spacing(val), + })), + ]), + }; +}; diff --git a/packages/grafana-ui/src/components/Layout/Stack/index.ts b/packages/grafana-ui/src/components/Layout/Stack/index.ts deleted file mode 100644 index 89768e71dc0..00000000000 --- a/packages/grafana-ui/src/components/Layout/Stack/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export { Stack } from './Stack'; -export { HorizontalStack } from './HorizontalStack'; diff --git a/packages/grafana-ui/src/unstable.ts b/packages/grafana-ui/src/unstable.ts index dedc5841a5b..f90909a1517 100644 --- a/packages/grafana-ui/src/unstable.ts +++ b/packages/grafana-ui/src/unstable.ts @@ -9,7 +9,5 @@ * be subject to the standard policies */ -export * from './components/Layout/Flex/Flex'; - export { Grid } from './components/Layout/Grid/Grid'; -export { Stack, HorizontalStack } from './components/Layout/Stack'; +export { Stack } from './components/Layout/Stack/Stack'; diff --git a/public/app/core/components/AppChrome/DockedMegaMenu/MegaMenu.tsx b/public/app/core/components/AppChrome/DockedMegaMenu/MegaMenu.tsx index 3f615d45a8b..dff065c4242 100644 --- a/public/app/core/components/AppChrome/DockedMegaMenu/MegaMenu.tsx +++ b/public/app/core/components/AppChrome/DockedMegaMenu/MegaMenu.tsx @@ -6,7 +6,7 @@ import { useLocation } from 'react-router-dom'; import { GrafanaTheme2 } from '@grafana/data'; import { selectors } from '@grafana/e2e-selectors'; import { CustomScrollbar, Icon, IconButton, useStyles2 } from '@grafana/ui'; -import { Flex } from '@grafana/ui/src/unstable'; +import { Stack } from '@grafana/ui/src/unstable'; import { useGrafana } from 'app/core/context/GrafanaContext'; import { t } from 'app/core/internationalization'; import { useSelector } from 'app/types'; @@ -55,7 +55,7 @@ export const MegaMenu = React.memo(
    {navItems.map((link, index) => ( - + )} - + ))}
diff --git a/public/app/features/admin/Users/OrgUnits.tsx b/public/app/features/admin/Users/OrgUnits.tsx index 846abb95f70..08a58be8854 100644 --- a/public/app/features/admin/Users/OrgUnits.tsx +++ b/public/app/features/admin/Users/OrgUnits.tsx @@ -2,7 +2,7 @@ import React, { forwardRef, PropsWithChildren } from 'react'; import { IconName } from '@grafana/data'; import { Icon, Tooltip, Box } from '@grafana/ui'; -import { Flex } from '@grafana/ui/src/unstable'; +import { Stack } from '@grafana/ui/src/unstable'; import { Unit } from 'app/types'; type OrgUnitProps = { units?: Unit[]; icon: IconName }; @@ -15,7 +15,7 @@ export const OrgUnits = ({ units, icon }: OrgUnitProps) => { return units.length > 1 ? ( {units?.map((unit) => {unit.name})}} + content={{units?.map((unit) => {unit.name})}} > {units.length} diff --git a/public/app/features/admin/Users/OrgUsersTable.tsx b/public/app/features/admin/Users/OrgUsersTable.tsx index be169eab5f2..7fec328d127 100644 --- a/public/app/features/admin/Users/OrgUsersTable.tsx +++ b/public/app/features/admin/Users/OrgUsersTable.tsx @@ -16,7 +16,7 @@ import { Avatar, Box, } from '@grafana/ui'; -import { Flex, Stack } from '@grafana/ui/src/unstable'; +import { Stack } from '@grafana/ui/src/unstable'; import { UserRolePicker } from 'app/core/components/RolePicker/UserRolePicker'; import { fetchRoleOptions } from 'app/core/components/RolePicker/api'; import { TagBadge } from 'app/core/components/TagFilter/TagBadge'; @@ -223,9 +223,9 @@ export const OrgUsersTable = ({ getRowId={(user) => String(user.userId)} fetchData={fetchData} /> - + - +
{Boolean(userToRemove) && ( ) => { return ( - + {row.original.isAdmin && ( )} - + ); }, sortType: (a, b) => (a.original.orgs?.length || 0) - (b.original.orgs?.length || 0), @@ -146,9 +146,9 @@ export const UsersTable = ({ String(user.id)} fetchData={fetchData} /> {showPaging && ( - + - + )} ); diff --git a/public/app/features/dashboard/dashgrid/DashboardEmpty.tsx b/public/app/features/dashboard/dashgrid/DashboardEmpty.tsx index 2e9e7c0eef6..0a521767cc6 100644 --- a/public/app/features/dashboard/dashgrid/DashboardEmpty.tsx +++ b/public/app/features/dashboard/dashgrid/DashboardEmpty.tsx @@ -5,7 +5,7 @@ import { GrafanaTheme2 } from '@grafana/data'; import { selectors } from '@grafana/e2e-selectors'; import { config, locationService, reportInteraction } from '@grafana/runtime'; import { Button, useStyles2, Text, Box } from '@grafana/ui'; -import { Flex } from '@grafana/ui/src/unstable'; +import { Stack } from '@grafana/ui/src/unstable'; import { Trans } from 'app/core/internationalization'; import { DashboardModel } from 'app/features/dashboard/state'; import { onAddLibraryPanel, onCreateNewPanel, onImportDashboard } from 'app/features/dashboard/utils/dashboard'; @@ -24,11 +24,11 @@ const DashboardEmpty = ({ dashboard, canCreate }: Props) => { const initialDatasource = useSelector((state) => state.dashboard.initialDatasource); return ( - +
- + - + Start your new dashboard by adding a visualization @@ -56,12 +56,12 @@ const DashboardEmpty = ({ dashboard, canCreate }: Props) => { > Add visualization - + - + {config.featureToggles.vizAndWidgetSplit && ( - + Add a widget @@ -82,11 +82,11 @@ const DashboardEmpty = ({ dashboard, canCreate }: Props) => { > Add widget - + )} - + Import panel @@ -109,10 +109,10 @@ const DashboardEmpty = ({ dashboard, canCreate }: Props) => { > Add library panel - + - + Import a dashboard @@ -136,12 +136,12 @@ const DashboardEmpty = ({ dashboard, canCreate }: Props) => { > Import dashboard - + - - + +
-
+ ); }; diff --git a/public/app/features/serviceaccounts/ServiceAccountsListPage.tsx b/public/app/features/serviceaccounts/ServiceAccountsListPage.tsx index 39241d9fb30..b943e841cb1 100644 --- a/public/app/features/serviceaccounts/ServiceAccountsListPage.tsx +++ b/public/app/features/serviceaccounts/ServiceAccountsListPage.tsx @@ -13,7 +13,7 @@ import { InlineField, Pagination, } from '@grafana/ui'; -import { Flex } from '@grafana/ui/src/unstable'; +import { Stack } from '@grafana/ui/src/unstable'; import EmptyListCTA from 'app/core/components/EmptyListCTA/EmptyListCTA'; import { Page } from 'app/core/components/Page/Page'; import PageLoader from 'app/core/components/PageLoader/PageLoader'; @@ -253,9 +253,9 @@ export const ServiceAccountsListPageUnconnected = ({ - + - +
)} diff --git a/public/app/features/teams/TeamList.tsx b/public/app/features/teams/TeamList.tsx index fca388998f8..10be5c44637 100644 --- a/public/app/features/teams/TeamList.tsx +++ b/public/app/features/teams/TeamList.tsx @@ -14,7 +14,7 @@ import { Pagination, Avatar, } from '@grafana/ui'; -import { Stack, Flex } from '@grafana/ui/src/unstable'; +import { Stack } from '@grafana/ui/src/unstable'; import EmptyListCTA from 'app/core/components/EmptyListCTA/EmptyListCTA'; import { Page } from 'app/core/components/Page/Page'; import { fetchRoleOptions } from 'app/core/components/RolePicker/api'; @@ -169,14 +169,14 @@ export const TeamList = ({ getRowId={(team) => String(team.id)} fetchData={changeSort} /> - + - +