Skip to content

Commit

Permalink
refactor(ui): Enhance components with responsive design and improved …
Browse files Browse the repository at this point in the history
…styling

- Refactored `Communities`, `Posts` & `PostVoteClient` components
- Refined PostFeed and EditorOutput styling with better color and layout
- Updated button and navigation components with more consistent design language
- Added Paragraph module in `EditorOutput`
  • Loading branch information
gupta-soham committed Nov 18, 2024
1 parent e4b91a8 commit b069afc
Show file tree
Hide file tree
Showing 10 changed files with 145 additions and 82 deletions.
4 changes: 2 additions & 2 deletions components/EditorOutput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ function CustomCodeRenderer({ data }: any) {
data;

return (
<pre className="bg-gray-800 rounded-md p-4">
<code className="text-gray-100 text-sm">{data.code}</code>
<pre className="bg-secondary rounded-md p-4 mt-2">
<code className="text-primary text-sm">{data.code}</code>
</pre>
);
}
Expand Down
6 changes: 3 additions & 3 deletions components/SubscribeLeaveToggle.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ export default function SubscribeLeaveToggle({
if (err.response?.status === 402) {
return toast({
title: "Creator cannot unsubscribe!",
description: "You're the creator this community 🪿",
description: "You're the creator of this community 🪿",
});
}
}
Expand All @@ -121,15 +121,15 @@ export default function SubscribeLeaveToggle({
<Button
onClick={() => unsubscribe()}
isLoading={isUnsubscribing}
className="w-full mt-1 mb-4"
className="w-full my-1"
>
Leave Community
</Button>
) : (
<Button
onClick={() => subscribe()}
isLoading={isSubscribing}
className="w-full mt-1 mb-4"
className="w-full my-1"
>
Join to Post
</Button>
Expand Down
115 changes: 75 additions & 40 deletions components/pages/Communities.tsx
Original file line number Diff line number Diff line change
@@ -1,70 +1,105 @@
"use client"
"use client";

import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
import { Button, buttonVariants } from "@/components/ui/button";
import { ChevronRight, Plus } from "lucide-react";
import { Button } from "@/components/ui/button";
import { ChevronRight, Menu, Plus } from "lucide-react";
import Link from "next/link";
import { useState } from "react";

type CommunityType = {
name: string;
members: string;
avatar: string;
link: string;
};

export function Communities() {
const [isMenuOpen, setIsMenuOpen] = useState(false);

return (
// <div className="bg-card rounded-lg border border-card-border p-4 space-y-4 ">
<div className={`bg-card rounded-lg border border-card-border p-4 space-y-4 ${isMenuOpen ? "block" : "hidden md:block"}`}>
<div className="flex items-center justify-between">
<h2 className="text-lg font-bold">Communities</h2>
<Button variant="ghost" size="icon">
<Link href='/sub/create' className={buttonVariants({variant: "ghost"})}>
<Plus className="w-5 h-5 hover:w-6 hover:h-6" />
</Link>
<span className="sr-only">Create Community</span>
</Button>
</div>
<div className="grid gap-2">
<CommunityLink name="Study Group" members="1.2k" avatar="SG" />
<CommunityLink name="Programming" members="5.4k" avatar="PG" />
<CommunityLink name="Design" members="2.8k" avatar="DS" />
<CommunityLink name="Universities" members="3.6k" avatar="Uni" />
<div className="space-y-4">
<Button
variant="ghost"
size="icon"
className="md:hidden"
onClick={() => setIsMenuOpen(!isMenuOpen)}
aria-label="Toggle communities menu"
>
<Menu className="h-5 w-5" />
</Button>

<div
className={`bg-card rounded-lg border shadow-sm transition-all duration-200 ${
isMenuOpen ? "block" : "hidden md:block"
}`}
>
<div className="p-4 space-y-4">
<div className="flex items-center justify-between">
<h2 className="text-lg font-semibold">Communities</h2>
<Link href="/sub/create">
<Button
variant="ghost"
size="icon"
className="group transition-colors"
>
<Plus className="h-5 w-5 transition-transform group-hover:scale-110" />
<span className="sr-only">Create Community</span>
</Button>
</Link>
</div>

<div className="space-y-2">
<CommunityLink
name="Study Group"
members="1.2k"
avatar="SG"
link="/sub/study-group"
/>
<CommunityLink
name="Programming"
members="5.4k"
avatar="PG"
link="/sub/programming"
/>
<CommunityLink
name="Design"
members="2.8k"
avatar="DS"
link="/sub/design"
/>
<CommunityLink
name="Universities"
members="3.6k"
avatar="Uni"
link="/sub/universities"
/>
</div>
</div>
</div>
</div>
);
}

function CommunityLink({ name, members, avatar }: CommunityType) {
function CommunityLink({ name, members, avatar, link }: CommunityType) {
return (
<Link
href="#"
className="flex items-center gap-3 bg-muted/20 rounded-md px-3 py-2 hover:bg-muted/30"
href={link}
className="group flex items-center gap-3 p-2 rounded-md hover:bg-accent/50 transition-colors"
prefetch={false}
>
<div className="w-10 h-10 rounded-full border overflow-hidden">
<Avatar>
<AvatarImage
src="/placeholder-user.jpg"
alt={name}
className="w-full h-full object-cover"
/>
<Avatar className="h-10 w-10 border shadow-sm">
<AvatarImage src="/placeholder-user.jpg" alt={name} />
<AvatarFallback className="bg-muted text-muted-foreground">
{avatar}
</AvatarFallback>
</Avatar>

<AvatarFallback className="w-full h-full flex items-center justify-center">
{avatar}
</AvatarFallback>
</Avatar>
</div>
<div className="flex-1">
<div className="font-medium">{name}</div>
<div className="flex-1 min-w-0">
<div className="font-medium text-sm truncate">{name}</div>
<div className="text-xs text-muted-foreground">{members} members</div>
</div>
<Button variant="ghost" size="icon">
<ChevronRight className="w-5 h-5" />
<span className="sr-only">View Community</span>
</Button>

<ChevronRight className="h-4 w-4 text-muted-foreground transition-transform group-hover:translate-x-0.5" />
</Link>
);
}
10 changes: 10 additions & 0 deletions components/pages/Editor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ export default function Editor({ subgroupId }: { subgroupId: string }) {
const LinkTool = (await import("@editorjs/link")).default;
const InlineCode = (await import("@editorjs/inline-code")).default;
const ImageTool = (await import("@editorjs/image")).default;
const Paragraph = (await import("@editorjs/paragraph")).default;

if (!ref.current) {
const editor = new EditorJS({
Expand Down Expand Up @@ -93,6 +94,7 @@ export default function Editor({ subgroupId }: { subgroupId: string }) {
inlineCode: InlineCode,
table: Table,
embed: Embed,
paragraph: Paragraph,
},
});
}
Expand Down Expand Up @@ -196,10 +198,18 @@ export default function Editor({ subgroupId }: { subgroupId: string }) {
// @ts-ignore
_titleRef.current = e;
}}
{...rest}
placeholder="Title"
className="w-full resize-none appearance-none overflow-hidden bg-transparent text-5xl font-bold focus:outline-none"
/>
<div id="editor" className="min-h-[500px]" />
<p className="text-sm text-gray-500">
Use{" "}
<kbd className="rounded-md border bg-muted px-1 text-xs uppercase">
Tab
</kbd>{" "}
to open the command menu.
</p>
</div>
</form>
</div>
Expand Down
5 changes: 4 additions & 1 deletion components/pages/PostFeed.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"use client";

import { Infinite_Scrolling_Pagination_Results } from "@/config";
import { ExtendedPost } from "@/types/db";
import { useIntersection } from "@mantine/hooks";
Expand All @@ -12,6 +13,7 @@ interface PostFeedTypes {
initialPosts: ExtendedPost[];
subgroupName?: string;
}

export default function PostFeed({
initialPosts,
subgroupName,
Expand Down Expand Up @@ -54,7 +56,8 @@ export default function PostFeed({
const posts = data.pages.flatMap((page) => page) ?? initialPosts;

return (
<ul className="flex flex-col col-span-2 space-y-6">
// <ul className="flex flex-col col-span-2 space-y-6">
<ul className="space-y-6">
{posts.map((post, index) => {
const totalVotes = post.votes.reduce((acc, vote) => {
if (vote.type === "UP") return acc + 1;
Expand Down
10 changes: 7 additions & 3 deletions components/pages/PostVoteClient.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ interface PostVoteClientProps {
initialTotalVotes: number;
initialVote: VoteType | null;
}

export default function PostVoteClient({
postId,
initialTotalVotes,
Expand Down Expand Up @@ -77,13 +78,14 @@ export default function PostVoteClient({
});

return (
<div className="flex flex-col gap-4 sm:gap-0 pr-6 sm:w-20 pb-4 sm:pb-0">
<div className="flex sm:flex-col items-center gap-1 sm:gap-2">
{/* upvote */}
<Button
onClick={() => vote("UP")}
size="sm"
variant="ghost"
aria-label="upvote"
className="p-0 sm:p-2"
>
<ArrowBigUp
className={cn("h-5 w-5 text-zinc-700", {
Expand All @@ -93,13 +95,15 @@ export default function PostVoteClient({
</Button>

{/* votes */}
<p className="text-center py-2 font-medium text-sm">{votesAmt}</p>
<p className="text-center py-2 font-medium text-sm text-zinc-900 dark:text-zinc-100">
{votesAmt}
</p>

{/* downvote */}
<Button
onClick={() => vote("DOWN")}
size="sm"
className={cn({
className={cn("p-0 sm:p-2", {
"text-emerald-500": currentVote === "DOWN",
})}
variant="ghost"
Expand Down
70 changes: 40 additions & 30 deletions components/pages/Posts.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ interface PostProps {
currentVote?: PartialVote;
commentAmt: number | null;
}

export default function Posts({
post,
totalVotes,
Expand All @@ -29,57 +30,66 @@ export default function Posts({
const pRef = useRef<HTMLParagraphElement>(null);

return (
<div className="rounded-md bg-white dark:bg-black/30 shadow">
<div className="px-6 py-4 flex justify-between">
<PostVoteClient
postId={post.id}
initialTotalVotes={totalVotes}
initialVote={currentVote?.type ?? null}
/>
<article className="rounded-lg border bg-card shadow-sm transition-colors">
<div className="flex flex-col sm:flex-row p-4 sm:p-6">
<div className="flex sm:flex-col items-center sm:items-start mb-4 sm:mb-0">
<PostVoteClient
postId={post.id}
initialTotalVotes={totalVotes}
initialVote={currentVote?.type ?? null}
/>
</div>

<div className="w-0 flex-1">
<div className="max-h-40 mt-1 text-xs text-gray-500">
{subgroupName ? (
<div className="flex-1 sm:ml-4 space-y-2">
<div className="flex flex-wrap items-center gap-2 text-xs text-muted-foreground">
{subgroupName && (
<>
<a
className="underline text-zinc-900 dark:text-zinc-100 text-sm underline-offset-2"
<Link
href={`/sub/${subgroupName}`}
className="font-medium text-foreground hover:underline"
>
sub/{subgroupName}
</a>
<span className="px-1"></span>
</Link>
<span></span>
</>
) : null}
<span>Posted by u/{post.author.username}</span>{" "}
{formatTimeToNow(new Date(post.createdAt))}
)}
<span>Posted by u/{post.author.username}</span>
<span></span>
<span>{formatTimeToNow(new Date(post.createdAt))}</span>
</div>
<a href={`/sub/${subgroupName}/post/${post.id}`}>
<h1 className="text-lg font-semibold py-2 leading-6 text-gray-900 dark:text-gray-100">

<Link
href={`/sub/${subgroupName}/post/${post.id}`}
className="block group"
>
<h2 className="text-xl font-semibold text-foreground group-hover:underline decoration-2 underline-offset-2">
{post.title}
</h1>
</a>
</h2>
</Link>

<div
className="relative text-sm max-h-40 w-full overflow-clip"
className="relative max-h-40 overflow-hidden text-sm text-muted-foreground"
ref={pRef}
>
<EditorOutput content={post.content} />
{pRef.current?.clientHeight === 160 ? (
// blur bottom if content is too long
<div className="absolute bottom-0 left-0 h-24 w-full bg-gradient-to-t from-white dark:from-black to-transparent"></div>
) : null}
{pRef.current?.clientHeight === 160 && (
<div className="absolute bottom-0 left-0 h-24 w-full bg-gradient-to-t from-background to-transparent" />
)}
</div>
</div>
</div>

<div className="bg-gray-50 dark:bg-zinc-900 z-20 text-sm px-4 py-4 sm:px-6">
<div className="border-t bg-muted/10 px-4 sm:px-6 py-3">
<Link
href={`/sub/${subgroupName}/post/${post.id}`}
className="w-fit flex items-center gap-2 text-gray-900 dark:text-gray-100"
className="inline-flex items-center gap-2 text-sm text-muted-foreground hover:text-foreground transition-colors"
>
<MessageSquare className="h-4 w-4" /> {commentAmt} comments
<MessageSquare className="h-4 w-4" />
<span>
{commentAmt} {commentAmt === 1 ? "comment" : "comments"}
</span>
</Link>
</div>
</div>
</article>
);
}
2 changes: 1 addition & 1 deletion components/pages/UserAccountNav.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ export default function UserAccountNav({ user }: UserAccountNavProps) {
</DropdownMenuItem>

<DropdownMenuItem asChild>
<Link href="/r/create">Create</Link>
<Link href="/sub/create">Create</Link>
</DropdownMenuItem>

<DropdownMenuItem asChild>
Expand Down
Loading

0 comments on commit b069afc

Please sign in to comment.