Animate drawer menu on mobile web (#7711)
* slide in/out drawer * increase width slightly * exponential easing function
This commit is contained in:
+9
-2
@@ -68,7 +68,6 @@ export const atoms = {
|
|||||||
* Used for the outermost components on screens, to ensure that they can fill
|
* Used for the outermost components on screens, to ensure that they can fill
|
||||||
* the screen and extend beyond.
|
* the screen and extend beyond.
|
||||||
*/
|
*/
|
||||||
// @ts-ignore - web only minHeight string
|
|
||||||
util_screen_outer: [
|
util_screen_outer: [
|
||||||
web({
|
web({
|
||||||
minHeight: '100vh',
|
minHeight: '100vh',
|
||||||
@@ -76,7 +75,7 @@ export const atoms = {
|
|||||||
native({
|
native({
|
||||||
height: '100%',
|
height: '100%',
|
||||||
}),
|
}),
|
||||||
] as ViewStyle,
|
] as StyleProp<ViewStyle>,
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Theme-independent bg colors
|
* Theme-independent bg colors
|
||||||
@@ -980,6 +979,14 @@ export const atoms = {
|
|||||||
zoom_out: web({
|
zoom_out: web({
|
||||||
animation: 'zoomOut ease-out 0.1s',
|
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
|
// special composite animation for dialogs
|
||||||
zoom_fade_in: web({
|
zoom_fade_in: web({
|
||||||
animation: 'zoomIn ease-out 0.1s, fadeIn ease-out 0.1s',
|
animation: 'zoomIn ease-out 0.1s, fadeIn ease-out 0.1s',
|
||||||
|
|||||||
@@ -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 */
|
/* animating radix dropdowns requires knowing the data attributes */
|
||||||
.dropdown-menu-transform-origin > * {
|
.dropdown-menu-transform-origin > * {
|
||||||
transform-origin: var(--radix-dropdown-menu-content-transform-origin);
|
transform-origin: var(--radix-dropdown-menu-content-transform-origin);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import React, {useEffect} from 'react'
|
import {useEffect, useLayoutEffect, useState} from 'react'
|
||||||
import {StyleSheet, TouchableWithoutFeedback, View} from 'react-native'
|
import {StyleSheet, TouchableWithoutFeedback, View} from 'react-native'
|
||||||
import {msg} from '@lingui/macro'
|
import {msg} from '@lingui/macro'
|
||||||
import {useLingui} from '@lingui/react'
|
import {useLingui} from '@lingui/react'
|
||||||
@@ -33,6 +33,20 @@ function ShellInner() {
|
|||||||
const closeAllActiveElements = useCloseAllActiveElements()
|
const closeAllActiveElements = useCloseAllActiveElements()
|
||||||
const {_} = useLingui()
|
const {_} = useLingui()
|
||||||
const showDrawer = !isDesktop && isDrawerOpen
|
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()
|
useComposerKeyboardShortcut()
|
||||||
useIntentHandler()
|
useIntentHandler()
|
||||||
@@ -56,7 +70,7 @@ function ShellInner() {
|
|||||||
<Lightbox />
|
<Lightbox />
|
||||||
<PortalOutlet />
|
<PortalOutlet />
|
||||||
|
|
||||||
{showDrawer && (
|
{showDrawerDelayedExit && (
|
||||||
<>
|
<>
|
||||||
<RemoveScrollBar />
|
<RemoveScrollBar />
|
||||||
<TouchableWithoutFeedback
|
<TouchableWithoutFeedback
|
||||||
@@ -66,20 +80,27 @@ function ShellInner() {
|
|||||||
setDrawerOpen(false)
|
setDrawerOpen(false)
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
accessibilityLabel={_(msg`Close navigation footer`)}
|
accessibilityLabel={_(msg`Close drawer menu`)}
|
||||||
accessibilityHint={_(msg`Closes bottom navigation bar`)}>
|
accessibilityHint="">
|
||||||
<View
|
<View
|
||||||
style={[
|
style={[
|
||||||
styles.drawerMask,
|
styles.drawerMask,
|
||||||
{
|
{
|
||||||
backgroundColor: select(t.name, {
|
backgroundColor: showDrawer
|
||||||
|
? select(t.name, {
|
||||||
light: 'rgba(0, 57, 117, 0.1)',
|
light: 'rgba(0, 57, 117, 0.1)',
|
||||||
dark: 'rgba(1, 82, 168, 0.1)',
|
dark: 'rgba(1, 82, 168, 0.1)',
|
||||||
dim: 'rgba(10, 13, 16, 0.8)',
|
dim: 'rgba(10, 13, 16, 0.8)',
|
||||||
}),
|
})
|
||||||
|
: 'transparent',
|
||||||
},
|
},
|
||||||
|
a.transition_color,
|
||||||
|
]}>
|
||||||
|
<View
|
||||||
|
style={[
|
||||||
|
styles.drawerContainer,
|
||||||
|
showDrawer ? a.slide_in_left : a.slide_out_left,
|
||||||
]}>
|
]}>
|
||||||
<View style={styles.drawerContainer}>
|
|
||||||
<DrawerContent />
|
<DrawerContent />
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
@@ -109,7 +130,6 @@ const styles = StyleSheet.create({
|
|||||||
backgroundColor: colors.black, // TODO
|
backgroundColor: colors.black, // TODO
|
||||||
},
|
},
|
||||||
drawerMask: {
|
drawerMask: {
|
||||||
// @ts-ignore web only
|
|
||||||
position: 'fixed',
|
position: 'fixed',
|
||||||
width: '100%',
|
width: '100%',
|
||||||
height: '100%',
|
height: '100%',
|
||||||
@@ -118,10 +138,11 @@ const styles = StyleSheet.create({
|
|||||||
},
|
},
|
||||||
drawerContainer: {
|
drawerContainer: {
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
// @ts-ignore web only
|
|
||||||
position: 'fixed',
|
position: 'fixed',
|
||||||
top: 0,
|
top: 0,
|
||||||
left: 0,
|
left: 0,
|
||||||
height: '100%',
|
height: '100%',
|
||||||
|
width: 330,
|
||||||
|
maxWidth: '80%',
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user