terry-staging #11

Merged
terry merged 37 commits from terry-staging into main 2026-05-29 19:29:58 +00:00
4 changed files with 19 additions and 33 deletions
Showing only changes of commit d7e2e56cde - Show all commits

View File

@@ -28,7 +28,7 @@ export function CollapsibleText({
children, children,
className = "", className = "",
wrapperClassName = "", wrapperClassName = "",
collapsedLines = 8, collapsedLines = 25,
}: { }: {
children: ReactNode; children: ReactNode;
/** Typography classes applied to the text container. */ /** Typography classes applied to the text container. */
@@ -110,7 +110,7 @@ export function CollapsibleText({
type="button" type="button"
onClick={() => setExpanded((v) => !v)} onClick={() => setExpanded((v) => !v)}
aria-expanded={expanded} aria-expanded={expanded}
className="group mt-1.5 inline-flex h-8 items-center gap-1 text-[13px] font-medium text-ark-gold transition-colors duration-200 hover:text-ark-gold2" className="group mt-1 inline-flex items-center gap-1 text-[13px] font-medium leading-5 text-ark-gold transition-colors duration-200 hover:text-ark-gold2"
> >
<span>{expanded ? t("showLess") : t("showMore")}</span> <span>{expanded ? t("showLess") : t("showMore")}</span>
<m.span <m.span

View File

@@ -1,6 +1,5 @@
import type { ComponentType } from "react"; import type { ComponentType } from "react";
import type { Post } from "../../types/post"; import type { Post } from "../../types/post";
import { useI18n } from "../../i18n";
import { TextBubble } from "./bubbles/TextBubble"; import { TextBubble } from "./bubbles/TextBubble";
import { FileDocBubble } from "./bubbles/FileDocBubble"; import { FileDocBubble } from "./bubbles/FileDocBubble";
import { ImageBubble } from "./bubbles/ImageBubble"; import { ImageBubble } from "./bubbles/ImageBubble";
@@ -24,7 +23,6 @@ export function pickBubble(post: Post): BubbleComponent {
} }
export function MessageBubble({ post }: { post: Post }) { export function MessageBubble({ post }: { post: Post }) {
const { lang } = useI18n();
const Bubble = pickBubble(post); const Bubble = pickBubble(post);
const isVisual = const isVisual =
Bubble === AlbumBubble || Bubble === AlbumBubble ||
@@ -49,7 +47,7 @@ export function MessageBubble({ post }: { post: Post }) {
isVisual ? "px-4 pb-3 pt-3" : "mt-3" isVisual ? "px-4 pb-3 pt-3" : "mt-3"
}`} }`}
> >
{formatDateTime(post.publishedAt, lang)} {formatDateTime(post.publishedAt)}
</time> </time>
</article> </article>
</div> </div>

View File

@@ -1,34 +1,17 @@
function localeFor(lang: string): string { function pad2(n: number): string {
const locales: Record<string, string> = { return String(n).padStart(2, "0");
zh: "zh-CN",
en: "en-US",
ja: "ja-JP",
ko: "ko-KR",
vi: "vi-VN",
id: "id-ID",
ms: "ms-MY",
};
return locales[lang] ?? "en-US";
} }
function formatDate(iso: string, lang: string): string { function formatDate(iso: string): string {
const d = new Date(iso); const d = new Date(iso);
return new Intl.DateTimeFormat(localeFor(lang), { return `${d.getFullYear()}/${d.getMonth() + 1}/${d.getDate()}`;
year: "numeric",
month: lang === "en" ? "short" : "numeric",
day: "numeric",
}).format(d);
} }
export function formatTime(iso: string, lang: string): string { export function formatTime(iso: string): string {
const d = new Date(iso); const d = new Date(iso);
return new Intl.DateTimeFormat(localeFor(lang), { return `${pad2(d.getHours())}:${pad2(d.getMinutes())}`;
hour: "numeric",
minute: "2-digit",
hour12: lang === "en",
}).format(d);
} }
export function formatDateTime(iso: string, lang: string): string { export function formatDateTime(iso: string): string {
return `${formatDate(iso, lang)} ${formatTime(iso, lang)}`; return `${formatDate(iso)} ${formatTime(iso)}`;
} }

View File

@@ -137,10 +137,15 @@ export function Home() {
for (let index = 0; index < figmaOrderedCategories.length; index += 9) { for (let index = 0; index < figmaOrderedCategories.length; index += 9) {
categoryPages.push(figmaOrderedCategories.slice(index, index + 9)); categoryPages.push(figmaOrderedCategories.slice(index, index + 9));
} }
const activeCategoryCount = categoryPages[activeCategoryPage]?.length ?? 0; // Use the tallest page so the carousel height doesn't shrink between
const activeCategoryRows = Math.ceil(activeCategoryCount / 3); // pages — otherwise the section below jumps up when swiping to a page
// with fewer categories.
const maxCategoryRows = categoryPages.reduce(
(max, page) => Math.max(max, Math.ceil(page.length / 3)),
0,
);
const mobileCategoryHeight = const mobileCategoryHeight =
activeCategoryRows * 88 + Math.max(0, activeCategoryRows - 1) * 8; maxCategoryRows * 88 + Math.max(0, maxCategoryRows - 1) * 8;
useEffect(() => { useEffect(() => {
const row = categoryRowRef.current; const row = categoryRowRef.current;