about summary refs log tree commit diff
path: root/src/components
diff options
context:
space:
mode:
authorSamuel Newman <mozzius@protonmail.com>2025-08-27 19:00:36 +0300
committerGitHub <noreply@github.com>2025-08-27 09:00:36 -0700
commit39d460db510d6545794f6acba8226fb52b506b40 (patch)
treeb3ca00a3dfb4c790fb78369942c122cee79ba9d0 /src/components
parenteac02901435d7bc79a28e0bff665352b814f9508 (diff)
downloadvoidsky-39d460db510d6545794f6acba8226fb52b506b40.tar.zst
Language select final tweaks (#8914)
* [APP-1303] Redesign/refactor post language select (#8884)

* Nightly source-language update

* Nightly source-language update

* [APP-1303] Redesign/refactor post language select

* update: stylesheets.create to use the latest structure

* update styles to modern structure

* update: dialog breakpoints on web and delete depricated language modals

* remove unused post languages settings dialog

* restructure Post languages dialog

* place the Dialog.Close inside the Dialog.ScrollableInner

* add: language search

* update search and language variables for clarity

* fix: memoize language state lists

* chore: add comments

* update proper colors to the background

* add back older error boundary

* add: tweaks to the mobile and web responsiveness

* add tweaks to center the container

* update labels

* update button and border

* added translation updates

* Update: text input to reuse search input

* remove unused file

* update: web breakpoints

* run eslint and prettier

---------

Co-authored-by: Elijah Seed-Arita <elijaharita@gmail.com>
Co-authored-by: Anastasiya Uraleva <anastasiya@Anastasiyas-MacBook-Pro.local>
Co-authored-by: Anastasiya Uraleva <anastasiya@Mac.localdomain>

* rm old file

* sort out styles, add FlatListFooter component

* rm cancel button in favor of search input X

* get dialog height working on iOS

* delete `DropdownButton`

* hide scroll indicators on android

* ios scroll indicator insets

* get footer sorta working on android

* change button color on press

* rm empty file

---------

Co-authored-by: Anastasiya Uraleva <anastasiyauraleva@gmail.com>
Co-authored-by: Elijah Seed-Arita <elijaharita@gmail.com>
Co-authored-by: Anastasiya Uraleva <anastasiya@Anastasiyas-MacBook-Pro.local>
Co-authored-by: Anastasiya Uraleva <anastasiya@Mac.localdomain>
Diffstat (limited to 'src/components')
-rw-r--r--src/components/Dialog/index.tsx61
-rw-r--r--src/components/Dialog/index.web.tsx38
-rw-r--r--src/components/forms/Toggle.tsx6
3 files changed, 94 insertions, 11 deletions
diff --git a/src/components/Dialog/index.tsx b/src/components/Dialog/index.tsx
index 4795385ee..de8287a53 100644
--- a/src/components/Dialog/index.tsx
+++ b/src/components/Dialog/index.tsx
@@ -12,9 +12,13 @@ import {
 import {
   KeyboardAwareScrollView,
   useKeyboardHandler,
+  useReanimatedKeyboardAnimation,
 } from 'react-native-keyboard-controller'
-import {runOnJS} from 'react-native-reanimated'
-import {type ReanimatedScrollEvent} from 'react-native-reanimated/lib/typescript/hook/commonTypes'
+import Animated, {
+  runOnJS,
+  type ScrollEvent,
+  useAnimatedStyle,
+} from 'react-native-reanimated'
 import {useSafeAreaInsets} from 'react-native-safe-area-context'
 import {msg} from '@lingui/macro'
 import {useLingui} from '@lingui/react'
@@ -26,7 +30,7 @@ import {isAndroid, isIOS} from '#/platform/detection'
 import {useA11y} from '#/state/a11y'
 import {useDialogStateControlContext} from '#/state/dialogs'
 import {List, type ListMethods, type ListProps} from '#/view/com/util/List'
-import {atoms as a, tokens, useTheme} from '#/alf'
+import {atoms as a, ios, platform, tokens, useTheme} from '#/alf'
 import {useThemeName} from '#/alf/util/useColorModeTheme'
 import {Context, useDialogContext} from '#/components/Dialog/context'
 import {
@@ -256,6 +260,7 @@ export const ScrollableInner = React.forwardRef<ScrollView, DialogInnerProps>(
           contentContainerStyle,
         ]}
         ref={ref}
+        showsVerticalScrollIndicator={isAndroid ? false : undefined}
         {...props}
         bounces={nativeSnapPoint === BottomSheetSnapPoint.Full}
         bottomOffset={30}
@@ -275,12 +280,15 @@ export const InnerFlatList = React.forwardRef<
   ListProps<any> & {
     webInnerStyle?: StyleProp<ViewStyle>
     webInnerContentContainerStyle?: StyleProp<ViewStyle>
+    footer?: React.ReactNode
   }
->(function InnerFlatList({style, ...props}, ref) {
+>(function InnerFlatList({footer, style, ...props}, ref) {
   const insets = useSafeAreaInsets()
   const {nativeSnapPoint, disableDrag, setDisableDrag} = useDialogContext()
 
-  const onScroll = (e: ReanimatedScrollEvent) => {
+  useEnableKeyboardController(isIOS)
+
+  const onScroll = (e: ScrollEvent) => {
     'worklet'
     if (!isAndroid) {
       return
@@ -300,13 +308,54 @@ export const InnerFlatList = React.forwardRef<
         bounces={nativeSnapPoint === BottomSheetSnapPoint.Full}
         ListFooterComponent={<View style={{height: insets.bottom + 100}} />}
         ref={ref}
+        showsVerticalScrollIndicator={isAndroid ? false : undefined}
         {...props}
-        style={[style]}
+        style={[a.h_full, style]}
       />
+      {footer}
     </ScrollProvider>
   )
 })
 
+export function FlatListFooter({children}: {children: React.ReactNode}) {
+  const t = useTheme()
+  const {top, bottom} = useSafeAreaInsets()
+  const {height} = useReanimatedKeyboardAnimation()
+
+  const animatedStyle = useAnimatedStyle(() => {
+    if (!isIOS) return {}
+    return {
+      transform: [{translateY: Math.min(0, height.get() + bottom - 10)}],
+    }
+  })
+
+  return (
+    <Animated.View
+      style={[
+        a.absolute,
+        a.bottom_0,
+        a.w_full,
+        a.z_10,
+        a.border_t,
+        t.atoms.bg,
+        t.atoms.border_contrast_low,
+        a.px_lg,
+        a.pt_md,
+        {
+          paddingBottom: platform({
+            ios: tokens.space.md + bottom,
+            android: tokens.space.md + bottom + top,
+          }),
+        },
+        // TODO: had to admit defeat here, but we should
+        // try and get this to work for Android as well -sfn
+        ios(animatedStyle),
+      ]}>
+      {children}
+    </Animated.View>
+  )
+}
+
 export function Handle({difference = false}: {difference?: boolean}) {
   const t = useTheme()
   const {_} = useLingui()
diff --git a/src/components/Dialog/index.web.tsx b/src/components/Dialog/index.web.tsx
index 7e10dfadc..1d62cbfdc 100644
--- a/src/components/Dialog/index.web.tsx
+++ b/src/components/Dialog/index.web.tsx
@@ -33,6 +33,9 @@ export * from '#/components/Dialog/types'
 export * from '#/components/Dialog/utils'
 export {Input} from '#/components/forms/TextField'
 
+// 100 minus 10vh of paddingVertical
+export const WEB_DIALOG_HEIGHT = '80vh'
+
 const stopPropagation = (e: any) => e.stopPropagation()
 const preventDefault = (e: any) => e.preventDefault()
 
@@ -215,9 +218,17 @@ export const InnerFlatList = React.forwardRef<
   FlatListProps<any> & {label: string} & {
     webInnerStyle?: StyleProp<ViewStyle>
     webInnerContentContainerStyle?: StyleProp<ViewStyle>
+    footer?: React.ReactNode
   }
 >(function InnerFlatList(
-  {label, style, webInnerStyle, webInnerContentContainerStyle, ...props},
+  {
+    label,
+    style,
+    webInnerStyle,
+    webInnerContentContainerStyle,
+    footer,
+    ...props
+  },
   ref,
 ) {
   const {gtMobile} = useBreakpoints()
@@ -227,8 +238,7 @@ export const InnerFlatList = React.forwardRef<
       style={[
         a.overflow_hidden,
         a.px_0,
-        // 100 minus 10vh of paddingVertical
-        web({maxHeight: '80vh'}),
+        web({maxHeight: WEB_DIALOG_HEIGHT}),
         webInnerStyle,
       ]}
       contentContainerStyle={[a.h_full, a.px_0, webInnerContentContainerStyle]}>
@@ -237,10 +247,32 @@ export const InnerFlatList = React.forwardRef<
         style={[a.h_full, gtMobile ? a.px_2xl : a.px_xl, flatten(style)]}
         {...props}
       />
+      {footer}
     </Inner>
   )
 })
 
+export function FlatListFooter({children}: {children: React.ReactNode}) {
+  const t = useTheme()
+
+  return (
+    <View
+      style={[
+        a.absolute,
+        a.bottom_0,
+        a.w_full,
+        a.z_10,
+        t.atoms.bg,
+        a.border_t,
+        t.atoms.border_contrast_low,
+        a.px_lg,
+        a.py_md,
+      ]}>
+      {children}
+    </View>
+  )
+}
+
 export function Close() {
   const {_} = useLingui()
   const {close} = React.useContext(Context)
diff --git a/src/components/forms/Toggle.tsx b/src/components/forms/Toggle.tsx
index 9c3564aa5..bb9fde2e1 100644
--- a/src/components/forms/Toggle.tsx
+++ b/src/components/forms/Toggle.tsx
@@ -1,5 +1,5 @@
 import React from 'react'
-import {Pressable, View, type ViewStyle} from 'react-native'
+import {Pressable, type StyleProp, View, type ViewStyle} from 'react-native'
 import Animated, {LinearTransition} from 'react-native-reanimated'
 
 import {HITSLOP_10} from '#/lib/constants'
@@ -59,6 +59,7 @@ export type GroupProps = React.PropsWithChildren<{
   disabled?: boolean
   onChange: (value: string[]) => void
   label: string
+  style?: StyleProp<ViewStyle>
 }>
 
 export type ItemProps = ViewStyleProp & {
@@ -84,6 +85,7 @@ export function Group({
   type = 'checkbox',
   maxSelections,
   label,
+  style,
 }: GroupProps) {
   const groupRole = type === 'radio' ? 'radiogroup' : undefined
   const values = type === 'radio' ? providedValues.slice(0, 1) : providedValues
@@ -136,7 +138,7 @@ export function Group({
   return (
     <GroupContext.Provider value={context}>
       <View
-        style={[a.w_full]}
+        style={[a.w_full, style]}
         role={groupRole}
         {...(groupRole === 'radiogroup'
           ? {