ensure alt text is scrollable (#10671)
Co-authored-by: Eric Bailey <git@esb.lol>
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
import {useCallback, useEffect, useRef, useState} from 'react'
|
import {useCallback, useEffect, useRef, useState} from 'react'
|
||||||
import {Pressable, StyleSheet, View} from 'react-native'
|
import {Pressable, ScrollView, StyleSheet, View} from 'react-native'
|
||||||
import {Image} from 'expo-image'
|
import {Image} from 'expo-image'
|
||||||
import {Trans, useLingui} from '@lingui/react/macro'
|
import {Trans, useLingui} from '@lingui/react/macro'
|
||||||
import {FocusGuards, FocusScope} from 'radix-ui/internal'
|
import {FocusGuards, FocusScope} from 'radix-ui/internal'
|
||||||
@@ -226,17 +226,21 @@ function LightboxGallery({
|
|||||||
)}
|
)}
|
||||||
</View>
|
</View>
|
||||||
{img.alt ? (
|
{img.alt ? (
|
||||||
<View
|
<ScrollView
|
||||||
|
// Cap the overlay height so long alt text scrolls within the overlay
|
||||||
|
// instead of growing past the top of the screen and pushing the image
|
||||||
|
// out of view. Only scrollable once expanded.
|
||||||
style={[
|
style={[
|
||||||
a.px_4xl,
|
styles.altScroll,
|
||||||
a.py_2xl,
|
|
||||||
{
|
{
|
||||||
backgroundColor: 'rgba(0, 0, 0, 0.5)',
|
backgroundColor: 'rgba(0, 0, 0, 0.5)',
|
||||||
// @ts-expect-error web only
|
// @ts-expect-error web only
|
||||||
backdropFilter: 'blur(16px)',
|
backdropFilter: 'blur(16px)',
|
||||||
},
|
},
|
||||||
delayedFadeInAnim,
|
delayedFadeInAnim,
|
||||||
]}>
|
]}
|
||||||
|
scrollEnabled={isAltExpanded}
|
||||||
|
contentContainerStyle={[a.px_4xl, a.py_2xl]}>
|
||||||
<Pressable
|
<Pressable
|
||||||
accessibilityLabel={l`Expand alt text`}
|
accessibilityLabel={l`Expand alt text`}
|
||||||
accessibilityHint={l`If alt text is long, toggles alt text expanded state`}
|
accessibilityHint={l`If alt text is long, toggles alt text expanded state`}
|
||||||
@@ -250,7 +254,7 @@ function LightboxGallery({
|
|||||||
{img.alt}
|
{img.alt}
|
||||||
</Text>
|
</Text>
|
||||||
</Pressable>
|
</Pressable>
|
||||||
</View>
|
</ScrollView>
|
||||||
) : null}
|
) : null}
|
||||||
{imgs.length > 1 && (
|
{imgs.length > 1 && (
|
||||||
<div aria-live="polite" aria-atomic="true" style={a.sr_only}>
|
<div aria-live="polite" aria-atomic="true" style={a.sr_only}>
|
||||||
@@ -449,6 +453,14 @@ const styles = StyleSheet.create({
|
|||||||
padding: 16,
|
padding: 16,
|
||||||
boxSizing: 'border-box',
|
boxSizing: 'border-box',
|
||||||
},
|
},
|
||||||
|
altScroll: {
|
||||||
|
// Size to content like the View it replaced, rather than filling the
|
||||||
|
// column via ScrollView's default flexGrow.
|
||||||
|
flexGrow: 0,
|
||||||
|
flexShrink: 0,
|
||||||
|
// @ts-ignore web-only -sfn
|
||||||
|
maxHeight: '50vh',
|
||||||
|
},
|
||||||
menuBtn: {
|
menuBtn: {
|
||||||
top: 20,
|
top: 20,
|
||||||
left: 20,
|
left: 20,
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
import {useRef} from 'react'
|
import {useRef} from 'react'
|
||||||
import {LayoutAnimation, ScrollView, StyleSheet, View} from 'react-native'
|
import {LayoutAnimation, ScrollView, StyleSheet, View} from 'react-native'
|
||||||
import {useSafeAreaInsets} from 'react-native-safe-area-context'
|
import {
|
||||||
|
useSafeAreaFrame,
|
||||||
|
useSafeAreaInsets,
|
||||||
|
} from 'react-native-safe-area-context'
|
||||||
import {BlurView} from 'expo-blur'
|
import {BlurView} from 'expo-blur'
|
||||||
import {useLingui} from '@lingui/react/macro'
|
import {useLingui} from '@lingui/react/macro'
|
||||||
|
|
||||||
@@ -17,10 +20,16 @@ export function Footer({altText, isAltExpanded, onToggleAltExpanded}: Props) {
|
|||||||
const {t: l} = useLingui()
|
const {t: l} = useLingui()
|
||||||
const t = useTheme()
|
const t = useTheme()
|
||||||
const insets = useSafeAreaInsets()
|
const insets = useSafeAreaInsets()
|
||||||
|
const {height: screenHeight} = useSafeAreaFrame()
|
||||||
const isMomentumScrolling = useRef(false)
|
const isMomentumScrolling = useRef(false)
|
||||||
|
|
||||||
if (!altText) return null
|
if (!altText) return null
|
||||||
|
|
||||||
|
// Cap the overlay height so long alt text - or text enlarged by the OS via
|
||||||
|
// Dynamic Type / font scaling - scrolls within the overlay instead of growing
|
||||||
|
// past the top of the screen. Leaves the upper half clear for the header.
|
||||||
|
const maxHeight = screenHeight / 2
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View
|
<View
|
||||||
style={[
|
style={[
|
||||||
@@ -46,6 +55,7 @@ export function Footer({altText, isAltExpanded, onToggleAltExpanded}: Props) {
|
|||||||
}),
|
}),
|
||||||
]}>
|
]}>
|
||||||
<ScrollView
|
<ScrollView
|
||||||
|
style={{maxHeight}}
|
||||||
scrollEnabled={isAltExpanded}
|
scrollEnabled={isAltExpanded}
|
||||||
onMomentumScrollBegin={() => {
|
onMomentumScrollBegin={() => {
|
||||||
isMomentumScrolling.current = true
|
isMomentumScrolling.current = true
|
||||||
|
|||||||
Reference in New Issue
Block a user