Skip to content

Commit

Permalink
[ui] Styling the bookmarks page
Browse files Browse the repository at this point in the history
  • Loading branch information
MohamedBassem committed Feb 7, 2024
1 parent daebbf0 commit 293869e
Show file tree
Hide file tree
Showing 11 changed files with 490 additions and 20 deletions.
1 change: 1 addition & 0 deletions .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
"no-redeclare": "off",
"@next/next/no-html-link-for-pages": "off",
"no-undef": "off",
"react/jsx-no-undef": "off",
"no-unused-vars": [
"error",
{
Expand Down
Binary file modified bun.lockb
Binary file not shown.
15 changes: 9 additions & 6 deletions web/app/bookmarks/components/AddLink.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
"use client";

import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import APIClient from "@/lib/api";
import { Plus } from "lucide-react";
import { useRouter } from "next/navigation";
import { useState } from "react";

Expand All @@ -11,15 +14,16 @@ export default function AddLink() {
const bookmarkLink = async () => {
const [_resp, error] = await APIClient.bookmarkLink(link);
if (error) {
// TODO: Proper error handling
alert(error.message);
return;
}
router.refresh();
};

return (
<div className="p-4">
<input
<div className="py-4 container flex w-full items-center space-x-2">
<Input
type="text"
placeholder="Link"
value={link}
Expand All @@ -30,11 +34,10 @@ export default function AddLink() {
setLink("");
}
}}
className="w-10/12 px-4 py-2 border rounded-md focus:outline-none focus:border-blue-300"
/>
<button className="w-2/12 px-1 py-2" onClick={bookmarkLink}>
Submit
</button>
<Button onClick={bookmarkLink}>
<Plus />
</Button>
</div>
);
}
74 changes: 61 additions & 13 deletions web/app/bookmarks/components/LinkCard.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,67 @@
"use client";

import { Button } from "@/components/ui/button";
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
import {
ImageCard,
ImageCardBody,
ImageCardFooter,
ImageCardTitle,
} from "@/components/ui/imageCard";
import { ZBookmarkedLink } from "@/lib/types/api/links";
import { MoreHorizontal, Trash2 } from "lucide-react";
import Link from "next/link";

export default async function LinkCard({ link }: { link: ZBookmarkedLink }) {
export function LinkOptions() {
// TODO: Implement deletion
return (
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="ghost">
<MoreHorizontal />
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent className="w-fit">
<DropdownMenuItem className="text-destructive">
<Trash2 className="mr-2 h-4 w-4" />
<span>Delete</span>
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
);
}

export default function LinkCard({ link }: { link: ZBookmarkedLink }) {
const parsedUrl = new URL(link.url);

return (
<Link href={link.url} className="border rounded-md hover:border-blue-300">
<div className="p-4">
<h2 className="text-lg font-semibold">
{link.details?.favicon && (
// eslint-disable-next-line @next/next/no-img-element
<img alt="" width="10" height="10" src={link.details?.favicon} />
)}
{link.details?.title ?? link.id}
</h2>
<p className="text-gray-600">{link.details?.description ?? link.url}</p>
</div>
</Link>
<ImageCard
className={
"bg-gray-50 duration-300 ease-in border border-grey-100 hover:transition-all hover:border-blue-300"
}
image={link.details?.imageUrl ?? undefined}
>
<ImageCardTitle>
<Link className="line-clamp-3" href={link.url}>
{link.details?.title ?? parsedUrl.host}
</Link>
</ImageCardTitle>
<ImageCardBody />
<ImageCardFooter>
<div className="flex justify-between text-gray-500">
<div className="my-auto">
<Link className="line-clamp-1 hover:text-black" href={link.url}>
{parsedUrl.host}
</Link>
</div>
<LinkOptions />
</div>
</ImageCardFooter>
</ImageCard>
);
}
2 changes: 1 addition & 1 deletion web/app/bookmarks/components/LinksGrid.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export default async function LinksGrid() {
const links = await getLinks(session.user.id);

return (
<div className="container mx-auto mt-8 grid gap-4 grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4">
<div className="container p-8 mx-auto grid gap-4 grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4">
{links.map((l) => (
<LinkCard key={l.id} link={l} />
))}
Expand Down
56 changes: 56 additions & 0 deletions web/components/ui/button.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import * as React from "react"
import { Slot } from "@radix-ui/react-slot"
import { cva, type VariantProps } from "class-variance-authority"

import { cn } from "@/lib/utils"

const buttonVariants = cva(
"inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50",
{
variants: {
variant: {
default: "bg-primary text-primary-foreground hover:bg-primary/90",
destructive:
"bg-destructive text-destructive-foreground hover:bg-destructive/90",
outline:
"border border-input bg-background hover:bg-accent hover:text-accent-foreground",
secondary:
"bg-secondary text-secondary-foreground hover:bg-secondary/80",
ghost: "hover:bg-accent hover:text-accent-foreground",
link: "text-primary underline-offset-4 hover:underline",
},
size: {
default: "h-10 px-4 py-2",
sm: "h-9 rounded-md px-3",
lg: "h-11 rounded-md px-8",
icon: "h-10 w-10",
},
},
defaultVariants: {
variant: "default",
size: "default",
},
}
)

export interface ButtonProps
extends React.ButtonHTMLAttributes<HTMLButtonElement>,
VariantProps<typeof buttonVariants> {
asChild?: boolean
}

const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
({ className, variant, size, asChild = false, ...props }, ref) => {
const Comp = asChild ? Slot : "button"
return (
<Comp
className={cn(buttonVariants({ variant, size, className }))}
ref={ref}
{...props}
/>
)
}
)
Button.displayName = "Button"

export { Button, buttonVariants }
79 changes: 79 additions & 0 deletions web/components/ui/card.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import * as React from "react"

import { cn } from "@/lib/utils"

const Card = React.forwardRef<
HTMLDivElement,
React.HTMLAttributes<HTMLDivElement>
>(({ className, ...props }, ref) => (
<div
ref={ref}
className={cn(
"rounded-lg border bg-card text-card-foreground shadow-sm",
className
)}
{...props}
/>
))
Card.displayName = "Card"

const CardHeader = React.forwardRef<
HTMLDivElement,
React.HTMLAttributes<HTMLDivElement>
>(({ className, ...props }, ref) => (
<div
ref={ref}
className={cn("flex flex-col space-y-1.5 p-6", className)}
{...props}
/>
))
CardHeader.displayName = "CardHeader"

const CardTitle = React.forwardRef<
HTMLParagraphElement,
React.HTMLAttributes<HTMLHeadingElement>
>(({ className, ...props }, ref) => (
<h3
ref={ref}
className={cn(
"text-2xl font-semibold leading-none tracking-tight",
className
)}
{...props}
/>
))
CardTitle.displayName = "CardTitle"

const CardDescription = React.forwardRef<
HTMLParagraphElement,
React.HTMLAttributes<HTMLParagraphElement>
>(({ className, ...props }, ref) => (
<p
ref={ref}
className={cn("text-sm text-muted-foreground", className)}
{...props}
/>
))
CardDescription.displayName = "CardDescription"

const CardContent = React.forwardRef<
HTMLDivElement,
React.HTMLAttributes<HTMLDivElement>
>(({ className, ...props }, ref) => (
<div ref={ref} className={cn("p-6 pt-0", className)} {...props} />
))
CardContent.displayName = "CardContent"

const CardFooter = React.forwardRef<
HTMLDivElement,
React.HTMLAttributes<HTMLDivElement>
>(({ className, ...props }, ref) => (
<div
ref={ref}
className={cn("flex items-center p-6 pt-0", className)}
{...props}
/>
))
CardFooter.displayName = "CardFooter"

export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent }
Loading

0 comments on commit 293869e

Please sign in to comment.