Commit b0515f46 by Marcus Andersson Committed by Torkel Ödegaard

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.
parent 35679d46
......@@ -2,7 +2,6 @@ import React, { AnchorHTMLAttributes, ButtonHTMLAttributes, useContext } from 'r
import { ThemeContext } from '../../themes';
import { getButtonStyles } from './styles';
import { ButtonContent } from './ButtonContent';
import cx from 'classnames';
import { ButtonSize, ButtonStyles, ButtonVariant } from './types';
type CommonProps = {
......@@ -31,11 +30,11 @@ export const Button = React.forwardRef<HTMLButtonElement, ButtonProps>((props, r
theme,
size: size || 'md',
variant: variant || 'primary',
textAndIcon: !!(children && icon),
});
const buttonClassName = cx(styles.button, icon && styles.buttonWithIcon, icon && !children && styles.iconButton);
return (
<button className={buttonClassName} {...buttonProps} ref={ref}>
<button className={styles.button} {...buttonProps} ref={ref}>
<ButtonContent icon={icon}>{children}</ButtonContent>
</button>
);
......@@ -59,11 +58,11 @@ export const LinkButton = React.forwardRef<HTMLAnchorElement, LinkButtonProps>((
theme,
size: size || 'md',
variant: variant || 'primary',
textAndIcon: !!(children && icon),
});
const buttonClassName = cx(styles.button, icon && styles.buttonWithIcon, icon && !children && styles.iconButton);
return (
<a className={buttonClassName} {...anchorProps} ref={ref}>
<a className={styles.button} {...anchorProps} ref={ref}>
<ButtonContent icon={icon}>{children}</ButtonContent>
</a>
);
......
......@@ -2,6 +2,7 @@ import React from 'react';
import { css } from 'emotion';
import { stylesFactory, useTheme } from '../../themes';
import { GrafanaTheme } from '@grafana/data';
import { ButtonSize } from './types';
const getStyles = stylesFactory((theme: GrafanaTheme) => ({
content: css`
......@@ -23,12 +24,22 @@ type Props = {
icon?: string;
className?: string;
children: React.ReactNode;
size?: ButtonSize;
};
export function ButtonContent(props: Props) {
const { icon, children } = props;
const theme = useTheme();
const styles = getStyles(theme);
if (!children) {
return (
<span className={styles.content}>
<i className={icon} />
</span>
);
}
const iconElement = icon && (
<span className={styles.icon}>
<i className={icon} />
......
// 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>"`;
import tinycolor from 'tinycolor2';
import { css } from 'emotion';
import { selectThemeVariant, stylesFactory } from '../../themes';
import { StyleDeps } from './types';
import { StyleDeps, ButtonSize } from './types';
import { GrafanaTheme } from '@grafana/data';
const buttonVariantStyles = (
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;
let padding,
background,
fontSize,
height,
fontWeight = theme.typography.weight.semibold;
const { padding, fontSize, height, fontWeight } = calculateMeasures(theme, size, !!textAndIcon);
switch (size) {
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;
}
let background;
switch (variant) {
case 'primary':
......@@ -120,13 +93,6 @@ export const getButtonStyles = stylesFactory(({ theme, size, variant }: StyleDep
box-shadow: none;
}
`,
buttonWithIcon: css`
padding-left: ${theme.spacing.sm};
`,
// used for buttons with icon onlys
iconButton: css`
padding-right: 0;
`,
iconWrap: css`
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;
size: ButtonSize;
variant: ButtonVariant;
textAndIcon?: boolean;
}
export interface ButtonStyles {
button: string;
buttonWithIcon: string;
iconButton: string;
iconWrap: string;
icon?: string;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment