Web: Common/Components: Added Hide Header on Scroll Down & Show on Scroll Up
This commit is contained in:
parent
aca906db56
commit
5c89eabc81
@ -1,5 +1,8 @@
|
|||||||
import { createContext } from 'react'
|
import { createContext } from 'react'
|
||||||
|
|
||||||
const ThemeContext = createContext({})
|
const RefContext = createContext({})
|
||||||
export const ThemeContextProvider = ThemeContext.Provider
|
const IsVisibleContext = createContext();
|
||||||
export const ThemeContextConsumer = ThemeContext.Consumer
|
export const RefContextProvider = RefContext.Provider
|
||||||
|
export const IsVisibleContextProvider = IsVisibleContext.Provider
|
||||||
|
export const RefContextConsumer = RefContext.Consumer
|
||||||
|
export const IsVisibleContextConsumer = IsVisibleContext.Consumer
|
@ -3,7 +3,7 @@ import React, { Component, createRef} from "react"
|
|||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
import { Scrollbar } from "asc-web-components";
|
import { Scrollbar } from "asc-web-components";
|
||||||
import { isMobile } from "react-device-detect";
|
import { isMobile } from "react-device-detect";
|
||||||
import {ThemeContextProvider} from "./context"
|
import {RefContextProvider, IsVisibleContextProvider} from "./context"
|
||||||
|
|
||||||
const StyledContainer = styled.div`
|
const StyledContainer = styled.div`
|
||||||
width:100%;
|
width:100%;
|
||||||
@ -12,11 +12,33 @@ height:100vh;
|
|||||||
class Layout extends Component{
|
class Layout extends Component{
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
|
this.state = {
|
||||||
|
|
||||||
|
prevScrollPosition: window.pageYOffset ,
|
||||||
|
visibleContent: true
|
||||||
|
};
|
||||||
this.scrollRefPage = createRef();
|
this.scrollRefPage = createRef();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
isMobile && document.getElementById("scroll").addEventListener("scroll", this.scrolledTheVerticalAxis,false);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
componentWillUnmount() {
|
||||||
|
isMobile && document.getElementById("scroll").removeEventListener("scroll", this.scrolledTheVerticalAxis,false);
|
||||||
|
}
|
||||||
|
|
||||||
|
scrolledTheVerticalAxis = () => {
|
||||||
|
const { prevScrollPosition } = this.state;
|
||||||
|
const currentScrollPosition = document.getElementById("scroll").scrollTop || window.pageYOffset ;
|
||||||
|
const visibleContent = prevScrollPosition > currentScrollPosition;
|
||||||
|
this.setState({
|
||||||
|
prevScrollPosition: currentScrollPosition,
|
||||||
|
visibleContent
|
||||||
|
});
|
||||||
|
};
|
||||||
render() {
|
render() {
|
||||||
const scrollProp = { ref: this.scrollRefPage } ;
|
const scrollProp = { ref: this.scrollRefPage } ;
|
||||||
const { children } = this.props
|
const { children } = this.props
|
||||||
@ -25,9 +47,11 @@ class Layout extends Component{
|
|||||||
<StyledContainer className="Layout">
|
<StyledContainer className="Layout">
|
||||||
{ isMobile
|
{ isMobile
|
||||||
? <Scrollbar {...scrollProp} stype="mediumBlack">
|
? <Scrollbar {...scrollProp} stype="mediumBlack">
|
||||||
<ThemeContextProvider value={this.scrollRefPage}>
|
<RefContextProvider value={this.scrollRefPage}>
|
||||||
{ children }
|
<IsVisibleContextProvider value={this.state.visibleContent}>
|
||||||
</ThemeContextProvider>
|
{ children }
|
||||||
|
</IsVisibleContextProvider>
|
||||||
|
</RefContextProvider>
|
||||||
</Scrollbar>
|
</Scrollbar>
|
||||||
|
|
||||||
: children
|
: children
|
||||||
|
@ -1,28 +1,16 @@
|
|||||||
import React, { useEffect } from "react";
|
import React, { useEffect } from "react";
|
||||||
import PropTypes from "prop-types";
|
import PropTypes from "prop-types";
|
||||||
import { Backdrop, Toast, Aside, utils } from "asc-web-components";
|
import { Backdrop, Toast, Aside} from "asc-web-components";
|
||||||
import Header from "./sub-components/header";
|
import Header from "./sub-components/header";
|
||||||
import HeaderNav from "./sub-components/header-nav";
|
import HeaderNav from "./sub-components/header-nav";
|
||||||
import HeaderUnAuth from "./sub-components/header-unauth";
|
import HeaderUnAuth from "./sub-components/header-unauth";
|
||||||
import styled from "styled-components"
|
|
||||||
import { I18nextProvider, withTranslation } from "react-i18next";
|
import { I18nextProvider, withTranslation } from "react-i18next";
|
||||||
import i18n from "./i18n";
|
import i18n from "./i18n";
|
||||||
import { connect } from "react-redux";
|
import { connect } from "react-redux";
|
||||||
|
|
||||||
import { withRouter } from "react-router";
|
import { withRouter } from "react-router";
|
||||||
|
|
||||||
import { getLanguage } from "../../store/auth/selectors";
|
import { getLanguage } from "../../store/auth/selectors";
|
||||||
const { tablet } = utils.device;
|
|
||||||
|
|
||||||
const StyledHideAndShow = styled.div`
|
|
||||||
@media ${tablet} {
|
|
||||||
top: 0px;
|
|
||||||
transition: top 0.3s;
|
|
||||||
z-index:100;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
`
|
|
||||||
class NavMenu extends React.Component {
|
class NavMenu extends React.Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
@ -112,7 +100,7 @@ class NavMenu extends React.Component {
|
|||||||
<Toast />
|
<Toast />
|
||||||
|
|
||||||
<Backdrop visible={isBackdropVisible} onClick={this.backdropClick} />
|
<Backdrop visible={isBackdropVisible} onClick={this.backdropClick} />
|
||||||
<StyledHideAndShow id="scroll">
|
|
||||||
<HeaderNav />
|
<HeaderNav />
|
||||||
|
|
||||||
{!isAuthenticated && isLoaded ? (
|
{!isAuthenticated && isLoaded ? (
|
||||||
@ -126,13 +114,13 @@ class NavMenu extends React.Component {
|
|||||||
toggleAside={this.toggleAside}
|
toggleAside={this.toggleAside}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</StyledHideAndShow>
|
|
||||||
{isAsideAvailable && (
|
{isAsideAvailable && (
|
||||||
<Aside visible={isAsideVisible} onClick={this.backdropClick}>
|
<Aside visible={isAsideVisible} onClick={this.backdropClick}>
|
||||||
{asideContent}
|
{asideContent}
|
||||||
</Aside>
|
</Aside>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ import NavItem from "./nav-item";
|
|||||||
import ProfileActions from "./profile-actions";
|
import ProfileActions from "./profile-actions";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { utils } from "asc-web-components";
|
import { utils } from "asc-web-components";
|
||||||
|
import {IsVisibleContextConsumer} from "asc-web-common"
|
||||||
const { tablet } = utils.device;
|
const { tablet } = utils.device;
|
||||||
import { logout } from "../../../store/auth/actions";
|
import { logout } from "../../../store/auth/actions";
|
||||||
|
|
||||||
@ -24,9 +25,6 @@ const StyledNav = styled.nav`
|
|||||||
height: 56px;
|
height: 56px;
|
||||||
z-index: 190;
|
z-index: 190;
|
||||||
|
|
||||||
@media ${tablet} {
|
|
||||||
position:fixed;
|
|
||||||
}
|
|
||||||
|
|
||||||
.profile-menu {
|
.profile-menu {
|
||||||
right: 12px;
|
right: 12px;
|
||||||
@ -41,11 +39,18 @@ const StyledNav = styled.nav`
|
|||||||
margin: 0 0 0 16px;
|
margin: 0 0 0 16px;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
min-width: 24px;
|
min-width: 24px;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@media ${tablet} {
|
@media ${tablet} {
|
||||||
padding: 0 16px;
|
padding: 0 16px;
|
||||||
|
position:fixed;
|
||||||
|
transition: top 0.3s;
|
||||||
|
top: ${props => props.valueTop ? "0" : "-56px"}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
`;
|
`;
|
||||||
const HeaderNav = React.memo(
|
const HeaderNav = React.memo(
|
||||||
({ history, homepage, modules, user, logout, isAuthenticated }) => {
|
({ history, homepage, modules, user, logout, isAuthenticated }) => {
|
||||||
@ -89,8 +94,11 @@ const HeaderNav = React.memo(
|
|||||||
|
|
||||||
//console.log("HeaderNav render");
|
//console.log("HeaderNav render");
|
||||||
return (
|
return (
|
||||||
<StyledNav>
|
<IsVisibleContextConsumer>
|
||||||
|
{value =>
|
||||||
|
<StyledNav valueTop={value}>
|
||||||
{modules.map((module) => (
|
{modules.map((module) => (
|
||||||
|
|
||||||
<NavItem
|
<NavItem
|
||||||
key={module.id}
|
key={module.id}
|
||||||
iconName={module.iconName}
|
iconName={module.iconName}
|
||||||
@ -105,6 +113,8 @@ const HeaderNav = React.memo(
|
|||||||
<ProfileActions userActions={getCurrentUserActions()} user={user} />
|
<ProfileActions userActions={getCurrentUserActions()} user={user} />
|
||||||
)}
|
)}
|
||||||
</StyledNav>
|
</StyledNav>
|
||||||
|
}
|
||||||
|
</IsVisibleContextConsumer>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -5,7 +5,7 @@ import NavItem from "./nav-item";
|
|||||||
import Headline from "../../Headline";
|
import Headline from "../../Headline";
|
||||||
import Nav from "./nav";
|
import Nav from "./nav";
|
||||||
import NavLogoItem from "./nav-logo-item";
|
import NavLogoItem from "./nav-logo-item";
|
||||||
|
import {IsVisibleContextConsumer} from "asc-web-common"
|
||||||
import { utils } from "asc-web-components";
|
import { utils } from "asc-web-components";
|
||||||
import { connect } from "react-redux";
|
import { connect } from "react-redux";
|
||||||
import {
|
import {
|
||||||
@ -31,7 +31,11 @@ const Header = styled.header`
|
|||||||
@media ${tablet} {
|
@media ${tablet} {
|
||||||
position:fixed;
|
position:fixed;
|
||||||
z-index:100;
|
z-index:100;
|
||||||
|
transition: top 0.3s;
|
||||||
|
top: ${props => props.valueTop ? "0" : "-56px"}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.header-logo-wrapper {
|
.header-logo-wrapper {
|
||||||
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
|
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
|
||||||
}
|
}
|
||||||
@ -106,7 +110,9 @@ const HeaderComponent = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Header module={currentProductName}>
|
<IsVisibleContextConsumer>
|
||||||
|
{value =>
|
||||||
|
<Header module={currentProductName} valueTop={value} >
|
||||||
<NavItem
|
<NavItem
|
||||||
iconName="MenuIcon"
|
iconName="MenuIcon"
|
||||||
badgeNumber={totalNotifications}
|
badgeNumber={totalNotifications}
|
||||||
@ -127,7 +133,8 @@ const HeaderComponent = ({
|
|||||||
<Headline className="header-module-title" type="header" color="#FFF">
|
<Headline className="header-module-title" type="header" color="#FFF">
|
||||||
{currentProductName}
|
{currentProductName}
|
||||||
</Headline>
|
</Headline>
|
||||||
</Header>
|
</Header>}
|
||||||
|
</IsVisibleContextConsumer>
|
||||||
{isNavAvailable && (
|
{isNavAvailable && (
|
||||||
<Nav
|
<Nav
|
||||||
opened={isNavOpened}
|
opened={isNavOpened}
|
||||||
|
@ -5,7 +5,7 @@ import { utils, Scrollbar, DragAndDrop } from "asc-web-components";
|
|||||||
import SelectedFrame from "./SelectedFrame";
|
import SelectedFrame from "./SelectedFrame";
|
||||||
import isEqual from "lodash/isEqual";
|
import isEqual from "lodash/isEqual";
|
||||||
import { isMobile } from "react-device-detect";
|
import { isMobile } from "react-device-detect";
|
||||||
import {ThemeContextConsumer} from "asc-web-common"
|
import {RefContextConsumer} from "asc-web-common"
|
||||||
const { tablet } = utils.device;
|
const { tablet } = utils.device;
|
||||||
|
|
||||||
const commonStyles = css`
|
const commonStyles = css`
|
||||||
@ -118,7 +118,7 @@ class SectionBody extends React.Component {
|
|||||||
{withScroll ? (
|
{withScroll ? (
|
||||||
|
|
||||||
!isMobile ? (
|
!isMobile ? (
|
||||||
<Scrollbar {...scrollProp} stype="mediumBlack">
|
<Scrollbar {...scrollProp} stype="mediumBlack" >
|
||||||
{console.log("Scroll ref in section", this.scrollRef)}
|
{console.log("Scroll ref in section", this.scrollRef)}
|
||||||
<SelectedFrame
|
<SelectedFrame
|
||||||
viewAs={viewAs}
|
viewAs={viewAs}
|
||||||
@ -134,7 +134,7 @@ class SectionBody extends React.Component {
|
|||||||
</SelectedFrame>
|
</SelectedFrame>
|
||||||
</Scrollbar>)
|
</Scrollbar>)
|
||||||
: (
|
: (
|
||||||
<ThemeContextConsumer>
|
<RefContextConsumer>
|
||||||
{value =>
|
{value =>
|
||||||
<SelectedFrame
|
<SelectedFrame
|
||||||
viewAs={viewAs}
|
viewAs={viewAs}
|
||||||
@ -149,7 +149,7 @@ class SectionBody extends React.Component {
|
|||||||
</div>
|
</div>
|
||||||
</SelectedFrame>
|
</SelectedFrame>
|
||||||
}
|
}
|
||||||
</ThemeContextConsumer>)
|
</RefContextConsumer>)
|
||||||
) : (
|
) : (
|
||||||
<SelectedFrame
|
<SelectedFrame
|
||||||
viewAs={viewAs}
|
viewAs={viewAs}
|
||||||
|
@ -3,7 +3,7 @@ import styled from "styled-components";
|
|||||||
import { utils } from "asc-web-components";
|
import { utils } from "asc-web-components";
|
||||||
import isEqual from "lodash/isEqual";
|
import isEqual from "lodash/isEqual";
|
||||||
import classnames from "classnames";
|
import classnames from "classnames";
|
||||||
|
import {IsVisibleContextConsumer} from "asc-web-common"
|
||||||
const { tablet } = utils.device;
|
const { tablet } = utils.device;
|
||||||
|
|
||||||
const StyledSectionHeader = styled.div`
|
const StyledSectionHeader = styled.div`
|
||||||
@ -20,12 +20,9 @@ const StyledSectionHeader = styled.div`
|
|||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
.section-header--hidden {
|
|
||||||
@media ${tablet} {
|
|
||||||
top: -50px;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
.section-header {
|
.section-header {
|
||||||
width: calc(100% - 76px);
|
width: calc(100% - 76px);
|
||||||
|
|
||||||
@ -53,43 +50,23 @@ const StyledSectionHeader = styled.div`
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.section-header--hidden {
|
||||||
|
@media ${tablet} {
|
||||||
|
top: -50px;
|
||||||
|
}
|
||||||
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
class SectionHeader extends React.Component {
|
class SectionHeader extends React.Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
this.state = {
|
|
||||||
|
|
||||||
prevScrollPosition: window.pageYOffset || document.documentElement.scrollTop,
|
|
||||||
visibleContent: true
|
|
||||||
};
|
|
||||||
this.focusRef = React.createRef();
|
this.focusRef = React.createRef();
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
|
||||||
window.addEventListener("scroll", this.scrolledTheVerticalAxis,false);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
componentWillUnmount() {
|
|
||||||
window.removeEventListener("scroll", this.scrolledTheVerticalAxis,false);
|
|
||||||
}
|
|
||||||
|
|
||||||
scrolledTheVerticalAxis = () => {
|
|
||||||
const { prevScrollPosition } = this.state;
|
|
||||||
// const first = document.documentElement.offsetTop
|
|
||||||
// const second = document.body.scrollTop || document.documentElement.scrollTop
|
|
||||||
const currentScrollPosition = window.pageYOffset || document.documentElement.scrollTop;
|
|
||||||
|
|
||||||
const visibleContent = prevScrollPosition > currentScrollPosition;
|
|
||||||
|
|
||||||
|
|
||||||
this.setState({
|
|
||||||
prevScrollPosition: currentScrollPosition,
|
|
||||||
visibleContent
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
shouldComponentUpdate(nextProps) {
|
shouldComponentUpdate(nextProps) {
|
||||||
return !isEqual(this.props, nextProps);
|
return !isEqual(this.props, nextProps);
|
||||||
}
|
}
|
||||||
@ -100,11 +77,18 @@ class SectionHeader extends React.Component {
|
|||||||
// eslint-disable-next-line react/prop-types
|
// eslint-disable-next-line react/prop-types
|
||||||
const { isArticlePinned, ...rest } = this.props;
|
const { isArticlePinned, ...rest } = this.props;
|
||||||
return (
|
return (
|
||||||
<StyledSectionHeader isArticlePinned={isArticlePinned}>
|
|
||||||
<div id="scroll" className={classnames("section-header" , {
|
<StyledSectionHeader isArticlePinned={isArticlePinned}>
|
||||||
"section-header--hidden": !this.state.visibleContent
|
<IsVisibleContextConsumer>
|
||||||
})} {...rest} />
|
{ value =>
|
||||||
|
<div id="scroll" className={classnames("section-header", {
|
||||||
|
"section-header--hidden": !value
|
||||||
|
})} {...rest}/>
|
||||||
|
}
|
||||||
|
</IsVisibleContextConsumer>
|
||||||
</StyledSectionHeader>
|
</StyledSectionHeader>
|
||||||
|
|
||||||
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,8 @@ export { default as PeopleSelector } from "./PeopleSelector";
|
|||||||
export { default as GroupSelector } from "./GroupSelector";
|
export { default as GroupSelector } from "./GroupSelector";
|
||||||
export { default as AdvancedSelector } from "./AdvancedSelector";
|
export { default as AdvancedSelector } from "./AdvancedSelector";
|
||||||
export { default as Layout } from "./Layout"
|
export { default as Layout } from "./Layout"
|
||||||
export { ThemeContextConsumer } from "./Layout/context"
|
export { RefContextConsumer } from "./Layout/context"
|
||||||
|
export { IsVisibleContextConsumer} from "./Layout/context"
|
||||||
export { default as PageLayout } from "./PageLayout";
|
export { default as PageLayout } from "./PageLayout";
|
||||||
export { default as ProfileMenu } from "./ProfileMenu";
|
export { default as ProfileMenu } from "./ProfileMenu";
|
||||||
export { default as ErrorContainer } from "./ErrorContainer";
|
export { default as ErrorContainer } from "./ErrorContainer";
|
||||||
|
@ -3,7 +3,7 @@ import PropTypes from "prop-types";
|
|||||||
import { Scrollbars } from "react-custom-scrollbars";
|
import { Scrollbars } from "react-custom-scrollbars";
|
||||||
|
|
||||||
const Scrollbar = React.forwardRef((props, ref) => {
|
const Scrollbar = React.forwardRef((props, ref) => {
|
||||||
//console.log("Scrollbar render");
|
|
||||||
const scrollbarType = {
|
const scrollbarType = {
|
||||||
smallWhite: {
|
smallWhite: {
|
||||||
thumbV: {
|
thumbV: {
|
||||||
@ -97,6 +97,7 @@ const Scrollbar = React.forwardRef((props, ref) => {
|
|||||||
style={{ ...style, ...view }}
|
style={{ ...style, ...view }}
|
||||||
tabIndex={-1}
|
tabIndex={-1}
|
||||||
className={"scroll-body"}
|
className={"scroll-body"}
|
||||||
|
id="scroll"
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user