diff --git a/frontend/index.html b/frontend/index.html index df2e671..1242bfb 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -3,12 +3,13 @@ - + + Gander -
+
diff --git a/frontend/public/images/favicon_goose.ico b/frontend/public/images/favicon_goose.ico new file mode 100644 index 0000000..1eb0628 Binary files /dev/null and b/frontend/public/images/favicon_goose.ico differ diff --git a/frontend/public/images/favicon.ico b/frontend/public/images/favicon_monke.ico similarity index 100% rename from frontend/public/images/favicon.ico rename to frontend/public/images/favicon_monke.ico diff --git a/frontend/src/assets/styles/index.css b/frontend/src/assets/styles/index.css index 965d103..f18263b 100644 --- a/frontend/src/assets/styles/index.css +++ b/frontend/src/assets/styles/index.css @@ -9,21 +9,21 @@ ::-webkit-scrollbar { - width: 10px; + width: 4px; } ::-webkit-scrollbar-track { - background: hsl(242, 100%, 10%); + background: transparent; border-radius: 5px; } ::-webkit-scrollbar-thumb { - background: #d5d5d5; + background: var(--scrollbar-color); border-radius: 5px; } ::-webkit-scrollbar-thumb:hover { - background: #555; + background: var(--scrollbar-hover); } @@ -31,6 +31,11 @@ body[data-theme="light"] { --bg-color: white; --text-color: black; + /*Global Background Colour*/ + background: linear-gradient(to top right, #2043ba, #0026a6, #63007a); + --scrollbar-color: white; + --scrollbar-hover: rgb(144, 144, 144); + --sideBar-bg: rgb(255, 255, 255); --sideBar-text: black; --sideBar-profile-bg: rgb(224, 205, 241); @@ -40,6 +45,9 @@ body[data-theme="light"] { --follow-bg: #aa00ff; --follow-text: white; --follow-shadow: 0px 0px 15px rgba(94, 94, 94, 0.754); + --streamer-box: #aa00ff; + --streamer-text: white; + --streamer-shadow: 0px 0px 10px rgba(0, 0, 0, 0.754); --liveNow: rgba(46, 16, 16, 0.6); --recommend: rgba(5, 46, 22, 0.6); @@ -80,7 +88,12 @@ body[data-theme="light"] { } body[data-theme="dark"] { - --bg-color: black; + /*Global Background Colour*/ + background: linear-gradient(to top right, #737787, #0d1e55, #567419); + --scrollbar-color: rgb(255, 255, 255); + --scrollbar-hover: rgb(255, 255, 255); + + --bg-color: black; --text-color: white; --sideBar-bg: black; @@ -92,11 +105,14 @@ body[data-theme="dark"] { --follow-bg: #a50000c6; --follow-text: rgb(255, 255, 255); --follow-shadow: 0px 0px 15px rgba(255, 255, 255, 0.966); + --streamer-box: #8b1711; + --streamer-text: white; + --streamer-shadow: 0px 0px 25px rgb(255, 255, 255); + --liveNow: rgba(77, 29, 29, 0.6); --recommend: rgba(4, 63, 28, 0.6); - --quickBar-title: rgb(255, 255, 255); --quickBar-title-bg: rgb(0, 0, 0); --quickBar-bg: #000000d3; @@ -136,6 +152,12 @@ body[data-theme="blue"] { --bg-color: #e0f7fa; --text-color: #00539b; + /*Global Background Colour*/ + background: linear-gradient(to top right, #223b3b, #3e7bff, #170055); + --scrollbar-color: white; + --scrollbar-hover: rgb(144, 144, 144); + + --sideBar-bg: #eefafffb; --sideBar-text: #002147; --sideBar-profile-bg: #003571; @@ -144,7 +166,9 @@ body[data-theme="blue"] { --follow-bg: #ffffff; --follow-shadow: 0px 0px 15px rgba(161, 222, 255, 0.823); - + --streamer-box: #00b3ff; + --streamer-text: white; + --streamer-shadow: 0px 0px 10px rgb(14, 18, 93); --liveNow: rgba(5, 59, 103, 0.801); --recommend: rgba(112, 116, 96, 0.6); @@ -185,6 +209,13 @@ body[data-theme="blue"] { } body[data-theme="green"] { + + /*Global Background Colour*/ + background: linear-gradient(to top right, #2a0d0d, #183f29, #16631e); + --scrollbar-color: white; + --scrollbar-hover: rgb(144, 144, 144); + + --bg-color: #e8f5e9; --text-color: #2e7d32; @@ -198,8 +229,10 @@ body[data-theme="green"] { --follow-bg: #b5ffb5; --follow-text: #2e7d32; --follow-shadow: 0px 0px 15px rgba(84, 255, 92, 0.754); - - --liveNow: rgba(69, 150, 74, 0.6); + --streamer-box: #32b90dd4; + --streamer-text: rgb(255, 255, 255); + --streamer-shadow: 0px 0px 10px rgb(1, 112, 25); + --liveNow: rgba(14, 173, 28, 0.491); --recommend: rgba(123, 94, 14, 0.6); /*Quick Settings*/ @@ -238,6 +271,12 @@ body[data-theme="green"] { } body[data-theme="orange"] { + + /*Global Background Colour*/ + background: linear-gradient(to top right, #074a84, #a17e1c, #4f2b61); + --scrollbar-color: white; + --scrollbar-hover: rgb(144, 144, 144); + --bg-color: #ffe0b2; --text-color: #e65100; @@ -250,9 +289,11 @@ body[data-theme="orange"] { --follow-bg: #fdfd00af; --follow-text: #000000; --follow-shadow: 0px 0px 15px rgba(0, 229, 255, 0.754); - - --liveNow: rgba(202, 192, 53, 0.6); - --recommend: rgba(192, 111, 18, 0.6); + --streamer-box: #ffff00; + --streamer-text: rgb(0, 0, 0); + --streamer-shadow: 0px 0px 10px rgba(195, 75, 0, 0.754); + --liveNow: #4c008285; + --recommend: #c49c2da5; --quickBar-title-bg: #E67E22; diff --git a/frontend/src/assets/styles/listRow.css b/frontend/src/assets/styles/listRow.css index 5c599c4..fd9f310 100644 --- a/frontend/src/assets/styles/listRow.css +++ b/frontend/src/assets/styles/listRow.css @@ -1,8 +1,23 @@ -.hide-scrollbar::-webkit-scrollbar { - display: none; +:root { + --scrollbar-background: linear-gradient(to right, #6a11cb, #2575fc); + --scrollbar-thumb: rgba(255, 255, 255, 0.6); } - -.hide-scrollbar { - -ms-overflow-style: none; - scrollbar-width: none; -} \ No newline at end of file + +::-webkit-scrollbar { + height: 4px; +} + +::-webkit-scrollbar-track { + background: transparent; + border-radius: 5px; +} + +::-webkit-scrollbar-thumb { + background: var(--scrollbar-thumb); + border-radius: 10px; +} + +::-webkit-scrollbar-thumb:hover { + background: rgba(255, 255, 255, 0.9); +} + diff --git a/frontend/src/components/Layout/DynamicPageContent.tsx b/frontend/src/components/Layout/DynamicPageContent.tsx index 4779643..e74ea8d 100644 --- a/frontend/src/components/Layout/DynamicPageContent.tsx +++ b/frontend/src/components/Layout/DynamicPageContent.tsx @@ -24,12 +24,19 @@ const DynamicPageContent: React.FC = ({ className={`${className} bg-[url(/images/background-pattern.svg)]`} style={style} > + {/* Hide Scrollbar for WebKit-based Browsers + */}
{children}
diff --git a/frontend/src/components/Layout/ListRow.tsx b/frontend/src/components/Layout/ListRow.tsx index e52e087..e2c532a 100644 --- a/frontend/src/components/Layout/ListRow.tsx +++ b/frontend/src/components/Layout/ListRow.tsx @@ -47,7 +47,7 @@ const ListRow = forwardRef((props, ref) => { const [currentItems, setCurrentItems] = useState(items); const slider = useRef(null); - const scrollAmount = window.innerWidth * 0.3; + const scrollAmount = window.innerWidth * 0.4; const navigate = useNavigate(); const addMoreItems = (newItems: ItemType[]) => { diff --git a/frontend/src/components/Navigation/Sidebar.tsx b/frontend/src/components/Navigation/Sidebar.tsx index 18b03b8..bd267dc 100644 --- a/frontend/src/components/Navigation/Sidebar.tsx +++ b/frontend/src/components/Navigation/Sidebar.tsx @@ -7,161 +7,167 @@ import { ToggleButton } from "../Input/Button"; import { getCategoryThumbnail } from "../../utils/thumbnailUtils"; interface Streamer { - user_id: number; - username: string; + user_id: number; + username: string; } interface Category { - category_id: number; - category_name: string; + category_id: number; + category_name: string; } interface SideBarProps { - extraClasses?: string; + extraClasses?: string; } const Sidebar: React.FC = ({ extraClasses = "" }) => { - const { showSideBar, setShowSideBar } = useSidebar(); - const navigate = useNavigate(); - const { username, isLoggedIn, profilePicture } = useAuth(); - const [followedStreamers, setFollowedStreamers] = useState([]); - const [followedCategories, setFollowedCategories] = useState([]); - const [justToggled, setJustToggled] = useState(false); - const sidebarId = useRef(Math.floor(Math.random() * 1000000)); + const { showSideBar, setShowSideBar } = useSidebar(); + const navigate = useNavigate(); + const { username, isLoggedIn, profilePicture } = useAuth(); + const [followedStreamers, setFollowedStreamers] = useState([]); + const [followedCategories, setFollowedCategories] = useState([]); + const [justToggled, setJustToggled] = useState(false); + const sidebarId = useRef(Math.floor(Math.random() * 1000000)); - // Fetch followed streamers & categories - useEffect(() => { - if (!isLoggedIn) return; + // Fetch followed streamers & categories + useEffect(() => { + if (!isLoggedIn) return; - const fetchFollowData = async () => { - try { - const response = await fetch("/api/user/following"); - if (!response.ok) throw new Error("Failed to fetch followed content"); - const data = await response.json(); - setFollowedStreamers(data.streams); - setFollowedCategories(data.categories); - } catch (error) { - console.error("Error fetching followed content:", error); - } - }; + const fetchFollowData = async () => { + try { + const response = await fetch("/api/user/following"); + if (!response.ok) throw new Error("Failed to fetch followed content"); + const data = await response.json(); + setFollowedStreamers(data.streams); + setFollowedCategories(data.categories); + } catch (error) { + console.error("Error fetching followed content:", error); + } + }; - fetchFollowData(); - }, [isLoggedIn]); + fetchFollowData(); + }, [isLoggedIn]); - const handleSideBar = () => { - setShowSideBar(!showSideBar); - setJustToggled(true); - setTimeout(() => setJustToggled(false), 200); - }; + const handleSideBar = () => { + setShowSideBar(!showSideBar); + setJustToggled(true); + setTimeout(() => setJustToggled(false), 200); + }; - // Keyboard shortcut to toggle sidebar - useEffect(() => { - const handleKeyPress = (e: KeyboardEvent) => { - if (e.key === "s" && document.activeElement == document.body && isLoggedIn) handleSideBar(); - }; + // Keyboard shortcut to toggle sidebar + useEffect(() => { + const handleKeyPress = (e: KeyboardEvent) => { + if (e.key === "s" && document.activeElement == document.body && isLoggedIn) handleSideBar(); + }; - document.addEventListener("keydown", handleKeyPress); + document.addEventListener("keydown", handleKeyPress); - return () => { - document.removeEventListener("keydown", handleKeyPress); - }; - }, [showSideBar, setShowSideBar, isLoggedIn]); + return () => { + document.removeEventListener("keydown", handleKeyPress); + }; + }, [showSideBar, setShowSideBar, isLoggedIn]); - return ( - <> - handleSideBar()} - extraClasses={`absolute group text-[1rem] top-[9vh] ${ - showSideBar ? "left-[16vw] duration-[0.5s]" : "left-[20px] duration-[1s]" - } ease-in-out cursor-pointer z-[50]`} - toggled={showSideBar} - > - + return ( + <> + handleSideBar()} + extraClasses={`absolute group text-[1rem] top-[9vh] ${showSideBar ? "left-[16vw] duration-[0.5s]" : "left-[20px] duration-[1s]" + } ease-in-out cursor-pointer z-[50]`} + toggled={showSideBar} + > + - {!showSideBar && !justToggled && ( - - Press S - - )} - -
+ Press S + + )} + +
- {/* Profile Info */} -
- { - e.currentTarget.src = "/images/pfps/default.png"; - e.currentTarget.onerror = null; - }} - alt="profile picture" - className="w-[3em] h-[3em] object-cover rounded-full border-[0.15em] border-purple-500 cursor-pointer" - onClick={() => navigate(`/user/${username}`)} - /> -
-
Logged in as
- -
-
+ > + {/* Profile Info */} +
+ { + e.currentTarget.src = "/images/pfps/default.png"; + e.currentTarget.onerror = null; + }} + alt="profile picture" + className="w-[3em] h-[3em] object-cover rounded-full border-[0.15em] border-purple-500 cursor-pointer" + onClick={() => navigate(`/user/${username}`)} + /> +
+
Logged in as
+ +
+
-
-
(e.currentTarget.style.boxShadow = "var(--follow-shadow)")} - onMouseLeave={(e) => (e.currentTarget.style.boxShadow = "none")} - > -

Following

-
-
-

Streamers

-
- {followedStreamers.map((streamer) => ( - - ))} -
-
+
+
(e.currentTarget.style.boxShadow = "var(--follow-shadow)")} + onMouseLeave={(e) => (e.currentTarget.style.boxShadow = "none")} + > +

Following

+
+
+

Streamers

+
+ {followedStreamers.map((streamer) => ( +
navigate(`/user/${streamer.username}`)} + onMouseEnter={(e) => (e.currentTarget.style.boxShadow = "var(--streamer-shadow)")} + onMouseLeave={(e) => (e.currentTarget.style.boxShadow = "none")} + > + {`${streamer.username}'s +
{streamer.username}
+
+ ))} +
+
-
-

Categories

+
+

Categories

- {/* Followed Categories */} -
- {followedCategories.map((category) => { - return ( -
+ {followedCategories.map((category) => { + return ( +
(window.location.href = `/category/${category.category_name}`)} - > - {category.category_name} -
- {category.category_name} -
-
- ); - })} -
-
-
-
- - ); + onClick={() => (window.location.href = `/category/${category.category_name}`)} + > + {category.category_name} +
+ {category.category_name} +
+
+ ); + })} +
+
+
+ + + ); }; export default Sidebar;