[Chat] NUX (#10848)

Co-authored-by: DS Boyce <260543580+ds-boyce@users.noreply.github.com>
Co-authored-by: Eric Bailey <git@esb.lol>
This commit is contained in:
Samuel Newman
2026-06-10 22:35:35 +03:00
committed by GitHub
parent 2d896983ab
commit 2efdc3fe35
14 changed files with 404 additions and 60 deletions
+43 -38
View File
@@ -218,7 +218,7 @@ export function Inner({children, style, header}: DialogInnerProps) {
export const ScrollableInner = forwardRef<ScrollView, DialogInnerProps>(
function ScrollableInner(
{children, contentContainerStyle, header, style, ...props},
{children, contentContainerStyle, header, footer, style, ...props},
ref,
) {
const {nativeSnapPoint, disableDrag, setDisableDrag, isHeightConstrained} =
@@ -248,42 +248,45 @@ export const ScrollableInner = forwardRef<ScrollView, DialogInnerProps>(
}
return (
<ScrollView
style={[isHeightConstrained && a.flex_1, style]}
contentContainerStyle={[
a.pt_2xl,
IS_LIQUID_GLASS ? a.px_2xl : a.px_xl,
platform({
ios: a.pb_2xl,
android: {
paddingBottom: keyboardHeight + insets.bottom + tokens.space.xl,
},
}),
contentContainerStyle,
]}
ref={ref}
showsVerticalScrollIndicator={IS_ANDROID ? false : undefined}
contentInsetAdjustmentBehavior={
isAtMaxSnapPoint ? 'automatic' : 'never'
}
automaticallyAdjustKeyboardInsets={isAtMaxSnapPoint}
{...props}
bounces={isAtMaxSnapPoint}
scrollEventThrottle={50}
// set drag state based on scroll on android.
// we want to detect if it's at the top or not, so watch
// scrollEndDrag and momentumScrollEnd as well
onScroll={android(onScroll)}
onScrollEndDrag={android(onScroll)}
onMomentumScrollEnd={android(onScroll)}
keyboardShouldPersistTaps="handled"
// TODO: figure out why this positions the header absolutely (rather than stickily)
// on Android. fine to disable for now, because we don't have any
// dialogs that use this that actually scroll -sfn
stickyHeaderIndices={ios(header ? [0] : undefined)}>
{header}
{children}
</ScrollView>
<>
<ScrollView
style={[isHeightConstrained && a.flex_1, style]}
contentContainerStyle={[
a.pt_2xl,
IS_LIQUID_GLASS ? a.px_2xl : a.px_xl,
platform({
ios: a.pb_2xl,
android: {
paddingBottom: keyboardHeight + insets.bottom + tokens.space.xl,
},
}),
contentContainerStyle,
]}
ref={ref}
showsVerticalScrollIndicator={IS_ANDROID ? false : undefined}
contentInsetAdjustmentBehavior={
isAtMaxSnapPoint ? 'automatic' : 'never'
}
automaticallyAdjustKeyboardInsets={isAtMaxSnapPoint}
{...props}
bounces={isAtMaxSnapPoint}
scrollEventThrottle={50}
// set drag state based on scroll on android.
// we want to detect if it's at the top or not, so watch
// scrollEndDrag and momentumScrollEnd as well
onScroll={android(onScroll)}
onScrollEndDrag={android(onScroll)}
onMomentumScrollEnd={android(onScroll)}
keyboardShouldPersistTaps="handled"
// TODO: figure out why this positions the header absolutely (rather than stickily)
// on Android. fine to disable for now, because we don't have any
// dialogs that use this that actually scroll -sfn
stickyHeaderIndices={ios(header ? [0] : undefined)}>
{header}
{children}
</ScrollView>
{footer}
</>
)
},
)
@@ -350,9 +353,11 @@ export const InnerFlatList = forwardRef<
export function FlatListFooter({
children,
onLayout,
border = true,
}: {
children: React.ReactNode
onLayout?: (event: LayoutChangeEvent) => void
border?: boolean
}) {
const t = useTheme()
const {bottom} = useSafeAreaInsets()
@@ -373,7 +378,7 @@ export function FlatListFooter({
a.bottom_0,
a.w_full,
a.z_10,
a.border_t,
border && a.border_t,
t.atoms.bg,
t.atoms.border_contrast_low,
a.px_lg,
+5 -1
View File
@@ -170,6 +170,7 @@ export function Inner({
accessibilityLabelledBy,
accessibilityDescribedBy,
header,
footer,
contentContainerStyle,
}: DialogInnerProps) {
const t = useTheme()
@@ -216,6 +217,7 @@ export function Inner({
<View style={[gtMobile ? a.p_2xl : a.p_xl, contentContainerStyle]}>
{children}
</View>
{footer}
</DismissableLayer.DismissableLayer>
</View>
</FocusScope.FocusScope>
@@ -266,9 +268,11 @@ export const InnerFlatList = forwardRef<
export function FlatListFooter({
children,
onLayout,
border = true,
}: {
children: React.ReactNode
onLayout?: (event: LayoutChangeEvent) => void
border?: boolean
}) {
const t = useTheme()
@@ -281,7 +285,7 @@ export function FlatListFooter({
a.w_full,
a.z_10,
t.atoms.bg,
a.border_t,
border && a.border_t,
t.atoms.border_contrast_low,
a.px_lg,
a.py_md,
+4
View File
@@ -79,14 +79,18 @@ export type DialogInnerProps =
accessibilityLabelledBy: A11yProps['aria-labelledby']
accessibilityDescribedBy: string
keyboardDismissMode?: ScrollViewProps['keyboardDismissMode']
showsVerticalScrollIndicator?: ScrollViewProps['showsVerticalScrollIndicator']
contentContainerStyle?: StyleProp<ViewStyle>
header?: React.ReactNode
footer?: React.ReactNode
}>
| DialogInnerPropsBase<{
label: string
accessibilityLabelledBy?: undefined
accessibilityDescribedBy?: undefined
keyboardDismissMode?: ScrollViewProps['keyboardDismissMode']
showsVerticalScrollIndicator?: ScrollViewProps['showsVerticalScrollIndicator']
contentContainerStyle?: StyleProp<ViewStyle>
header?: React.ReactNode
footer?: React.ReactNode
}>