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,33 +122,41 @@ function Page(props: Props) {
> >
{getSideNavElem()} {getSideNavElem()}
<main <div
id={'main-content'} className={classnames({
className={classnames(MAIN_CLASS, className, { 'sidebar--pusher': fullWidthPage,
'main--full-width': fullWidthPage, 'sidebar--pusher--open': sidebarOpen && fullWidthPage,
'main--auth-page': authPage, 'sidebar--pusher--filepage': !fullWidthPage,
'main--file-page': filePage,
'main--settings-page': settingsPage,
'main--markdown': isMarkdown,
'main--theater-mode': isOnFilePage && videoTheaterMode && !livestream,
'main--livestream': livestream && !chatDisabled,
})} })}
> >
{children} <main
id={'main-content'}
className={classnames(MAIN_CLASS, className, {
'main--full-width': fullWidthPage,
'main--auth-page': authPage,
'main--file-page': filePage,
'main--settings-page': settingsPage,
'main--markdown': isMarkdown,
'main--theater-mode': isOnFilePage && videoTheaterMode && !livestream,
'main--livestream': livestream && !chatDisabled,
})}
>
{children}
{!isMobile && rightSide && <div className="main__right-side">{rightSide}</div>} {!isMobile && rightSide && <div className="main__right-side">{rightSide}</div>}
</main> </main>
{/* @if TARGET='web' */}
{!noFooter && (
<React.Suspense fallback={null}>
<Footer />
</React.Suspense>
)}
{/* @endif */}
</div>
{/* @if TARGET='app' */} {/* @if TARGET='app' */}
<StatusBar /> <StatusBar />
{/* @endif */} {/* @endif */}
</div> </div>
{/* @if TARGET='web' */}
{!noFooter && (
<React.Suspense fallback={null}>
<Footer />
</React.Suspense>
)}
{/* @endif */}
</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,25 +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': showMicroMenu,
'navigation--micro': microNavigation, 'navigation--push': showPushMenu,
})} 'navigation-file-page-and-mobile': hideMenuFromView,
> })}
<div> >
<ul className={classnames('navigation-links', { 'navigation-links--micro': !sidebarOpen })}> {(!canDisposeMenu || sidebarOpen) && (
<div className="navigation-inner-container">
<ul className="navigation-links--absolute mobile-only">
{notificationsEnabled && getLink(NOTIFICATIONS)}
{email && livestreamEnabled && getLink(GO_LIVE)}
</ul>
<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={classnames('navigation-links', { 'navigation-links--micro': !sidebarOpen })}> <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 */}
@ -416,54 +457,24 @@ function SideNavigation(props: Props) {
)} )}
</ul> </ul>
<ul className="navigation-links--absolute mobile-only">
{email && MOBILE_LINKS.map((linkProps) => getLink(linkProps))}
{!email && UNAUTH_LINKS.map((linkProps) => getLink(linkProps))}
</ul>
{getSubscriptionSection()} {getSubscriptionSection()}
{getFollowedTagsSection()} {getFollowedTagsSection()}
{!isAuthenticated && sidebarOpen && unAuthNudge} {!isAuthenticated && sidebarOpen && unAuthNudge}
</div> </div>
)}
{sidebarOpen && helpLinks} {(!canDisposeMenu || sidebarOpen) && shouldRenderLargeMenuPushorAbsolute && helpLinks}
</nav> </nav>
)} <div
className={classnames('navigation__overlay', {
{(isOnFilePage || isMediumScreen) && sidebarOpen && ( 'navigation__overlay--active': isAbsolute && sidebarOpen,
<> })}
<nav className="navigation--absolute"> onClick={() => setSidebarOpen(false)}
<div> />
<ul className="navigation-links--absolute mobile-only">
{notificationsEnabled && getLink(NOTIFICATIONS)}
{email && livestreamEnabled && getLink(GO_LIVE)}
</ul>
<ul className="navigation-links--absolute">
{getLink(HOME)}
{getLink(RECENT_FROM_FOLLOWING)}
{getLink(PLAYLISTS)}
</ul>
<ul className="navigation-links--absolute">
{EXTRA_SIDEBAR_LINKS && (
<>
{/* $FlowFixMe -- GetLinksData should fix it's data type */}
{EXTRA_SIDEBAR_LINKS.map((linkProps) => getLink(linkProps))}
{getLink(WILD_WEST)}
</>
)}
</ul>
<ul className="navigation-links--absolute mobile-only">
{email && MOBILE_LINKS.map((linkProps) => getLink(linkProps))}
{!email && UNAUTH_LINKS.map((linkProps) => getLink(linkProps))}
</ul>
{getSubscriptionSection()}
{getFollowedTagsSection()}
{!isAuthenticated && unAuthNudge}
{helpLinks}
</div>
</nav>
<div className="navigation__overlay" 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;
max-width: none;
@media (min-width: $breakpoint-large) {
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) {