Added new menu animations

This commit is contained in:
Max Kotlan 2021-12-11 09:59:32 -05:00 committed by Thomas Zarebczan
parent bc514b1d5c
commit 7418e27994
5 changed files with 166 additions and 101 deletions

View file

@ -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>
); );
} }

View file

@ -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>
); );
} }

View file

@ -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 {

View file

@ -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);

View file

@ -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) {