Animate drawer menu on mobile web (#7711)

* slide in/out drawer

* increase width slightly

* exponential easing function
This commit is contained in:
Samuel Newman
2025-02-12 21:51:16 +00:00
committed by GitHub
parent 66f5e3a833
commit 1a3ecdf6ec
3 changed files with 60 additions and 14 deletions
+9 -2
View File
@@ -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',
+18
View File
@@ -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);
+33 -12
View File
@@ -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%',
},
})