diff options
author | Samuel Newman <mozzius@protonmail.com> | 2025-02-12 21:51:16 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-02-12 21:51:16 +0000 |
commit | 1a3ecdf6ecb411f7bf0e1a360f0c57d3b3d65f48 (patch) | |
tree | ed6e914bb059e0d9f63298b29844990dcbfadbcc /src | |
parent | 66f5e3a8330faf616e36db56e90c365637bae722 (diff) | |
download | voidsky-1a3ecdf6ecb411f7bf0e1a360f0c57d3b3d65f48.tar.zst |
Animate drawer menu on mobile web (#7711)
* slide in/out drawer * increase width slightly * exponential easing function
Diffstat (limited to 'src')
-rw-r--r-- | src/alf/atoms.ts | 11 | ||||
-rw-r--r-- | src/style.css | 18 | ||||
-rw-r--r-- | src/view/shell/index.web.tsx | 45 |
3 files changed, 60 insertions, 14 deletions
diff --git a/src/alf/atoms.ts b/src/alf/atoms.ts index 6982de75f..ae89fa2cf 100644 --- a/src/alf/atoms.ts +++ b/src/alf/atoms.ts @@ -68,7 +68,6 @@ export const atoms = { * Used for the outermost components on screens, to ensure that they can fill * the screen and extend beyond. */ - // @ts-ignore - web only minHeight string util_screen_outer: [ web({ minHeight: '100vh', @@ -76,7 +75,7 @@ export const atoms = { native({ height: '100%', }), - ] as ViewStyle, + ] as StyleProp<ViewStyle>, /* * Theme-independent bg colors @@ -980,6 +979,14 @@ export const atoms = { zoom_out: web({ animation: 'zoomOut ease-out 0.1s', }), + slide_in_left: web({ + // exponential easing function + animation: 'slideInLeft cubic-bezier(0.16, 1, 0.3, 1) 0.5s', + }), + slide_out_left: web({ + animation: 'slideOutLeft ease-in 0.15s', + animationFillMode: 'forwards', + }), // special composite animation for dialogs zoom_fade_in: web({ animation: 'zoomIn ease-out 0.1s, fadeIn ease-out 0.1s', diff --git a/src/style.css b/src/style.css index dd13b13be..2e118c433 100644 --- a/src/style.css +++ b/src/style.css @@ -215,6 +215,24 @@ input:focus { } } +@keyframes slideInLeft { + from { + transform: translateX(-100%); + } + to { + transform: translateX(0); + } +} + +@keyframes slideOutLeft { + from { + transform: translateX(0); + } + to { + transform: translateX(-100%); + } +} + /* animating radix dropdowns requires knowing the data attributes */ .dropdown-menu-transform-origin > * { transform-origin: var(--radix-dropdown-menu-content-transform-origin); diff --git a/src/view/shell/index.web.tsx b/src/view/shell/index.web.tsx index 8c30813ab..e194a49de 100644 --- a/src/view/shell/index.web.tsx +++ b/src/view/shell/index.web.tsx @@ -1,4 +1,4 @@ -import React, {useEffect} from 'react' +import {useEffect, useLayoutEffect, useState} from 'react' import {StyleSheet, TouchableWithoutFeedback, View} from 'react-native' import {msg} from '@lingui/macro' import {useLingui} from '@lingui/react' @@ -33,6 +33,20 @@ function ShellInner() { const closeAllActiveElements = useCloseAllActiveElements() const {_} = useLingui() const showDrawer = !isDesktop && isDrawerOpen + const [showDrawerDelayedExit, setShowDrawerDelayedExit] = useState(showDrawer) + + useLayoutEffect(() => { + if (showDrawer !== showDrawerDelayedExit) { + if (showDrawer) { + setShowDrawerDelayedExit(true) + } else { + const timeout = setTimeout(() => { + setShowDrawerDelayedExit(false) + }, 160) + return () => clearTimeout(timeout) + } + } + }, [showDrawer, showDrawerDelayedExit]) useComposerKeyboardShortcut() useIntentHandler() @@ -56,7 +70,7 @@ function ShellInner() { <Lightbox /> <PortalOutlet /> - {showDrawer && ( + {showDrawerDelayedExit && ( <> <RemoveScrollBar /> <TouchableWithoutFeedback @@ -66,20 +80,27 @@ function ShellInner() { setDrawerOpen(false) } }} - accessibilityLabel={_(msg`Close navigation footer`)} - accessibilityHint={_(msg`Closes bottom navigation bar`)}> + accessibilityLabel={_(msg`Close drawer menu`)} + accessibilityHint=""> <View style={[ styles.drawerMask, { - backgroundColor: select(t.name, { - light: 'rgba(0, 57, 117, 0.1)', - dark: 'rgba(1, 82, 168, 0.1)', - dim: 'rgba(10, 13, 16, 0.8)', - }), + backgroundColor: showDrawer + ? select(t.name, { + light: 'rgba(0, 57, 117, 0.1)', + dark: 'rgba(1, 82, 168, 0.1)', + dim: 'rgba(10, 13, 16, 0.8)', + }) + : 'transparent', }, + a.transition_color, ]}> - <View style={styles.drawerContainer}> + <View + style={[ + styles.drawerContainer, + showDrawer ? a.slide_in_left : a.slide_out_left, + ]}> <DrawerContent /> </View> </View> @@ -109,7 +130,6 @@ const styles = StyleSheet.create({ backgroundColor: colors.black, // TODO }, drawerMask: { - // @ts-ignore web only position: 'fixed', width: '100%', height: '100%', @@ -118,10 +138,11 @@ const styles = StyleSheet.create({ }, drawerContainer: { display: 'flex', - // @ts-ignore web only position: 'fixed', top: 0, left: 0, height: '100%', + width: 330, + maxWidth: '80%', }, }) |