mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
DeleteButton: Button with icon only was not centered correctly. (#21432)
* Refactoring to get the correct spacing between the first icon and button border. * Should not be smaller then 8px to the left. * Removed unused dependency. * Updated snapshot for LinkButton.
This commit is contained in:
parent
35679d4689
commit
b0515f46cc
@ -2,7 +2,6 @@ import React, { AnchorHTMLAttributes, ButtonHTMLAttributes, useContext } from 'r
|
|||||||
import { ThemeContext } from '../../themes';
|
import { ThemeContext } from '../../themes';
|
||||||
import { getButtonStyles } from './styles';
|
import { getButtonStyles } from './styles';
|
||||||
import { ButtonContent } from './ButtonContent';
|
import { ButtonContent } from './ButtonContent';
|
||||||
import cx from 'classnames';
|
|
||||||
import { ButtonSize, ButtonStyles, ButtonVariant } from './types';
|
import { ButtonSize, ButtonStyles, ButtonVariant } from './types';
|
||||||
|
|
||||||
type CommonProps = {
|
type CommonProps = {
|
||||||
@ -31,11 +30,11 @@ export const Button = React.forwardRef<HTMLButtonElement, ButtonProps>((props, r
|
|||||||
theme,
|
theme,
|
||||||
size: size || 'md',
|
size: size || 'md',
|
||||||
variant: variant || 'primary',
|
variant: variant || 'primary',
|
||||||
|
textAndIcon: !!(children && icon),
|
||||||
});
|
});
|
||||||
|
|
||||||
const buttonClassName = cx(styles.button, icon && styles.buttonWithIcon, icon && !children && styles.iconButton);
|
|
||||||
return (
|
return (
|
||||||
<button className={buttonClassName} {...buttonProps} ref={ref}>
|
<button className={styles.button} {...buttonProps} ref={ref}>
|
||||||
<ButtonContent icon={icon}>{children}</ButtonContent>
|
<ButtonContent icon={icon}>{children}</ButtonContent>
|
||||||
</button>
|
</button>
|
||||||
);
|
);
|
||||||
@ -59,11 +58,11 @@ export const LinkButton = React.forwardRef<HTMLAnchorElement, LinkButtonProps>((
|
|||||||
theme,
|
theme,
|
||||||
size: size || 'md',
|
size: size || 'md',
|
||||||
variant: variant || 'primary',
|
variant: variant || 'primary',
|
||||||
|
textAndIcon: !!(children && icon),
|
||||||
});
|
});
|
||||||
|
|
||||||
const buttonClassName = cx(styles.button, icon && styles.buttonWithIcon, icon && !children && styles.iconButton);
|
|
||||||
return (
|
return (
|
||||||
<a className={buttonClassName} {...anchorProps} ref={ref}>
|
<a className={styles.button} {...anchorProps} ref={ref}>
|
||||||
<ButtonContent icon={icon}>{children}</ButtonContent>
|
<ButtonContent icon={icon}>{children}</ButtonContent>
|
||||||
</a>
|
</a>
|
||||||
);
|
);
|
||||||
|
@ -2,6 +2,7 @@ import React from 'react';
|
|||||||
import { css } from 'emotion';
|
import { css } from 'emotion';
|
||||||
import { stylesFactory, useTheme } from '../../themes';
|
import { stylesFactory, useTheme } from '../../themes';
|
||||||
import { GrafanaTheme } from '@grafana/data';
|
import { GrafanaTheme } from '@grafana/data';
|
||||||
|
import { ButtonSize } from './types';
|
||||||
|
|
||||||
const getStyles = stylesFactory((theme: GrafanaTheme) => ({
|
const getStyles = stylesFactory((theme: GrafanaTheme) => ({
|
||||||
content: css`
|
content: css`
|
||||||
@ -23,12 +24,22 @@ type Props = {
|
|||||||
icon?: string;
|
icon?: string;
|
||||||
className?: string;
|
className?: string;
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
|
size?: ButtonSize;
|
||||||
};
|
};
|
||||||
|
|
||||||
export function ButtonContent(props: Props) {
|
export function ButtonContent(props: Props) {
|
||||||
const { icon, children } = props;
|
const { icon, children } = props;
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const styles = getStyles(theme);
|
const styles = getStyles(theme);
|
||||||
|
|
||||||
|
if (!children) {
|
||||||
|
return (
|
||||||
|
<span className={styles.content}>
|
||||||
|
<i className={icon} />
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
const iconElement = icon && (
|
const iconElement = icon && (
|
||||||
<span className={styles.icon}>
|
<span className={styles.icon}>
|
||||||
<i className={icon} />
|
<i className={icon} />
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
exports[`Button renders correct html 1`] = `"<button class=\\"css-1ffx2x7-button css-5383lb\\" type=\\"button\\"><span class=\\"css-1beih13\\"><span class=\\"css-xhe2zh\\"><i class=\\"fa fa-plus\\"></i></span><span>Click me</span></span></button>"`;
|
exports[`Button renders correct html 1`] = `"<button class=\\"css-uzitec-button\\" type=\\"button\\"><span class=\\"css-1beih13\\"><span class=\\"css-xhe2zh\\"><i class=\\"fa fa-plus\\"></i></span><span>Click me</span></span></button>"`;
|
||||||
|
|
||||||
exports[`LinkButton renders correct html 1`] = `"<a class=\\"css-1ffx2x7-button css-5383lb\\"><span class=\\"css-1beih13\\"><span class=\\"css-xhe2zh\\"><i class=\\"fa fa-plus\\"></i></span><span>Click me</span></span></a>"`;
|
exports[`LinkButton renders correct html 1`] = `"<a class=\\"css-uzitec-button\\"><span class=\\"css-1beih13\\"><span class=\\"css-xhe2zh\\"><i class=\\"fa fa-plus\\"></i></span><span>Click me</span></span></a>"`;
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
import tinycolor from 'tinycolor2';
|
import tinycolor from 'tinycolor2';
|
||||||
import { css } from 'emotion';
|
import { css } from 'emotion';
|
||||||
import { selectThemeVariant, stylesFactory } from '../../themes';
|
import { selectThemeVariant, stylesFactory } from '../../themes';
|
||||||
import { StyleDeps } from './types';
|
import { StyleDeps, ButtonSize } from './types';
|
||||||
|
import { GrafanaTheme } from '@grafana/data';
|
||||||
|
|
||||||
const buttonVariantStyles = (
|
const buttonVariantStyles = (
|
||||||
from: string,
|
from: string,
|
||||||
@ -24,39 +25,11 @@ const buttonVariantStyles = (
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const getButtonStyles = stylesFactory(({ theme, size, variant }: StyleDeps) => {
|
export const getButtonStyles = stylesFactory(({ theme, size, variant, textAndIcon }: StyleDeps) => {
|
||||||
const borderRadius = theme.border.radius.sm;
|
const borderRadius = theme.border.radius.sm;
|
||||||
let padding,
|
const { padding, fontSize, height, fontWeight } = calculateMeasures(theme, size, !!textAndIcon);
|
||||||
background,
|
|
||||||
fontSize,
|
|
||||||
height,
|
|
||||||
fontWeight = theme.typography.weight.semibold;
|
|
||||||
|
|
||||||
switch (size) {
|
let background;
|
||||||
case 'sm':
|
|
||||||
padding = `${theme.spacing.xs} ${theme.spacing.sm}`;
|
|
||||||
fontSize = theme.typography.size.sm;
|
|
||||||
height = theme.height.sm;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'md':
|
|
||||||
padding = `${theme.spacing.sm} ${theme.spacing.md}`;
|
|
||||||
fontSize = theme.typography.size.md;
|
|
||||||
height = theme.height.md;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'lg':
|
|
||||||
padding = `${theme.spacing.md} ${theme.spacing.lg}`;
|
|
||||||
fontSize = theme.typography.size.lg;
|
|
||||||
fontWeight = theme.typography.weight.regular;
|
|
||||||
height = theme.height.lg;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
padding = `${theme.spacing.sm} ${theme.spacing.md}`;
|
|
||||||
fontSize = theme.typography.size.base;
|
|
||||||
height = theme.height.md;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (variant) {
|
switch (variant) {
|
||||||
case 'primary':
|
case 'primary':
|
||||||
@ -120,13 +93,6 @@ export const getButtonStyles = stylesFactory(({ theme, size, variant }: StyleDep
|
|||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
buttonWithIcon: css`
|
|
||||||
padding-left: ${theme.spacing.sm};
|
|
||||||
`,
|
|
||||||
// used for buttons with icon onlys
|
|
||||||
iconButton: css`
|
|
||||||
padding-right: 0;
|
|
||||||
`,
|
|
||||||
iconWrap: css`
|
iconWrap: css`
|
||||||
label: button-icon-wrap;
|
label: button-icon-wrap;
|
||||||
& + * {
|
& + * {
|
||||||
@ -135,3 +101,56 @@ export const getButtonStyles = stylesFactory(({ theme, size, variant }: StyleDep
|
|||||||
`,
|
`,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
type ButtonMeasures = {
|
||||||
|
padding: string;
|
||||||
|
fontSize: string;
|
||||||
|
height: string;
|
||||||
|
fontWeight: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
const calculateMeasures = (theme: GrafanaTheme, size: ButtonSize, textAndIcon: boolean): ButtonMeasures => {
|
||||||
|
switch (size) {
|
||||||
|
case 'sm': {
|
||||||
|
return {
|
||||||
|
padding: `${theme.spacing.xs} ${theme.spacing.sm}`,
|
||||||
|
fontSize: theme.typography.size.sm,
|
||||||
|
height: theme.height.sm,
|
||||||
|
fontWeight: theme.typography.weight.semibold,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'md': {
|
||||||
|
const leftPadding = textAndIcon ? theme.spacing.sm : theme.spacing.md;
|
||||||
|
|
||||||
|
return {
|
||||||
|
padding: `${theme.spacing.sm} ${theme.spacing.md} ${theme.spacing.sm} ${leftPadding}`,
|
||||||
|
fontSize: theme.typography.size.md,
|
||||||
|
height: theme.height.md,
|
||||||
|
fontWeight: theme.typography.weight.semibold,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'lg': {
|
||||||
|
const leftPadding = textAndIcon ? theme.spacing.md : theme.spacing.lg;
|
||||||
|
|
||||||
|
return {
|
||||||
|
padding: `${theme.spacing.md} ${theme.spacing.lg} ${theme.spacing.md} ${leftPadding}`,
|
||||||
|
fontSize: theme.typography.size.lg,
|
||||||
|
height: theme.height.lg,
|
||||||
|
fontWeight: theme.typography.weight.regular,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
default: {
|
||||||
|
const leftPadding = textAndIcon ? theme.spacing.sm : theme.spacing.md;
|
||||||
|
|
||||||
|
return {
|
||||||
|
padding: `${theme.spacing.sm} ${theme.spacing.md} ${theme.spacing.sm} ${leftPadding}`,
|
||||||
|
fontSize: theme.typography.size.base,
|
||||||
|
height: theme.height.md,
|
||||||
|
fontWeight: theme.typography.weight.regular,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
@ -8,12 +8,11 @@ export interface StyleDeps {
|
|||||||
theme: GrafanaTheme;
|
theme: GrafanaTheme;
|
||||||
size: ButtonSize;
|
size: ButtonSize;
|
||||||
variant: ButtonVariant;
|
variant: ButtonVariant;
|
||||||
|
textAndIcon?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ButtonStyles {
|
export interface ButtonStyles {
|
||||||
button: string;
|
button: string;
|
||||||
buttonWithIcon: string;
|
|
||||||
iconButton: string;
|
|
||||||
iconWrap: string;
|
iconWrap: string;
|
||||||
icon?: string;
|
icon?: string;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user