Added new menu animations
This commit is contained in:
parent
bc514b1d5c
commit
7418e27994
5 changed files with 166 additions and 101 deletions
|
@ -122,6 +122,13 @@ function Page(props: Props) {
|
||||||
>
|
>
|
||||||
{getSideNavElem()}
|
{getSideNavElem()}
|
||||||
|
|
||||||
|
<div
|
||||||
|
className={classnames({
|
||||||
|
'sidebar--pusher': fullWidthPage,
|
||||||
|
'sidebar--pusher--open': sidebarOpen && fullWidthPage,
|
||||||
|
'sidebar--pusher--filepage': !fullWidthPage,
|
||||||
|
})}
|
||||||
|
>
|
||||||
<main
|
<main
|
||||||
id={'main-content'}
|
id={'main-content'}
|
||||||
className={classnames(MAIN_CLASS, className, {
|
className={classnames(MAIN_CLASS, className, {
|
||||||
|
@ -138,10 +145,6 @@ function Page(props: Props) {
|
||||||
|
|
||||||
{!isMobile && rightSide && <div className="main__right-side">{rightSide}</div>}
|
{!isMobile && rightSide && <div className="main__right-side">{rightSide}</div>}
|
||||||
</main>
|
</main>
|
||||||
{/* @if TARGET='app' */}
|
|
||||||
<StatusBar />
|
|
||||||
{/* @endif */}
|
|
||||||
</div>
|
|
||||||
{/* @if TARGET='web' */}
|
{/* @if TARGET='web' */}
|
||||||
{!noFooter && (
|
{!noFooter && (
|
||||||
<React.Suspense fallback={null}>
|
<React.Suspense fallback={null}>
|
||||||
|
@ -149,6 +152,11 @@ function Page(props: Props) {
|
||||||
</React.Suspense>
|
</React.Suspense>
|
||||||
)}
|
)}
|
||||||
{/* @endif */}
|
{/* @endif */}
|
||||||
|
</div>
|
||||||
|
{/* @if TARGET='app' */}
|
||||||
|
<StatusBar />
|
||||||
|
{/* @endif */}
|
||||||
|
</div>
|
||||||
</Fragment>
|
</Fragment>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@ import Icon from 'component/common/icon';
|
||||||
import NotificationBubble from 'component/notificationBubble';
|
import NotificationBubble from 'component/notificationBubble';
|
||||||
import I18nMessage from 'component/i18nMessage';
|
import I18nMessage from 'component/i18nMessage';
|
||||||
import ChannelThumbnail from 'component/channelThumbnail';
|
import ChannelThumbnail from 'component/channelThumbnail';
|
||||||
import { useIsLargeScreen } from 'effects/use-screensize';
|
import { useIsMobile, useIsLargeScreen } from 'effects/use-screensize';
|
||||||
import { GetLinksData } from 'util/buildHomepage';
|
import { GetLinksData } from 'util/buildHomepage';
|
||||||
import { DOMAIN, ENABLE_UI_NOTIFICATIONS, ENABLE_NO_SOURCE_CLAIMS, CHANNEL_STAKED_LEVEL_LIVESTREAM } from 'config';
|
import { DOMAIN, ENABLE_UI_NOTIFICATIONS, ENABLE_NO_SOURCE_CLAIMS, CHANNEL_STAKED_LEVEL_LIVESTREAM } from 'config';
|
||||||
|
|
||||||
|
@ -219,9 +219,33 @@ function SideNavigation(props: Props) {
|
||||||
|
|
||||||
const isPersonalized = !IS_WEB || isAuthenticated;
|
const isPersonalized = !IS_WEB || isAuthenticated;
|
||||||
const isAbsolute = isOnFilePage || isMediumScreen;
|
const isAbsolute = isOnFilePage || isMediumScreen;
|
||||||
const microNavigation = !sidebarOpen || isMediumScreen;
|
const isMobile = useIsMobile();
|
||||||
|
|
||||||
const showSubscriptionSection = sidebarOpen && isPersonalized && subscriptions && subscriptions.length > 0;
|
const menuCanCloseCompletey = livestreamEnabled || isOnFilePage || isMobile;
|
||||||
|
const hideMenuFromView = menuCanCloseCompletey && !sidebarOpen;
|
||||||
|
|
||||||
|
const [canDisposeMenu, setCanDisposeMenu] = React.useState(false);
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
if (hideMenuFromView) {
|
||||||
|
const handler = setTimeout(() => {
|
||||||
|
setCanDisposeMenu(true);
|
||||||
|
}, 250);
|
||||||
|
return () => {
|
||||||
|
clearTimeout(handler);
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
setCanDisposeMenu(false);
|
||||||
|
}
|
||||||
|
}, [hideMenuFromView]);
|
||||||
|
|
||||||
|
const shouldRenderLargeMenuPushorAbsolute = menuCanCloseCompletey || sidebarOpen;
|
||||||
|
|
||||||
|
const showMicroMenu = !sidebarOpen && !menuCanCloseCompletey;
|
||||||
|
const showPushMenu = sidebarOpen && !menuCanCloseCompletey;
|
||||||
|
|
||||||
|
const showSubscriptionSection =
|
||||||
|
shouldRenderLargeMenuPushorAbsolute && isPersonalized && subscriptions && subscriptions.length > 0;
|
||||||
const showTagSection = sidebarOpen && isPersonalized && followedTags && followedTags.length;
|
const showTagSection = sidebarOpen && isPersonalized && followedTags && followedTags.length;
|
||||||
|
|
||||||
let displayedSubscriptions = subscriptions;
|
let displayedSubscriptions = subscriptions;
|
||||||
|
@ -388,59 +412,42 @@ function SideNavigation(props: Props) {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={classnames('navigation__wrapper', {
|
className={classnames('navigation__wrapper', {
|
||||||
'navigation__wrapper--micro': microNavigation && !isOnFilePage,
|
'navigation__wrapper--micro': showMicroMenu,
|
||||||
'navigation__wrapper--absolute': isAbsolute,
|
'navigation__wrapper--absolute': isAbsolute,
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
{!isOnFilePage && (
|
|
||||||
<nav
|
<nav
|
||||||
aria-label={'Sidebar'}
|
aria-label={'Sidebar'}
|
||||||
className={classnames('navigation', {
|
className={classnames('navigation', {
|
||||||
'navigation--micro': microNavigation,
|
'navigation--micro': showMicroMenu,
|
||||||
|
'navigation--push': showPushMenu,
|
||||||
|
'navigation-file-page-and-mobile': hideMenuFromView,
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
<div>
|
{(!canDisposeMenu || sidebarOpen) && (
|
||||||
<ul className={classnames('navigation-links', { 'navigation-links--micro': !sidebarOpen })}>
|
<div className="navigation-inner-container">
|
||||||
{getLink(HOME)}
|
|
||||||
{getLink(RECENT_FROM_FOLLOWING)}
|
|
||||||
{getLink(PLAYLISTS)}
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
<ul className={classnames('navigation-links', { 'navigation-links--micro': !sidebarOpen })}>
|
|
||||||
{EXTRA_SIDEBAR_LINKS && (
|
|
||||||
<>
|
|
||||||
{/* $FlowFixMe -- GetLinksData should fix it's data type */}
|
|
||||||
{EXTRA_SIDEBAR_LINKS.map((linkProps) => getLink(linkProps))}
|
|
||||||
{getLink(WILD_WEST)}
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
{getSubscriptionSection()}
|
|
||||||
{getFollowedTagsSection()}
|
|
||||||
{!isAuthenticated && sidebarOpen && unAuthNudge}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{sidebarOpen && helpLinks}
|
|
||||||
</nav>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{(isOnFilePage || isMediumScreen) && sidebarOpen && (
|
|
||||||
<>
|
|
||||||
<nav className="navigation--absolute">
|
|
||||||
<div>
|
|
||||||
<ul className="navigation-links--absolute mobile-only">
|
<ul className="navigation-links--absolute mobile-only">
|
||||||
{notificationsEnabled && getLink(NOTIFICATIONS)}
|
{notificationsEnabled && getLink(NOTIFICATIONS)}
|
||||||
{email && livestreamEnabled && getLink(GO_LIVE)}
|
{email && livestreamEnabled && getLink(GO_LIVE)}
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<ul className="navigation-links--absolute">
|
<ul
|
||||||
|
className={classnames('navigation-links', {
|
||||||
|
'navigation-links--micro': showMicroMenu,
|
||||||
|
'navigation-links--absolute': shouldRenderLargeMenuPushorAbsolute,
|
||||||
|
})}
|
||||||
|
>
|
||||||
{getLink(HOME)}
|
{getLink(HOME)}
|
||||||
{getLink(RECENT_FROM_FOLLOWING)}
|
{getLink(RECENT_FROM_FOLLOWING)}
|
||||||
{getLink(PLAYLISTS)}
|
{getLink(PLAYLISTS)}
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<ul className="navigation-links--absolute">
|
<ul
|
||||||
|
className={classnames('navigation-links', {
|
||||||
|
'navigation-links--micro': showMicroMenu,
|
||||||
|
'navigation-links--absolute': shouldRenderLargeMenuPushorAbsolute,
|
||||||
|
})}
|
||||||
|
>
|
||||||
{EXTRA_SIDEBAR_LINKS && (
|
{EXTRA_SIDEBAR_LINKS && (
|
||||||
<>
|
<>
|
||||||
{/* $FlowFixMe -- GetLinksData should fix it's data type */}
|
{/* $FlowFixMe -- GetLinksData should fix it's data type */}
|
||||||
|
@ -457,13 +464,17 @@ function SideNavigation(props: Props) {
|
||||||
|
|
||||||
{getSubscriptionSection()}
|
{getSubscriptionSection()}
|
||||||
{getFollowedTagsSection()}
|
{getFollowedTagsSection()}
|
||||||
{!isAuthenticated && unAuthNudge}
|
{!isAuthenticated && sidebarOpen && unAuthNudge}
|
||||||
{helpLinks}
|
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
|
||||||
<div className="navigation__overlay" onClick={() => setSidebarOpen(false)} />
|
|
||||||
</>
|
|
||||||
)}
|
)}
|
||||||
|
{(!canDisposeMenu || sidebarOpen) && shouldRenderLargeMenuPushorAbsolute && helpLinks}
|
||||||
|
</nav>
|
||||||
|
<div
|
||||||
|
className={classnames('navigation__overlay', {
|
||||||
|
'navigation__overlay--active': isAbsolute && sidebarOpen,
|
||||||
|
})}
|
||||||
|
onClick={() => setSidebarOpen(false)}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,19 +47,43 @@
|
||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.sidebar--pusher {
|
||||||
|
animation-timing-function: var(--resizing-animation-function);
|
||||||
|
transition: transform var(--resizing-animation-timing);
|
||||||
|
transform-origin: left;
|
||||||
|
position: absolute;
|
||||||
|
|
||||||
|
@media (max-width: $breakpoint-small) {
|
||||||
|
transform: translateX(0);
|
||||||
|
width: calc(100% - var(--spacing-m));
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: $breakpoint-small) {
|
||||||
|
transform: translateX(var(--side-nav-width--micro));
|
||||||
|
width: calc(100% - ((var(--side-nav-width--micro))));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar--pusher--filepage {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar--pusher--open {
|
||||||
|
@media (min-width: $breakpoint-medium) {
|
||||||
|
transform: translateX(var(--side-nav-width));
|
||||||
|
width: calc(100% - var(--side-nav-width));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.main {
|
.main {
|
||||||
position: relative;
|
position: relative;
|
||||||
width: calc(100% - var(--side-nav-width) - var(--spacing-l));
|
width: calc(100% - 2 * var(--spacing-l));
|
||||||
max-width: var(--page-max-width);
|
max-width: var(--page-max-width);
|
||||||
z-index: 0;
|
z-index: 0;
|
||||||
margin-right: auto;
|
margin-right: auto;
|
||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
|
|
||||||
@media (max-width: $breakpoint-medium) and (min-width: $breakpoint-small) {
|
@media (max-width: $breakpoint-small) {
|
||||||
margin: 0 var(--spacing-l);
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: $breakpoint-medium) {
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -254,12 +278,7 @@
|
||||||
|
|
||||||
.main--full-width {
|
.main--full-width {
|
||||||
@extend .main;
|
@extend .main;
|
||||||
|
|
||||||
@media (min-width: $breakpoint-large) {
|
|
||||||
max-width: none;
|
max-width: none;
|
||||||
width: 100%;
|
|
||||||
margin: 0 var(--spacing-l);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.main--auth-page {
|
.main--auth-page {
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
position: fixed;
|
position: fixed;
|
||||||
left: 0;
|
left: 0;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
|
overflow-x: hidden;
|
||||||
top: var(--header-height);
|
top: var(--header-height);
|
||||||
width: var(--side-nav-width);
|
width: var(--side-nav-width);
|
||||||
height: calc(100vh - var(--header-height));
|
height: calc(100vh - var(--header-height));
|
||||||
|
@ -30,6 +31,13 @@
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|
||||||
|
animation-timing-function: var(--resizing-animation-function);
|
||||||
|
transition: transform var(--resizing-animation-timing);
|
||||||
|
z-index: 4;
|
||||||
|
background-color: var(--color-card-background);
|
||||||
|
transform: translateX(0);
|
||||||
|
transform-origin: left;
|
||||||
|
|
||||||
@media (min-width: $breakpoint-small) {
|
@media (min-width: $breakpoint-small) {
|
||||||
overflow-y: hidden;
|
overflow-y: hidden;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
|
@ -45,25 +53,25 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.navigation--push-back {
|
||||||
|
transform: translateX(calc(-1 * (var(--side-nav-width) - var(--side-nav-width--micro))));
|
||||||
|
}
|
||||||
|
|
||||||
|
.navigation--push {
|
||||||
|
transform: translateX(0);
|
||||||
|
}
|
||||||
|
|
||||||
.navigation--mac {
|
.navigation--mac {
|
||||||
top: calc(var(--header-height) + var(--mac-titlebar-height));
|
top: calc(var(--header-height) + var(--mac-titlebar-height));
|
||||||
}
|
}
|
||||||
|
|
||||||
.navigation--absolute {
|
.navigation-file-page-and-mobile {
|
||||||
@extend .navigation;
|
transform: translateX(calc(-1 * var(--side-nav-width)));
|
||||||
z-index: 4;
|
|
||||||
width: var(--side-nav-width);
|
|
||||||
background-color: var(--color-card-background);
|
|
||||||
box-shadow: var(--card-box-shadow);
|
|
||||||
|
|
||||||
.navigation-link {
|
|
||||||
padding-left: var(--spacing-m);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.navigation--micro {
|
.navigation--micro {
|
||||||
@extend .navigation;
|
@extend .navigation;
|
||||||
width: var(--side-nav-width--micro);
|
transform: translateX(calc(-1 * (var(--side-nav-width) - var(--side-nav-width--micro))));
|
||||||
|
|
||||||
@media (max-width: $breakpoint-small) {
|
@media (max-width: $breakpoint-small) {
|
||||||
display: none;
|
display: none;
|
||||||
|
@ -101,6 +109,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.button__content {
|
.button__content {
|
||||||
|
margin-left: auto;
|
||||||
padding: var(--spacing-s);
|
padding: var(--spacing-s);
|
||||||
justify-content: flex-start;
|
justify-content: flex-start;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
@ -188,6 +197,10 @@
|
||||||
list-style: none;
|
list-style: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.navigation-inner-container {
|
||||||
|
width: var(--side-nav-width);
|
||||||
|
}
|
||||||
|
|
||||||
.navigation-links--micro {
|
.navigation-links--micro {
|
||||||
.icon {
|
.icon {
|
||||||
height: 1.5rem;
|
height: 1.5rem;
|
||||||
|
@ -271,12 +284,22 @@
|
||||||
z-index: 3;
|
z-index: 3;
|
||||||
left: 0;
|
left: 0;
|
||||||
top: var(--header-height);
|
top: var(--header-height);
|
||||||
|
visibility: hidden;
|
||||||
|
opacity: 0;
|
||||||
|
animation-timing-function: var(--resizing-animation-function);
|
||||||
|
transition: visibility var(--resizing-animation-timing), opacity var(--resizing-animation-timing);
|
||||||
|
|
||||||
&.navigation__overlay--mac {
|
&.navigation__overlay--mac {
|
||||||
top: calc(var(--header-height) + var(--mac-titlebar-height));
|
top: calc(var(--header-height) + var(--mac-titlebar-height));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.navigation__overlay--active {
|
||||||
|
opacity: 1;
|
||||||
|
visibility: visible;
|
||||||
|
animation: fadeIn var(--resizing-animation-timing) var(--resizing-animation-function);
|
||||||
|
}
|
||||||
|
|
||||||
.navigation__auth-nudge {
|
.navigation__auth-nudge {
|
||||||
@extend .card;
|
@extend .card;
|
||||||
margin: var(--spacing-s);
|
margin: var(--spacing-s);
|
||||||
|
|
|
@ -100,6 +100,10 @@ $breakpoint-large: 1600px;
|
||||||
--tag-height: 1.5rem;
|
--tag-height: 1.5rem;
|
||||||
|
|
||||||
--livestream-comments-width: 30rem;
|
--livestream-comments-width: 30rem;
|
||||||
|
|
||||||
|
// Animations
|
||||||
|
--resizing-animation-function: ease-in;
|
||||||
|
--resizing-animation-timing: 180ms;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: $breakpoint-small) {
|
@media (max-width: $breakpoint-small) {
|
||||||
|
|
Loading…
Reference in a new issue