fix(feed): side padding on action row + stable FAB right-anchor

- Post action row (chat / ❤ / eye / share) had only a small paddingRight
  and no left padding. First icon sat flush under the avatar and share
  iron against the card edge. Replaced with paddingHorizontal: 12 so
  both sides get equal breathing room; each of the four cells still
  flex:1 so the icons distribute evenly.
- FAB kept appearing at the LEFT edge instead of the right on user's
  device despite position:absolute + right:12. Pressable's dynamic-
  function style can drop absolute-positioning fields between renders
  on some RN versions. Wrapping the Pressable in a plain absolute-
  positioned View fixes this: positioning lives on the View (never
  re-evaluated mid-render), the Pressable inside only declares size
  and visuals. pointerEvents="box-none" on the wrapper keeps taps
  outside the button passing through to the feed list below.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
vsecoder
2026-04-18 20:31:03 +03:00
parent f688f45739
commit 7bfd8c7dea
2 changed files with 35 additions and 21 deletions

View File

@@ -251,16 +251,27 @@ export default function FeedScreen() {
contentContainerStyle={posts.length === 0 ? { flexGrow: 1 } : undefined} contentContainerStyle={posts.length === 0 ? { flexGrow: 1 } : undefined}
/> />
{/* Floating compose button — pinned 12px from the right edge of {/* Floating compose button.
the screen and 12px above the NavBar top. The Feed screen's *
container ends at the NavBar top (see (app)/_layout.tsx), so * Pressable's dynamic-function style sometimes drops absolute
a plain bottom: 12 measures from exactly that edge. */} * positioning on re-render on some RN versions — we've seen the
<Pressable * button slide to the left edge after the first render. Wrap it
onPress={() => router.push('/(app)/compose' as never)} * in a plain absolute-positioned View so positioning lives on a
style={({ pressed }) => ({ * stable element; the Pressable inside only declares its size
* and visuals. The parent Feed screen's container ends at the
* NavBar top (see (app)/_layout.tsx), so bottom: 12 means 12px
* above the NavBar on every device. */}
<View
pointerEvents="box-none"
style={{
position: 'absolute', position: 'absolute',
right: 12, right: 12,
bottom: 12, bottom: 12,
}}
>
<Pressable
onPress={() => router.push('/(app)/compose' as never)}
style={({ pressed }) => ({
width: 56, height: 56, width: 56, height: 56,
borderRadius: 28, borderRadius: 28,
backgroundColor: pressed ? '#1a8cd8' : '#1d9bf0', backgroundColor: pressed ? '#1a8cd8' : '#1d9bf0',
@@ -275,6 +286,7 @@ export default function FeedScreen() {
<Ionicons name="create-outline" size={24} color="#ffffff" /> <Ionicons name="create-outline" size={24} color="#ffffff" />
</Pressable> </Pressable>
</View> </View>
</View>
); );
} }

View File

@@ -247,14 +247,16 @@ function PostCardInner({ post, likedByMe, onStatsChanged, onDeleted, compact }:
{/* Action row — 4 evenly-spaced buttons (Twitter-style). Each is {/* Action row — 4 evenly-spaced buttons (Twitter-style). Each is
wrapped in a flex: 1 container so even if one label is wrapped in a flex: 1 container so even if one label is
wider than another, visual spacing between centres stays wider than another, visual spacing between centres stays
balanced. */} balanced. paddingHorizontal gives extra breathing room on
both sides so the first icon isn't flush under the avatar
and the share icon isn't flush with the card edge. */}
<View <View
style={{ style={{
flexDirection: 'row', flexDirection: 'row',
alignItems: 'center', alignItems: 'center',
justifyContent: 'space-between', justifyContent: 'space-between',
marginTop: 12, marginTop: 12,
paddingRight: 4, paddingHorizontal: 12,
}} }}
> >
<View style={{ flex: 1, alignItems: 'flex-start' }}> <View style={{ flex: 1, alignItems: 'flex-start' }}>