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

Merge branch 'dev/4.0.x' into support/reactify-pagemanagement-modal-for-merge

itizawa 5 лет назад
Родитель
Сommit
52f83d2059

+ 2 - 3
src/client/js/bootstrap.jsx

@@ -3,7 +3,7 @@ import React from 'react';
 import loggerFactory from '@alias/logger';
 import Xss from '@commons/service/xss';
 
-import HeaderSearchBox from './components/HeaderSearchBox';
+import SearchTop from './components/Navbar/SearchTop';
 import NavbarToggler from './components/Navbar/NavbarToggler';
 import PersonalDropdown from './components/Navbar/PersonalDropdown';
 import Sidebar from './components/Sidebar';
@@ -41,8 +41,7 @@ appContainer.injectToWindow();
 const componentMappings = {
   'grw-navbar-toggler': <NavbarToggler />,
 
-  'search-top': <HeaderSearchBox />,
-  'search-sidebar': <HeaderSearchBox crowi={appContainer} />,
+  'grw-search-top': <SearchTop />,
   'personal-dropdown': <PersonalDropdown />,
 
   'create-page-button': <PageCreateButton />,

+ 15 - 19
src/client/js/components/Admin/Customize/CustomizeThemeOptions.jsx

@@ -15,29 +15,31 @@ class CustomizeThemeOptions extends React.Component {
     const { t, adminCustomizeContainer } = this.props;
     const { currentLayout, currentTheme } = adminCustomizeContainer.state;
 
+    /* eslint-disable no-multi-spaces */
     const lightNDarkTheme = [{
-      name: 'default', bg: '#ffffff', topbar: '#334455', theme: '#112744',
+      name: 'default',    bg: '#ffffff', topbar: '#2a2929', sidebar: '#122c55', theme: '#209fd8',
     }, {
-      name: 'mono-blue', bg: '#F7FBFD', topbar: '#00587A', theme: '#00587A',
+      name: 'mono-blue',  bg: '#F7FBFD', topbar: '#2a2929', sidebar: '#00587A', theme: '#00587A',
     }];
 
     const uniqueTheme = [{
-      name: 'nature', bg: '#f9fff3', topbar: '#118050', theme: '#460039',
+      name: 'nature',     bg: '#f9fff3', topbar: '#2a2929', sidebar: '#118050', theme: '#460039',
     }, {
-      name: 'wood', bg: '#fffefb', topbar: '#aaa45f', theme: '#dddebf',
+      name: 'wood',       bg: '#fffefb', topbar: '#2a2929', sidebar: '#aaa45f', theme: '#dddebf',
     }, {
-      name: 'island', bg: '#8ecac0', topbar: '#0c2a44', theme: '#cef2ef',
+      name: 'island',     bg: '#8ecac0', topbar: '#2a2929', sidebar: '#0c2a44', theme: '#cef2ef',
     }, {
-      name: 'christmas', bg: '#fffefb', topbar: '#b3000c', theme: '#017e20',
+      name: 'christmas',  bg: '#fffefb', topbar: '#2a2929', sidebar: '#b3000c', theme: '#017e20',
     }, {
-      name: 'antarctic', bg: '#ffffff', topbar: '#000080', theme: '#99cccc',
+      name: 'antarctic',  bg: '#ffffff', topbar: '#2a2929', sidebar: '#000080', theme: '#99cccc',
     }, {
-      name: 'spring', bg: '#fff5ee', topbar: '#ff69b4', theme: '#ffb6c1',
+      name: 'spring',     bg: '#fff5ee', topbar: '#2a2929', sidebar: '#ff69b4', theme: '#ffb6c1',
     }, {
-      name: 'future', bg: '#16282D', topbar: '#011414', theme: '#04B4AE',
+      name: 'future',     bg: '#16282D', topbar: '#2a2929', sidebar: '#011414', theme: '#04B4AE',
     }, {
-      name: 'halloween', bg: '#030003', topbar: '#cc5d1f', theme: '#e9af2b',
+      name: 'halloween',  bg: '#030003', topbar: '#2a2929', sidebar: '#cc5d1f', theme: '#e9af2b',
     }];
+    /* eslint-enable no-multi-spaces */
 
     return (
       <div id="themeOptions" className={`${currentLayout === 'kibela' && 'disabled'}`}>
@@ -51,17 +53,14 @@ class CustomizeThemeOptions extends React.Component {
                   key={theme.name}
                   isSelected={currentTheme === theme.name}
                   onSelected={() => adminCustomizeContainer.switchThemeType(theme.name)}
-                  name={theme.name}
-                  bg={theme.bg}
-                  topbar={theme.topbar}
-                  theme={theme.theme}
+                  {...theme}
                 />
               );
             })}
           </div>
         </div>
         {/* Unique Theme */}
-        <div>
+        <div className="mt-3">
           <h3>{t('admin:customize_setting.theme_desc.unique')}</h3>
           <div className="d-flex flex-wrap">
             {uniqueTheme.map((theme) => {
@@ -70,10 +69,7 @@ class CustomizeThemeOptions extends React.Component {
                   key={theme.name}
                   isSelected={currentTheme === theme.name}
                   onSelected={() => adminCustomizeContainer.switchThemeType(theme.name)}
-                  name={theme.name}
-                  bg={theme.bg}
-                  topbar={theme.topbar}
-                  theme={theme.theme}
+                  {...theme}
                 />
               );
             })}

+ 11 - 10
src/client/js/components/Admin/Customize/ThemeColorBox.jsx

@@ -5,23 +5,23 @@ import PropTypes from 'prop-types';
 class ThemeColorBox extends React.PureComponent {
 
   render() {
-    const { name } = this.props;
+    const {
+      isSelected, onSelected, name, bg, topbar, sidebar, theme,
+    } = this.props;
 
     return (
       <div
         id={`theme-option-${name}`}
-        className={`theme-option-container d-flex flex-column align-items-center ${this.props.isSelected && 'active'}`}
-        onClick={this.props.onSelected}
+        className={`theme-option-container d-flex flex-column align-items-center ${isSelected && 'active'}`}
+        onClick={onSelected}
       >
-        <a
-          className={`m-0 ${name} theme-button`}
-          id={name}
-        >
+        <a id={name} type="button" className={`m-0 ${name} theme-button`}>
           <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" width="64" height="64">
             <g>
-              <path d="M -1 -1 L65 -1 L65 65 L-1 65 L-1 -1 Z" fill={this.props.bg}></path>
-              <path d="M -1 -1 L65 -1 L65 15 L-1 15 L-1 -1 Z" fill={this.props.topbar}></path>
-              <path d="M 44 15 L65 15 L65 65 L44 65 L44 15 Z" fill={this.props.theme}></path>
+              <path d="M -1 -1 L65 -1 L65 65 L-1 65 L-1 -1 Z" fill={bg}></path>
+              <path d="M -1 -1 L65 -1 L65 15 L-1 15 L-1 -1 Z" fill={topbar}></path>
+              <path d="M -1 15 L15 15 L15 65 L-1 65 L-1 15 Z" fill={sidebar}></path>
+              <path d="M 65 45 L65 65 L45 65 L65 45 Z" fill={theme}></path>
             </g>
           </svg>
         </a>
@@ -39,6 +39,7 @@ ThemeColorBox.propTypes = {
   name: PropTypes.string.isRequired,
   bg: PropTypes.string.isRequired,
   topbar: PropTypes.string.isRequired,
+  sidebar: PropTypes.string.isRequired,
   theme: PropTypes.string.isRequired,
 };
 

+ 3 - 13
src/client/js/components/Navbar/GrowiSubNavigation.jsx

@@ -61,7 +61,7 @@ const GrowiSubNavigation = (props) => {
   const isPageForbidden = document.querySelector('#grw-subnav').getAttribute('data-is-forbidden-page') === 'true';
   const { appContainer, pageContainer } = props;
   const {
-    pageId, path, createdAt, creator, updatedAt, revisionAuthor, isHeaderSticky, isSubnavCompact,
+    pageId, path, createdAt, creator, updatedAt, revisionAuthor,
   } = pageContainer.state;
 
   const isPageNotFound = pageId == null;
@@ -77,16 +77,6 @@ const GrowiSubNavigation = (props) => {
   }
 
   const additionalClassNames = ['grw-subnavbar'];
-  const layoutType = appContainer.getConfig().layoutType;
-
-  if (layoutType === 'growi') {
-    if (isHeaderSticky) {
-      additionalClassNames.push('grw-subnavbar-sticky');
-    }
-    if (isSubnavCompact) {
-      additionalClassNames.push('grw-subnavbar-compact');
-    }
-  }
 
   return (
     <div className={`d-flex align-items-center justify-content-between px-3 py-1 ${additionalClassNames.join(' ')}`}>
@@ -116,12 +106,12 @@ const GrowiSubNavigation = (props) => {
         <ul className="authors text-nowrap d-none d-lg-block d-edit-none">
           { creator != null && (
             <li>
-              <PageCreator creator={creator} createdAt={createdAt} isCompactMode={isSubnavCompact} />
+              <PageCreator creator={creator} createdAt={createdAt} />
             </li>
           ) }
           { revisionAuthor != null && (
             <li className="mt-1">
-              <RevisionAuthor revisionAuthor={revisionAuthor} updatedAt={updatedAt} isCompactMode={isSubnavCompact} />
+              <RevisionAuthor revisionAuthor={revisionAuthor} updatedAt={updatedAt} />
             </li>
           ) }
         </ul>

+ 2 - 10
src/client/js/components/Navbar/GrowiSubNavigationForUserPage.jsx

@@ -36,22 +36,14 @@ const GrowiSubNavigationForUserPage = (props) => {
   const pageUser = JSON.parse(document.querySelector('#grw-subnav-for-user-page').getAttribute('data-page-user'));
   const { appContainer, pageContainer } = props;
   const {
-    pageId, path, isHeaderSticky, isSubnavCompact,
+    pageId, path,
   } = pageContainer.state;
 
   const additionalClassNames = ['grw-subnavbar', 'grw-subnavbar-user-page'];
   const layoutType = appContainer.getConfig().layoutType;
 
   if (layoutType === 'growi') {
-    if (isHeaderSticky) {
-      additionalClassNames.push('grw-subnavbar-sticky');
-    }
-    if (isSubnavCompact) {
-      additionalClassNames.push('py-2 grw-subnavbar-compact');
-    }
-    else {
-      additionalClassNames.push('py-3');
-    }
+    additionalClassNames.push('py-3');
   }
 
   return (

+ 42 - 15
src/client/js/components/HeaderSearchBox.jsx → src/client/js/components/Navbar/SearchTop.jsx

@@ -2,13 +2,13 @@ import React from 'react';
 import PropTypes from 'prop-types';
 import { withTranslation } from 'react-i18next';
 
-import { createSubscribedElement } from './UnstatedUtils';
-import AppContainer from '../services/AppContainer';
+import { createSubscribedElement } from '../UnstatedUtils';
+import AppContainer from '../../services/AppContainer';
 
-import SearchForm from './SearchForm';
+import SearchForm from '../SearchForm';
 
 
-class HeaderSearchBox extends React.Component {
+class SearchTop extends React.Component {
 
   constructor(props) {
     super(props);
@@ -16,6 +16,7 @@ class HeaderSearchBox extends React.Component {
     this.state = {
       text: '',
       isScopeChildren: false,
+      isCollapsed: true,
     };
 
     this.onInputChange = this.onInputChange.bind(this);
@@ -24,10 +25,14 @@ class HeaderSearchBox extends React.Component {
     this.search = this.search.bind(this);
   }
 
-  componentDidMount() {
+  componentWillMount() {
+    this.initBreakpointEvents();
   }
 
-  componentWillUnmount() {
+  initBreakpointEvents() {
+    this.props.appContainer.addBreakpointListener('md', (mql) => {
+      this.setState({ isCollapsed: !mql.matches });
+    }, true);
   }
 
   onInputChange(text) {
@@ -56,7 +61,23 @@ class HeaderSearchBox extends React.Component {
     window.location.href = url.href;
   }
 
-  render() {
+  Root = ({ children }) => {
+    const { isCollapsed } = this.state;
+
+    return isCollapsed
+      ? (
+        <div id="grw-search-top-collapse" className="collapse bg-dark p-3">
+          {children}
+        </div>
+      )
+      : (
+        <div className="grw-search-top-fixed position-fixed">
+          {children}
+        </div>
+      );
+  };
+
+  SearchTopForm = () => {
     const { t, appContainer } = this.props;
     const scopeLabel = this.state.isScopeChildren
       ? t('header_search_box.label.This tree')
@@ -94,19 +115,25 @@ class HeaderSearchBox extends React.Component {
     );
   }
 
+  render() {
+    const { Root, SearchTopForm } = this;
+    return (
+      <Root><SearchTopForm /></Root>
+    );
+  }
+
 }
 
+SearchTop.propTypes = {
+  t: PropTypes.func.isRequired, // i18next
+  appContainer: PropTypes.instanceOf(AppContainer).isRequired,
+};
 
 /**
  * Wrapper component for using unstated
  */
-const HeaderSearchBoxWrapper = (props) => {
-  return createSubscribedElement(HeaderSearchBox, props, [AppContainer]);
-};
-
-HeaderSearchBox.propTypes = {
-  t: PropTypes.func.isRequired, // i18next
-  appContainer: PropTypes.instanceOf(AppContainer).isRequired,
+const SearchTopWrapper = (props) => {
+  return createSubscribedElement(SearchTop, props, [AppContainer]);
 };
 
-export default withTranslation()(HeaderSearchBoxWrapper);
+export default withTranslation()(SearchTopWrapper);

+ 25 - 37
src/client/js/components/Sidebar.jsx

@@ -38,44 +38,32 @@ class Sidebar extends React.Component {
   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 });
+    const mdOrAvobeHandler = (mql) => {
+      // sm -> md
+      if (mql.matches) {
+        appContainer.setState({ isDrawerOpened: false });
+        navigationUIController.enableResize();
+
+        // restore width
+        if (this.sidebarWidthCached != null) {
+          navigationUIController.setState({ productNavWidth: this.sidebarWidthCached });
         }
-        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);
-    });
+      }
+      // md -> sm
+      else {
+        // cache width
+        this.sidebarWidthCached = navigationUIController.state.productNavWidth;
+
+        appContainer.setState({ isDrawerOpened: false });
+        navigationUIController.disableResize();
+        navigationUIController.expand();
+
+        // fix width
+        navigationUIController.setState({ productNavWidth: sidebarDefaultWidth });
+      }
+    };
+
+    appContainer.addBreakpointListener('md', mdOrAvobeHandler, true);
   }
 
   backdropClickedHandler = () => {

+ 23 - 1
src/client/js/services/AppContainer.js

@@ -35,6 +35,7 @@ export default class AppContainer extends Container {
       editorMode: null,
       preferDarkModeByMediaQuery: false,
       preferDarkModeByUser: null,
+      breakpoint: 'xs',
       isDrawerOpened: false,
 
       isPageCreateModalShown: false,
@@ -110,7 +111,6 @@ export default class AppContainer extends Container {
   }
 
   init() {
-    // this.initBreakpointEvents();
     this.initColorScheme();
     this.initPlugins();
   }
@@ -235,6 +235,28 @@ export default class AppContainer extends Container {
     return this.componentInstances[id];
   }
 
+  /**
+   *
+   * @param {string} breakpoint id of breakpoint
+   * @param {function} handler event handler for media query
+   * @param {boolean} invokeOnInit invoke handler after the initialization if true
+   */
+  addBreakpointListener(breakpoint, handler, invokeOnInit = false) {
+    document.addEventListener('DOMContentLoaded', () => {
+      // get the value of '--breakpoint-*'
+      const breakpointPixel = parseInt(window.getComputedStyle(document.documentElement).getPropertyValue(`--breakpoint-${breakpoint}`), 10);
+
+      const mediaQuery = window.matchMedia(`(min-width: ${breakpointPixel}px)`);
+
+      // add event listener
+      mediaQuery.addListener(handler);
+      // initialize
+      if (invokeOnInit) {
+        handler(mediaQuery);
+      }
+    });
+  }
+
   getOriginRenderer() {
     return this.originRenderer;
   }

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

@@ -1,8 +1,4 @@
 .admin-page {
-  header.grw-header {
-    height: unset;
-  }
-
   .admin-user-menu {
     .dropdown-menu {
       right: 0;
@@ -168,4 +164,4 @@
 
 .admin-navigation > a + a {
   margin-top: 2px;
-}
+}

+ 0 - 3
src/client/styles/scss/_me.scss

@@ -1,5 +1,2 @@
 .user-settings-page {
-  header.grw-header {
-    height: unset;
-  }
 }

+ 18 - 9
src/client/styles/scss/_search.scss

@@ -18,6 +18,7 @@
 
 .search-typeahead {
   position: relative;
+  width: 100%;
 
   .search-clear {
     position: absolute;
@@ -102,17 +103,25 @@
 
 // layout
 .search-top {
-  .rbt-input.form-control {
-    width: 200px;
-    transition: 0.3s ease-out;
+  .grw-search-top-fixed {
+    // centering on navbar
+    top: $grw-navbar-height / 2;
+    left: 50vw;
+    z-index: $zindex-fixed + 1;
+    transform: translate(-50%, -50%);
 
-    // focus
-    &.focus {
-      width: 300px;
-    }
+    .rbt-input.form-control {
+      width: 200px;
+      transition: 0.3s ease-out;
 
-    @include media-breakpoint-up(md) {
-      width: 300px;
+      // focus
+      &.focus {
+        width: 300px;
+      }
+
+      @include media-breakpoint-up(md) {
+        width: 300px;
+      }
     }
   }
 }

+ 1 - 1
src/client/styles/scss/_sidebar.scss

@@ -51,7 +51,6 @@
   $navbar-total-height: $grw-navbar-height + $grw-navbar-border-width;
   div[class$='-LayoutContainer'] {
     height: calc(100vh - #{$navbar-total-height});
-    margin-top: $navbar-total-height;
   }
   div[class$='-NavigationContainer'] {
     top: $navbar-total-height;
@@ -118,6 +117,7 @@
   }
   div[class$='-ScrollableTransitionGroup'] {
     // remove horizontal line
+    > div,
     > div > div {
       &:before,
       &:after {

+ 0 - 42
src/client/styles/scss/_subnav.scss

@@ -5,48 +5,6 @@ $easeInOutCubic: cubic-bezier(0.65, 0, 0.35, 1);
   transition: all 300ms $easeInOutCubic;
 }
 
-/*
- * layout for sticky
- */
-header.grw-header {
-  top: $grw-navbar-height + $grw-navbar-border-width;
-
-  // Adjust to be on top of the growi subnavigation
-  z-index: $zindex-sticky;
-
-  height: 110px;
-  pointer-events: none; // disable pointer events for sticky
-
-  .grw-subnav {
-    overflow: unset;
-    pointer-events: all; // enable pointer events
-  }
-}
-
-/*
- * Compact Mode Switching
- */
-.grw-subnavbar {
-  &.grw-subnavbar-compact {
-    @extend %transitionForCompactMode;
-
-    h1 {
-      @include variable-font-size(18px);
-      @extend %transitionForCompactMode;
-    }
-  }
-}
-
-/*
- * Sticky Mode Switching
- */
-.grw-subnavbar {
-  &.grw-subnavbar-sticky {
-    // set transition-duration (init -> sticky)
-    transition: all 400ms linear !important;
-  }
-}
-
 /*
  * Styles
  */

+ 0 - 4
src/client/styles/scss/_tag.scss

@@ -1,8 +1,4 @@
 .tags-page {
-  header.grw-header {
-    height: unset;
-  }
-
   .list-tag-count {
     background: rgba(0, 0, 0, 0.08);
   }

+ 0 - 35
src/client/styles/scss/_user.scss

@@ -5,41 +5,6 @@ $easeInOutCubic: cubic-bezier(0.65, 0, 0.35, 1);
   transition: all 300ms $easeInOutCubic;
 }
 
-.grw-header.grw-header-user-page {
-  height: 150px;
-}
-
-/*
- * Compact Mode Switching
- */
-.grw-subnavbar.grw-subnavbar-user-page {
-  &.grw-subnavbar-compact {
-    .grw-user-page-path {
-      margin-bottom: 0;
-      font-size: 14px;
-
-      @extend %transitionForCompactMode;
-    }
-    .picture {
-      width: 62px;
-      height: 62px;
-
-      @extend %transitionForCompactMode;
-    }
-    h1 {
-      font-size: 1.5em;
-      line-height: 30px;
-
-      @extend %transitionForCompactMode;
-    }
-    .users-meta {
-      margin-left: 15px;
-
-      @extend %transitionForCompactMode;
-    }
-  }
-}
-
 /*
  * Styles
  */

+ 4 - 17
src/client/styles/scss/theme/_apply-colors-dark.scss

@@ -1,3 +1,6 @@
+// determine optional variables
+$bgcolor-subnabvar: lighten($bgcolor-global, 3%) !default;
+
 /*
   * Form
   */
@@ -131,24 +134,8 @@ ul.pagination {
 /*
  * GROWI subnavigation
  */
-.admin-page,
-.user-settings-page,
-.tags-page {
-  .grw-header {
-    background-color: rgba(darken($bgcolor-global, 90%), 0.9);
-  }
-}
-
 .grw-subnavbar {
-  background-color: rgba(darken($bgcolor-global, 90%), 1);
-
-  &.grw-subnavbar-sticky {
-    background-color: rgba(darken($bgcolor-global, 90%), 0.9);
-    box-shadow: 0 3px 2px -2px darken($bgcolor-global, 5%);
-  }
-}
-
-.grw-subnavbar-sticky {
+  background-color: $bgcolor-subnabvar;
 }
 
 /*

+ 4 - 14
src/client/styles/scss/theme/_apply-colors-light.scss

@@ -1,3 +1,6 @@
+// determine optional variables
+$bgcolor-subnabvar: darken($bgcolor-global, 3%) !default;
+
 /*
  * Form
  */
@@ -26,21 +29,8 @@
 /*
  * GROWI subnavigation
  */
-.admin-page,
-.user-settings-page,
-.tags-page {
-  .grw-header {
-    background-color: rgba(darken($bgcolor-global, 6%), 0.9);
-  }
-}
-
 .grw-subnavbar {
-  background-color: rgba(darken($bgcolor-global, 5%), 1);
-
-  &.grw-subnavbar-sticky {
-    background-color: rgba(darken($bgcolor-global, 6%), 0.9);
-    box-shadow: 0 3px 2px -2px darken($bgcolor-global, 40%);
-  }
+  background-color: $bgcolor-subnabvar;
 }
 
 /*

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

@@ -64,6 +64,9 @@ html[light] {
   // Sidebar list group
   $bgcolor-sidebar-list-group: #fafbff; // optional
 
+  // Subnavigation
+  // $bgcolor-subnabvar: #fafafa; // optional
+
   // Icon colors
   $color-editor-icons: $color-global;
 
@@ -130,9 +133,9 @@ html[dark] {
   $bgcolor-sidebar-nav-item-active: rgba(#969494, 0.3); // optional
   $text-shadow-sidebar-nav-item-active: 0px 0px 10px #0099ff; // optional
   // Sidebar resize button
-  $color-resize-button: $color-global;
+  $color-resize-button: white;
   $bgcolor-resize-button: $primary;
-  $color-resize-button-hover: $color-global;
+  $color-resize-button-hover: white;
   $bgcolor-resize-button-hover: darken($bgcolor-resize-button, 5%);
   // Sidebar contents
   $bgcolor-sidebar-context: #111d2f;
@@ -140,6 +143,9 @@ html[dark] {
   // Sidebar list group
   $bgcolor-sidebar-list-group: #1c2a3e; // optional
 
+  // Subnavigation
+  $bgcolor-subnabvar: lighten($bgcolor-global, 4%); // optional
+
   // Icon colors
   $color-editor-icons: $color-global;
 

+ 12 - 12
src/client/styles/scss/theme/mono-blue.scss

@@ -35,7 +35,7 @@ html[light] {
 
   // Navbar
   $bgcolor-navbar: #2a2929;
-  $bgcolor-search-top-dropdown: $primary;
+  $bgcolor-search-top-dropdown: $themecolor;
   $border-image-navbar: linear-gradient(to right, #54bafd 0%, #3d98a3 50%, #708b0b 100%);
 
   // Logo colors
@@ -44,7 +44,7 @@ html[light] {
 
   // Sidebar
   $bgcolor-sidebar: $themecolor;
-  $bgcolor-sidebar-nav-item-active: rgba(#000000, 0.37); // optional
+  // $bgcolor-sidebar-nav-item-active: rgba(#, 0.37); // optional
   $text-shadow-sidebar-nav-item-active: 0px 0px 10px #0099ff; // optional
   // Sidebar resize button
   $color-resize-button: $color-reversal;
@@ -53,9 +53,9 @@ html[light] {
   $bgcolor-resize-button-hover: lighten($bgcolor-resize-button, 5%);
   // Sidebar contents
   $color-sidebar-context: $color-global;
-  $bgcolor-sidebar-context: #f4f6fc;
+  $bgcolor-sidebar-context: #f1fcff;
   // Sidebar list group
-  $bgcolor-sidebar-list-group: #fafbff; // optional
+  // $bgcolor-sidebar-list-group: #; // optional
 
   // Icon colors
   $color-editor-icons: $color-global;
@@ -96,12 +96,12 @@ html[light] {
 
 html[dark] {
   // Theme colors
-  $themecolor: #0090c8;
+  $themecolor: #00587a;
   $themedark: #061f2f;
   $accentcolor: #16617d;
   $subthemecolor: #c1f1f0;
 
-  $primary: $themecolor;
+  $primary: #0090c8;
   $dark: #031018;
 
   // Background colors
@@ -130,8 +130,8 @@ html[dark] {
 
   // Navbar
   $bgcolor-navbar: #2a2929;
-  $bgcolor-search-top-dropdown: $primary;
-  $border-image-navbar: linear-gradient(to right, #36c9ff 0%, #36c9ff 33%, #7926ff 66%, #ff2eff 100%);
+  $bgcolor-search-top-dropdown: $themecolor;
+  $border-image-navbar: linear-gradient(to right, #54bafd 0%, #3d98a3 50%, #708b0b 100%);
 
   // Logo colors
   $bgcolor-logo: #13191c;
@@ -140,18 +140,18 @@ html[dark] {
 
   // Sidebar
   $bgcolor-sidebar: $accentcolor;
-  $bgcolor-sidebar-nav-item-active: rgba(#969494, 0.3); // optional
+  // $bgcolor-sidebar-nav-item-active: rgba(#, 0.3); // optional
   $text-shadow-sidebar-nav-item-active: 0px 0px 10px #0099ff; // optional
   // Sidebar resize button
   $color-resize-button: $color-global;
-  $bgcolor-resize-button: $primary;
+  $bgcolor-resize-button: $themecolor;
   $color-resize-button-hover: $color-global;
   $bgcolor-resize-button-hover: darken($bgcolor-resize-button, 5%);
   // Sidebar contents
-  $bgcolor-sidebar-context: #111d2f;
+  $bgcolor-sidebar-context: darken($bgcolor-sidebar, 13%);
   $color-sidebar-context: $color-global;
   // Sidebar list group
-  $bgcolor-sidebar-list-group: #1c2a3e; // optional
+  // $bgcolor-sidebar-list-group: #; // optional
 
   // Icon colors
   $color-editor-icons: $color-global;

+ 1 - 1
src/server/views/layout-growi/base/layout.html

@@ -9,7 +9,7 @@
 {% block layout_main %}
 
 {% block content_header_wrapper %}
-<header class="py-0 position-sticky grw-header">
+<header class="py-0 grw-header">
   {% block content_header %}
   {% endblock %}
 </header>

+ 1 - 1
src/server/views/layout-growi/user_page.html

@@ -6,7 +6,7 @@
 {% endblock %}
 
 {% block content_header_wrapper %}
-  <header class="py-0 position-sticky grw-header grw-header-user-page">
+  <header class="py-0 grw-header grw-header-user-page">
     {% if pageUser %}
       <div id="grw-subnav-for-user-page" class="grw-subnav" data-page-user="{{ pageUser|json }}"></div>
     {% else %}

+ 21 - 16
src/server/views/layout/layout.html

@@ -86,42 +86,47 @@
       </a>
     </div>
 
-    {# Search #}
-    <ul class="navbar-nav grw-navbar-search d-none d-md-block">
-      <li>
-        {% if isSearchServiceConfigured() %}
-        <div class="search-top" role="search" id="search-top"></div>
-        {% endif %}
-      </li>
-    </ul>
-
     {# Navbar Right #}
     <ul class="navbar-nav ml-auto">
       {% if user %}
-      <li id="create-page-button" class="nav-item d-none d-md-block"></li>
-      <li id="personal-dropdown" class="nav-item dropdown dropdown-toggle"></li>
+        <li id="create-page-button" class="nav-item d-none d-md-block"></li>
+        {% if isSearchServiceConfigured() %}
+          <li class="nav-item d-md-none">
+            <a type="button" class="nav-link px-4" data-target="#grw-search-top-collapse" data-toggle="collapse">
+              <i class="icon-magnifier mr-2"></i>
+            </a>
+          </li>
+        {% endif %}
+        <li id="personal-dropdown" class="nav-item dropdown dropdown-toggle"></li>
       {% else %}
-      <li id="login-user" class="nav-item"><a class="nav-link" href="/login">Login</a></li>
+        <li id="login-user" class="nav-item"><a class="nav-link" href="/login">Login</a></li>
       {% endif %}
+
       {% if getConfig('crowi', 'app:confidential') %}
       <li class="nav-item confidential text-light">{{ getConfig('crowi', 'app:confidential') }}</li>
       {% endif %}
     </ul>
 
   </nav>
+
   {% include '../modal/create_page.html' %}
   {% endblock  %} {# layout_head_nav #}
 
   {% block head_warn_breaking_changes %}{% include '../widget/alert_breaking_changes.html' %}{% endblock %}
 
-  <div class="d-flex">
+  <div id="page-wrapper" class="page-wrapper d-flex">
     {# Sidebar #}
     <div id="grw-sidebar-wrapper"></div>
 
-    <div id="page-wrapper" class="flex-grow-1">
+    <div class="flex-grow-1">
       {% block head_warn_alert_siteurl_undefined %}{% include '../widget/alert_siteurl_undefined.html' %}{% endblock %}
-      {% block layout_main %}
-      {% endblock %} {# layout_main #}
+
+      {# Search #}
+      {% if isSearchServiceConfigured() %}
+        <div id="grw-search-top" class="search-top" role="search"></div>
+      {% endif %}
+
+      {% block layout_main %}{% endblock %}
     </div>
   </div>
 

+ 1 - 1
src/server/views/tags.html

@@ -5,7 +5,7 @@
 {% block html_base_css %}tags-page{% endblock %}
 
 {% block layout_main %}
-<header class="py-0 position-sticky grw-header">
+<header class="py-0 grw-header">
   <h1 class="title">{{ t('Tags') }}</h1>
 </header>