Просмотр исходного кода

Merge pull request #3134 from weseek/imprv/custom-nav-responsive

Imprv/custom nav responsive
Yuki Takei 5 лет назад
Родитель
Сommit
488b6d92a6

+ 2 - 2
src/client/js/components/Admin/Notification/NotificationSetting.jsx

@@ -11,7 +11,7 @@ import { withLoadingSppiner } from '../../SuspenseUtils';
 
 import AdminNotificationContainer from '../../../services/AdminNotificationContainer';
 
-import { CustomNav } from '../../CustomNavigation';
+import { CustomNavTab } from '../../CustomNavigation/CustomNav';
 
 import SlackAppConfiguration from './SlackAppConfiguration';
 import UserTriggerNotification from './UserTriggerNotification';
@@ -72,7 +72,7 @@ function NotificationSetting(props) {
 
   return (
     <>
-      <CustomNav activeTab={activeTab} navTabMapping={navTabMapping} onNavSelected={switchActiveTab} hideBorderBottom />
+      <CustomNavTab activeTab={activeTab} navTabMapping={navTabMapping} onNavSelected={switchActiveTab} hideBorderBottom />
 
       <TabContent activeTab={activeTab} className="p-5">
         <TabPane tabId="slack_configuration">

+ 8 - 2
src/client/js/components/Admin/Security/SecurityManagementContents.jsx

@@ -16,7 +16,7 @@ import TwitterSecuritySetting from './TwitterSecuritySetting';
 import FacebookSecuritySetting from './FacebookSecuritySetting';
 import ShareLinkSetting from './ShareLinkSetting';
 
-import { CustomNav } from '../../CustomNavigation';
+import CustomNav from '../../CustomNavigation/CustomNav';
 
 function SecurityManagementContents(props) {
   const { t } = props;
@@ -104,7 +104,13 @@ function SecurityManagementContents(props) {
 
       <div className="auth-mechanism-configurations">
         <h2 className="border-bottom">{t('security_setting.Authentication mechanism settings')}</h2>
-        <CustomNav activeTab={activeTab} navTabMapping={navTabMapping} onNavSelected={switchActiveTab} hideBorderBottom />
+        <CustomNav
+          activeTab={activeTab}
+          navTabMapping={navTabMapping}
+          onNavSelected={switchActiveTab}
+          hideBorderBottom
+          breakpointToSwitchDropdownDown="md"
+        />
         <TabContent activeTab={activeTab} className="p-5">
           <TabPane tabId="passport_local">
             {activeComponents.has('passport_local') && <LocalSecuritySetting />}

+ 0 - 164
src/client/js/components/CustomNavigation.jsx

@@ -1,164 +0,0 @@
-import React, {
-  useEffect, useState, useRef, useMemo, useCallback,
-} from 'react';
-import PropTypes from 'prop-types';
-import {
-  Nav, NavItem, NavLink, TabContent, TabPane,
-} from 'reactstrap';
-
-
-export const CustomNav = (props) => {
-  const navContainer = useRef();
-  const [sliderWidth, setSliderWidth] = useState(0);
-  const [sliderMarginLeft, setSliderMarginLeft] = useState(0);
-
-  const {
-    activeTab, navTabMapping, onNavSelected, hideBorderBottom,
-  } = props;
-
-  const navTabRefs = useMemo(() => {
-    const obj = {};
-    Object.keys(navTabMapping).forEach((key) => {
-      obj[key] = React.createRef();
-    });
-    return obj;
-  }, [navTabMapping]);
-
-  const navLinkClickHandler = useCallback((key) => {
-    if (onNavSelected != null) {
-      onNavSelected(key);
-    }
-  }, [onNavSelected]);
-
-  function registerNavLink(key, elm) {
-    if (elm != null) {
-      navTabRefs[key] = elm;
-    }
-  }
-
-  // Might make this dynamic for px, %, pt, em
-  function getPercentage(min, max) {
-    return min / max * 100;
-  }
-
-  useEffect(() => {
-    if (activeTab === '') {
-      return;
-    }
-
-    if (navContainer == null) {
-      return;
-    }
-
-    let tempML = 0;
-
-    const styles = Object.entries(navTabRefs).map((el) => {
-      const width = getPercentage(el[1].offsetWidth, navContainer.current.offsetWidth);
-      const marginLeft = tempML;
-      tempML += width;
-      return { width, marginLeft };
-    });
-    const { width, marginLeft } = styles[navTabMapping[activeTab].index];
-
-    setSliderWidth(width);
-    setSliderMarginLeft(marginLeft);
-
-  }, [activeTab, navTabRefs, navTabMapping]);
-
-  return (
-    <div className="grw-custom-nav">
-      <div ref={navContainer}>
-        <Nav className="nav-title">
-          {Object.entries(navTabMapping).map(([key, value]) => {
-
-            const isActive = activeTab === key;
-            const isLinkEnabled = value.isLinkEnabled != null ? value.isLinkEnabled(value) : true;
-            const { Icon, i18n } = value;
-
-            return (
-              <NavItem
-                key={key}
-                className={`p-0 grw-custom-navtab ${isActive && 'active'}`}
-              >
-                <NavLink type="button" key={key} innerRef={elm => registerNavLink(key, elm)} disabled={!isLinkEnabled} onClick={() => navLinkClickHandler(key)}>
-                  <Icon /> {i18n}
-                </NavLink>
-              </NavItem>
-            );
-          })}
-        </Nav>
-      </div>
-      <hr className="my-0 grw-nav-slide-hr border-none" style={{ width: `${sliderWidth}%`, marginLeft: `${sliderMarginLeft}%` }} />
-      { !hideBorderBottom && <hr className="my-0 border-top-0 border-bottom" /> }
-    </div>
-  );
-
-};
-
-CustomNav.propTypes = {
-  activeTab: PropTypes.string.isRequired,
-  navTabMapping: PropTypes.object.isRequired,
-  onNavSelected: PropTypes.func,
-  hideBorderBottom: PropTypes.bool,
-};
-
-CustomNav.defaultProps = {
-  hideBorderBottom: false,
-};
-
-
-export const CustomTabContent = (props) => {
-
-  const { activeTab, navTabMapping, additionalClassNames } = props;
-
-  return (
-    <TabContent activeTab={activeTab} className={additionalClassNames.join(' ')}>
-      {Object.entries(navTabMapping).map(([key, value]) => {
-
-        const { Content } = value;
-
-        return (
-          <TabPane key={key} tabId={key}>
-            <Content />
-          </TabPane>
-        );
-      })}
-    </TabContent>
-  );
-
-};
-
-CustomTabContent.propTypes = {
-  activeTab: PropTypes.string.isRequired,
-  navTabMapping: PropTypes.object.isRequired,
-  additionalClassNames: PropTypes.arrayOf(PropTypes.string),
-};
-CustomTabContent.defaultProps = {
-  additionalClassNames: [],
-};
-
-
-const CustomNavigation = (props) => {
-  const { navTabMapping, defaultTabIndex, tabContentClasses } = props;
-  const [activeTab, setActiveTab] = useState(Object.keys(props.navTabMapping)[defaultTabIndex || 0]);
-
-  return (
-    <React.Fragment>
-
-      <CustomNav activeTab={activeTab} navTabMapping={navTabMapping} onNavSelected={setActiveTab} />
-      <CustomTabContent activeTab={activeTab} navTabMapping={navTabMapping} additionalClassNames={tabContentClasses} />
-
-    </React.Fragment>
-  );
-};
-
-CustomNavigation.propTypes = {
-  navTabMapping: PropTypes.object.isRequired,
-  defaultTabIndex: PropTypes.number,
-  tabContentClasses: PropTypes.arrayOf(PropTypes.string),
-};
-CustomNavigation.defaultProps = {
-  tabContentClasses: ['p-4'],
-};
-
-export default CustomNavigation;

+ 231 - 0
src/client/js/components/CustomNavigation/CustomNav.jsx

@@ -0,0 +1,231 @@
+import React, {
+  useEffect, useState, useRef, useMemo, useCallback,
+} from 'react';
+import PropTypes from 'prop-types';
+import {
+  Nav, NavItem, NavLink,
+} from 'reactstrap';
+
+
+function getBreakpointOneLevelLarger(breakpoint) {
+  switch (breakpoint) {
+    case 'sm':
+      return 'md';
+    case 'md':
+      return 'lg';
+    case 'lg':
+      return 'xl';
+    case 'xl':
+    default:
+      return '2xl';
+  }
+}
+
+
+export const CustomNavDropdown = (props) => {
+  const {
+    activeTab, navTabMapping, onNavSelected,
+  } = props;
+
+  const activeObj = navTabMapping[activeTab];
+
+  const menuItemClickHandler = useCallback((key) => {
+    if (onNavSelected != null) {
+      onNavSelected(key);
+    }
+  }, [onNavSelected]);
+
+  return (
+    <div className="grw-custom-nav-dropdown btn-group btn-block">
+      <button
+        className="btn btn-outline-primary btn-lg btn-block dropdown-toggle text-right"
+        type="button"
+        data-toggle="dropdown"
+        aria-haspopup="true"
+        aria-expanded="false"
+      >
+        <span className="float-left">
+          { activeObj != null && (
+            <><activeObj.Icon /> {activeObj.i18n}</>
+          ) }
+        </span>
+      </button>
+      <div className="dropdown-menu dropdown-menu-right">
+        {Object.entries(navTabMapping).map(([key, value]) => {
+
+          const isActive = activeTab === key;
+          const isLinkEnabled = value.isLinkEnabled != null ? value.isLinkEnabled(value) : true;
+          const { Icon, i18n } = value;
+
+          return (
+            <button
+              key={key}
+              type="button"
+              className={`dropdown-item px-3 py-2 ${isActive ? 'active' : ''}`}
+              disabled={!isLinkEnabled}
+              onClick={() => menuItemClickHandler(key)}
+            >
+              <Icon /> {i18n}
+            </button>
+          );
+        })}
+      </div>
+    </div>
+  );
+};
+
+CustomNavDropdown.propTypes = {
+  activeTab: PropTypes.string.isRequired,
+  navTabMapping: PropTypes.object.isRequired,
+  onNavSelected: PropTypes.func,
+};
+
+
+export const CustomNavTab = (props) => {
+  const navContainer = useRef();
+  const [sliderWidth, setSliderWidth] = useState(0);
+  const [sliderMarginLeft, setSliderMarginLeft] = useState(0);
+
+  const {
+    activeTab, navTabMapping, onNavSelected, hideBorderBottom, breakpointToHideInactiveTabsDown,
+  } = props;
+
+  const navTabRefs = useMemo(() => {
+    const obj = {};
+    Object.keys(navTabMapping).forEach((key) => {
+      obj[key] = React.createRef();
+    });
+    return obj;
+  }, [navTabMapping]);
+
+  const navLinkClickHandler = useCallback((key) => {
+    if (onNavSelected != null) {
+      onNavSelected(key);
+    }
+  }, [onNavSelected]);
+
+  function registerNavLink(key, elm) {
+    if (elm != null) {
+      navTabRefs[key] = elm;
+    }
+  }
+
+  // Might make this dynamic for px, %, pt, em
+  function getPercentage(min, max) {
+    return min / max * 100;
+  }
+
+  useEffect(() => {
+    if (activeTab === '') {
+      return;
+    }
+
+    if (navContainer == null) {
+      return;
+    }
+
+    let tempML = 0;
+
+    const styles = Object.entries(navTabRefs).map((el) => {
+      const width = getPercentage(el[1].offsetWidth, navContainer.current.offsetWidth);
+      const marginLeft = tempML;
+      tempML += width;
+      return { width, marginLeft };
+    });
+    const { width, marginLeft } = styles[navTabMapping[activeTab].index];
+
+    setSliderWidth(width);
+    setSliderMarginLeft(marginLeft);
+
+  }, [activeTab, navTabRefs, navTabMapping]);
+
+  // determine inactive classes to hide NavItem
+  const inactiveClassnames = [];
+  if (breakpointToHideInactiveTabsDown != null) {
+    const breakpointOneLevelLarger = getBreakpointOneLevelLarger(breakpointToHideInactiveTabsDown);
+    inactiveClassnames.push('d-none');
+    inactiveClassnames.push(`d-${breakpointOneLevelLarger}-block`);
+  }
+
+  return (
+    <div className="grw-custom-nav-tab">
+      <div ref={navContainer}>
+        <Nav className="nav-title">
+          {Object.entries(navTabMapping).map(([key, value]) => {
+
+            const isActive = activeTab === key;
+            const isLinkEnabled = value.isLinkEnabled != null ? value.isLinkEnabled(value) : true;
+            const { Icon, i18n } = value;
+
+            return (
+              <NavItem
+                key={key}
+                className={`p-0 ${isActive ? 'active' : inactiveClassnames.join(' ')}`}
+              >
+                <NavLink type="button" key={key} innerRef={elm => registerNavLink(key, elm)} disabled={!isLinkEnabled} onClick={() => navLinkClickHandler(key)}>
+                  <Icon /> {i18n}
+                </NavLink>
+              </NavItem>
+            );
+          })}
+        </Nav>
+      </div>
+      <hr className="my-0 grw-nav-slide-hr border-none" style={{ width: `${sliderWidth}%`, marginLeft: `${sliderMarginLeft}%` }} />
+      { !hideBorderBottom && <hr className="my-0 border-top-0 border-bottom" /> }
+    </div>
+  );
+
+};
+
+CustomNavTab.propTypes = {
+  activeTab: PropTypes.string.isRequired,
+  navTabMapping: PropTypes.object.isRequired,
+  onNavSelected: PropTypes.func,
+  hideBorderBottom: PropTypes.bool,
+  breakpointToHideInactiveTabsDown: PropTypes.oneOf(['xs', 'sm', 'md', 'lg', 'xl']),
+};
+
+CustomNavTab.defaultProps = {
+  hideBorderBottom: false,
+};
+
+
+const CustomNav = (props) => {
+
+  const tabClassnames = ['d-none'];
+  const dropdownClassnames = ['d-block'];
+
+  // determine classes to show/hide
+  const breakpointOneLevelLarger = getBreakpointOneLevelLarger(props.breakpointToSwitchDropdownDown);
+  tabClassnames.push(`d-${breakpointOneLevelLarger}-block`);
+  dropdownClassnames.push(`d-${breakpointOneLevelLarger}-none`);
+
+  return (
+    <div className="grw-custom-nav">
+      <div className={tabClassnames.join(' ')}>
+        <CustomNavTab {...props} />
+      </div>
+      <div className={dropdownClassnames.join(' ')}>
+        <CustomNavDropdown {...props} />
+      </div>
+    </div>
+  );
+
+};
+
+CustomNav.propTypes = {
+  activeTab: PropTypes.string.isRequired,
+  navTabMapping: PropTypes.object.isRequired,
+  onNavSelected: PropTypes.func,
+  hideBorderBottom: PropTypes.bool,
+  breakpointToHideInactiveTabsDown: PropTypes.oneOf(['xs', 'sm', 'md', 'lg', 'xl']),
+  breakpointToSwitchDropdownDown: PropTypes.oneOf(['xs', 'sm', 'md', 'lg', 'xl']),
+};
+
+CustomNav.defaultProps = {
+  hideBorderBottom: false,
+  breakpointToSwitchDropdownDown: 'sm',
+};
+
+
+export default CustomNav;

+ 52 - 0
src/client/js/components/CustomNavigation/CustomNavAndContents.jsx

@@ -0,0 +1,52 @@
+import React, { useState } from 'react';
+import PropTypes from 'prop-types';
+
+import CustomNav, { CustomNavTab, CustomNavDropdown } from './CustomNav';
+import CustomTabContent from './CustomTabContent';
+
+
+const CustomNavAndContents = (props) => {
+  const {
+    navTabMapping, defaultTabIndex, navigationMode, tabContentClasses, breakpointToHideInactiveTabsDown,
+  } = props;
+  const [activeTab, setActiveTab] = useState(Object.keys(props.navTabMapping)[defaultTabIndex || 0]);
+
+  let SelectedNav;
+  switch (navigationMode) {
+    case 'tab':
+      SelectedNav = CustomNavTab;
+      break;
+    case 'dropdown':
+      SelectedNav = CustomNavDropdown;
+      break;
+    case 'both':
+      SelectedNav = CustomNav;
+      break;
+  }
+
+  return (
+    <>
+      <SelectedNav
+        activeTab={activeTab}
+        navTabMapping={navTabMapping}
+        onNavSelected={setActiveTab}
+        breakpointToHideInactiveTabsDown={breakpointToHideInactiveTabsDown}
+      />
+      <CustomTabContent activeTab={activeTab} navTabMapping={navTabMapping} additionalClassNames={tabContentClasses} />
+    </>
+  );
+};
+
+CustomNavAndContents.propTypes = {
+  navTabMapping: PropTypes.object.isRequired,
+  defaultTabIndex: PropTypes.number,
+  navigationMode: PropTypes.oneOf(['both', 'tab', 'dropdown']),
+  tabContentClasses: PropTypes.arrayOf(PropTypes.string),
+  breakpointToHideInactiveTabsDown: PropTypes.oneOf(['xs', 'sm', 'md', 'lg', 'xl']),
+};
+CustomNavAndContents.defaultProps = {
+  navigationMode: 'tab',
+  tabContentClasses: ['p-4'],
+};
+
+export default CustomNavAndContents;

+ 37 - 0
src/client/js/components/CustomNavigation/CustomTabContent.jsx

@@ -0,0 +1,37 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import {
+  TabContent, TabPane,
+} from 'reactstrap';
+
+const CustomTabContent = (props) => {
+
+  const { activeTab, navTabMapping, additionalClassNames } = props;
+
+  return (
+    <TabContent activeTab={activeTab} className={additionalClassNames.join(' ')}>
+      {Object.entries(navTabMapping).map(([key, value]) => {
+
+        const { Content } = value;
+
+        return (
+          <TabPane key={key} tabId={key}>
+            <Content />
+          </TabPane>
+        );
+      })}
+    </TabContent>
+  );
+
+};
+
+CustomTabContent.propTypes = {
+  activeTab: PropTypes.string.isRequired,
+  navTabMapping: PropTypes.object.isRequired,
+  additionalClassNames: PropTypes.arrayOf(PropTypes.string),
+};
+CustomTabContent.defaultProps = {
+  additionalClassNames: [],
+};
+
+export default CustomTabContent;

+ 2 - 2
src/client/js/components/ForbiddenPage.jsx

@@ -2,7 +2,7 @@ import React, { useMemo } from 'react';
 import PropTypes from 'prop-types';
 import { withTranslation } from 'react-i18next';
 import PageListIcon from './Icons/PageListIcon';
-import CustomNavigation from './CustomNavigation';
+import CustomNavAndContents from './CustomNavigation/CustomNavAndContents';
 import PageList from './PageList';
 
 
@@ -41,7 +41,7 @@ const ForbiddenPage = (props) => {
         </div>
       </div>
       <div className="mt-5">
-        <CustomNavigation navTabMapping={navTabMapping} />
+        <CustomNavAndContents navTabMapping={navTabMapping} />
       </div>
     </>
   );

+ 3 - 2
src/client/js/components/Me/PersonalSettings.jsx

@@ -2,7 +2,8 @@
 import React, { useMemo } from 'react';
 import PropTypes from 'prop-types';
 import { withTranslation } from 'react-i18next';
-import CustomNavigation from '../CustomNavigation';
+
+import CustomNavAndContents from '../CustomNavigation/CustomNavAndContents';
 import UserSettings from './UserSettings';
 import PasswordSettings from './PasswordSettings';
 import ExternalAccountLinkedMe from './ExternalAccountLinkedMe';
@@ -43,7 +44,7 @@ const PersonalSettings = (props) => {
 
 
   return (
-    <CustomNavigation navTabMapping={navTabMapping} tabContentClasses={['px-0']} />
+    <CustomNavAndContents navTabMapping={navTabMapping} navigationMode="both" tabContentClasses={['px-0']} />
   );
 
 };

+ 2 - 2
src/client/js/components/NotFoundPage.jsx

@@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
 import { withTranslation } from 'react-i18next';
 import PageListIcon from './Icons/PageListIcon';
 import TimeLineIcon from './Icons/TimeLineIcon';
-import CustomNavigation from './CustomNavigation';
+import CustomNavAndContents from './CustomNavigation/CustomNavAndContents';
 import PageList from './PageList';
 import PageTimeline from './PageTimeline';
 
@@ -30,7 +30,7 @@ const NotFoundPage = (props) => {
 
   return (
     <div className="mt-5 d-edit-none">
-      <CustomNavigation navTabMapping={navTabMapping} />
+      <CustomNavAndContents navTabMapping={navTabMapping} />
     </div>
   );
 };

+ 13 - 8
src/client/js/components/PageAccessoriesModal.jsx

@@ -19,7 +19,7 @@ import PageTimeline from './PageTimeline';
 import PageList from './PageList';
 import PageHistory from './PageHistory';
 import ShareLink from './ShareLink/ShareLink';
-import { CustomNav } from './CustomNavigation';
+import { CustomNavTab } from './CustomNavigation/CustomNav';
 import ExpandOrContractButton from './ExpandOrContractButton';
 
 const PageAccessoriesModal = (props) => {
@@ -80,17 +80,16 @@ const PageAccessoriesModal = (props) => {
   };
 
   const buttons = (
-    <span>
-      {/* change order because of `float: right` by '.close' class */}
-      <button type="button" className="close" onClick={closeModalHandler} aria-label="Close">
-        <span aria-hidden="true">&times;</span>
-      </button>
+    <div className="d-flex flex-nowrap">
       <ExpandOrContractButton
         isWindowExpanded={isWindowExpanded}
         expandWindow={expandWindow}
         contractWindow={contractWindow}
       />
-    </span>
+      <button type="button" className="close" onClick={closeModalHandler} aria-label="Close">
+        <span aria-hidden="true">&times;</span>
+      </button>
+    </div>
   );
 
   return (
@@ -102,7 +101,13 @@ const PageAccessoriesModal = (props) => {
         className={`grw-page-accessories-modal ${isWindowExpanded ? 'grw-modal-expanded' : ''} `}
       >
         <ModalHeader className="p-0" toggle={closeModalHandler} close={buttons}>
-          <CustomNav activeTab={activeTab} navTabMapping={navTabMapping} onNavSelected={switchActiveTab} hideBorderBottom />
+          <CustomNavTab
+            activeTab={activeTab}
+            navTabMapping={navTabMapping}
+            onNavSelected={switchActiveTab}
+            breakpointToHideInactiveTabsDown="md"
+            hideBorderBottom
+          />
         </ModalHeader>
         <ModalBody className="overflow-auto grw-modal-body-style p-0">
           {/* Do not use CustomTabContent because of performance problem:

+ 2 - 2
src/client/js/components/PageComment/CommentEditor.jsx

@@ -21,7 +21,7 @@ import SlackNotification from '../SlackNotification';
 
 import CommentPreview from './CommentPreview';
 import NotAvailableForGuest from '../NotAvailableForGuest';
-import { CustomNav } from '../CustomNavigation';
+import { CustomNavTab } from '../CustomNavigation/CustomNav';
 
 const navTabMapping = {
   comment_editor: {
@@ -298,7 +298,7 @@ class CommentEditor extends React.Component {
     return (
       <>
         <div className="comment-write">
-          <CustomNav activeTab={activeTab} navTabMapping={navTabMapping} onNavSelected={this.handleSelect} hideBorderBottom />
+          <CustomNavTab activeTab={activeTab} navTabMapping={navTabMapping} onNavSelected={this.handleSelect} hideBorderBottom />
           <TabContent activeTab={activeTab}>
             <TabPane tabId="comment_editor">
               <Editor

+ 2 - 2
src/client/js/components/TrashPageList.jsx

@@ -2,7 +2,7 @@ import React, { useMemo } from 'react';
 import PropTypes from 'prop-types';
 import { withTranslation } from 'react-i18next';
 import PageListIcon from './Icons/PageListIcon';
-import CustomNavigation from './CustomNavigation';
+import CustomNavAndContents from './CustomNavigation/CustomNavAndContents';
 import PageList from './PageList';
 
 
@@ -22,7 +22,7 @@ const TrashPageList = (props) => {
 
   return (
     <div className="mt-5 d-edit-none">
-      <CustomNavigation navTabMapping={navTabMapping} />
+      <CustomNavAndContents navTabMapping={navTabMapping} />
     </div>
   );
 };

+ 11 - 8
src/client/styles/scss/_navbar.scss

@@ -76,20 +76,23 @@
   }
 }
 
-.grw-custom-nav {
+.grw-custom-nav-tab,
+.grw-custom-nav-dropdown {
+  svg {
+    width: 17px;
+    height: 17px;
+    margin-right: 5px;
+    vertical-align: text-bottom;
+  }
+}
+
+.grw-custom-nav-tab {
   .nav-title {
     flex-wrap: nowrap;
   }
 
   .nav-link {
     padding: 1rem 1.5rem;
-
-    svg {
-      width: 17px;
-      height: 17px;
-      margin-right: 5px;
-      vertical-align: text-bottom;
-    }
   }
 
   .grw-nav-slide-hr {

+ 3 - 2
src/client/styles/scss/theme/_apply-colors.scss

@@ -100,7 +100,8 @@ pre:not(.hljs):not(.CodeMirror-line) {
   }
 
   &:active,
-  &.active {
+  &.active,
+  &.active:hover {
     color: $color-dropdown-link-active;
     background-color: $bgcolor-dropdown-link-active;
 
@@ -326,7 +327,7 @@ ul.pagination {
   }
 }
 
-.grw-custom-nav {
+.grw-custom-nav-tab {
   .nav-item {
     &:hover,
     &:focus {