mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Stack: Add size props (#86900)
* Abstract sizing styles from Box * Upd name * Stack: Add sizing props * Revert * Update LoginServiceButtons
This commit is contained in:
@@ -1,5 +1,4 @@
|
||||
import { css } from '@emotion/css';
|
||||
import { Property } from 'csstype';
|
||||
import { css, cx } from '@emotion/css';
|
||||
import React, { ElementType, forwardRef, PropsWithChildren } from 'react';
|
||||
|
||||
import { GrafanaTheme2, ThemeSpacingTokens, ThemeShape, ThemeShadows } from '@grafana/data';
|
||||
@@ -7,6 +6,7 @@ import { GrafanaTheme2, ThemeSpacingTokens, ThemeShape, ThemeShadows } from '@gr
|
||||
import { useStyles2 } from '../../../themes';
|
||||
import { AlignItems, Direction, FlexProps, JustifyContent } from '../types';
|
||||
import { ResponsiveProp, getResponsiveStyle } from '../utils/responsiveness';
|
||||
import { getSizeStyles, SizeProps } from '../utils/styles';
|
||||
|
||||
type Display = 'flex' | 'block' | 'inline' | 'inline-block' | 'none';
|
||||
export type BackgroundColor = keyof GrafanaTheme2['colors']['background'] | 'error' | 'success' | 'warning' | 'info';
|
||||
@@ -15,7 +15,7 @@ export type BorderColor = keyof GrafanaTheme2['colors']['border'] | 'error' | 's
|
||||
export type BorderRadius = keyof ThemeShape['radius'];
|
||||
export type BoxShadow = keyof ThemeShadows;
|
||||
|
||||
interface BoxProps extends FlexProps, Omit<React.HTMLAttributes<HTMLElement>, 'className' | 'style'> {
|
||||
interface BoxProps extends FlexProps, SizeProps, Omit<React.HTMLAttributes<HTMLElement>, 'className' | 'style'> {
|
||||
// Margin props
|
||||
/** Sets the property `margin` */
|
||||
margin?: ResponsiveProp<ThemeSpacingTokens>;
|
||||
@@ -59,15 +59,6 @@ interface BoxProps extends FlexProps, Omit<React.HTMLAttributes<HTMLElement>, 'c
|
||||
justifyContent?: ResponsiveProp<JustifyContent>;
|
||||
gap?: ResponsiveProp<ThemeSpacingTokens>;
|
||||
|
||||
// Size props
|
||||
minWidth?: ResponsiveProp<Property.MinWidth<number>>;
|
||||
maxWidth?: ResponsiveProp<Property.MaxWidth<number>>;
|
||||
width?: ResponsiveProp<Property.Width<number>>;
|
||||
|
||||
minHeight?: ResponsiveProp<Property.MinHeight<number>>;
|
||||
maxHeight?: ResponsiveProp<Property.MaxHeight<number>>;
|
||||
height?: ResponsiveProp<Property.Height<number>>;
|
||||
|
||||
// Other props
|
||||
backgroundColor?: ResponsiveProp<BackgroundColor>;
|
||||
display?: ResponsiveProp<Display>;
|
||||
@@ -145,18 +136,13 @@ export const Box = forwardRef<HTMLElement, PropsWithChildren<BoxProps>>((props,
|
||||
justifyContent,
|
||||
alignItems,
|
||||
boxShadow,
|
||||
gap,
|
||||
width,
|
||||
minWidth,
|
||||
maxWidth,
|
||||
height,
|
||||
minHeight,
|
||||
maxHeight
|
||||
gap
|
||||
);
|
||||
const sizeStyles = useStyles2(getSizeStyles, width, minWidth, maxWidth, height, minHeight, maxHeight);
|
||||
const Element = element ?? 'div';
|
||||
|
||||
return (
|
||||
<Element ref={ref} className={styles.root} {...rest}>
|
||||
<Element ref={ref} className={cx(styles.root, sizeStyles)} {...rest}>
|
||||
{children}
|
||||
</Element>
|
||||
);
|
||||
@@ -217,13 +203,7 @@ const getStyles = (
|
||||
justifyContent: BoxProps['justifyContent'],
|
||||
alignItems: BoxProps['alignItems'],
|
||||
boxShadow: BoxProps['boxShadow'],
|
||||
gap: BoxProps['gap'],
|
||||
width: BoxProps['width'],
|
||||
minWidth: BoxProps['minWidth'],
|
||||
maxWidth: BoxProps['maxWidth'],
|
||||
height: BoxProps['height'],
|
||||
minHeight: BoxProps['minHeight'],
|
||||
maxHeight: BoxProps['maxHeight']
|
||||
gap: BoxProps['gap']
|
||||
) => {
|
||||
return {
|
||||
root: css([
|
||||
@@ -318,24 +298,6 @@ const getStyles = (
|
||||
getResponsiveStyle(theme, gap, (val) => ({
|
||||
gap: theme.spacing(val),
|
||||
})),
|
||||
getResponsiveStyle(theme, width, (val) => ({
|
||||
width: theme.spacing(val),
|
||||
})),
|
||||
getResponsiveStyle(theme, minWidth, (val) => ({
|
||||
minWidth: theme.spacing(val),
|
||||
})),
|
||||
getResponsiveStyle(theme, maxWidth, (val) => ({
|
||||
maxWidth: theme.spacing(val),
|
||||
})),
|
||||
getResponsiveStyle(theme, height, (val) => ({
|
||||
height: theme.spacing(val),
|
||||
})),
|
||||
getResponsiveStyle(theme, minHeight, (val) => ({
|
||||
minHeight: theme.spacing(val),
|
||||
})),
|
||||
getResponsiveStyle(theme, maxHeight, (val) => ({
|
||||
maxHeight: theme.spacing(val),
|
||||
})),
|
||||
]),
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { css } from '@emotion/css';
|
||||
import { css, cx } from '@emotion/css';
|
||||
import React from 'react';
|
||||
|
||||
import { GrafanaTheme2, ThemeSpacingTokens } from '@grafana/data';
|
||||
@@ -6,8 +6,9 @@ import { GrafanaTheme2, ThemeSpacingTokens } from '@grafana/data';
|
||||
import { useStyles2 } from '../../../themes';
|
||||
import { AlignItems, Direction, FlexProps, JustifyContent, Wrap } from '../types';
|
||||
import { ResponsiveProp, getResponsiveStyle } from '../utils/responsiveness';
|
||||
import { getSizeStyles, SizeProps } from '../utils/styles';
|
||||
|
||||
interface StackProps extends FlexProps, Omit<React.HTMLAttributes<HTMLElement>, 'className' | 'style'> {
|
||||
interface StackProps extends FlexProps, SizeProps, Omit<React.HTMLAttributes<HTMLElement>, 'className' | 'style'> {
|
||||
gap?: ResponsiveProp<ThemeSpacingTokens>;
|
||||
alignItems?: ResponsiveProp<AlignItems>;
|
||||
justifyContent?: ResponsiveProp<JustifyContent>;
|
||||
@@ -17,11 +18,29 @@ interface StackProps extends FlexProps, Omit<React.HTMLAttributes<HTMLElement>,
|
||||
}
|
||||
|
||||
export const Stack = React.forwardRef<HTMLDivElement, StackProps>((props, ref) => {
|
||||
const { gap = 1, alignItems, justifyContent, direction, wrap, children, grow, shrink, basis, flex, ...rest } = props;
|
||||
const {
|
||||
gap = 1,
|
||||
alignItems,
|
||||
justifyContent,
|
||||
direction,
|
||||
wrap,
|
||||
children,
|
||||
grow,
|
||||
shrink,
|
||||
basis,
|
||||
flex,
|
||||
width,
|
||||
minWidth,
|
||||
maxWidth,
|
||||
height,
|
||||
minHeight,
|
||||
maxHeight,
|
||||
...rest
|
||||
} = props;
|
||||
const styles = useStyles2(getStyles, gap, alignItems, justifyContent, direction, wrap, grow, shrink, basis, flex);
|
||||
|
||||
const sizeStyles = useStyles2(getSizeStyles, width, minWidth, maxWidth, height, minHeight, maxHeight);
|
||||
return (
|
||||
<div ref={ref} className={styles.flex} {...rest}>
|
||||
<div ref={ref} className={cx(styles.flex, sizeStyles)} {...rest}>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
|
||||
46
packages/grafana-ui/src/components/Layout/utils/styles.ts
Normal file
46
packages/grafana-ui/src/components/Layout/utils/styles.ts
Normal file
@@ -0,0 +1,46 @@
|
||||
import { css } from '@emotion/css';
|
||||
import { Property } from 'csstype';
|
||||
|
||||
import { GrafanaTheme2 } from '@grafana/data';
|
||||
|
||||
import { getResponsiveStyle, ResponsiveProp } from './responsiveness';
|
||||
|
||||
export interface SizeProps {
|
||||
minWidth?: ResponsiveProp<Property.MinWidth<number>>;
|
||||
maxWidth?: ResponsiveProp<Property.MaxWidth<number>>;
|
||||
width?: ResponsiveProp<Property.Width<number>>;
|
||||
|
||||
minHeight?: ResponsiveProp<Property.MinHeight<number>>;
|
||||
maxHeight?: ResponsiveProp<Property.MaxHeight<number>>;
|
||||
height?: ResponsiveProp<Property.Height<number>>;
|
||||
}
|
||||
export const getSizeStyles = (
|
||||
theme: GrafanaTheme2,
|
||||
width: SizeProps['width'],
|
||||
minWidth: SizeProps['minWidth'],
|
||||
maxWidth: SizeProps['maxWidth'],
|
||||
height: SizeProps['height'],
|
||||
minHeight: SizeProps['minHeight'],
|
||||
maxHeight: SizeProps['maxHeight']
|
||||
) => {
|
||||
return css([
|
||||
getResponsiveStyle(theme, width, (val) => ({
|
||||
width: theme.spacing(val),
|
||||
})),
|
||||
getResponsiveStyle(theme, minWidth, (val) => ({
|
||||
minWidth: theme.spacing(val),
|
||||
})),
|
||||
getResponsiveStyle(theme, maxWidth, (val) => ({
|
||||
maxWidth: theme.spacing(val),
|
||||
})),
|
||||
getResponsiveStyle(theme, height, (val) => ({
|
||||
height: theme.spacing(val),
|
||||
})),
|
||||
getResponsiveStyle(theme, minHeight, (val) => ({
|
||||
minHeight: theme.spacing(val),
|
||||
})),
|
||||
getResponsiveStyle(theme, maxHeight, (val) => ({
|
||||
maxHeight: theme.spacing(val),
|
||||
})),
|
||||
]);
|
||||
};
|
||||
@@ -149,27 +149,24 @@ export const LoginServiceButtons = () => {
|
||||
|
||||
if (hasServices) {
|
||||
return (
|
||||
// TODO: Remove extra div when Stack supports width
|
||||
<div style={{ width: '100%' }}>
|
||||
<Stack direction={'column'}>
|
||||
<LoginDivider />
|
||||
{Object.entries(enabledServices).map(([key, service]) => {
|
||||
const serviceName = service.name;
|
||||
return (
|
||||
<LinkButton
|
||||
key={key}
|
||||
className={getButtonStyleFor(service, styles, theme)}
|
||||
href={`login/${service.hrefName ? service.hrefName : key}`}
|
||||
target="_self"
|
||||
fullWidth
|
||||
>
|
||||
<Icon className={styles.buttonIcon} name={service.icon} />
|
||||
<Trans i18nKey="login.services.sing-in-with-prefix">Sign in with {{ serviceName }}</Trans>
|
||||
</LinkButton>
|
||||
);
|
||||
})}
|
||||
</Stack>
|
||||
</div>
|
||||
<Stack direction={'column'} width={'100%'}>
|
||||
<LoginDivider />
|
||||
{Object.entries(enabledServices).map(([key, service]) => {
|
||||
const serviceName = service.name;
|
||||
return (
|
||||
<LinkButton
|
||||
key={key}
|
||||
className={getButtonStyleFor(service, styles, theme)}
|
||||
href={`login/${service.hrefName ? service.hrefName : key}`}
|
||||
target="_self"
|
||||
fullWidth
|
||||
>
|
||||
<Icon className={styles.buttonIcon} name={service.icon} />
|
||||
<Trans i18nKey="login.services.sing-in-with-prefix">Sign in with {{ serviceName }}</Trans>
|
||||
</LinkButton>
|
||||
);
|
||||
})}
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user