TabSelector.tsx 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. import React, { Component } from "react";
  2. import styled from "styled-components";
  3. export interface selectOption<T> {
  4. value: T;
  5. label: string;
  6. component?: any;
  7. }
  8. type PropsType<T> = {
  9. currentTab: string;
  10. options: selectOption<T>[];
  11. setCurrentTab: (value: T) => void;
  12. addendum?: any;
  13. color?: string;
  14. noBuffer?: boolean;
  15. };
  16. type StateType = {};
  17. export default class TabSelector<T> extends Component<PropsType<T>, StateType> {
  18. getCurrentComponent() {
  19. const currentOption = this.props.options.find(
  20. (option) => option.value === this.props.currentTab
  21. );
  22. if (currentOption?.component) {
  23. return currentOption.component;
  24. }
  25. return null;
  26. }
  27. handleTabClick = (value: T) => {
  28. this.props.setCurrentTab(value);
  29. };
  30. renderTabList = () => {
  31. let color = this.props.color || "#aaaabb";
  32. return this.props.options.map((option: selectOption<T>, i: number) => {
  33. return (
  34. <Tab
  35. key={i}
  36. onClick={() => this.handleTabClick(option.value)}
  37. lastItem={i === this.props.options.length - 1}
  38. highlight={option.value === this.props.currentTab ? color : null}
  39. >
  40. {option.label}
  41. </Tab>
  42. );
  43. });
  44. };
  45. renderAddendumBuffer = () => {};
  46. render() {
  47. return (
  48. <>
  49. <StyledTabSelector>
  50. <TabWrapper>
  51. <Line />
  52. {this.renderTabList()}
  53. <Tab lastItem={true} highlight={null}>
  54. {this.props.noBuffer ? null : <Buffer />}
  55. </Tab>
  56. </TabWrapper>
  57. {this.props.addendum}
  58. </StyledTabSelector>
  59. {this.getCurrentComponent()}
  60. </>
  61. );
  62. }
  63. }
  64. const Line = styled.div`
  65. height: 1px;
  66. position: absolute;
  67. top: 29px;
  68. z-index: 0;
  69. left: 0;
  70. background: #aaaabb55;
  71. width: 100%;
  72. `;
  73. const Buffer = styled.div`
  74. width: 138px;
  75. height: 10px;
  76. `;
  77. // Keeps the scrollbar beneath all tabs on overflow
  78. const TabWrapper = styled.div`
  79. display: flex;
  80. overflow-x: auto;
  81. padding-bottom: 15px;
  82. margin-bottom: -15px;
  83. `;
  84. const Tab = styled.div`
  85. height: 30px;
  86. margin-right: ${(props: { lastItem: boolean; highlight: string | null}) =>
  87. props.lastItem ? "" : "30px"};
  88. display: flex;
  89. font-family: "Work Sans", sans-serif;
  90. font-size: 13px;
  91. user-select: none;
  92. color: ${(props: { lastItem: boolean; highlight: string | null }) =>
  93. props.highlight ? props.highlight : "#aaaabb55"};
  94. flex-direction: column;
  95. padding-top: 7px;
  96. padding-bottom: 2px;
  97. margin-bottom: -2px;
  98. align-items: center;
  99. cursor: pointer;
  100. white-space: nowrap;
  101. border-bottom: 1px solid
  102. ${(props: { lastItem: boolean; highlight: string | null }) =>
  103. props.highlight ? props.highlight : "none"};
  104. :hover {
  105. color: ${(props: { lastItem: boolean; highlight: string | null }) =>
  106. props.highlight ? "" : "#aaaabb"};
  107. }
  108. `;
  109. const StyledTabSelector = styled.div`
  110. display: flex;
  111. width: calc(100% - 2px);
  112. align-items: center;
  113. padding-bottom: 1px;
  114. margin-left: 1px;
  115. position: relative;
  116. `;