91 lines
2.0 KiB
TypeScript
91 lines
2.0 KiB
TypeScript
import React from 'react';
|
|
import { View, TouchableOpacity, ActivityIndicator } from 'react-native';
|
|
import { ThemedText } from '@/components/themed-text';
|
|
|
|
type TabKey = 'all' | 'image' | 'video';
|
|
|
|
const TABS: { key: TabKey; label: string }[] = [
|
|
{ key: 'all', label: 'All' },
|
|
{ key: 'image', label: 'Image' },
|
|
{ key: 'video', label: 'Video' },
|
|
];
|
|
|
|
export function ContentTabs({
|
|
activeTab,
|
|
onChangeTab,
|
|
isLoading = false,
|
|
}: {
|
|
activeTab: TabKey;
|
|
onChangeTab: (tab: TabKey) => void;
|
|
isLoading?: boolean;
|
|
}) {
|
|
const palette = darkPalette;
|
|
|
|
return (
|
|
<View style={[styles.tabsBar]}>
|
|
{TABS.map(tab => {
|
|
const isActive = tab.key === activeTab;
|
|
return (
|
|
<TouchableOpacity
|
|
key={tab.key}
|
|
activeOpacity={0.85}
|
|
onPress={() => onChangeTab(tab.key)}
|
|
disabled={isLoading}
|
|
style={[
|
|
styles.tabButton,
|
|
{
|
|
backgroundColor: isActive ? palette.tabActive : 'transparent',
|
|
},
|
|
]}
|
|
>
|
|
<ThemedText
|
|
style={[
|
|
styles.tabLabel,
|
|
{
|
|
color: isActive ? palette.onAccent : palette.textSecondary,
|
|
},
|
|
]}
|
|
>
|
|
{tab.label}
|
|
</ThemedText>
|
|
</TouchableOpacity>
|
|
);
|
|
})}
|
|
</View>
|
|
);
|
|
}
|
|
|
|
const darkPalette = {
|
|
pill: '#16171C',
|
|
border: '#1D1E24',
|
|
tabActive: '#FFFFFF',
|
|
onAccent: '#050505',
|
|
textSecondary: '#8E9098',
|
|
};
|
|
|
|
const styles = {
|
|
tabsBar: {
|
|
flexDirection: 'row' as const,
|
|
alignItems: 'center' as const,
|
|
justifyContent: 'flex-start' as const,
|
|
borderWidth: 0,
|
|
borderRadius: 999,
|
|
padding: 0,
|
|
gap: 4,
|
|
},
|
|
tabButton: {
|
|
borderRadius: 999,
|
|
paddingVertical: 10,
|
|
paddingHorizontal: 20,
|
|
alignItems: 'center' as const,
|
|
justifyContent: 'center' as const,
|
|
},
|
|
tabLabel: {
|
|
fontSize: 15,
|
|
fontWeight: '600' as const,
|
|
},
|
|
loadingIndicator: {
|
|
height: 18,
|
|
},
|
|
};
|