SaveButton.tsx 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. import React, { Component } from 'react';
  2. import styled from 'styled-components';
  3. import loading from '../assets/loading.gif';
  4. type PropsType = {
  5. text: string,
  6. onClick: () => void,
  7. disabled?: boolean,
  8. status?: string | null,
  9. color?: string,
  10. helper?: string | null,
  11. // Makes flush with corner if not within a modal
  12. makeFlush?: boolean
  13. };
  14. type StateType = {
  15. };
  16. export default class SaveButton extends Component<PropsType, StateType> {
  17. renderStatus = () => {
  18. if (this.props.status) {
  19. if (this.props.status === 'successful') {
  20. return (
  21. <StatusWrapper successful={true}>
  22. <i className="material-icons">done</i> Successfully updated
  23. </StatusWrapper>
  24. );
  25. } else if (this.props.status === 'loading') {
  26. return (
  27. <StatusWrapper successful={false}>
  28. <LoadingGif src={loading} /> Updating . . .
  29. </StatusWrapper>
  30. );
  31. } else if (this.props.status === 'error') {
  32. return (
  33. <StatusWrapper successful={false}>
  34. <i className="material-icons">error_outline</i> Could not update
  35. </StatusWrapper>
  36. );
  37. } else {
  38. return (
  39. <StatusWrapper successful={false}>
  40. <i className="material-icons">error_outline</i> {this.props.status}
  41. </StatusWrapper>
  42. );
  43. }
  44. } else if (this.props.helper) {
  45. return (
  46. <StatusWrapper successful={true}>{this.props.helper}</StatusWrapper>
  47. );
  48. }
  49. }
  50. render() {
  51. return (
  52. <ButtonWrapper makeFlush={this.props.makeFlush}>
  53. {this.renderStatus()}
  54. <Button
  55. disabled={this.props.disabled}
  56. onClick={this.props.onClick}
  57. color={this.props.color || '#616FEEcc'}
  58. >
  59. {this.props.text}
  60. </Button>
  61. </ButtonWrapper>
  62. );
  63. }
  64. }
  65. const LoadingGif = styled.img`
  66. width: 15px;
  67. height: 15px;
  68. margin-right: 9px;
  69. margin-bottom: 0px;
  70. `;
  71. const StatusWrapper = styled.div`
  72. display: flex;
  73. align-items: center;
  74. font-family: 'Work Sans', sans-serif;
  75. font-size: 13px;
  76. color: #ffffff55;
  77. margin-right: 25px;
  78. > i {
  79. font-size: 18px;
  80. margin-right: 10px;
  81. color: ${(props: { successful: boolean }) => props.successful ? '#4797ff' : '#fcba03'};
  82. }
  83. animation: statusFloatIn 0.5s;
  84. animation-fill-mode: forwards;
  85. @keyframes statusFloatIn {
  86. from {
  87. opacity: 0; transform: translateY(10px);
  88. }
  89. to {
  90. opacity: 1; transform: translateY(0px);
  91. }
  92. }
  93. `;
  94. const ButtonWrapper = styled.div`
  95. display: flex;
  96. align-items: center;
  97. position: absolute;
  98. ${(props: { makeFlush: boolean }) => {
  99. if (!props.makeFlush) {
  100. return (`
  101. bottom: 25px;
  102. right: 27px;
  103. `);
  104. }
  105. return (`
  106. bottom: 0;
  107. right: 0;
  108. `);
  109. }}
  110. `;
  111. const Button = styled.button`
  112. height: 35px;
  113. font-size: 13px;
  114. font-weight: 500;
  115. font-family: 'Work Sans', sans-serif;
  116. color: white;
  117. padding: 6px 20px 7px 20px;
  118. text-align: left;
  119. border: 0;
  120. border-radius: 5px;
  121. background: ${(props) => (!props.disabled ? props.color : '#aaaabb')};
  122. box-shadow: ${(props) => (!props.disabled ? '0 2px 5px 0 #00000030' : 'none')};
  123. cursor: ${(props) => (!props.disabled ? 'pointer' : 'default')};
  124. user-select: none;
  125. :focus { outline: 0 }
  126. :hover {
  127. filter: ${(props) => (!props.disabled ? 'brightness(120%)' : '')};
  128. }
  129. `;