Procházet zdrojové kódy

Merge pull request #1839 from weseek/imprv/fix-subnavigation

Imprv/fix subnavigation
Ryohei Kawahara před 6 roky
rodič
revize
c1135125a7

+ 12 - 5
src/client/js/components/Navbar/GrowiSubNavigation.jsx

@@ -18,8 +18,9 @@ const GrowiSubNavigation = (props) => {
   const isPageForbidden = document.querySelector('#grw-subnav').getAttribute('data-is-forbidden-page');
   const { appContainer, pageContainer } = props;
   const {
-    pageId, path, createdAt, creator, updatedAt, revisionAuthor,
+    pageId, path, createdAt, creator, updatedAt, revisionAuthor, isCompactMode,
   } = pageContainer.state;
+  const compactClassName = isCompactMode ? 'fixed-top grw-compact-subnavbar px-3' : null;
 
   // Display only the RevisionPath if the page is trash or forbidden
   if (isTrashPage(path) || isPageForbidden) {
@@ -35,7 +36,7 @@ const GrowiSubNavigation = (props) => {
   }
 
   return (
-    <div className="d-flex align-items-center">
+    <div className={`d-flex align-items-center ${compactClassName}`}>
 
       {/* Page Path */}
       <div className="title-container mr-auto">
@@ -54,9 +55,15 @@ const GrowiSubNavigation = (props) => {
       </div>
 
       {/* Page Authors */}
-      <ul className="authors hidden-sm hidden-xs text-nowrap">
-        {creator != null && <li><PageCreator creator={creator} createdAt={createdAt} /></li>}
-        {revisionAuthor != null && <li className="mt-1"><RevisionAuthor revisionAuthor={revisionAuthor} updatedAt={updatedAt} /></li>}
+      <ul className="authors text-nowrap d-none d-lg-block">
+        {creator != null && <li><PageCreator creator={creator} createdAt={createdAt} isCompactMode={isCompactMode} /></li>}
+        { revisionAuthor != null
+          && (
+            <li className="mt-1">
+              <RevisionAuthor revisionAuthor={revisionAuthor} updatedAt={updatedAt} isCompactMode={isCompactMode} />
+            </li>
+          )
+        }
       </ul>
 
     </div>

+ 12 - 6
src/client/js/components/Navbar/PageCreator.jsx

@@ -5,17 +5,18 @@ import UserPicture from '../User/UserPicture';
 import { userPageRoot } from '../../../../lib/util/path-utils';
 
 const PageCreator = (props) => {
-  const { creator, createdAt } = props;
+  const { creator, createdAt, isCompactMode } = props;
+  const creatInfo = isCompactMode
+    ? (<div>Created in <span className="text-muted">{createdAt}</span></div>)
+    : (<div><div>Created by <a href={userPageRoot(creator)}>{creator.name}</a></div><div className="text-muted">{createdAt}</div></div>);
+  const pictureSize = isCompactMode ? 'xs' : 'sm';
 
   return (
     <div className="d-flex align-items-center">
       <div className="mr-2" href={userPageRoot(creator)} data-toggle="tooltip" data-placement="bottom" title={creator.name}>
-        <UserPicture user={creator} size="sm" />
-      </div>
-      <div>
-        <div>Created by <a href={userPageRoot(creator)}>{creator.name}</a></div>
-        <div className="text-muted">{createdAt}</div>
+        <UserPicture user={creator} size={pictureSize} />
       </div>
+      {creatInfo}
     </div>
   );
 };
@@ -24,6 +25,11 @@ PageCreator.propTypes = {
 
   creator: PropTypes.object.isRequired,
   createdAt: PropTypes.string.isRequired,
+  isCompactMode: PropTypes.bool,
+};
+
+PageCreator.defaultProps = {
+  isCompactMode: false,
 };
 
 

+ 11 - 6
src/client/js/components/Navbar/RevisionAuthor.jsx

@@ -5,17 +5,18 @@ import UserPicture from '../User/UserPicture';
 import { userPageRoot } from '../../../../lib/util/path-utils';
 
 const RevisionAuthor = (props) => {
-  const { revisionAuthor, updatedAt } = props;
+  const { revisionAuthor, updatedAt, isCompactMode } = props;
+  const updateInfo = isCompactMode
+    ? (<div>Updated in <span className="text-muted">{updatedAt}</span></div>)
+    : (<div><div>Updated in  <a href={userPageRoot(revisionAuthor)}>{revisionAuthor.name}</a></div><div className="text-muted">{updatedAt}</div></div>);
+  const pictureSize = isCompactMode ? 'xs' : 'sm';
 
   return (
     <div className="d-flex align-items-center">
       <div className="mr-2" href={userPageRoot(revisionAuthor)} data-toggle="tooltip" data-placement="bottom" title={revisionAuthor.name}>
-        <UserPicture user={revisionAuthor} size="sm" />
-      </div>
-      <div>
-        <div>Updated by  <a href={userPageRoot(revisionAuthor)}>{revisionAuthor.name}</a></div>
-        <div className="text-muted">{updatedAt}</div>
+        <UserPicture user={revisionAuthor} size={pictureSize} />
       </div>
+      {updateInfo}
     </div>
   );
 };
@@ -24,7 +25,11 @@ RevisionAuthor.propTypes = {
 
   revisionAuthor: PropTypes.object.isRequired,
   updatedAt: PropTypes.string.isRequired,
+  isCompactMode: PropTypes.bool,
 };
 
+RevisionAuthor.defaultProps = {
+  isCompactMode: false,
+};
 
 export default RevisionAuthor;

+ 1 - 1
src/client/js/components/Page/RevisionPath.jsx

@@ -152,7 +152,7 @@ class RevisionPath extends React.Component {
     });
 
     return (
-      <span className="d-flex align-items-center">
+      <span className="d-flex align-items-center flex-wrap">
 
         {rootElement}
         {afterElements}

+ 8 - 0
src/client/js/services/PageContainer.js

@@ -5,7 +5,10 @@ import loggerFactory from '@alias/logger';
 import * as entities from 'entities';
 import * as toastr from 'toastr';
 
+import { throttle } from 'throttle-debounce';
+
 const logger = loggerFactory('growi:services:PageContainer');
+const scrollAmountForFixed = 122;
 
 /**
  * Service container related to Page
@@ -55,6 +58,7 @@ export default class PageContainer extends Container {
       pageIdOnHackmd: mainContent.getAttribute('data-page-id-on-hackmd') || null,
       hasDraftOnHackmd: !!mainContent.getAttribute('data-page-has-draft-on-hackmd'),
       isHackmdDraftUpdatingInRealtime: false,
+      isCompactMode: false,
     };
 
     this.initStateMarkdown();
@@ -64,6 +68,10 @@ export default class PageContainer extends Container {
     this.save = this.save.bind(this);
     this.addWebSocketEventHandlers = this.addWebSocketEventHandlers.bind(this);
     this.addWebSocketEventHandlers();
+
+    window.addEventListener('scroll', throttle(300, () => {
+      this.setState({ isCompactMode: window.pageYOffset > scrollAmountForFixed });
+    }));
   }
 
   /**

+ 15 - 0
src/client/styles/scss/_page_growi.scss

@@ -20,5 +20,20 @@
         }
       }
     }
+    .grw-compact-subnavbar {
+      h2 {
+        font-size: 20px;
+        line-height: 1.1em;
+        @include media-breakpoint-down(md) {
+          font-size: 18px;
+        }
+        @include media-breakpoint-down(sm) {
+          font-size: 14px;
+        }
+        @include media-breakpoint-down(xs) {
+          font-size: 12px;
+        }
+      }
+    }
   }
 }

+ 8 - 0
src/client/styles/scss/theme/_apply-colors-dark.scss

@@ -136,6 +136,14 @@ header.affix {
   }
 }
 
+/*
+ * GROWI subnavigation
+ */
+.grw-compact-subnavbar {
+  background-color: rgba(darken($bgcolor-global, 90%), 0.9);
+  box-shadow: 0 0 2px darken($bgcolor-global, 5%);
+}
+
 /*
  * GROWI search page
  */

+ 8 - 0
src/client/styles/scss/theme/_apply-colors-light.scss

@@ -32,6 +32,14 @@ header.affix {
   }
 }
 
+/*
+ * GROWI subnavigation
+ */
+.grw-compact-subnavbar {
+  background-color: rgba(darken($bgcolor-global, 6%), 0.9);
+  box-shadow: 0 0 2px darken($bgcolor-global, 40%);
+}
+
 /*
  * GROWI page list
  */

+ 1 - 1
src/client/styles/scss/theme/_apply-colors.scss

@@ -317,4 +317,4 @@ body.on-edit {
       }
     }
   }
-}
+}