improved masonry look

This commit is contained in:
daniel31x13 2024-04-27 12:23:33 -04:00
parent 6f4759d928
commit b4ea7dcd8e
6 changed files with 61 additions and 35 deletions

View File

@ -19,10 +19,11 @@ export default function MasonryView({
const breakpointColumnsObj = useMemo(() => { const breakpointColumnsObj = useMemo(() => {
return { return {
default: 4, default: 5,
1900: 3, 1900: 4,
[fullConfig.theme.screens.xl]: 2, 1500: 3,
[fullConfig.theme.screens.sm]: 1, 880: 2,
550: 1,
}; };
}, []); }, []);
@ -30,7 +31,7 @@ export default function MasonryView({
<Masonry <Masonry
breakpointCols={breakpointColumnsObj} breakpointCols={breakpointColumnsObj}
columnClassName="flex flex-col gap-5 !w-full" columnClassName="flex flex-col gap-5 !w-full"
className="grid min-[1900px]:grid-cols-4 xl:grid-cols-3 sm:grid-cols-2 grid-cols-1 gap-5 pb-5" className="grid min-[1901px]:grid-cols-5 min-[1501px]:grid-cols-4 min-[881px]:grid-cols-3 min-[551px]:grid-cols-2 grid-cols-1 gap-5 pb-5"
> >
{links.map((e, i) => { {links.map((e, i) => {
return ( return (

View File

@ -15,7 +15,7 @@ export default function LinkDate({
}); });
return ( return (
<div className="flex items-center gap-1 text-neutral"> <div className="flex items-center gap-1 text-neutral min-w-fit">
<i className="bi-calendar3 text-lg"></i> <i className="bi-calendar3 text-lg"></i>
<p>{formattedDate}</p> <p>{formattedDate}</p>
</div> </div>

View File

@ -5,23 +5,35 @@ import React from "react";
export default function LinkIcon({ export default function LinkIcon({
link, link,
width,
className, className,
size,
}: { }: {
link: LinkIncludingShortenedCollectionAndTags; link: LinkIncludingShortenedCollectionAndTags;
width?: string;
className?: string; className?: string;
size?: "small" | "medium";
}) { }) {
let iconClasses: string =
"bg-white shadow rounded-md border-[2px] flex item-center justify-center border-white select-none z-10 " +
(className || "");
let dimension;
switch (size) {
case "small":
dimension = " w-8 h-8";
break;
case "medium":
dimension = " w-12 h-12";
break;
default:
size = "medium";
dimension = " w-12 h-12";
break;
}
const url = const url =
isValidUrl(link.url || "") && link.url ? new URL(link.url) : undefined; isValidUrl(link.url || "") && link.url ? new URL(link.url) : undefined;
const iconClasses: string =
"bg-white shadow rounded-md border-[2px] flex item-center justify-center border-white select-none z-10" +
" " +
(width || "w-12") +
" " +
(className || "");
const [showFavicon, setShowFavicon] = React.useState<boolean>(true); const [showFavicon, setShowFavicon] = React.useState<boolean>(true);
return ( return (
@ -33,23 +45,29 @@ export default function LinkIcon({
width={64} width={64}
height={64} height={64}
alt="" alt=""
className={iconClasses} className={iconClasses + dimension}
draggable="false" draggable="false"
onError={() => { onError={() => {
setShowFavicon(false); setShowFavicon(false);
}} }}
/> />
) : ( ) : (
<LinkPlaceholderIcon iconClasses={iconClasses} icon="bi-link-45deg" /> <LinkPlaceholderIcon
iconClasses={iconClasses + dimension}
size={size}
icon="bi-link-45deg"
/>
) )
) : link.type === "pdf" ? ( ) : link.type === "pdf" ? (
<LinkPlaceholderIcon <LinkPlaceholderIcon
iconClasses={iconClasses} iconClasses={iconClasses + dimension}
size={size}
icon="bi-file-earmark-pdf" icon="bi-file-earmark-pdf"
/> />
) : link.type === "image" ? ( ) : link.type === "image" ? (
<LinkPlaceholderIcon <LinkPlaceholderIcon
iconClasses={iconClasses} iconClasses={iconClasses + dimension}
size={size}
icon="bi-file-earmark-image" icon="bi-file-earmark-image"
/> />
) : undefined} ) : undefined}
@ -59,13 +77,19 @@ export default function LinkIcon({
const LinkPlaceholderIcon = ({ const LinkPlaceholderIcon = ({
iconClasses, iconClasses,
size,
icon, icon,
}: { }: {
iconClasses: string; iconClasses: string;
size?: "small" | "medium";
icon: string; icon: string;
}) => { }) => {
return ( return (
<div className={`text-4xl text-black aspect-square ${iconClasses}`}> <div
className={`${
size === "small" ? "text-2xl" : "text-4xl"
} text-black aspect-square ${iconClasses}`}
>
<i className={`${icon} m-auto`}></i> <i className={`${icon} m-auto`}></i>
</div> </div>
); );

View File

@ -27,8 +27,8 @@ export default function LinkTypeBadge({
}} }}
className="flex gap-1 item-center select-none text-neutral mt-1 hover:opacity-70 duration-100" className="flex gap-1 item-center select-none text-neutral mt-1 hover:opacity-70 duration-100"
> >
<i className="bi-link-45deg text-lg mt-[0.1rem] leading-none"></i> <i className="bi-link-45deg text-lg leading-none"></i>
<p className="text-sm truncate">{shortendURL}</p> <p className="text-xs truncate">{shortendURL}</p>
</Link> </Link>
) : ( ) : (
<div className="badge badge-primary badge-sm my-1 select-none"> <div className="badge badge-primary badge-sm my-1 select-none">

View File

@ -125,8 +125,7 @@ export default function LinkCardCompact({
<div className="shrink-0"> <div className="shrink-0">
<LinkIcon <LinkIcon
link={link} link={link}
width="sm:w-12 w-8" className="mt-1 sm:mt-0 sm:w-12 w-8 sm:h-12 h-8 text-xl sm:text-4xl"
className="mt-1 sm:mt-0"
/> />
</div> </div>

View File

@ -141,7 +141,6 @@ export default function LinkMasonry({ link, flipDropdown, editMode }: Props) {
height={720} height={720}
alt="" alt=""
className="rounded-t-2xl select-none object-cover z-10 h-40 w-full shadow opacity-80 scale-105" className="rounded-t-2xl select-none object-cover z-10 h-40 w-full shadow opacity-80 scale-105"
style={{ filter: "blur(2px)" }}
draggable="false" draggable="false"
onError={(e) => { onError={(e) => {
const target = e.target as HTMLElement; const target = e.target as HTMLElement;
@ -151,9 +150,6 @@ export default function LinkMasonry({ link, flipDropdown, editMode }: Props) {
) : link.preview === "unavailable" ? null : ( ) : link.preview === "unavailable" ? null : (
<div className="duration-100 h-40 bg-opacity-80 skeleton rounded-none"></div> <div className="duration-100 h-40 bg-opacity-80 skeleton rounded-none"></div>
)} )}
<div className="absolute top-0 left-0 right-0 bottom-0 rounded-t-2xl flex items-center justify-center shadow rounded-md">
<LinkIcon link={link} />
</div>
</div> </div>
{link.preview !== "unavailable" && ( {link.preview !== "unavailable" && (
@ -162,15 +158,21 @@ export default function LinkMasonry({ link, flipDropdown, editMode }: Props) {
<div className="p-3 mt-1 flex flex-col gap-2"> <div className="p-3 mt-1 flex flex-col gap-2">
<div className="w-full pr-8"> <div className="w-full pr-8">
<p className="text-primary">{unescapeString(link.name)}</p> <div
className={`rounded-t-2xl flex items-center justify-center shadow rounded-md float-left mr-2 ${
link.type === "url" ? "" : "hidden"
}`}
>
<LinkIcon link={link} size="small" className="mt-1" />
</div>
<p className="text-primary text-sm">{unescapeString(link.name)}</p>
{link.description && (
<p className="text-sm">{unescapeString(link.description)}</p>
)}
<LinkTypeBadge link={link} /> <LinkTypeBadge link={link} />
</div> </div>
{link.description && (
<p className="text-sm">{unescapeString(link.description)}</p>
)}
{link.tags[0] && ( {link.tags[0] && (
<div className="flex gap-1 items-center flex-wrap"> <div className="flex gap-1 items-center flex-wrap">
{link.tags.map((e, i) => ( {link.tags.map((e, i) => (
@ -191,8 +193,8 @@ export default function LinkMasonry({ link, flipDropdown, editMode }: Props) {
<hr className="divider mt-2 mb-1 last:hidden border-t border-neutral-content h-[1px]" /> <hr className="divider mt-2 mb-1 last:hidden border-t border-neutral-content h-[1px]" />
<div className="flex justify-between text-xs text-neutral px-3 pb-1"> <div className="flex justify-between gap-1 text-xs text-neutral px-3 pb-1">
<div className="cursor-pointer w-fit"> <div className="cursor-pointer w-fit truncate">
{collection && ( {collection && (
<LinkCollection link={link} collection={collection} /> <LinkCollection link={link} collection={collection} />
)} )}