@kiwicom/orbit-components
Version:
<div align="center"> <a href="https://orbit.kiwi" target="_blank"> <img alt="orbit-components" src="https://orbit.kiwi/wp-content/uploads/2018/08/orbit-components.png" srcset="https://orbit.kiwi/wp-content/uploads/2018/08/orbit-components@2x.png 2x"
240 lines (218 loc) • 7.18 kB
JavaScript
// @flow
import * as React from "react";
import styled from "styled-components";
import defaultTokens from "../defaultTokens";
import { TYPES, SIZES, TOKENS } from "./consts";
import { ICON_SIZES } from "../Icon/consts";
import { getSize } from "../Icon";
import type { Props } from "./index";
const getSizeToken = name => ({ theme, size }) => {
const tokens = {
[TOKENS.heightButton]: {
[SIZES.LARGE]: theme.orbit.heightButtonLarge,
[SIZES.NORMAL]: theme.orbit.heightButtonNormal,
[SIZES.SMALL]: theme.orbit.heightButtonSmall,
},
[TOKENS.fontSizeButton]: {
[SIZES.LARGE]: theme.orbit.fontSizeButtonLarge,
[SIZES.NORMAL]: theme.orbit.fontSizeButtonNormal,
[SIZES.SMALL]: theme.orbit.fontSizeButtonSmall,
},
[TOKENS.paddingButton]: {
[SIZES.LARGE]: theme.orbit.paddingButtonLarge,
[SIZES.NORMAL]: theme.orbit.paddingButtonNormal,
[SIZES.SMALL]: theme.orbit.paddingButtonSmall,
},
[TOKENS.paddingButtonWithIcon]: {
[SIZES.LARGE]: theme.orbit.paddingButtonLargeWithIcon,
[SIZES.NORMAL]: theme.orbit.paddingButtonNormalWithIcon,
[SIZES.SMALL]: theme.orbit.paddingButtonSmallWithIcon,
},
[TOKENS.marginRightIcon]: {
[SIZES.LARGE]: theme.orbit.marginButtonIconLarge,
[SIZES.NORMAL]: theme.orbit.marginButtonIconNormal,
[SIZES.SMALL]: theme.orbit.marginButtonIconSmall,
},
};
return tokens[name][size];
};
const getTypeToken = name => ({ theme, type }) => {
const tokens = {
[TOKENS.backgroundButton]: {
[TYPES.PRIMARY]: theme.orbit.backgroundButtonLinkPrimary,
[TYPES.SECONDARY]: theme.orbit.backgroundButtonLinkSecondary,
},
[TOKENS.backgroundButtonHover]: {
[TYPES.PRIMARY]: theme.orbit.backgroundButtonLinkPrimaryHover,
[TYPES.SECONDARY]: theme.orbit.backgroundButtonLinkSecondaryHover,
},
[TOKENS.backgroundButtonActive]: {
[TYPES.PRIMARY]: theme.orbit.backgroundButtonLinkPrimaryHover,
[TYPES.SECONDARY]: theme.orbit.backgroundButtonLinkSecondaryHover,
},
[TOKENS.colorTextButton]: {
[TYPES.PRIMARY]: theme.orbit.colorTextButtonLinkPrimary,
[TYPES.SECONDARY]: theme.orbit.colorTextButtonLinkSecondary,
},
[TOKENS.colorTextButtonHover]: {
[TYPES.PRIMARY]: theme.orbit.colorTextButtonLinkPrimaryHover,
[TYPES.SECONDARY]: theme.orbit.colorTextButtonLinkSecondaryHover,
},
[TOKENS.colorTextButtonActive]: {
[TYPES.PRIMARY]: theme.orbit.colorTextButtonLinkPrimaryActive,
[TYPES.SECONDARY]: theme.orbit.colorTextButtonLinkSecondaryActive,
},
};
return tokens[name][type];
};
const IconContainer = styled(({ theme, sizeIcon, type, onlyIcon, ...props }) => <div {...props} />)`
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
margin-right: ${({ onlyIcon }) => (onlyIcon ? "0" : getSizeToken(TOKENS.marginRightIcon))};
> * {
width: ${getSize()};
height: ${getSize()};
}
`;
IconContainer.defaultProps = {
theme: defaultTokens,
};
const IconContainerRight = styled(IconContainer)`
margin-right: 0;
margin-left: ${({ onlyIcon }) => (onlyIcon ? "0" : getSizeToken(TOKENS.marginRightIcon))};
`;
IconContainerRight.defaultProps = {
theme: defaultTokens,
};
export const StyledButtonLink = styled(
({
onlyIcon,
component,
circled,
external,
block,
type,
icon,
iconLeft,
iconRight,
sizeIcon,
width,
children,
transparent,
style,
theme,
dataTest,
submit,
...props
}) => {
const isButtonWithHref = component === "button" && props.href;
const Component = isButtonWithHref ? "a" : component;
const buttonType = submit ? "submit" : "button";
return (
<Component data-test={dataTest} type={!isButtonWithHref ? buttonType : undefined} {...props}>
{children}
</Component>
);
},
)`
font-family: ${({ theme }) => theme.orbit.fontFamily};
box-sizing: border-box;
appearance: none;
display: inline-flex;
justify-content: center;
align-items: center;
width: ${({ block, width, onlyIcon }) =>
block
? "100%"
: (width && `${width}px`) || (onlyIcon && getSizeToken(TOKENS.heightButton)) || "auto"};
height: ${getSizeToken(TOKENS.heightButton)};
background: ${getTypeToken(TOKENS.backgroundButton)};
color: ${getTypeToken(TOKENS.colorTextButton)}!important;
border: 0;
border-radius: ${({ theme, circled }) =>
circled ? getSizeToken(TOKENS.heightButton) : theme.orbit.borderRadiusNormal};
padding: 0;
padding-right: ${({ onlyIcon, iconRight }) =>
(onlyIcon && "0") ||
(iconRight ? getSizeToken(TOKENS.paddingButtonWithIcon) : getSizeToken(TOKENS.paddingButton))};
padding-left: ${({ onlyIcon, icon, iconLeft }) =>
(onlyIcon && "0") ||
(iconLeft || icon
? getSizeToken(TOKENS.paddingButtonWithIcon)
: getSizeToken(TOKENS.paddingButton))};
font-weight: ${({ theme }) => theme.orbit.fontWeightBold}!important;
font-size: ${getSizeToken(TOKENS.fontSizeButton)};
cursor: ${({ disabled }) => (disabled ? "default" : "pointer")};
opacity: ${({ disabled, theme }) => (disabled ? theme.orbit.opacityButtonDisabled : "1")};
transition: all 0.15s ease-in-out !important;
outline: 0;
text-decoration: none;
&:enabled:hover {
background: ${({ transparent }) => !transparent && getTypeToken(TOKENS.backgroundButtonHover)};
color: ${getTypeToken(TOKENS.colorTextButtonHover)}!important;
}
&:enabled:active {
transform: scale(${({ theme }) => theme.orbit.modifierScaleButtonActive});
background: ${({ transparent }) => !transparent && getTypeToken(TOKENS.backgroundButtonActive)};
color: ${getTypeToken(TOKENS.colorTextButtonActive)}!important;
}
&:enabled:focus {
box-shadow: ${({ transparent, theme }) => !transparent && theme.orbit.boxShadowButtonFocus};
&:active {
box-shadow: none;
}
}
`;
StyledButtonLink.defaultProps = {
theme: defaultTokens,
};
const ButtonLink = (props: Props) => {
const {
external,
children,
component,
href,
size = SIZES.NORMAL,
icon,
iconRight,
type = TYPES.PRIMARY,
onClick,
} = props;
const iconLeft = props.iconLeft || icon;
const sizeIcon = size === ICON_SIZES.SMALL ? ICON_SIZES.SMALL : ICON_SIZES.MEDIUM;
const onlyIcon = iconLeft && !children;
return (
<StyledButtonLink
onClick={onClick}
component={component}
onlyIcon={onlyIcon}
sizeIcon={sizeIcon}
type={type}
target={href && external ? "_blank" : undefined}
{...props}
>
{iconLeft && (
<IconContainer size={size} type={type} onlyIcon={onlyIcon} sizeIcon={sizeIcon}>
{iconLeft}
</IconContainer>
)}
{children}
{iconRight && (
<IconContainerRight size={size} type={type} onlyIcon={onlyIcon} sizeIcon={sizeIcon}>
{iconRight}
</IconContainerRight>
)}
</StyledButtonLink>
);
};
ButtonLink.defaultProps = {
component: "button",
external: false,
type: "primary",
size: "normal",
width: 0,
transparent: false,
};
export default ButtonLink;