Button.tsx 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. import React, { FC } from "react";
  2. import styled, { css } from "styled-components";
  3. import { switchProp, prop, ifProp } from "styled-tools";
  4. import { Flex, BoxProps } from "reflexbox/styled-components";
  5. // TODO: another solution for inline SVG
  6. import SVG from "react-inlinesvg";
  7. import { spin } from "../helpers/animations";
  8. interface Props extends BoxProps {
  9. color?: "purple" | "gray" | "blue";
  10. disabled?: boolean;
  11. icon?: string; // TODO: better typing
  12. isRound?: boolean;
  13. onClick?: any; // TODO: better typing
  14. type?: "button" | "submit" | "reset";
  15. }
  16. const StyledButton = styled(Flex)<Props>`
  17. position: relative;
  18. align-items: center;
  19. justify-content: center;
  20. font-weight: normal;
  21. text-align: center;
  22. line-height: 1;
  23. word-break: keep-all;
  24. color: ${switchProp(prop("color", "blue"), {
  25. blue: "white",
  26. purple: "white",
  27. gray: "#444"
  28. })};
  29. background: ${switchProp(prop("color", "blue"), {
  30. blue: "linear-gradient(to right, #42a5f5, #2979ff)",
  31. purple: "linear-gradient(to right, #7e57c2, #6200ea)",
  32. gray: "linear-gradient(to right, #e0e0e0, #bdbdbd)"
  33. })};
  34. box-shadow: ${switchProp(prop("color", "blue"), {
  35. blue: "0 5px 6px rgba(66, 165, 245, 0.5)",
  36. purple: "0 5px 6px rgba(81, 45, 168, 0.5)",
  37. gray: "0 5px 6px rgba(160, 160, 160, 0.5)"
  38. })};
  39. border: none;
  40. border-radius: 100px;
  41. transition: all 0.4s ease-out;
  42. cursor: pointer;
  43. overflow: hidden;
  44. :hover,
  45. :focus {
  46. outline: none;
  47. box-shadow: ${switchProp(prop("color", "blue"), {
  48. blue: "0 6px 15px rgba(66, 165, 245, 0.5)",
  49. purple: "0 6px 15px rgba(81, 45, 168, 0.5)",
  50. gray: "0 6px 15px rgba(160, 160, 160, 0.5)"
  51. })};
  52. transform: translateY(-2px) scale(1.02, 1.02);
  53. }
  54. a & {
  55. text-decoration: none;
  56. border: none;
  57. }
  58. ${ifProp(
  59. { size: "big" },
  60. css`
  61. height: 56px;
  62. @media only screen and (max-width: 448px) {
  63. height: 40px;
  64. }
  65. `
  66. )}
  67. `;
  68. const Icon = styled(SVG)`
  69. svg {
  70. width: 16px;
  71. height: 16px;
  72. margin-right: 12px;
  73. stroke: ${ifProp({ color: "gray" }, "#444", "#fff")};
  74. ${ifProp(
  75. { icon: "loader" },
  76. css`
  77. width: 20px;
  78. height: 20px;
  79. margin: 0;
  80. animation: ${spin} 1s linear infinite;
  81. `
  82. )}
  83. ${ifProp(
  84. "isRound",
  85. css`
  86. width: 15px;
  87. height: 15px;
  88. margin: 0;
  89. `
  90. )}
  91. @media only screen and (max-width: 768px) {
  92. width: 12px;
  93. height: 12px;
  94. margin-right: 6px;
  95. }
  96. }
  97. `;
  98. const Button: FC<Props> = props => {
  99. const SVGIcon = props.icon ? (
  100. <Icon
  101. icon={props.icon}
  102. isRound={props.isRound}
  103. color={props.color}
  104. src={`/images/${props.icon}.svg`}
  105. />
  106. ) : (
  107. ""
  108. );
  109. return (
  110. <StyledButton {...props}>
  111. {SVGIcon}
  112. {props.icon !== "loader" && props.children}
  113. </StyledButton>
  114. );
  115. };
  116. Button.defaultProps = {
  117. as: "button",
  118. width: "auto",
  119. flex: "0 0 auto",
  120. height: [32, 40],
  121. py: 0,
  122. px: [24, 32],
  123. fontSize: [12, 13],
  124. color: "blue",
  125. icon: "",
  126. isRound: false
  127. };
  128. export default Button;