129 lines
3.3 KiB
TypeScript
129 lines
3.3 KiB
TypeScript
import * as React from "react";
|
|
import styled from "styled-components";
|
|
import Loader from "./Loader";
|
|
import { colors, fonts, shadows, transitions } from "../styles";
|
|
|
|
interface ButtonStyleProps {
|
|
fetching: boolean;
|
|
outline: boolean;
|
|
type: "button" | "submit" | "reset";
|
|
color: string;
|
|
disabled: boolean;
|
|
icon: any;
|
|
left: boolean;
|
|
}
|
|
|
|
interface ButtonProps extends ButtonStyleProps {
|
|
children: React.ReactNode;
|
|
onClick?: any;
|
|
}
|
|
|
|
const SIcon = styled.div`
|
|
position: absolute;
|
|
height: 15px;
|
|
width: 15px;
|
|
margin: 0 8px;
|
|
top: calc((100% - 15px) / 2);
|
|
`;
|
|
|
|
const SHoverLayer = styled.div`
|
|
transition: ${transitions.button};
|
|
position: absolute;
|
|
height: 100%;
|
|
width: 100%;
|
|
background-color: rgb(${colors.white}, 0.1);
|
|
top: 0;
|
|
bottom: 0;
|
|
right: 0;
|
|
left: 0;
|
|
pointer-events: none;
|
|
opacity: 0;
|
|
visibility: hidden;
|
|
`;
|
|
|
|
const SButton = styled.button<ButtonStyleProps>`
|
|
transition: ${transitions.button};
|
|
position: relative;
|
|
border: none;
|
|
border-style: none;
|
|
box-sizing: border-box;
|
|
background-color: ${({ outline, color }) => (outline ? "transparent" : `rgb(${colors[color]})`)};
|
|
border: ${({ outline, color }) => (outline ? `1px solid rgb(${colors[color]})` : "none")};
|
|
color: ${({ outline, color }) => (outline ? `rgb(${colors[color]})` : `rgb(${colors.white})`)};
|
|
box-shadow: ${({ outline }) => (outline ? "none" : `${shadows.soft}`)};
|
|
border-radius: 8px;
|
|
font-size: ${fonts.size.medium};
|
|
font-weight: ${fonts.weight.semibold};
|
|
padding: ${({ icon, left }) =>
|
|
icon ? (left ? "7px 12px 8px 28px" : "7px 28px 8px 12px") : "8px 12px"};
|
|
cursor: ${({ disabled }) => (disabled ? "auto" : "pointer")};
|
|
will-change: transform;
|
|
|
|
&:disabled {
|
|
opacity: 0.6;
|
|
box-shadow: ${({ outline }) => (outline ? "none" : `${shadows.soft}`)};
|
|
}
|
|
|
|
@media (hover: hover) {
|
|
&:hover {
|
|
transform: ${({ disabled }) => (!disabled ? "translateY(-1px)" : "none")};
|
|
box-shadow: ${({ disabled, outline }) =>
|
|
!disabled ? (outline ? "none" : `${shadows.hover}`) : `${shadows.soft}`};
|
|
}
|
|
|
|
&:hover ${SHoverLayer} {
|
|
opacity: 1;
|
|
visibility: visible;
|
|
}
|
|
}
|
|
|
|
&:active {
|
|
transform: ${({ disabled }) => (!disabled ? "translateY(1px)" : "none")};
|
|
box-shadow: ${({ outline }) => (outline ? "none" : `${shadows.soft}`)};
|
|
color: ${({ outline, color }) =>
|
|
outline ? `rgb(${colors[color]})` : `rgba(${colors.white}, 0.24)`};
|
|
|
|
& ${SIcon} {
|
|
opacity: 0.8;
|
|
}
|
|
}
|
|
|
|
& ${SIcon} {
|
|
right: ${({ left }) => (left ? "auto" : "0")};
|
|
left: ${({ left }) => (left ? "0" : "auto")};
|
|
display: ${({ icon }) => (icon ? "block" : "none")};
|
|
mask: ${({ icon }) => (icon ? `url(${icon}) center no-repeat` : "none")};
|
|
background-color: ${({ outline, color }) =>
|
|
outline ? `rgb(${colors[color]})` : `rgb(${colors.white})`};
|
|
transition: 0.15s ease;
|
|
}
|
|
`;
|
|
|
|
const Button = (props: ButtonProps) => (
|
|
<SButton
|
|
{...props}
|
|
type={props.type}
|
|
outline={props.outline}
|
|
color={props.color}
|
|
disabled={props.disabled}
|
|
icon={props.icon}
|
|
left={props.left}
|
|
>
|
|
<SHoverLayer />
|
|
<SIcon />
|
|
{props.fetching ? <Loader size={20} color="white" /> : props.children}
|
|
</SButton>
|
|
);
|
|
|
|
Button.defaultProps = {
|
|
fetching: false,
|
|
outline: false,
|
|
type: "button",
|
|
color: "lightBlue",
|
|
disabled: false,
|
|
icon: null,
|
|
left: false,
|
|
};
|
|
|
|
export default Button;
|