improved masonry look
This commit is contained in:
parent
6f4759d928
commit
b4ea7dcd8e
|
@ -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 (
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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>
|
||||||
);
|
);
|
||||||
|
|
|
@ -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">
|
||||||
|
|
|
@ -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>
|
||||||
|
|
||||||
|
|
|
@ -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,14 +158,20 @@ 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 ${
|
||||||
<LinkTypeBadge link={link} />
|
link.type === "url" ? "" : "hidden"
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
<LinkIcon link={link} size="small" className="mt-1" />
|
||||||
</div>
|
</div>
|
||||||
|
<p className="text-primary text-sm">{unescapeString(link.name)}</p>
|
||||||
|
|
||||||
{link.description && (
|
{link.description && (
|
||||||
<p className="text-sm">{unescapeString(link.description)}</p>
|
<p className="text-sm">{unescapeString(link.description)}</p>
|
||||||
)}
|
)}
|
||||||
|
<LinkTypeBadge link={link} />
|
||||||
|
</div>
|
||||||
|
|
||||||
{link.tags[0] && (
|
{link.tags[0] && (
|
||||||
<div className="flex gap-1 items-center flex-wrap">
|
<div className="flex gap-1 items-center flex-wrap">
|
||||||
|
@ -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} />
|
||||||
)}
|
)}
|
||||||
|
|
Ŝarĝante…
Reference in New Issue