diff --git a/src/components/SectionHeader.tsx b/src/components/SectionHeader.tsx index e152d5e..4516673 100644 --- a/src/components/SectionHeader.tsx +++ b/src/components/SectionHeader.tsx @@ -11,16 +11,19 @@ export function SectionHeader({ viewAllLabel: string; }) { return ( -
-
- -

+
+
+ +

{title}

{viewAllLabel} diff --git a/src/components/messageStream/FilterChips.tsx b/src/components/messageStream/FilterChips.tsx index 5083101..e184ee9 100644 --- a/src/components/messageStream/FilterChips.tsx +++ b/src/components/messageStream/FilterChips.tsx @@ -23,17 +23,17 @@ export function FilterChips({ type, onTypeChange }: FilterChipsProps) { const tabClass = (active: boolean) => [ - "relative shrink-0 whitespace-nowrap px-1 py-3 text-[15px] leading-none outline-none transition-colors", - "border-b-2", + "relative flex h-[52px] shrink-0 items-center whitespace-nowrap px-3 pb-4 pt-3 text-[15px] leading-6 outline-none transition-colors md:h-auto md:px-1 md:py-3 md:leading-none", + "border-b-0 md:border-b-2", active - ? "border-ark-gold text-ark-gold font-medium" - : "border-transparent text-neutral-400 hover:text-ark-gold/80", + ? "border-ark-gold font-medium text-white md:text-ark-gold" + : "border-transparent text-[#97989A] hover:text-ark-gold/80 md:text-neutral-400", ].join(" "); return ( -
+
{TYPE_FILTERS.map((tp) => { @@ -51,6 +51,10 @@ export function FilterChips({ type, onTypeChange }: FilterChipsProps) { ); })} +
); diff --git a/src/components/messageStream/MessageStream.tsx b/src/components/messageStream/MessageStream.tsx index 586e3cc..2462c39 100644 --- a/src/components/messageStream/MessageStream.tsx +++ b/src/components/messageStream/MessageStream.tsx @@ -72,10 +72,10 @@ export function MessageStream({ scope }: MessageStreamProps) { }; return ( -
+
updateParam("type", v)} /> -
+
{groups.map((group) => (
{group.items.map((post) => ( diff --git a/src/components/messageStream/bubbles/FileDocBubble.tsx b/src/components/messageStream/bubbles/FileDocBubble.tsx index 19907d4..6cbd7dd 100644 --- a/src/components/messageStream/bubbles/FileDocBubble.tsx +++ b/src/components/messageStream/bubbles/FileDocBubble.tsx @@ -14,7 +14,6 @@ import { postDisplayText } from "../utils/postText"; function AttachmentRow({ postId, att }: { postId: string; att: Attachment }) { const { t } = useI18n(); - const isImageAsDoc = att.mime.startsWith("image/"); const { Icon, color } = fileIcon({ mime: att.mime, filename: att.filename }); const displayFilename = filenameWithExtension(att.filename, att.mime); const [isDownloading, setIsDownloading] = useState(false); @@ -28,50 +27,41 @@ function AttachmentRow({ postId, att }: { postId: string; att: Attachment }) { }; return ( -
+
+ +
+
+ {middleEllipsisFilename(displayFilename)} +
+
+ {isDownloading ? t("downloading") : formatBytes(att.sizeBytes)} +
+
-
-
- {middleEllipsisFilename(displayFilename)} -
-
- {isDownloading ? t("downloading") : formatBytes(att.sizeBytes)} -
-
); } @@ -80,12 +70,12 @@ export function FileDocBubble({ post }: { post: Post }) { const { lang } = useI18n(); const text = postDisplayText(post, lang); return ( -
+
{post.attachments.map((att) => ( ))} {text ? ( -
+
{text}
) : null} diff --git a/src/layouts/PublicLayout.tsx b/src/layouts/PublicLayout.tsx index c4dc84b..3c0bdf1 100644 --- a/src/layouts/PublicLayout.tsx +++ b/src/layouts/PublicLayout.tsx @@ -531,8 +531,10 @@ export function PublicLayout() {
diff --git a/src/pages/Browse/index.tsx b/src/pages/Browse/index.tsx index f35dd90..1ae55af 100644 --- a/src/pages/Browse/index.tsx +++ b/src/pages/Browse/index.tsx @@ -1,5 +1,6 @@ import { useSearchParams } from "react-router-dom"; import { MessageStream } from "../../components/messageStream/MessageStream"; +import { SectionHeader } from "../../components/SectionHeader"; import { useI18n } from "../../i18n"; export function Browse() { @@ -7,10 +8,14 @@ export function Browse() { const [sp] = useSearchParams(); const q = sp.get("q") || ""; return ( -
-

- {q ? `${t("search")}: ${q}` : t("all")} -

+
+
+ +
); diff --git a/src/pages/Home/index.tsx b/src/pages/Home/index.tsx index a3fcf26..e97ea78 100644 --- a/src/pages/Home/index.tsx +++ b/src/pages/Home/index.tsx @@ -26,6 +26,8 @@ export function Home() { const [latest, setLatest] = useState([]); const [err, setErr] = useState(null); const recRowRef = useRef(null); + const categoryRowRef = useRef(null); + const [activeCategoryPage, setActiveCategoryPage] = useState(0); const [canScrollRec, setCanScrollRec] = useState(false); const [recScroll, setRecScroll] = useState({ ratio: 1, progress: 0 }); @@ -58,6 +60,31 @@ export function Home() { const iconKeyForResource = (r: PostBackedResource) => cats.find((c) => c.id === r.categoryId)?.iconKey ?? "folder"; + const categoryPages: Category[][] = []; + for (let index = 0; index < cats.length; index += 9) { + categoryPages.push(cats.slice(index, index + 9)); + } + + useEffect(() => { + const row = categoryRowRef.current; + if (!row) return; + + const update = () => { + const width = row.clientWidth || 1; + const next = Math.round(row.scrollLeft / width); + setActiveCategoryPage((prev) => (prev === next ? prev : next)); + }; + + update(); + row.addEventListener("scroll", update, { passive: true }); + return () => row.removeEventListener("scroll", update); + }, [cats.length]); + + useEffect(() => { + setActiveCategoryPage(0); + categoryRowRef.current?.scrollTo({ left: 0 }); + }, [lang]); + useEffect(() => { const row = recRowRef.current; if (!row) { @@ -113,7 +140,70 @@ export function Home() { viewAllTo="/browse" viewAllLabel={t("viewAll")} /> -
+ +
+
+ {categoryPages.map((page, pageIndex) => ( +
+ {page.map((c) => ( + + +
+ {c.name} +
+ + ))} +
+ ))} +
+ + {categoryPages.length > 1 ? ( +
+ {categoryPages.map((_, index) => ( +
+ ) : null} +
+ +
{cats.map((c) => { const { line1, line2 } = categoryCardLines(c.name); return (