Skip to content

Commit

Permalink
Make the pager take full width (#7066)
Browse files Browse the repository at this point in the history
* Wide tabs for web

* Wide tabs on mobile

* Tweak min for profile

* Driveby border fix

* Fix single tab indicator
  • Loading branch information
gaearon authored Dec 12, 2024
1 parent 704e36c commit 8816692
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 12 deletions.
2 changes: 1 addition & 1 deletion src/screens/Hashtag.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ export default function HashtagScreen({

return (
<Layout.Screen>
<Layout.Header.Outer>
<Layout.Header.Outer noBottomBorder>
<Layout.Header.BackButton />
<Layout.Header.Content>
<Layout.Header.TitleText>{headerTitle}</Layout.Header.TitleText>
Expand Down
58 changes: 48 additions & 10 deletions src/view/com/pager/TabBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ export function TabBar({
const containerSize = useSharedValue(0)
const scrollX = useSharedValue(0)
const layouts = useSharedValue<{x: number; width: number}[]>([])
const textLayouts = useSharedValue<{width: number}[]>([])
const itemsLength = items.length

const scrollToOffsetJS = useCallback(
Expand Down Expand Up @@ -211,21 +212,40 @@ export function TabBar({
[layouts],
)

const onTextLayout = useCallback(
(i: number, layout: {width: number}) => {
'worklet'
textLayouts.modify(ls => {
ls[i] = layout
return ls
})
},
[textLayouts],
)

const indicatorStyle = useAnimatedStyle(() => {
if (!_WORKLET) {
return {opacity: 0}
}
const layoutsValue = layouts.get()
const textLayoutsValue = textLayouts.get()
if (
layoutsValue.length !== itemsLength ||
layoutsValue.some(l => l === undefined)
textLayoutsValue.length !== itemsLength
) {
return {
opacity: 0,
}
}
if (layoutsValue.length === 1) {
return {opacity: 1}
if (textLayoutsValue.length === 1) {
return {
opacity: 1,
transform: [
{
scaleX: textLayoutsValue[0].width / contentSize.get(),
},
],
}
}
return {
opacity: 1,
Expand All @@ -240,10 +260,8 @@ export function TabBar({
{
scaleX: interpolate(
dragProgress.get(),
layoutsValue.map((l, i) => i),
layoutsValue.map(
l => (l.width - ITEM_PADDING * 2) / contentSize.get(),
),
textLayoutsValue.map((l, i) => i),
textLayoutsValue.map(l => l.width / contentSize.get()),
),
},
],
Expand Down Expand Up @@ -287,7 +305,7 @@ export function TabBar({
onLayout={e => {
contentSize.set(e.nativeEvent.layout.width)
}}
style={{flexDirection: 'row'}}>
style={{flexDirection: 'row', flexGrow: 1}}>
{items.map((item, i) => {
return (
<TabBarItem
Expand All @@ -298,6 +316,7 @@ export function TabBar({
item={item}
onPressItem={onPressItem}
onItemLayout={onItemLayout}
onTextLayout={onTextLayout}
/>
)
})}
Expand Down Expand Up @@ -328,13 +347,15 @@ function TabBarItem({
item,
onPressItem,
onItemLayout,
onTextLayout,
}: {
index: number
testID: string | undefined
dragProgress: SharedValue<number>
item: string
onPressItem: (index: number) => void
onItemLayout: (index: number, layout: {x: number; width: number}) => void
onTextLayout: (index: number, layout: {width: number}) => void
}) {
const t = useTheme()
const style = useAnimatedStyle(() => {
Expand All @@ -358,8 +379,15 @@ function TabBarItem({
[index, onItemLayout],
)

const handleTextLayout = useCallback(
(e: LayoutChangeEvent) => {
runOnUI(onTextLayout)(index, e.nativeEvent.layout)
},
[index, onTextLayout],
)

return (
<View onLayout={handleLayout}>
<View onLayout={handleLayout} style={{flexGrow: 1}}>
<PressableWithHover
testID={`${testID}-selector-${index}`}
style={styles.item}
Expand All @@ -370,7 +398,8 @@ function TabBarItem({
<Text
emoji
testID={testID ? `${testID}-${item}` : undefined}
style={[t.atoms.text, a.text_md, a.font_bold, {lineHeight: 20}]}>
style={[styles.itemText, t.atoms.text, a.text_md, a.font_bold]}
onLayout={handleTextLayout}>
{item}
</Text>
</Animated.View>
Expand All @@ -381,19 +410,28 @@ function TabBarItem({

const styles = StyleSheet.create({
contentContainer: {
flexGrow: 1,
backgroundColor: 'transparent',
paddingHorizontal: CONTENT_PADDING,
},
item: {
flexGrow: 1,
paddingTop: 10,
paddingHorizontal: ITEM_PADDING,
justifyContent: 'center',
},
itemInner: {
alignItems: 'center',
flexGrow: 1,
paddingBottom: 10,
borderBottomWidth: 3,
borderBottomColor: 'transparent',
},
itemText: {
lineHeight: 20,
minWidth: 45,
textAlign: 'center',
},
outerBottomBorder: {
position: 'absolute',
left: 0,
Expand Down
21 changes: 20 additions & 1 deletion src/view/com/pager/TabBar.web.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -115,12 +115,14 @@ export function TabBar({
hoverStyle={t.atoms.bg_contrast_25}
onPress={() => onPressItem(i)}
accessibilityRole="tab">
<View style={[styles.itemInner, selected && indicatorStyle]}>
<View style={styles.itemInner}>
<Text
emoji
testID={testID ? `${testID}-${item}` : undefined}
style={[
styles.itemText,
selected ? t.atoms.text : t.atoms.text_contrast_medium,
selected && indicatorStyle,
a.text_md,
a.font_bold,
{lineHeight: 20},
Expand All @@ -143,15 +145,23 @@ const desktopStyles = StyleSheet.create({
width: 598,
},
contentContainer: {
flexGrow: 1,
paddingHorizontal: 0,
backgroundColor: 'transparent',
},
item: {
flexGrow: 1,
alignItems: 'stretch',
paddingTop: 14,
paddingHorizontal: 14,
justifyContent: 'center',
},
itemInner: {
alignItems: 'center',
},
itemText: {
textAlign: 'center',
minWidth: 45,
paddingBottom: 12,
borderBottomWidth: 3,
borderBottomColor: 'transparent',
Expand All @@ -170,15 +180,24 @@ const mobileStyles = StyleSheet.create({
flexDirection: 'row',
},
contentContainer: {
flexGrow: 1,
backgroundColor: 'transparent',
paddingHorizontal: 6,
},
item: {
flexGrow: 1,
alignItems: 'stretch',
paddingTop: 10,
paddingHorizontal: 10,
justifyContent: 'center',
},
itemInner: {
flexGrow: 1,
alignItems: 'center',
},
itemText: {
textAlign: 'center',
minWidth: 45,
paddingBottom: 10,
borderBottomWidth: 2,
borderBottomColor: 'transparent',
Expand Down

0 comments on commit 8816692

Please sign in to comment.