- {children}
+
+ {columns.map((artifacts, index) => (
+
+ {artifacts}
+
+ ))}
);
}
-function clearCardLayout(card: HTMLElement) {
- card.style.removeProperty("grid-column-start");
- card.style.removeProperty("grid-row-start");
- card.style.removeProperty("grid-row-end");
- card.style.removeProperty("--artifact-offset-x");
- card.style.removeProperty("--artifact-offset-y");
-}
+function useColumnCount(): number {
+ const [columnCount, setColumnCount] = useState(getColumnCount);
-function setArtifactOffset(card: HTMLElement, seed: string, index: number) {
- const hash = hashString(`${seed}:artifact:${index}`);
- const horizontalOffset = (hash % 17) - 8;
- const verticalOffset = ((hash >>> 5) % 13) - 6;
+ useLayoutEffect(() => {
+ function updateColumnCount() {
+ setColumnCount(getColumnCount());
+ }
- card.style.setProperty("--artifact-offset-x", `${horizontalOffset}px`);
- card.style.setProperty("--artifact-offset-y", `${verticalOffset}px`);
-}
+ window.addEventListener("resize", updateColumnCount);
+ updateColumnCount();
-function getColumnCount(gridTemplateColumns: string): number {
- if (gridTemplateColumns === "none") {
- return 0;
- }
+ return () => window.removeEventListener("resize", updateColumnCount);
+ }, []);
- return gridTemplateColumns.split(" ").length;
+ return columnCount;
}
-function getShortestColumn(columnHeights: number[]): number {
- return columnHeights.reduce(
- (shortestIndex, height, index) =>
- height < columnHeights[shortestIndex]! ? index : shortestIndex,
- 0,
- );
-}
+function getColumnCount(): number {
+ if (window.innerWidth >= THREE_COLUMN_BREAKPOINT) {
+ return 3;
+ }
-function getRowSpan(
- card: HTMLElement,
- rowHeight: number,
- rowGap: number,
-): number {
- return Math.ceil(
- (card.getBoundingClientRect().height + rowGap) / (rowHeight + rowGap),
- );
+ if (window.innerWidth >= TWO_COLUMN_BREAKPOINT) {
+ return 2;
+ }
+
+ return 1;
}
diff --git a/src/components/plyr-tracks.tsx b/src/components/plyr-tracks.tsx
index b78c611..7eb019f 100644
--- a/src/components/plyr-tracks.tsx
+++ b/src/components/plyr-tracks.tsx
@@ -44,11 +44,13 @@ export function PlyrTrackArtifact({ track }: { track: PlyrTrack }) {
}
function formatDuration(duration: number): string | null {
- if (!Number.isFinite(duration)) {
+ const parsedDuration = Number(duration);
+
+ if (!Number.isFinite(parsedDuration)) {
return null;
}
- const totalSeconds = Math.max(0, Math.round(duration));
+ const totalSeconds = Math.max(0, Math.round(parsedDuration));
const seconds = totalSeconds % 60;
const minutes = Math.floor(totalSeconds / 60) % 60;
const hours = Math.floor(totalSeconds / 3600);
diff --git a/src/components/profile-sections.tsx b/src/components/profile-sections.tsx
index 0c03956..bddf372 100644
--- a/src/components/profile-sections.tsx
+++ b/src/components/profile-sections.tsx
@@ -1,6 +1,8 @@
+import type { ReactNode } from "react";
import { useEffect, useState } from "react";
import { GrainPhotoArtifact } from "~/components/grain-photos";
+import { MasonryGrid } from "~/components/masonry-grid";
import { PlyrTrackArtifact } from "~/components/plyr-tracks";
import { ProfileArtifact } from "~/components/profile-artifact";
import { RockskyScrobble } from "~/components/rocksky-scrobble-list";
@@ -14,6 +16,7 @@ import { getMostStarredTangledRepos } from "~/lib/providers/tangled";
import { getRecentStandardDocuments } from "~/lib/providers/standard-site";
type ProfileSectionsProps = {
+ children: ReactNode;
did: string;
handle: string | null;
pds: string;
@@ -27,7 +30,12 @@ type ProfileData = {
tangledRepos: Awaited
>;
};
-export function ProfileSections({ did, handle, pds }: ProfileSectionsProps) {
+export function ProfileSections({
+ children,
+ did,
+ handle,
+ pds,
+}: ProfileSectionsProps) {
const [data, setData] = useState(null);
useEffect(() => {
@@ -57,10 +65,13 @@ export function ProfileSections({ did, handle, pds }: ProfileSectionsProps) {
if (!data) {
return (
-
- Gathering signals
- Searching the Atmosphere…
-
+
+ {children}
+
+ Gathering signals
+ Searching the Atmosphere…
+
+
);
}
@@ -99,5 +110,10 @@ export function ProfileSections({ did, handle, pds }: ProfileSectionsProps) {
)),
];
- return <>{getDidSectionOrder(did, artifacts)}>;
+ return (
+
+ {children}
+ {getDidSectionOrder(did, artifacts)}
+
+ );
}
diff --git a/src/styles/globals.css b/src/styles/globals.css
index 9235597..56dfc53 100644
--- a/src/styles/globals.css
+++ b/src/styles/globals.css
@@ -290,20 +290,13 @@ body {
.profile-grid {
display: grid;
- grid-template-columns: repeat(auto-fit, minmax(min(100%, 20rem), 1fr));
- align-items: start;
gap: 1.5rem;
}
-.profile-grid-masonry {
- grid-auto-rows: 0.5rem;
-}
-
-.profile-grid-masonry > * {
- transform: translate(
- var(--artifact-offset-x, 0),
- var(--artifact-offset-y, 0)
- );
+.profile-grid-column {
+ display: flex;
+ flex-direction: column;
+ gap: 1.5rem;
}
.profile-card {