CustomNavbar.jsx 2.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. import React, { useEffect, useState } from 'react';
  2. import PropTypes from 'prop-types';
  3. import {
  4. Nav, NavItem, NavLink, TabContent, TabPane,
  5. } from 'reactstrap';
  6. import { withTranslation } from 'react-i18next';
  7. import { withUnstatedContainers } from './UnstatedUtils';
  8. import PageAccessoriesContainer from '../services/PageAccessoriesContainer';
  9. const CustomNavbar = (props) => {
  10. const { t, pageAccessoriesContainer } = props;
  11. const { switchActiveTab } = pageAccessoriesContainer;
  12. const { activeTab } = pageAccessoriesContainer.state;
  13. const [sliderWidth, setSliderWidth] = useState(null);
  14. const [sliderMarginLeft, setSliderMarginLeft] = useState(null);
  15. // Might make this dynamic for px, %, pt, em
  16. function getPercentage(min, max) {
  17. return min / max * 100;
  18. }
  19. // [TODO: apply animation by gw4075]
  20. useEffect(() => {
  21. if (activeTab === '') {
  22. return;
  23. }
  24. const navTitle = document.getElementById('nav-title');
  25. const navTabs = document.querySelectorAll('li.nav-link');
  26. if (navTitle == null || navTabs == null) {
  27. return;
  28. }
  29. let tempML = 0;
  30. const styles = [].map.call(navTabs, (el) => {
  31. const width = getPercentage(el.offsetWidth, navTitle.offsetWidth);
  32. const marginLeft = tempML;
  33. tempML += width;
  34. return { width, marginLeft };
  35. });
  36. const { width, marginLeft } = styles[props.navTabMapping[activeTab].index];
  37. setSliderWidth(width);
  38. setSliderMarginLeft(marginLeft);
  39. }, [activeTab]);
  40. return (
  41. <React.Fragment>
  42. <Nav className="nav-title" id="nav-title">
  43. {Object.entries(props.navTabMapping).map(([key, value]) => {
  44. return (
  45. <NavItem key={key} type="button" className={`p-0 nav-link ${activeTab === key && 'active'}`}>
  46. <NavLink onClick={() => { switchActiveTab(key) }}>
  47. {value.icon}
  48. {t(value.i18n)}
  49. </NavLink>
  50. </NavItem>
  51. );
  52. })}
  53. </Nav>
  54. <hr className="my-0 grw-nav-slide-hr border-none" style={{ width: `${sliderWidth}%`, marginLeft: `${sliderMarginLeft}%` }} />
  55. <TabContent activeTab={activeTab} className="p-5">
  56. {Object.entries(props.navTabMapping).map(([key, value]) => {
  57. return (
  58. <TabPane key={key} tabId={key}>
  59. {value.tabContent}
  60. </TabPane>
  61. );
  62. })}
  63. </TabContent>
  64. </React.Fragment>
  65. );
  66. };
  67. /**
  68. * Wrapper component for using unstated
  69. */
  70. const PageAccessoriesModalWrapper = withUnstatedContainers(CustomNavbar, [PageAccessoriesContainer]);
  71. CustomNavbar.propTypes = {
  72. t: PropTypes.func.isRequired, // i18next
  73. // pageContainer: PropTypes.instanceOf(PageContainer).isRequired,
  74. pageAccessoriesContainer: PropTypes.instanceOf(PageAccessoriesContainer).isRequired,
  75. navTabMapping: PropTypes.object,
  76. };
  77. export default withTranslation()(PageAccessoriesModalWrapper);