Skip to content

Commit 2f1ae64

Browse files
authored
Merge pull request #9 from TritonSE/shared-components
complete navbar
2 parents 1c3eaa9 + 771594a commit 2f1ae64

File tree

10 files changed

+140
-3
lines changed

10 files changed

+140
-3
lines changed
Lines changed: 3 additions & 0 deletions
Loading

frontend/assets/icons/home.svg

Lines changed: 3 additions & 0 deletions
Loading
Lines changed: 3 additions & 0 deletions
Loading

frontend/assets/icons/library.svg

Lines changed: 3 additions & 0 deletions
Loading
Lines changed: 4 additions & 0 deletions
Loading

frontend/assets/icons/search.svg

Lines changed: 3 additions & 0 deletions
Loading
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import { Platform, StyleSheet } from "react-native";
2+
3+
export const styles = StyleSheet.create({
4+
container: {
5+
flexDirection: "row",
6+
justifyContent: "space-between", // Matches Figma "Auto" spacing
7+
alignItems: "center",
8+
backgroundColor: "#FFFFFF",
9+
10+
borderTopWidth: 1,
11+
borderTopColor: "#E5E5E5",
12+
13+
paddingHorizontal: 40,
14+
paddingTop: 10,
15+
paddingBottom: Platform.OS === "ios" ? 30 : 16,
16+
17+
// Shadow for depth
18+
shadowColor: "#000",
19+
shadowOffset: { width: 0, height: -2 },
20+
shadowOpacity: 0.05,
21+
shadowRadius: 4,
22+
elevation: 5,
23+
},
24+
tab: {
25+
alignItems: "center",
26+
justifyContent: "center",
27+
minWidth: 50,
28+
},
29+
iconContainer: {
30+
marginBottom: 6,
31+
height: 24,
32+
justifyContent: "center",
33+
alignItems: "center",
34+
},
35+
label: {
36+
fontFamily: "Instrument Sans",
37+
fontSize: 11,
38+
fontWeight: "600",
39+
letterSpacing: 0.2,
40+
lineHeight: 12,
41+
},
42+
});

frontend/src/components/Navbar.tsx

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
import React from "react";
2+
import { Text, TouchableOpacity, View } from "react-native";
3+
4+
// SVG Imports
5+
import HomeFilledIcon from "../../assets/icons/home-filled.svg";
6+
import HomeIcon from "../../assets/icons/home.svg";
7+
import LibraryFilledIcon from "../../assets/icons/library-filled.svg";
8+
import LibraryIcon from "../../assets/icons/library.svg";
9+
import SearchFilledIcon from "../../assets/icons/search-filled.svg";
10+
import SearchIcon from "../../assets/icons/search.svg";
11+
12+
import { styles } from "./Navbar.styles";
13+
14+
export type TabName = "Home" | "Search" | "Library";
15+
16+
type NavbarProps = {
17+
currentTab: TabName;
18+
onSwitchTab: (tab: TabName) => void;
19+
};
20+
21+
type TabButtonProps = {
22+
tab: TabName;
23+
isActive: boolean;
24+
onPress: () => void;
25+
};
26+
27+
const ACTIVE_TEXT_COLOR = "#153A7A";
28+
const INACTIVE_TEXT_COLOR = "#909090";
29+
30+
const getTabIcon = (tab: TabName, isActive: boolean) => {
31+
switch (tab) {
32+
case "Home":
33+
return isActive ? <HomeFilledIcon /> : <HomeIcon />;
34+
case "Search":
35+
return isActive ? <SearchFilledIcon /> : <SearchIcon />;
36+
case "Library":
37+
return isActive ? <LibraryFilledIcon /> : <LibraryIcon />;
38+
default:
39+
return null;
40+
}
41+
};
42+
43+
const TabButton: React.FC<TabButtonProps> = ({ tab, isActive, onPress }) => {
44+
return (
45+
<TouchableOpacity
46+
style={styles.tab}
47+
onPress={onPress}
48+
activeOpacity={0.7}
49+
accessibilityRole="button"
50+
accessibilityState={{ selected: isActive }}
51+
>
52+
<View style={styles.iconContainer}>{getTabIcon(tab, isActive)}</View>
53+
<Text style={[styles.label, { color: isActive ? ACTIVE_TEXT_COLOR : INACTIVE_TEXT_COLOR }]}>
54+
{tab}
55+
</Text>
56+
</TouchableOpacity>
57+
);
58+
};
59+
60+
export const Navbar: React.FC<NavbarProps> = ({ currentTab, onSwitchTab }) => {
61+
return (
62+
<View style={styles.container}>
63+
<TabButton tab="Home" isActive={currentTab === "Home"} onPress={() => onSwitchTab("Home")} />
64+
<TabButton
65+
tab="Search"
66+
isActive={currentTab === "Search"}
67+
onPress={() => onSwitchTab("Search")}
68+
/>
69+
<TabButton
70+
tab="Library"
71+
isActive={currentTab === "Library"}
72+
onPress={() => onSwitchTab("Library")}
73+
/>
74+
</View>
75+
);
76+
};

frontend/src/data/mockActivities.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ export const mockActivities: Activity[] = [
6666
description:
6767
"A high-energy tournament style game where students compete to become the ultimate champion.",
6868
energyLevel: "High",
69-
environment: "Both",
69+
environment: "Outdoor",
7070
isSaved: true,
7171
hasTutorial: false,
7272
imageUrl: "https://via.placeholder.com/400x300",
@@ -231,7 +231,7 @@ export const mockActivities: Activity[] = [
231231
description:
232232
"A physical puzzle where a group must untangle themselves without letting go of hands.",
233233
energyLevel: "Medium",
234-
environment: "Both",
234+
environment: "Indoor",
235235
isSaved: false,
236236
hasTutorial: true,
237237
imageUrl: "https://via.placeholder.com/400x300",

frontend/src/types/activity.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ export type Category =
88

99
export type EnergyLevel = "Low" | "Medium" | "High";
1010

11-
export type Environment = "Indoor" | "Outdoor" | "Both";
11+
export type Environment = "Indoor" | "Outdoor";
1212

1313
// Helper type for numeric ranges (filtering)
1414
export type Range = {

0 commit comments

Comments
 (0)