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

Merge remote-tracking branch 'origin/dev/4.0.x' into support/apply-bootstrap4

itizawa 6 лет назад
Родитель
Сommit
d175efde2e

+ 1 - 1
src/client/js/bootstrap.jsx

@@ -44,7 +44,7 @@ const componentMappings = {
   'search-sidebar': <HeaderSearchBox crowi={appContainer} />,
   'personal-dropdown': <PersonalDropdown />,
 
-  'grw-sidebar': <Sidebar />,
+  'grw-sidebar-wrapper': <Sidebar />,
 
   'staff-credit': <StaffCredit />,
 };

+ 12 - 3
src/client/js/components/Navbar/NavbarToggler.jsx

@@ -8,13 +8,22 @@ import AppContainer from '../../services/AppContainer';
 
 const NavbarToggler = (props) => {
 
-  // eslint-disable-next-line no-unused-vars
   const { appContainer } = props;
 
+  const clickHandler = () => {
+    appContainer.toggleDrawer();
+  };
+
   return (
-    <button className="navbar-toggler grw-navbar-toggler border-0" type="button" aria-expanded="false" aria-label="Toggle navigation">
+    <a
+      className="nav-link grw-navbar-toggler border-0 waves-effect waves-light"
+      type="button"
+      aria-expanded="false"
+      aria-label="Toggle navigation"
+      onClick={clickHandler}
+    >
       <i className="icon-menu"></i>
-    </button>
+    </a>
   );
 
 };

+ 88 - 38
src/client/js/components/Sidebar.jsx

@@ -10,8 +10,6 @@ import {
   ThemeProvider, modeGenerator,
 } from '@atlaskit/navigation-next';
 
-import Drawer from '@atlaskit/drawer';
-
 import { createSubscribedElement } from './UnstatedUtils';
 import AppContainer from '../services/AppContainer';
 
@@ -19,20 +17,71 @@ import SidebarNav from './Sidebar/SidebarNav';
 import History from './Sidebar/History';
 import CustomSidebar from './Sidebar/CustomSidebar';
 
+
+const sidebarDefaultWidth = 240;
+
 class Sidebar extends React.Component {
 
   static propTypes = {
+    appContainer: PropTypes.instanceOf(AppContainer).isRequired,
     navigationUIController: PropTypes.any.isRequired,
   };
 
   state = {
     currentContentsId: 'custom',
-    isDrawerOpen: false,
   };
 
-  openDrawer = () => this.setState({ isDrawerOpen: true });
+  componentWillMount() {
+    this.initBreakpointEvents();
+  }
 
-  closeDrawer = () => this.setState({ isDrawerOpen: false });
+  initBreakpointEvents() {
+    const { appContainer, navigationUIController } = this.props;
+
+    document.addEventListener('DOMContentLoaded', () => {
+      // get the value of '--breakpoint-*'
+      // const breakpointSm = parseInt(window.getComputedStyle(document.documentElement).getPropertyValue('--breakpoint-sm'), 10);
+      const breakpointMd = parseInt(window.getComputedStyle(document.documentElement).getPropertyValue('--breakpoint-md'), 10);
+
+      const smHandler = (mql) => {
+        if (mql.matches) {
+          // cache width
+          this.sidebarWidthCached = navigationUIController.state.productNavWidth;
+
+          appContainer.setState({ isDrawerOpened: false });
+          navigationUIController.disableResize();
+          navigationUIController.expand();
+
+          // fix width
+          navigationUIController.setState({ productNavWidth: sidebarDefaultWidth });
+        }
+        else {
+          appContainer.setState({ isDrawerOpened: false });
+          navigationUIController.enableResize();
+
+          // restore width
+          if (this.sidebarWidthCached != null) {
+            navigationUIController.setState({ productNavWidth: this.sidebarWidthCached });
+          }
+        }
+      };
+
+      // const mediaQueryForXs = window.matchMedia(`(max-width: ${breakpointSm}px)`);
+      const mediaQueryForSm = window.matchMedia(`(max-width: ${breakpointMd}px)`);
+
+      // add event listener
+      // mediaQueryForXs.addListener(xsHandler);
+      mediaQueryForSm.addListener(smHandler);
+      // initialize
+      // xsHandler(mediaQueryForXs);
+      smHandler(mediaQueryForSm);
+    });
+  }
+
+  backdropClickedHandler = () => {
+    const { appContainer } = this.props;
+    appContainer.setState({ isDrawerOpened: false });
+  }
 
   itemSelectedHandler = (contentsId) => {
     const { navigationUIController } = this.props;
@@ -47,19 +96,10 @@ class Sidebar extends React.Component {
       this.setState({ currentContentsId: contentsId });
       navigationUIController.expand();
     }
-
-    // if (contentsId === 'drawer') {
-    //   this.openDrawer();
-    // }
   }
 
   renderGlobalNavigation = () => (
-    <>
-      <SidebarNav currentContentsId={this.state.currentContentsId} onItemSelected={this.itemSelectedHandler} />
-      <Drawer onClose={this.closeDrawer} isOpen={this.state.isDrawerOpen} width="wide">
-        <code>Drawer contents</code>
-      </Drawer>
-    </>
+    <SidebarNav currentContentsId={this.state.currentContentsId} onItemSelected={this.itemSelectedHandler} />
   );
 
   renderSidebarContents = () => {
@@ -75,30 +115,40 @@ class Sidebar extends React.Component {
   }
 
   render() {
+    const { isDrawerOpened } = this.props.appContainer.state;
+
     return (
-      <ThemeProvider
-        theme={theme => ({
-          ...theme,
-          context: 'product',
-          mode: modeGenerator({
-            product: { text: '#ffffff', background: '#334455' },
-          }),
-        })}
-      >
-        <LayoutManager
-          globalNavigation={this.renderGlobalNavigation}
-          productNavigation={() => null}
-          containerNavigation={this.renderSidebarContents}
-          experimental_hideNavVisuallyOnCollapse
-          experimental_flyoutOnHover
-          experimental_alternateFlyoutBehaviour
-          // experimental_fullWidthFlyout
-          shouldHideGlobalNavShadow
-          showContextualNavigation
-          topOffset={50}
-        >
-        </LayoutManager>
-      </ThemeProvider>
+      <>
+        <div className={`grw-sidebar ${isDrawerOpened ? 'open' : ''}`}>
+          <ThemeProvider
+            theme={theme => ({
+              ...theme,
+              context: 'product',
+              mode: modeGenerator({
+                product: { text: '#ffffff', background: '#334455' },
+              }),
+            })}
+          >
+            <LayoutManager
+              globalNavigation={this.renderGlobalNavigation}
+              productNavigation={() => null}
+              containerNavigation={this.renderSidebarContents}
+              experimental_hideNavVisuallyOnCollapse
+              experimental_flyoutOnHover
+              experimental_alternateFlyoutBehaviour
+              // experimental_fullWidthFlyout
+              shouldHideGlobalNavShadow
+              showContextualNavigation
+              topOffset={50}
+            >
+            </LayoutManager>
+          </ThemeProvider>
+        </div>
+
+        { isDrawerOpened && (
+          <div className="grw-sidebar-backdrop modal-backdrop show" onClick={this.backdropClickedHandler}></div>
+        ) }
+      </>
     );
   }
 

+ 7 - 0
src/client/js/services/AppContainer.js

@@ -33,6 +33,7 @@ export default class AppContainer extends Container {
       editorMode: null,
       preferDarkModeByMediaQuery: false,
       preferDarkModeByUser: null,
+      isDrawerOpened: false,
     };
 
     const body = document.querySelector('body');
@@ -100,6 +101,7 @@ export default class AppContainer extends Container {
   }
 
   init() {
+    // this.initBreakpointEvents();
     this.initColorScheme();
     this.initPlugins();
   }
@@ -323,6 +325,11 @@ export default class AppContainer extends Container {
     return users;
   }
 
+  toggleDrawer() {
+    const { isDrawerOpened } = this.state;
+    this.setState({ isDrawerOpened: !isDrawerOpened });
+  }
+
   launchHandsontableModal(componentKind, beginLineNumber, endLineNumber) {
     let targetComponent;
     switch (componentKind) {

+ 0 - 56
src/client/styles/scss/_layout.scss

@@ -49,66 +49,10 @@
   font-weight: bold;
 }
 
-.grw-sidebar {
-  .ak-navigation-resize-button {
-    top: calc(50vh - 20px);
-  }
-
-  // override @atlaskit/navigation-next styles
-  div[class$='-NavigationContainer'] {
-    // Adjust to be on top of the growi subnavigation
-    z-index: $zindex-sticky + 5;
-  }
-
-  // override @atlaskit/navigation-next styles
-  div[class$='-Outer'] {
-    div[class$='-Shadow'] {
-      background: unset;
-      border-right: 1px solid $border;
-    }
-  }
-
-  .grw-global-item-container {
-    i {
-      font-size: 1.5em;
-    }
-
-    // icon opacity
-    &:not(.active) {
-      i {
-        opacity: 0.4;
-      }
-      &:hover,
-      &:focus {
-        i {
-          opacity: 0.7;
-        }
-      }
-    }
-
-    &.active {
-      button {
-        @extend %fukidashi-for-active;
-      }
-    }
-  }
-}
-
 #page-wrapper {
   margin-top: $grw-navbar-height;
 }
 
-.grw-sidebar-header-container {
-  padding: 10px;
-
-  h3 {
-    margin-bottom: 0;
-  }
-}
-
-.grw-sidebar-content-container {
-}
-
 .grw-modal-head {
   font-size: 1em;
   border-bottom: 1px solid $grw-line-gray;

+ 89 - 0
src/client/styles/scss/_sidebar.scss

@@ -0,0 +1,89 @@
+.grw-sidebar {
+  .ak-navigation-resize-button {
+    top: calc(50vh - 20px);
+  }
+
+  // override @atlaskit/navigation-next styles
+  div[data-testid='GlobalNavigation'] {
+    width: $grw-sidebar-nav-width;
+  }
+  div[class$='-NavigationContainer'] {
+    // Adjust to be on top of the growi subnavigation
+    z-index: $zindex-sticky + 5;
+  }
+  div[class$='-Outer'] {
+    div[class$='-Shadow'] {
+      background: unset;
+      border-right: 1px solid $border;
+    }
+  }
+
+  .grw-global-item-container {
+    i {
+      font-size: 1.5em;
+    }
+
+    // icon opacity
+    &:not(.active) {
+      i {
+        opacity: 0.4;
+      }
+      &:hover,
+      &:focus {
+        i {
+          opacity: 0.7;
+        }
+      }
+    }
+
+    &.active {
+      button {
+        @extend %fukidashi-for-active;
+      }
+    }
+  }
+}
+
+// Drawer Mode
+@include media-breakpoint-down(sm) {
+  .grw-sidebar {
+    position: fixed;
+    z-index: $zindex-fixed - 2;
+
+    // override @atlaskit/navigation-next styles
+    div[class$='-Outer'],
+    div[class$='-teprsg'] {
+      display: none;
+    }
+
+    &:not(.open) {
+      div[class$='-NavigationContainer'] {
+        left: -#{$grw-sidebar-nav-width + $grw-sidebar-content-min-width};
+      }
+    }
+    &.open {
+      div[class$='-NavigationContainer'] {
+        left: 0;
+      }
+    }
+
+    div[class$='-NavigationContainer'] {
+      transition: left 300ms cubic-bezier(0.25, 1, 0.5, 1);
+    }
+  }
+
+  .grw-sidebar-backdrop.modal-backdrop {
+    z-index: $zindex-fixed - 4;
+  }
+}
+
+.grw-sidebar-header-container {
+  padding: 10px;
+
+  h3 {
+    margin-bottom: 0;
+  }
+}
+
+.grw-sidebar-content-container {
+}

+ 5 - 1
src/client/styles/scss/_variables.scss

@@ -6,7 +6,11 @@ $font-family-monospace-not-strictly: Monaco, Menlo, Consolas, 'Courier New', Mei
 
 //== Layout
 $grw-navbar-height: 50px;
-$grw-logo-width: 64px;
+
+$grw-sidebar-nav-width: 64px;
+$grw-sidebar-content-min-width: 240px;
+
+$grw-logo-width: $grw-sidebar-nav-width;
 $grw-logomark-width: 40px;
 
 // fix tab width to 95 pixels

+ 1 - 0
src/client/styles/scss/_vendor.scss

@@ -3,6 +3,7 @@
 @import '~bootstrap/scss/variables';
 @import '~bootstrap/scss/mixins';
 @import '~bootstrap/scss/utilities';
+@import '~bootstrap/scss/root';
 
 // increase specificity with ':root' for GROWI theming
 :root {

+ 1 - 0
src/client/styles/scss/style-app.scss

@@ -50,6 +50,7 @@
 @import 'page';
 @import 'search';
 @import 'shortcuts';
+@import 'sidebar';
 @import 'subnav';
 @import 'tag';
 @import 'user';

+ 0 - 2
src/client/styles/scss/theme/default.scss

@@ -17,7 +17,6 @@
 //
 html[light] {
   $primary: #112744;
-  $light: white;
 
   // Background colors
   $bgcolor-global: white;
@@ -62,7 +61,6 @@ html[light] {
 //
 html[dark] {
   $primary: #d65a31;
-  $light: white;
 
   $basecolor: #222831;
 

+ 7 - 6
src/server/views/layout/layout.html

@@ -74,11 +74,13 @@
 <div id="wrapper">
 
   {% block layout_head_nav %}
-  <nav class="navbar grw-navbar navbar-expand-sm navbar-dark fixed-top mb-0 p-sm-0">
-    <div id="grw-navbar-toggler" class="d-sm-none mr-auto"></div>
+  <nav class="navbar grw-navbar navbar-expand navbar-dark fixed-top mb-0 px-0">
+    <ul class="navbar-nav d-md-none mr-auto">
+      <li id="grw-navbar-toggler" class="nav-item"></li>
+    </ul>
 
     {# Brand Logo #}
-    <div class="navbar-brand mr-sm-auto">
+    <div class="navbar-brand mr-md-auto">
       <a class="grw-logo d-block" href="/">
         {% include '../widget/logo.html' %}
       </a>
@@ -134,9 +136,8 @@
 
   <div class="d-flex">
     {# Sidebar #}
-    <nav class="d-none d-sm-block">
-      <div id="grw-sidebar" class="grw-sidebar"></div>
-    </nav>
+    <div id="grw-sidebar-wrapper"></div>
+
     <div id="page-wrapper" class="flex-grow-1">
       {% block layout_main %}
       {% endblock %} {# layout_main #}