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

Merge branch 'support/apply-bootstrap4' into imprv/edit-table-bs4-replace

ryohek 6 лет назад
Родитель
Сommit
e5ec719a52
30 измененных файлов с 287 добавлено и 140 удалено
  1. 8 0
      resource/cdn-manifests.js
  2. 3 0
      src/client/js/bootstrap.jsx
  3. 15 15
      src/client/js/components/Admin/App/AwsSetting.jsx
  4. 1 1
      src/client/js/components/Admin/App/SiteUrlSetting.jsx
  5. 2 2
      src/client/js/components/Admin/ImportDataPage.jsx
  6. 35 0
      src/client/js/components/Navbar/NavbarToggler.jsx
  7. 1 1
      src/client/js/components/Navbar/PersonalDropdown.jsx
  8. 2 2
      src/client/js/components/PageEditor/OptionsSelector.jsx
  9. 1 1
      src/client/js/components/PageHistory/RevisionDiff.jsx
  10. 1 4
      src/client/js/components/Sidebar.jsx
  11. 36 8
      src/client/js/components/Sidebar/SidebarNav.jsx
  12. 3 3
      src/client/js/services/PageContainer.js
  13. 1 1
      src/client/styles/scss/_admin.scss
  14. 75 1
      src/client/styles/scss/_layout.scss
  15. 0 22
      src/client/styles/scss/_layout_variable.scss
  16. 1 1
      src/client/styles/scss/_me.scss
  17. 1 1
      src/client/styles/scss/_mixins.scss
  18. 5 0
      src/client/styles/scss/_navbar.scss
  19. 0 4
      src/client/styles/scss/_on-edit.scss
  20. 1 1
      src/client/styles/scss/_override-bootstrap-variables.scss
  21. 1 0
      src/client/styles/scss/_page.scss
  22. 8 5
      src/client/styles/scss/_subnav.scss
  23. 1 1
      src/client/styles/scss/_tag.scss
  24. 5 5
      src/client/styles/scss/_user.scss
  25. 2 2
      src/client/styles/scss/_variables.scss
  26. 7 2
      src/client/styles/scss/theme/_apply-colors.scss
  27. 1 1
      src/server/views/layout-growi/base/layout.html
  28. 1 1
      src/server/views/layout-growi/user_page.html
  29. 68 54
      src/server/views/layout/layout.html
  30. 1 1
      src/server/views/tags.html

+ 8 - 0
resource/cdn-manifests.js

@@ -138,6 +138,14 @@ module.exports = {
         integrity: '',
         integrity: '',
       },
       },
     },
     },
+    {
+      name: 'animate.css',
+      url: 'https://cdn.jsdelivr.net/npm/animate.css@3.7.2/animate.min.css',
+      groups: ['basis'],
+      args: {
+        integrity: '',
+      },
+    },
     {
     {
       name: 'jquery-ui',
       name: 'jquery-ui',
       url: 'https://cdn.jsdelivr.net/jquery.ui/1.11.4/jquery-ui.min.css',
       url: 'https://cdn.jsdelivr.net/jquery.ui/1.11.4/jquery-ui.min.css',

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

@@ -4,6 +4,7 @@ import loggerFactory from '@alias/logger';
 import Xss from '@commons/service/xss';
 import Xss from '@commons/service/xss';
 
 
 import HeaderSearchBox from './components/HeaderSearchBox';
 import HeaderSearchBox from './components/HeaderSearchBox';
+import NavbarToggler from './components/Navbar/NavbarToggler';
 import PersonalDropdown from './components/Navbar/PersonalDropdown';
 import PersonalDropdown from './components/Navbar/PersonalDropdown';
 import Sidebar from './components/Sidebar';
 import Sidebar from './components/Sidebar';
 import StaffCredit from './components/StaffCredit/StaffCredit';
 import StaffCredit from './components/StaffCredit/StaffCredit';
@@ -37,6 +38,8 @@ appContainer.injectToWindow();
  *  value: React Element
  *  value: React Element
  */
  */
 const componentMappings = {
 const componentMappings = {
+  'grw-navbar-toggler': <NavbarToggler />,
+
   'search-top': <HeaderSearchBox />,
   'search-top': <HeaderSearchBox />,
   'search-sidebar': <HeaderSearchBox crowi={appContainer} />,
   'search-sidebar': <HeaderSearchBox crowi={appContainer} />,
   'personal-dropdown': <PersonalDropdown />,
   'personal-dropdown': <PersonalDropdown />,

+ 15 - 15
src/client/js/components/Admin/App/AwsSetting.jsx

@@ -50,11 +50,11 @@ class AwsSetting extends React.Component {
           </span>
           </span>
         </p>
         </p>
 
 
-        <div className="row form-group mb-5">
-          <label className="col-3 col-form-label">
+        <div className="row form-group">
+          <label className="text-left text-md-right col-md-3 col-form-label">
             {t('admin:app_setting.region')}
             {t('admin:app_setting.region')}
           </label>
           </label>
-          <div className="col-6">
+          <div className="col-md-6">
             <input
             <input
               className="form-control"
               className="form-control"
               placeholder={`${t('eg')} ap-northeast-1`}
               placeholder={`${t('eg')} ap-northeast-1`}
@@ -66,11 +66,11 @@ class AwsSetting extends React.Component {
           </div>
           </div>
         </div>
         </div>
 
 
-        <div className="row form-group mb-5">
-          <label className="col-3 col-form-label">
+        <div className="row form-group">
+          <label className="text-left text-md-right col-md-3 col-form-label">
             {t('admin:app_setting.custom_endpoint')}
             {t('admin:app_setting.custom_endpoint')}
           </label>
           </label>
-          <div className="col-6">
+          <div className="col-md-6">
             <input
             <input
               className="form-control"
               className="form-control"
               type="text"
               type="text"
@@ -84,11 +84,11 @@ class AwsSetting extends React.Component {
           </div>
           </div>
         </div>
         </div>
 
 
-        <div className="row form-group mb-5">
-          <label className="col-3 col-form-label">
+        <div className="row form-group">
+          <label className="text-left text-md-right col-md-3 col-form-label">
             {t('admin:app_setting.bucket_name')}
             {t('admin:app_setting.bucket_name')}
           </label>
           </label>
-          <div className="col-6">
+          <div className="col-md-6">
             <input
             <input
               className="form-control"
               className="form-control"
               type="text"
               type="text"
@@ -101,11 +101,11 @@ class AwsSetting extends React.Component {
           </div>
           </div>
         </div>
         </div>
 
 
-        <div className="row form-group mb-5">
-          <label className="col-3 col-form-label">
+        <div className="row form-group">
+          <label className="text-left text-md-right col-md-3 col-form-label">
             Access Key ID
             Access Key ID
           </label>
           </label>
-          <div className="col-6">
+          <div className="col-md-6">
             <input
             <input
               className="form-control"
               className="form-control"
               type="text"
               type="text"
@@ -117,11 +117,11 @@ class AwsSetting extends React.Component {
           </div>
           </div>
         </div>
         </div>
 
 
-        <div className="row form-group mb-5">
-          <label className="col-3 col-form-label">
+        <div className="row form-group">
+          <label className="text-left text-md-right col-md-3 col-form-label">
             Secret Access Key
             Secret Access Key
           </label>
           </label>
-          <div className="col-6">
+          <div className="col-md-6">
             <input
             <input
               className="form-control"
               className="form-control"
               type="text"
               type="text"

+ 1 - 1
src/client/js/components/Admin/App/SiteUrlSetting.jsx

@@ -43,7 +43,7 @@ class SiteUrlSetting extends React.Component {
           && (<p className="alert alert-danger"><i className="icon-exclamation"></i> {t('admin:app_setting.site_url_warn')}</p>)}
           && (<p className="alert alert-danger"><i className="icon-exclamation"></i> {t('admin:app_setting.site_url_warn')}</p>)}
 
 
         <div className="row form-group">
         <div className="row form-group">
-          <div className="col-9 offset-3">
+          <div className="col-md-9 offset-md-3">
             <table className="table settings-table">
             <table className="table settings-table">
               <colgroup>
               <colgroup>
                 <col className="from-db" />
                 <col className="from-db" />

+ 2 - 2
src/client/js/components/Admin/ImportDataPage.jsx

@@ -216,7 +216,7 @@ class ImportDataPage extends React.Component {
                     name="Esa"
                     name="Esa"
                     type="button"
                     type="button"
                     id="importFromEsa"
                     id="importFromEsa"
-                    className="btn btn-outline-secondary btn-esa"
+                    className="btn btn-secondary btn-esa"
                     onClick={this.esaHandleSubmitTest}
                     onClick={this.esaHandleSubmitTest}
                     value={t('admin:importer_management.esa_settings.test_connection')}
                     value={t('admin:importer_management.esa_settings.test_connection')}
                   />
                   />
@@ -309,7 +309,7 @@ class ImportDataPage extends React.Component {
                     name="Qiita"
                     name="Qiita"
                     type="button"
                     type="button"
                     id="importFromQiita"
                     id="importFromQiita"
-                    className="btn btn-outline-secondary btn-qiita"
+                    className="btn btn-secondary btn-qiita"
                     onClick={this.qiitaHandleSubmitTest}
                     onClick={this.qiitaHandleSubmitTest}
                     value={t('admin:importer_management.qiita_settings.test_connection')}
                     value={t('admin:importer_management.qiita_settings.test_connection')}
                   />
                   />

+ 35 - 0
src/client/js/components/Navbar/NavbarToggler.jsx

@@ -0,0 +1,35 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+
+import { withTranslation } from 'react-i18next';
+
+import { createSubscribedElement } from '../UnstatedUtils';
+import AppContainer from '../../services/AppContainer';
+
+const NavbarToggler = (props) => {
+
+  // eslint-disable-next-line no-unused-vars
+  const { appContainer } = props;
+
+  return (
+    <button className="navbar-toggler grw-navbar-toggler border-0" type="button" aria-expanded="false" aria-label="Toggle navigation">
+      <i className="icon-menu"></i>
+    </button>
+  );
+
+};
+
+/**
+ * Wrapper component for using unstated
+ */
+const NavbarTogglerWrapper = (props) => {
+  return createSubscribedElement(NavbarToggler, props, [AppContainer]);
+};
+
+
+NavbarToggler.propTypes = {
+  t: PropTypes.func.isRequired, //  i18next
+  appContainer: PropTypes.instanceOf(AppContainer).isRequired,
+};
+
+export default withTranslation()(NavbarTogglerWrapper);

+ 1 - 1
src/client/js/components/Navbar/PersonalDropdown.jsx

@@ -59,7 +59,7 @@ const PersonalDropdown = (props) => {
       {/* remove .dropdown-toggle for hide caret */}
       {/* remove .dropdown-toggle for hide caret */}
       {/* See https://stackoverflow.com/a/44577512/13183572 */}
       {/* See https://stackoverflow.com/a/44577512/13183572 */}
       <a className="nav-link waves-effect waves-light" data-toggle="dropdown">
       <a className="nav-link waves-effect waves-light" data-toggle="dropdown">
-        <UserPicture user={user} withoutLink />&nbsp;{user.name}
+        <UserPicture user={user} withoutLink /><span className="d-none d-sm-inline-block">&nbsp;{user.name}</span>
       </a>
       </a>
 
 
       {/* Menu */}
       {/* Menu */}

+ 2 - 2
src/client/js/components/PageEditor/OptionsSelector.jsx

@@ -110,7 +110,7 @@ class OptionsSelector extends React.Component {
 
 
     return (
     return (
       <div className="my-0 form-group">
       <div className="my-0 form-group">
-        <label>Theme:</label>
+        <label className="mr-2">Theme:</label>
         <div className="btn-group btn-group-sm dropup">
         <div className="btn-group btn-group-sm dropup">
           <button className="btn btn-outline-secondary dropdown-toggle" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
           <button className="btn btn-outline-secondary dropdown-toggle" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
             {selectedTheme}
             {selectedTheme}
@@ -137,7 +137,7 @@ class OptionsSelector extends React.Component {
 
 
     return (
     return (
       <div className="my-0 form-group">
       <div className="my-0 form-group">
-        <label>Keymap:</label>
+        <label className="mr-2">Keymap:</label>
         <div className="btn-group btn-group-sm dropup">
         <div className="btn-group btn-group-sm dropup">
           <button className="btn btn-outline-secondary dropdown-toggle" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
           <button className="btn btn-outline-secondary dropdown-toggle" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
             {selectedKeymapMode}
             {selectedKeymapMode}

+ 1 - 1
src/client/js/components/PageHistory/RevisionDiff.jsx

@@ -39,7 +39,7 @@ export default class RevisionDiff extends React.Component {
 
 
     const diffView = { __html: diffViewHTML };
     const diffView = { __html: diffViewHTML };
     // eslint-disable-next-line react/no-danger
     // eslint-disable-next-line react/no-danger
-    return <div className="revision-history-diff" dangerouslySetInnerHTML={diffView} />;
+    return <div className="revision-history-diff d-table w-100" dangerouslySetInnerHTML={diffView} />;
   }
   }
 
 
 }
 }

+ 1 - 4
src/client/js/components/Sidebar.jsx

@@ -15,7 +15,6 @@ import Drawer from '@atlaskit/drawer';
 import { createSubscribedElement } from './UnstatedUtils';
 import { createSubscribedElement } from './UnstatedUtils';
 import AppContainer from '../services/AppContainer';
 import AppContainer from '../services/AppContainer';
 
 
-import GrowiLogo from './GrowiLogo';
 import SidebarNav from './Sidebar/SidebarNav';
 import SidebarNav from './Sidebar/SidebarNav';
 import History from './Sidebar/History';
 import History from './Sidebar/History';
 import CustomSidebar from './Sidebar/CustomSidebar';
 import CustomSidebar from './Sidebar/CustomSidebar';
@@ -56,9 +55,6 @@ class Sidebar extends React.Component {
 
 
   renderGlobalNavigation = () => (
   renderGlobalNavigation = () => (
     <>
     <>
-      <div className="grw-logo">
-        <a href="/"><GrowiLogo /></a>
-      </div>
       <SidebarNav currentContentsId={this.state.currentContentsId} onItemSelected={this.itemSelectedHandler} />
       <SidebarNav currentContentsId={this.state.currentContentsId} onItemSelected={this.itemSelectedHandler} />
       <Drawer onClose={this.closeDrawer} isOpen={this.state.isDrawerOpen} width="wide">
       <Drawer onClose={this.closeDrawer} isOpen={this.state.isDrawerOpen} width="wide">
         <code>Drawer contents</code>
         <code>Drawer contents</code>
@@ -99,6 +95,7 @@ class Sidebar extends React.Component {
           // experimental_fullWidthFlyout
           // experimental_fullWidthFlyout
           shouldHideGlobalNavShadow
           shouldHideGlobalNavShadow
           showContextualNavigation
           showContextualNavigation
+          topOffset={50}
         >
         >
         </LayoutManager>
         </LayoutManager>
       </ThemeProvider>
       </ThemeProvider>

+ 36 - 8
src/client/js/components/Sidebar/SidebarNav.jsx

@@ -5,6 +5,7 @@ import { withTranslation } from 'react-i18next';
 
 
 import {
 import {
   GlobalNav,
   GlobalNav,
+  GlobalItem,
 } from '@atlaskit/navigation-next';
 } from '@atlaskit/navigation-next';
 
 
 import { createSubscribedElement } from '../UnstatedUtils';
 import { createSubscribedElement } from '../UnstatedUtils';
@@ -28,13 +29,37 @@ class SidebarNav extends React.Component {
     }
     }
   }
   }
 
 
-  generateSidebarItemObj(id, label, icon) {
+  generatePrimaryItemObj(id, label, icon) {
+    const isSelected = this.props.currentContentsId === id;
+
     return {
     return {
       id,
       id,
-      icon,
-      label,
-      isSelected: this.props.currentContentsId === id,
-      onClick: () => this.itemSelectedHandler(id),
+      component: ({ className }) => (
+        <div className={`${className} grw-global-item-container ${isSelected ? 'active' : ''}`}>
+          <GlobalItem
+            icon={icon}
+            label={label}
+            isSelected={isSelected}
+            onClick={() => this.itemSelectedHandler(id)}
+          />
+        </div>
+      ),
+    };
+  }
+
+  generateSecondaryItemObj(id, label, icon, href) {
+    return {
+      id,
+      component: ({ className }) => (
+        <div className={`${className} grw-global-item-container d-block d-md-none`}>
+          <a href={href}>
+            <GlobalItem
+              icon={icon}
+              label={label}
+            />
+          </a>
+        </div>
+      ),
     };
     };
   }
   }
 
 
@@ -46,10 +71,13 @@ class SidebarNav extends React.Component {
     return (
     return (
       <GlobalNav
       <GlobalNav
         primaryItems={[
         primaryItems={[
-          this.generateSidebarItemObj('custom', 'Custom Sidebar', this.generateIconFactory('fa fa-2x fa-code')),
-          this.generateSidebarItemObj('history', 'History', this.generateIconFactory('icon-clock fa-2x')),
+          this.generatePrimaryItemObj('custom', 'Custom Sidebar', this.generateIconFactory('fa fa-code')),
+          this.generatePrimaryItemObj('history', 'History', this.generateIconFactory('icon-clock')),
+        ]}
+        secondaryItems={[
+          this.generateSecondaryItemObj('admin', 'Admin', this.generateIconFactory('icon-settings'), '/admin'),
+          this.generateSecondaryItemObj('help', 'Help', this.generateIconFactory('icon-question'), 'https://docs.growi.org'),
         ]}
         ]}
-        secondaryItems={[]}
       />
       />
     );
     );
   }
   }

+ 3 - 3
src/client/js/services/PageContainer.js

@@ -6,9 +6,9 @@ import * as entities from 'entities';
 import * as toastr from 'toastr';
 import * as toastr from 'toastr';
 
 
 const logger = loggerFactory('growi:services:PageContainer');
 const logger = loggerFactory('growi:services:PageContainer');
-const scrollThresForSticky = 50;
-const scrollThresForCompact = 100;
-const scrollThresForThrottling = 200;
+const scrollThresForSticky = 0;
+const scrollThresForCompact = 30;
+const scrollThresForThrottling = 100;
 
 
 /**
 /**
  * Service container related to Page
  * Service container related to Page

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

@@ -1,5 +1,5 @@
 .admin-page {
 .admin-page {
-  .grw-header.sticky-top {
+  header.grw-header {
     height: unset;
     height: unset;
   }
   }
 
 

+ 75 - 1
src/client/styles/scss/_layout.scss

@@ -1,5 +1,24 @@
 @import 'layout_variable';
 @import 'layout_variable';
 
 
+%fukidashi-for-active {
+  position: relative;
+
+  // speech balloon
+  &:after {
+    position: absolute;
+    top: 0.5em;
+    right: -1em;
+    display: block;
+    width: 0;
+    content: '';
+    border: 1em solid transparent;
+    border-left-width: 0;
+
+    // @include media-breakpoint-down(xs) {
+    // }
+  }
+}
+
 // FIXME: replace with mt-2 or mt-3
 // FIXME: replace with mt-2 or mt-3
 .grw-mt-10px {
 .grw-mt-10px {
   margin-top: 10px !important;
   margin-top: 10px !important;
@@ -32,10 +51,53 @@
 
 
 .grw-sidebar {
 .grw-sidebar {
   .ak-navigation-resize-button {
   .ak-navigation-resize-button {
-    top: 110px;
+    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 {
 .grw-sidebar-header-container {
   padding: 10px;
   padding: 10px;
 
 
@@ -100,6 +162,18 @@
   }
   }
 }
 }
 
 
+.grw-fixed-controls-container {
+  position: fixed;
+  right: 1em;
+  bottom: 3em;
+
+  transition: all 200ms linear;
+
+  .grw-fixed-controls-button-container {
+    box-shadow: 0 3px 4px rgba($black, 0.3);
+  }
+}
+
 // printable style
 // printable style
 @media print {
 @media print {
   padding: 30px;
   padding: 30px;

+ 0 - 22
src/client/styles/scss/_layout_variable.scss

@@ -1,30 +1,8 @@
 /* color variables */
 /* color variables */
 
 
-/* green */
-$grw-base-green: rgb(7, 146, 72);
-$grw-mos-green: rgb(5, 70, 35);
-$grw-light-green: rgb(204, 238, 220);
-$grw-white-green: #f8fffb;
-$grw-sea-green: seagreen;
-
-.bg-grw-green {
-  background: $grw-base-green;
-}
-
-.bg-grw-mos-green {
-  background: $grw-mos-green;
-}
-
-.bg-grw-light-green {
-  background: $grw-light-green;
-}
-
 /* blue */
 /* blue */
 $grw-alice-blue: aliceblue;
 $grw-alice-blue: aliceblue;
 
 
 /* gray */
 /* gray */
 $grw-line-gray: #dee2e6;
 $grw-line-gray: #dee2e6;
 $grw-line-light-gray: #ddd;
 $grw-line-light-gray: #ddd;
-
-/* white */
-$grw-floral-white: floralwhite;

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

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

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

@@ -72,7 +72,7 @@
         .hackmd-preinit,
         .hackmd-preinit,
         .hackmd-error,
         .hackmd-error,
         #iframe-hackmd-container > iframe {
         #iframe-hackmd-container > iframe {
-          width: 100vw;
+          width: 100%;
           height: calc(100vh - #{$header-plus-footer});
           height: calc(100vh - #{$header-plus-footer});
           min-height: calc(100vh - #{$header-plus-footer}); // for IE11
           min-height: calc(100vh - #{$header-plus-footer}); // for IE11
         }
         }

+ 5 - 0
src/client/styles/scss/_navbar.scss

@@ -1,4 +1,9 @@
 .grw-navbar {
 .grw-navbar {
+  .grw-navbar-toggler {
+    padding: 0.5rem;
+    font-size: 1.5em;
+  }
+
   .nav-link,
   .nav-link,
   .nav-item.confidential {
   .nav-item.confidential {
     display: flex;
     display: flex;

+ 0 - 4
src/client/styles/scss/_on-edit.scss

@@ -197,10 +197,6 @@ body.on-edit {
     }
     }
 
 
     #page-editor-options-selector {
     #page-editor-options-selector {
-      label {
-        margin-right: 0.5em;
-      }
-
       .grw-editor-configuration-dropdown {
       .grw-editor-configuration-dropdown {
         .icon-container {
         .icon-container {
           display: inline-block;
           display: inline-block;

+ 1 - 1
src/client/styles/scss/_override-bootstrap-variables.scss

@@ -18,7 +18,7 @@ $dark: #3e4d6c !default;
 //## Font, line-height, and color for body text, headings, and more.
 //## Font, line-height, and color for body text, headings, and more.
 $font-family-sans-serif:  Lato, -apple-system, BlinkMacSystemFont, 'Hiragino Kaku Gothic ProN', Meiryo, sans-serif;
 $font-family-sans-serif:  Lato, -apple-system, BlinkMacSystemFont, 'Hiragino Kaku Gothic ProN', Meiryo, sans-serif;
 $font-family-serif:       Georgia, "Times New Roman", Times, serif;
 $font-family-serif:       Georgia, "Times New Roman", Times, serif;
-$font-family-monospace: Osaka-Mono, 'MS Gothic', Monaco, Menlo, Consolas, 'Courier New', monospace;
+$font-family-monospace: SFMono-Regular, Consolas, Liberation Mono, Menlo, monospace;
 $font-family-base:        $font-family-sans-serif;
 $font-family-base:        $font-family-sans-serif;
 
 
 $font-size-root: 14px;
 $font-size-root: 14px;

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

@@ -70,6 +70,7 @@
       .revision-history-diff {
       .revision-history-diff {
         padding-left: 40px;
         padding-left: 40px;
         color: #333;
         color: #333;
+        table-layout: fixed;
       }
       }
     }
     }
 
 

+ 8 - 5
src/client/styles/scss/_subnav.scss

@@ -1,6 +1,6 @@
 $easeInOutCubic: cubic-bezier(0.65, 0, 0.35, 1);
 $easeInOutCubic: cubic-bezier(0.65, 0, 0.35, 1);
 
 
-@mixin setTransitionForCompactMode() {
+%transitionForCompactMode {
   // set transition-duration (normal -> compact)
   // set transition-duration (normal -> compact)
   transition: all 300ms $easeInOutCubic;
   transition: all 300ms $easeInOutCubic;
 }
 }
@@ -8,9 +8,12 @@ $easeInOutCubic: cubic-bezier(0.65, 0, 0.35, 1);
 /*
 /*
  * layout for sticky
  * layout for sticky
  */
  */
-.grw-header.sticky-top {
+header.grw-header {
+  top: $grw-navbar-height;
+
   // Adjust to be on top of the growi subnavigation
   // Adjust to be on top of the growi subnavigation
-  z-index: $zindex-sticky - 100;
+  z-index: $zindex-sticky;
+
   height: 80px;
   height: 80px;
   pointer-events: none; // disable pointer events for sticky
   pointer-events: none; // disable pointer events for sticky
 
 
@@ -25,11 +28,11 @@ $easeInOutCubic: cubic-bezier(0.65, 0, 0.35, 1);
  */
  */
 .grw-subnavbar {
 .grw-subnavbar {
   &.grw-subnavbar-compact {
   &.grw-subnavbar-compact {
-    @include setTransitionForCompactMode();
+    @extend %transitionForCompactMode;
 
 
     h1 {
     h1 {
       @include variable-font-size(18px);
       @include variable-font-size(18px);
-      @include setTransitionForCompactMode();
+      @extend %transitionForCompactMode;
     }
     }
   }
   }
 }
 }

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

@@ -1,5 +1,5 @@
 .tags-page {
 .tags-page {
-  .grw-header.sticky-top {
+  header.grw-header {
     height: unset;
     height: unset;
   }
   }
 
 

+ 5 - 5
src/client/styles/scss/_user.scss

@@ -1,6 +1,6 @@
 $easeInOutCubic: cubic-bezier(0.65, 0, 0.35, 1);
 $easeInOutCubic: cubic-bezier(0.65, 0, 0.35, 1);
 
 
-@mixin setTransitionForCompactMode() {
+%transitionForCompactMode {
   // set transition-duration (normal -> compact)
   // set transition-duration (normal -> compact)
   transition: all 300ms $easeInOutCubic;
   transition: all 300ms $easeInOutCubic;
 }
 }
@@ -18,24 +18,24 @@ $easeInOutCubic: cubic-bezier(0.65, 0, 0.35, 1);
       margin-bottom: 0;
       margin-bottom: 0;
       font-size: 14px;
       font-size: 14px;
 
 
-      @include setTransitionForCompactMode();
+      @extend %transitionForCompactMode;
     }
     }
     .picture {
     .picture {
       width: 62px;
       width: 62px;
       height: 62px;
       height: 62px;
 
 
-      @include setTransitionForCompactMode();
+      @extend %transitionForCompactMode;
     }
     }
     h1 {
     h1 {
       font-size: 1.5em;
       font-size: 1.5em;
       line-height: 30px;
       line-height: 30px;
 
 
-      @include setTransitionForCompactMode();
+      @extend %transitionForCompactMode;
     }
     }
     .users-meta {
     .users-meta {
       margin-left: 15px;
       margin-left: 15px;
 
 
-      @include setTransitionForCompactMode();
+      @extend %transitionForCompactMode;
     }
     }
   }
   }
 }
 }

+ 2 - 2
src/client/styles/scss/_variables.scss

@@ -6,8 +6,8 @@ $font-family-monospace-not-strictly: Monaco, Menlo, Consolas, 'Courier New', Mei
 
 
 //== Layout
 //== Layout
 $grw-navbar-height: 50px;
 $grw-navbar-height: 50px;
-$grw-logo-width: 60px;
-$grw-logomark-width: 32px;
+$grw-logo-width: 64px;
+$grw-logomark-width: 40px;
 
 
 // fix tab width to 95 pixels
 // fix tab width to 95 pixels
 // see also '_on-edit.scss'
 // see also '_on-edit.scss'

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

@@ -56,6 +56,8 @@ $link-hover-color: $color-link-hover;
 //
 //
 
 
 .grw-logo {
 .grw-logo {
+  background-color: darken($bgcolor-navbar, 10%);
+
   // set transition for fill
   // set transition for fill
   svg * {
   svg * {
     transition: fill 0.8s ease-out;
     transition: fill 0.8s ease-out;
@@ -86,8 +88,11 @@ $link-hover-color: $color-link-hover;
 }
 }
 
 
 .grw-sidebar {
 .grw-sidebar {
-  .grw-logo {
-    background-color: darken($bgcolor-navbar, 10%);
+  .grw-global-item-container.active {
+    button:after {
+      // fukidashi color
+      border-right-color: darken($bgcolor-global, 4%);
+    }
   }
   }
 }
 }
 
 

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

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

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

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

+ 68 - 54
src/server/views/layout/layout.html

@@ -71,74 +71,88 @@
   data-userlang="{% if user %}{{ user.lang }}{% endif %}"
   data-userlang="{% if user %}{{ user.lang }}{% endif %}"
  >
  >
 
 
-<div id="wrapper" class="d-flex">
+<div id="wrapper">
 
 
-  {# Sidebar #}
-  <nav>
-    <div id="grw-sidebar" class="grw-sidebar"></div>
-  </nav>
+  {% 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>
 
 
-  <div class="flex-grow-1">
-
-    {% block layout_head_nav %}
-    <nav class="navbar grw-navbar navbar-expand-sm navbar-dark mb-0 p-0">
-      {# Navbar Left #}
-      <ul class="navbar-nav mr-auto pl-4">
-        <li>
-          {% if isSearchServiceConfigured() %}
-          <div class="navbar-form navbar-left search-top" role="search" id="search-top"></div>
-          {% endif %}
-        </li>
-      </ul>
-
-      {# Navbar Right #}
-      <ul class="navbar-nav">
-        {% if user and user.admin %}
-        <li class="nav-item">
-          <a class="nav-link" href="/admin">
-            <i class="icon-settings mr-2"></i>
-            <span class="d-none d-md-inline-block">{{ t('Admin') }}</span>
-          </a>
-        </li>
-        {% endif %}
+    {# Brand Logo #}
+    <div class="navbar-brand mr-sm-auto">
+      <a class="grw-logo d-block" href="/">
+        {% include '../widget/logo.html' %}
+      </a>
+    </div>
 
 
-        {% if user %}
-        <li class="nav-item">
-          <a class="nav-link create-page" href="#" data-target="#create-page" data-toggle="modal">
-            <i class="icon-pencil mr-2"></i>
-            <span class="d-none d-md-inline-block">{{ t('New') }}</span>
-          </a>
-        </li>
-        <li class="nav-item">
-          <a class="nav-link" href="https://docs.growi.org/" target="_blank">
-            <i class="icon-question mr-2"></i><span class="d-none d-md-inline-block mr-2">{{ t('Help') }}</span><span class="text-muted small"><i class="icon-share-alt"></i></span>
-          </a>
-        </li>
-        <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>
+    {# Navbar Center #}
+    <ul class="navbar-nav d-none d-md-block">
+      <li>
+        {% if isSearchServiceConfigured() %}
+        <div class="search-top" role="search" id="search-top"></div>
         {% endif %}
         {% endif %}
-        {% if getConfig('crowi', 'app:confidential') %}
-        <li class="nav-item confidential text-light">{{ getConfig('crowi', 'app:confidential') }}</li>
-        {% endif %}
-      </ul>
+      </li>
+    </ul>
+
+    {# Navbar Right #}
+    <ul class="navbar-nav ml-auto">
+      {% if user and user.admin %}
+      <li class="nav-item d-none d-md-block">
+        <a class="nav-link" href="/admin">
+          <i class="icon-settings mr-2"></i>
+          {{ t('Admin') }}
+        </a>
+      </li>
+      {% endif %}
+
+      {% if user %}
+      <li class="nav-item d-none d-md-block">
+        <a class="nav-link create-page" href="#" data-target="#create-page" data-toggle="modal">
+          <i class="icon-pencil mr-2"></i>
+          {{ t('New') }}
+        </a>
+      </li>
+      <li class="nav-item d-none d-md-block">
+        <a class="nav-link" href="https://docs.growi.org/" target="_blank">
+          <i class="icon-question mr-2"></i><span class="mr-2">{{ t('Help') }}</span><span class="small"><i class="icon-share-alt"></i></span>
+        </a>
+      </li>
+      <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>
+      {% 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 #}
+  </nav>
+  {% include '../modal/create_page.html' %}
+  {% endblock  %} {# layout_head_nav #}
 
 
-    {% block head_warn_alert_siteurl_undefined %}{% include '../widget/alert_siteurl_undefined.html' %}{% endblock %}
-    {% block head_warn_breaking_changes %}{% include '../widget/alert_breaking_changes.html' %}{% endblock %}
+  {% block head_warn_alert_siteurl_undefined %}{% include '../widget/alert_siteurl_undefined.html' %}{% endblock %}
+  {% block head_warn_breaking_changes %}{% include '../widget/alert_breaking_changes.html' %}{% endblock %}
 
 
-    <div id="page-wrapper">
+  <div class="d-flex">
+    {# Sidebar #}
+    <nav class="d-none d-sm-block">
+      <div id="grw-sidebar" class="grw-sidebar"></div>
+    </nav>
+    <div id="page-wrapper" class="flex-grow-1">
       {% block layout_main %}
       {% block layout_main %}
       {% endblock %} {# layout_main #}
       {% endblock %} {# layout_main #}
     </div>
     </div>
-
   </div>
   </div>
 
 
 </div><!-- /#wrapper -->
 </div><!-- /#wrapper -->
 
 
+<div class="grw-fixed-controls-container d-md-none animated fadeInUp faster">
+  <div class="grw-fixed-controls-button-container rounded-circle">
+    <button class="btn btn-lg btn-primary rounded-circle waves-effect waves-light" type="button" data-target="#create-page" data-toggle="modal">
+      <i class="icon-pencil"></i>
+    </button>
+  </div>
+</div>
+
 <!-- /#staff-credit -->
 <!-- /#staff-credit -->
 <div id="staff-credit"></div>
 <div id="staff-credit"></div>
 
 

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

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