Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve mobile responsiveness and layout #16

Merged
merged 3 commits into from
Jan 16, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 29 additions & 19 deletions frontend/src/components/FeedList.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { useQuery } from "@tanstack/react-query";
import { Link, useParams } from "@tanstack/react-router";
import { FaChevronRight } from "react-icons/fa";

interface Feed {
id: string;
Expand All @@ -22,25 +23,34 @@ const FeedList = () => {
});

return (
<nav className="space-y-2">
{feeds?.map((feed) => (
<Link
key={feed.id}
to="/feed/$feedId"
params={{ feedId: feed.id }}
className={`block px-4 py-2 text-sm border-2 border-black shadow-sharp transition-all duration-200 mb-2 ${
feedId === feed.id
? "bg-gray-100 text-black font-medium translate-x-0.5 translate-y-0.5 shadow-none"
: "text-gray-600 hover:shadow-sharp-hover hover:-translate-x-0.5 hover:-translate-y-0.5 hover:bg-gray-50"
}`}
>
<div className="flex items-center">
<span className="flex-1">{feed.name}</span>
<span className="text-xs text-gray-400">#{feed.hashtag}</span>
</div>
</Link>
))}
</nav>
<div className="flex flex-col md:block">
<div className="flex justify-between items-center px-4 md:px-0 mb-4">
<h1 className="text-xl font-bold">Feeds</h1>
<span className="md:hidden text-gray-400 flex items-center">
<span className="mr-1">scroll</span>
<FaChevronRight className="h-3 w-3" />
</span>
</div>
<nav className="flex md:block overflow-x-auto p-1">
{feeds?.map((feed) => (
<Link
key={feed.id}
to="/feed/$feedId"
params={{ feedId: feed.id }}
className={`flex-shrink-0 min-w-[200px] mx-2 md:mx-0 md:min-w-0 block px-4 py-2 text-sm border-2 border-black shadow-sharp transition-all duration-200 md:mb-2 ${
feedId === feed.id
? "bg-gray-100 text-black font-medium translate-x-0.5 translate-y-0.5 shadow-none"
: "text-gray-600 hover:shadow-sharp-hover hover:-translate-x-0.5 hover:-translate-y-0.5 hover:bg-gray-50"
}`}
>
<div className="flex items-center">
<span className="flex-1">{feed.name}</span>
<span className="text-xs text-gray-400">#{feed.hashtag}</span>
</div>
</Link>
))}
</nav>
</div>
);
};

Expand Down
8 changes: 6 additions & 2 deletions frontend/src/components/Header.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
import { FaTwitter, FaBook, FaGithub, FaTelegram } from "react-icons/fa";
import { Link } from "@tanstack/react-router";

const Header = () => {
return (
<header className="sticky top-0 flex justify-between items-center p-4 border-b-2 border-black bg-white z-10">
<div className="flex items-center">
<Link
to="/"
className="flex items-center hover:opacity-80 transition-opacity"
>
<img
src="/curatedotfuntransparenticon.png"
alt="curate.fun Logo"
Expand All @@ -12,7 +16,7 @@ const Header = () => {
<div className="flex">
<h1 className="text-2xl h-8">curate.fun</h1>
</div>
</div>
</Link>
<nav className="flex space-x-4 mx-4">
<a
href="https://twitter.com/curatedotfun"
Expand Down
55 changes: 47 additions & 8 deletions frontend/src/components/Layout.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { ReactNode } from "react";
import { ReactNode, useState } from "react";
import Header from "./Header";
import { FaEllipsisV } from "react-icons/fa";

interface LayoutProps {
children: ReactNode;
Expand All @@ -8,26 +9,64 @@ interface LayoutProps {
}

const Layout = ({ children, sidebar, rightPanel }: LayoutProps) => {
const [showRightPanel, setShowRightPanel] = useState(false);
return (
<div className="flex flex-col h-screen bg-white">
<Header />
{/* Mobile Feeds List */}
<div className="md:hidden overflow-x-auto whitespace-nowrap border-b-2 border-black">
{sidebar}
</div>

<div className="flex flex-1 overflow-hidden">
{/* Left Sidebar - Feed List */}
<div className="w-64 panel custom-scrollbar overflow-y-auto h-[calc(100vh-theme(spacing.24))] sm:h-[calc(100vh-theme(spacing.28))]">
{/* Left Sidebar - Feed List (Desktop) */}
<div className="hidden md:block w-64 panel custom-scrollbar overflow-y-auto">
<div className="p-4">{sidebar}</div>
</div>

{/* Main Content Area */}
<div className="flex-1 flex">
<div className="flex-1 flex relative">
{/* Center Panel - Feed Items */}
<div className="flex-1 panel custom-scrollbar overflow-y-auto h-[calc(100vh-theme(spacing.24))] sm:h-[calc(100vh-theme(spacing.28))]">
<div className="p-6">{children}</div>
<div className="flex-1 panel custom-scrollbar overflow-y-auto h-full">
<div className="p-6 pb-20">
{/* Mobile Right Panel Toggle */}
{rightPanel && (
<button
onClick={() => setShowRightPanel(!showRightPanel)}
className="lg:hidden absolute top-2 right-2 p-2 text-xl"
>
<FaEllipsisV />
</button>
)}
{children}
</div>
</div>

{/* Right Panel - Feed Details */}
<div className="w-80 panel custom-scrollbar overflow-y-auto h-[calc(100vh-theme(spacing.24))] sm:h-[calc(100vh-theme(spacing.28))]">
<div className="p-4">{rightPanel}</div>
<div
className={`${
showRightPanel ? "translate-x-0" : "translate-x-full"
} lg:translate-x-0 fixed lg:relative right-0 top-0 w-80 bg-white custom-scrollbar overflow-y-auto transition-transform duration-300 ease-in-out z-20 lg:z-0 border-l-2 border-black h-full panel`}
>
<div className="p-4 pb-20">
{/* Mobile Close Button */}
<button
onClick={() => setShowRightPanel(false)}
className="lg:hidden absolute top-2 right-2 p-2"
>
</button>
{rightPanel}
</div>
</div>

{/* Mobile Overlay */}
{showRightPanel && (
<div
className="lg:hidden fixed inset-0 bg-black bg-opacity-50 z-10"
onClick={() => setShowRightPanel(false)}
/>
)}
</div>
</div>
<footer className="fixed bottom-0 w-full py-2 sm:py-4 text-center bg-white/80 backdrop-blur text-sm sm:text-base border-t-2 border-black">
Expand Down
14 changes: 8 additions & 6 deletions frontend/src/routes/feed.$feedId.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ function FeedPage() {

const sidebarContent = (
<div className="p-4">
<h1 className="text-xl font-bold mb-4">Feeds</h1>
<FeedList />
</div>
);
Expand Down Expand Up @@ -130,13 +129,16 @@ function FeedPage() {
return (
<Layout sidebar={sidebarContent} rightPanel={rightPanelContent}>
<div className="space-y-4">
<div className="flex items-center justify-between mb-6">
<div className="flex items-center justify-between mb-6 mr-4">
<h2 className="text-2xl font-bold">{feed?.name || "Loading..."}</h2>
<LiveStatus />
</div>
{items?.map((item) => (
<FeedItem key={item.tweetId} submission={item} />
))}
{items.length === 0 ? (
<div className="flex justify-center items-center p-8">
<p className="text-gray-500">No items yet</p>
</div>
) : (
items.map((item) => <FeedItem key={item.tweetId} submission={item} />)
)}
</div>
</Layout>
);
Expand Down
Loading