Files
bsky-social-app/src/components/PolicyUpdateOverlay/Overlay.tsx
T
Eric Bailey 0589bd7d9e Move /platform/detection vars into /env (#9707)
* Add platform vars to env

* Replace /platform/detection with /env
2026-01-16 16:28:17 -06:00

140 lines
3.7 KiB
TypeScript

import {type ReactNode} from 'react'
import {ScrollView, View} from 'react-native'
import {
useSafeAreaFrame,
useSafeAreaInsets,
} from 'react-native-safe-area-context'
import {LinearGradient} from 'expo-linear-gradient'
import {utils} from '@bsky.app/alf'
import {useA11y} from '#/state/a11y'
import {atoms as a, useBreakpoints, useTheme, web} from '#/alf'
import {FocusScope} from '#/components/FocusScope'
import {LockScroll} from '#/components/LockScroll'
import {IS_ANDROID, IS_NATIVE} from '#/env'
const GUTTER = 24
export function Overlay({
children,
label,
}: {
children: ReactNode
label: string
}) {
const t = useTheme()
const {gtPhone} = useBreakpoints()
const {reduceMotionEnabled} = useA11y()
const insets = useSafeAreaInsets()
const frame = useSafeAreaFrame()
return (
<>
<LockScroll />
<View style={[a.fixed, a.inset_0, !reduceMotionEnabled && a.fade_in]}>
{gtPhone ? (
<View style={[a.absolute, a.inset_0, {opacity: 0.8}]}>
<View
style={[
a.fixed,
a.inset_0,
{backgroundColor: t.palette.black},
!reduceMotionEnabled && a.fade_in,
]}
/>
</View>
) : (
<LinearGradient
colors={[
utils.alpha(t.atoms.bg.backgroundColor, 0),
t.atoms.bg.backgroundColor,
t.atoms.bg.backgroundColor,
]}
start={[0.5, 0]}
end={[0.5, 1]}
style={[a.absolute, a.inset_0]}
/>
)}
</View>
<ScrollView
showsVerticalScrollIndicator={false}
style={[
a.z_10,
gtPhone &&
web({
paddingHorizontal: GUTTER,
paddingVertical: '10vh',
}),
]}
contentContainerStyle={[a.align_center]}>
{/**
* This is needed to prevent centered dialogs from overflowing
* above the screen, and provides a "natural" centering so that
* stacked dialogs appear relatively aligned.
*/}
<View
style={[
a.w_full,
a.z_20,
a.align_center,
!gtPhone && [a.justify_end, {minHeight: frame.height}],
IS_NATIVE && [
{
paddingBottom: Math.max(insets.bottom, a.p_2xl.padding),
},
],
]}>
{!gtPhone && (
<View
style={[
a.flex_1,
a.w_full,
{
minHeight: Math.max(insets.top, a.p_2xl.padding),
},
]}>
<LinearGradient
colors={[
utils.alpha(t.atoms.bg.backgroundColor, 0),
t.atoms.bg.backgroundColor,
]}
start={[0.5, 0]}
end={[0.5, 1]}
style={[a.absolute, a.inset_0]}
/>
</View>
)}
<FocusScope>
<View
accessible={IS_ANDROID}
role="dialog"
aria-role="dialog"
aria-label={label}
style={[
a.relative,
a.w_full,
a.p_2xl,
t.atoms.bg,
!reduceMotionEnabled && a.zoom_fade_in,
gtPhone && [
a.rounded_md,
a.border,
t.atoms.shadow_lg,
t.atoms.border_contrast_low,
web({
maxWidth: 420,
}),
],
]}>
{children}
</View>
</FocusScope>
</View>
</ScrollView>
</>
)
}