about summary refs log tree commit diff
path: root/src/view/shell
diff options
context:
space:
mode:
authorEric Bailey <git@esb.lol>2024-12-05 18:59:26 -0600
committerGitHub <noreply@github.com>2024-12-05 18:59:26 -0600
commit143e2c802d1d8d8498e6658c174ed1e657c4ec12 (patch)
treecbe937bec7e0a241774060ade7428180c4fe0aaf /src/view/shell
parent8467dfd452b4cb1b62214b3abe87fd90d23a183b (diff)
downloadvoidsky-143e2c802d1d8d8498e6658c174ed1e657c4ec12.tar.zst
[Layout] Base (#6907)
* Add common gutter styles as hook

* Add computed scrollbar gutter CSS vars

* Add new layout components

* Replace layout components in settings screens

* Remove old back button

* Invert web border logic for easier migration

* Clean up Slot API

* Port over FF handling of scrollbar offset

* Trade boilerplate for ease of use

* Limit to one line

* Allow two lines, fix wrapping

* Fix alignment

* sticky headers

* set max with on header and center

* [Layout] Notifications Header (#6910)

* Replace notifications screen header

* fix cropped indicator

---------

Co-authored-by: Samuel Newman <mozzius@protonmail.com>

* Replace Hashtag header (#6928)

* [Layout] ChatList header (#6929)

* Replace ChatList header

* update chat settings as well

---------

Co-authored-by: Samuel Newman <mozzius@protonmail.com>

* Add web borders to Chat settings

* Remove unused var

* Move ChatList header outside center

* Replace empty chat layout

* fix breakpoints

* [Layout] Scrollbar gutters (#6908)

* Fix sidebar alignment

* Make sure scrollbars don't hide

* Gift left nav more space

* Use stable one-edge, update logic in RightNav

* Ope

* Increase width

* Reset

* Add transform to sidebars

* Remove bg in sidebars

* Handle shifts in layout components

* Replace scroll-removal handling

* Make react-remove-scroll an explicit dep

* Remove unused script

* use correct scroll insets (#6950)

* [Layout] Feeds headers (#6913)

* Replace ViewHeader internals, duplicate old ViewHeader

* Replace Feeds header

* Replace SavedFeeds header

* Visual alignment

* Uglier but clear

* Use old ViewHeader for SavedFeeds

* use Layout.Center instead of Layout.Content

* use left-aligned header for feed edit

* delete unused old view header

---------

Co-authored-by: Samuel Newman <mozzius@protonmail.com>

* [Layout] Every other screen (#6953)

* attempt to fix double borders on every other screen

* delete ListHeaderDesktop

* delete `SimpleViewHeader` and fix screens (#6956)

* Make Layout.Center not full height

* Refactor List to use Layout.Center, remove built-in borders

* Fix Home screen

* Refactor PagerWithHeader to use Layout components

* Replace components in ProfileFeed and ProfileList

* Borders on Profile

* Search screen replacements

* use new header for profile subpage header (#6958)

* Search AutocompleteResults

* use new header for starter pack wizard (#6957)

* Fix post thread

* Enable borders by default

* Moderation muted and blocked accounts

* Fix scrollbar offset on Labeler

* Remove ScrollView from Moderation

* Remove ScrollView from Deactivated

* Remove ScrollView from onboarding

* Remove ScrollView from SignupQueued

* Mark deprecations

* fix lint

* Fix double borders on profile load

* Remove unneeded CenteredView from noty Feed

* Remove double Center layout on Notifications screen

* Remove double Center layout on ChatList screen

* Handle scrollbar offset in chat

* Use new atom for other scrollbar offsets

* Remove borders from old views

* Better doc

* Remove temp migration prop

* Fix new atom usage on native

* Clean up Hashtag screen

* Layout docs

* Clarify usage in Pager

* Handle nested offset contexts

* Clean up Layout

* fix feeds page

* asymmetric header on native (#6969)

* Reusable header const

* Fix up home header

* Add back button to convo

* Add hitslop to header buttons

* Comment

* Better handling on native for new atom

* Format

* Fix nested flatlist on mod screens

* Use react-remove-scroll-bar directly

* Fix notification count overflow on web

* Clarify doc

---------

Co-authored-by: Samuel Newman <mozzius@protonmail.com>
Diffstat (limited to 'src/view/shell')
-rw-r--r--src/view/shell/Composer.web.tsx11
-rw-r--r--src/view/shell/desktop/LeftNav.tsx131
-rw-r--r--src/view/shell/desktop/RightNav.tsx11
-rw-r--r--src/view/shell/index.web.tsx54
4 files changed, 96 insertions, 111 deletions
diff --git a/src/view/shell/Composer.web.tsx b/src/view/shell/Composer.web.tsx
index 9f407248a..47a86ed24 100644
--- a/src/view/shell/Composer.web.tsx
+++ b/src/view/shell/Composer.web.tsx
@@ -3,8 +3,8 @@ import {StyleSheet, View} from 'react-native'
 import {DismissableLayer} from '@radix-ui/react-dismissable-layer'
 import {useFocusGuards} from '@radix-ui/react-focus-guards'
 import {FocusScope} from '@radix-ui/react-focus-scope'
+import {RemoveScrollBar} from 'react-remove-scroll-bar'
 
-import {useWebBodyScrollLock} from '#/lib/hooks/useWebBodyScrollLock'
 import {useModals} from '#/state/modals'
 import {ComposerOpts, useComposerState} from '#/state/shell/composer'
 import {
@@ -20,8 +20,6 @@ export function Composer({}: {winHeight: number}) {
   const state = useComposerState()
   const isActive = !!state
 
-  useWebBodyScrollLock(isActive)
-
   // rendering
   // =
 
@@ -29,7 +27,12 @@ export function Composer({}: {winHeight: number}) {
     return <View />
   }
 
-  return <Inner state={state} />
+  return (
+    <>
+      <RemoveScrollBar />
+      <Inner state={state} />
+    </>
+  )
 }
 
 function Inner({state}: {state: ComposerOpts}) {
diff --git a/src/view/shell/desktop/LeftNav.tsx b/src/view/shell/desktop/LeftNav.tsx
index 0af80854c..7c2ccd958 100644
--- a/src/view/shell/desktop/LeftNav.tsx
+++ b/src/view/shell/desktop/LeftNav.tsx
@@ -1,9 +1,6 @@
 import React from 'react'
-import {StyleSheet, TouchableOpacity, View} from 'react-native'
-import {
-  FontAwesomeIcon,
-  FontAwesomeIconStyle,
-} from '@fortawesome/react-native-fontawesome'
+import {StyleSheet, View} from 'react-native'
+import {FontAwesomeIconStyle} from '@fortawesome/react-native-fontawesome'
 import {msg, Trans} from '@lingui/macro'
 import {useLingui} from '@lingui/react'
 import {
@@ -14,9 +11,9 @@ import {
 
 import {usePalette} from '#/lib/hooks/usePalette'
 import {useWebMediaQueries} from '#/lib/hooks/useWebMediaQueries'
-import {getCurrentRoute, isStateAtTabRoot, isTab} from '#/lib/routes/helpers'
+import {getCurrentRoute, isTab} from '#/lib/routes/helpers'
 import {makeProfileLink} from '#/lib/routes/links'
-import {CommonNavigatorParams, NavigationProp} from '#/lib/routes/types'
+import {CommonNavigatorParams} from '#/lib/routes/types'
 import {isInvalidHandle} from '#/lib/strings/handles'
 import {emitSoftReset} from '#/state/events'
 import {useFetchHandle} from '#/state/queries/handle'
@@ -101,47 +98,6 @@ function ProfileCard() {
   )
 }
 
-const HIDDEN_BACK_BNT_ROUTES = ['StarterPackWizard', 'StarterPackEdit']
-
-function BackBtn() {
-  const {isTablet} = useWebMediaQueries()
-  const pal = usePalette('default')
-  const navigation = useNavigation<NavigationProp>()
-  const {_} = useLingui()
-  const shouldShow = useNavigationState(
-    state =>
-      !isStateAtTabRoot(state) &&
-      !HIDDEN_BACK_BNT_ROUTES.includes(getCurrentRoute(state).name),
-  )
-
-  const onPressBack = React.useCallback(() => {
-    if (navigation.canGoBack()) {
-      navigation.goBack()
-    } else {
-      navigation.navigate('Home')
-    }
-  }, [navigation])
-
-  if (!shouldShow || isTablet) {
-    return <></>
-  }
-  return (
-    <TouchableOpacity
-      testID="viewHeaderBackOrMenuBtn"
-      onPress={onPressBack}
-      style={styles.backBtn}
-      accessibilityRole="button"
-      accessibilityLabel={_(msg`Go back`)}
-      accessibilityHint="">
-      <FontAwesomeIcon
-        size={24}
-        icon="angle-left"
-        style={pal.text as FontAwesomeIconStyle}
-      />
-    </TouchableOpacity>
-  )
-}
-
 interface NavItemProps {
   count?: string
   href: string
@@ -220,35 +176,44 @@ function NavItem({count, href, icon, iconFilled, label}: NavItemProps) {
         ]}>
         {isCurrent ? iconFilled : icon}
         {typeof count === 'string' && count ? (
-          <Text
-            accessibilityLabel={_(msg`${count} unread items`)}
-            accessibilityHint=""
-            accessible={true}
+          <View
             style={[
               a.absolute,
-              a.text_xs,
-              a.font_bold,
-              a.rounded_full,
-              a.text_center,
-              {
-                top: '-10%',
-                left: count.length === 1 ? '50%' : '40%',
-                backgroundColor: t.palette.primary_500,
-                color: t.palette.white,
-                lineHeight: a.text_sm.fontSize,
-                paddingHorizontal: 4,
-                paddingVertical: 1,
-                minWidth: 16,
-              },
-              isTablet && [
+              a.inset_0,
+              {right: -20}, // more breathing room
+            ]}>
+            <Text
+              accessibilityLabel={_(msg`${count} unread items`)}
+              accessibilityHint=""
+              accessible={true}
+              numberOfLines={1}
+              style={[
+                a.absolute,
+                a.text_xs,
+                a.font_bold,
+                a.rounded_full,
+                a.text_center,
+                a.leading_tight,
                 {
-                  top: '10%',
-                  left: count.length === 1 ? '50%' : '40%',
+                  top: '-10%',
+                  left: count.length === 1 ? 12 : 8,
+                  backgroundColor: t.palette.primary_500,
+                  color: t.palette.white,
+                  lineHeight: a.text_sm.fontSize,
+                  paddingHorizontal: 4,
+                  paddingVertical: 1,
+                  minWidth: 16,
                 },
-              ],
-            ]}>
-            {count}
-          </Text>
+                isTablet && [
+                  {
+                    top: '10%',
+                    left: count.length === 1 ? 20 : 16,
+                  },
+                ],
+              ]}>
+              {count}
+            </Text>
+          </View>
         ) : null}
       </View>
       {gtTablet && (
@@ -366,9 +331,9 @@ export function DesktopLeftNav() {
     <View
       role="navigation"
       style={[
+        a.px_xl,
         styles.leftNav,
         isTablet && styles.leftNavTablet,
-        pal.view,
         pal.border,
       ]}>
       {hasSession ? (
@@ -381,8 +346,6 @@ export function DesktopLeftNav() {
 
       {hasSession && (
         <>
-          <BackBtn />
-
           <NavItem
             href="/"
             icon={
@@ -525,8 +488,17 @@ const styles = StyleSheet.create({
     position: 'fixed',
     top: 10,
     // @ts-ignore web only
-    left: 'calc(50vw - 300px - 220px - 20px)',
-    width: 220,
+    left: '50%',
+    transform: [
+      {
+        translateX: -300,
+      },
+      {
+        translateX: '-100%',
+      },
+      ...a.scrollbar_offset.transform,
+    ],
+    width: 240,
     // @ts-ignore web only
     maxHeight: 'calc(100vh - 10px)',
     overflowY: 'auto',
@@ -538,7 +510,10 @@ const styles = StyleSheet.create({
     borderRightWidth: 1,
     height: '100%',
     width: 76,
+    paddingLeft: 0,
+    paddingRight: 0,
     alignItems: 'center',
+    transform: [],
   },
 
   profileCard: {
diff --git a/src/view/shell/desktop/RightNav.tsx b/src/view/shell/desktop/RightNav.tsx
index 4f413211f..7814f3548 100644
--- a/src/view/shell/desktop/RightNav.tsx
+++ b/src/view/shell/desktop/RightNav.tsx
@@ -28,7 +28,7 @@ export function DesktopRightNav({routeName}: {routeName: string}) {
   }
 
   return (
-    <View style={[styles.rightNav, pal.view]}>
+    <View style={[a.px_xl, styles.rightNav]}>
       <View style={{paddingVertical: 20}}>
         {routeName === 'Search' ? (
           <View style={{marginBottom: 18}}>
@@ -122,8 +122,13 @@ const styles = StyleSheet.create({
     // @ts-ignore web only
     position: 'fixed',
     // @ts-ignore web only
-    left: 'calc(50vw + 300px + 20px)',
-    width: 300,
+    left: '50%',
+    transform: [
+      {
+        translateX: 300,
+      },
+      ...a.scrollbar_offset.transform,
+    ],
     maxHeight: '100%',
     overflowY: 'auto',
   },
diff --git a/src/view/shell/index.web.tsx b/src/view/shell/index.web.tsx
index f55437356..8c30813ab 100644
--- a/src/view/shell/index.web.tsx
+++ b/src/view/shell/index.web.tsx
@@ -3,10 +3,10 @@ import {StyleSheet, TouchableWithoutFeedback, View} from 'react-native'
 import {msg} from '@lingui/macro'
 import {useLingui} from '@lingui/react'
 import {useNavigation} from '@react-navigation/native'
+import {RemoveScrollBar} from 'react-remove-scroll-bar'
 
 import {useColorSchemeStyle} from '#/lib/hooks/useColorSchemeStyle'
 import {useIntentHandler} from '#/lib/hooks/useIntentHandler'
-import {useWebBodyScrollLock} from '#/lib/hooks/useWebBodyScrollLock'
 import {useWebMediaQueries} from '#/lib/hooks/useWebMediaQueries'
 import {NavigationProp} from '#/lib/routes/types'
 import {colors} from '#/lib/styles'
@@ -34,7 +34,6 @@ function ShellInner() {
   const {_} = useLingui()
   const showDrawer = !isDesktop && isDrawerOpen
 
-  useWebBodyScrollLock(showDrawer)
   useComposerKeyboardShortcut()
   useIntentHandler()
 
@@ -58,31 +57,34 @@ function ShellInner() {
       <PortalOutlet />
 
       {showDrawer && (
-        <TouchableWithoutFeedback
-          onPress={ev => {
-            // Only close if press happens outside of the drawer
-            if (ev.target === ev.currentTarget) {
-              setDrawerOpen(false)
-            }
-          }}
-          accessibilityLabel={_(msg`Close navigation footer`)}
-          accessibilityHint={_(msg`Closes bottom navigation bar`)}>
-          <View
-            style={[
-              styles.drawerMask,
-              {
-                backgroundColor: select(t.name, {
-                  light: 'rgba(0, 57, 117, 0.1)',
-                  dark: 'rgba(1, 82, 168, 0.1)',
-                  dim: 'rgba(10, 13, 16, 0.8)',
-                }),
-              },
-            ]}>
-            <View style={styles.drawerContainer}>
-              <DrawerContent />
+        <>
+          <RemoveScrollBar />
+          <TouchableWithoutFeedback
+            onPress={ev => {
+              // Only close if press happens outside of the drawer
+              if (ev.target === ev.currentTarget) {
+                setDrawerOpen(false)
+              }
+            }}
+            accessibilityLabel={_(msg`Close navigation footer`)}
+            accessibilityHint={_(msg`Closes bottom navigation bar`)}>
+            <View
+              style={[
+                styles.drawerMask,
+                {
+                  backgroundColor: select(t.name, {
+                    light: 'rgba(0, 57, 117, 0.1)',
+                    dark: 'rgba(1, 82, 168, 0.1)',
+                    dim: 'rgba(10, 13, 16, 0.8)',
+                  }),
+                },
+              ]}>
+              <View style={styles.drawerContainer}>
+                <DrawerContent />
+              </View>
             </View>
-          </View>
-        </TouchableWithoutFeedback>
+          </TouchableWithoutFeedback>
+        </>
       )}
     </>
   )