Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions web/src/features/memory/ArchiveCalendar.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import "@testing-library/jest-dom/vitest";
import { cleanup, fireEvent, render, screen } from "@testing-library/react";
import { afterEach, expect, it, vi } from "vitest";

import { NavigationProvider } from "../../app/navigation";
import i18n from "../../i18n";
import { ArchiveCalendar } from "./ArchiveCalendar";

afterEach(async () => {
cleanup();
await i18n.changeLanguage("zh-CN");
});

it.each(["zh-CN", "en"])("uses numeric archive dates in %s", async (locale) => {
await i18n.changeLanguage(locale);
render(
<NavigationProvider>
<ArchiveCalendar
months={[{ year: 2026, month: 8, count: 1 }]}
monthCounts={new Map([["2026-08", 1]])}
dayCounts={new Map([[10, 1]])}
visibleMonth="2026-08"
range={{ oldest: "2026-08", newest: "2026-08" }}
selectedDay={null}
today="2026-08-11"
positioned={false}
note={null}
variant="column"
onVisibleMonthChange={vi.fn()}
/>
</NavigationProvider>,
);
const title = screen.getByRole("button", { name: /2026-08/ });
expect(title).toHaveTextContent("2026-08");
expect(screen.getByRole("link", { name: /2026-08-10/ })).toHaveAttribute(
"href",
"/archive?day=2026-08-10",
);
fireEvent.click(title);
const month = await screen.findByRole("link", { name: /2026-08[,,]/ });
expect(month).toHaveTextContent(/^8/);
const count = locale === "en" ? /^1 post$/ : /^1 条$/;
expect(month.querySelector("small")).toHaveTextContent(count);
const years = screen.getByRole("group", { name: i18n.t("年份") });
expect(years.querySelector("button small")).toHaveTextContent(count);
});
57 changes: 18 additions & 39 deletions web/src/features/memory/ArchiveCalendar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -102,38 +102,29 @@ function MonthPicker({
{count > 0 ? (
<InternalLink
aria-current={key === visibleMonth ? "date" : undefined}
aria-label={t("{{value1}}年{{value2}}月,{{value3}} 条 Moment", {
count: count,
value1: year,
value2: index,
value3: count,
aria-label={t("{{value1}},{{value2}} 条 Moment{{value3}}", {
count,
value1: key,
value2: count,
value3: "",
})}
href={archiveHref({ month: key })}
onClick={(event) => {
onNavigate?.(event);
setOpen(false);
}}
>
<strong>
{index}
{t("月")}
</strong>
<strong>{index}</strong>
<small>
{count} {t("条")}
{count} {t("条", { count })}
</small>
</InternalLink>
) : (
<span
aria-label={t("{{value1}}年{{value2}}月,没有 Moment", {
value1: year,
value2: index,
})}
aria-label={t("{{value1}},没有 Moment", { value1: key })}
className={styles.pickerEmptyMonth}
>
<strong>
{index}
{t("月")}
</strong>
<strong>{index}</strong>
<small>—</small>
</span>
)}
Expand All @@ -153,19 +144,14 @@ function MonthPicker({
open={open}
>
<h2 className={styles.calendarTitle}>
<span aria-hidden="true" className={styles.calendarTitleGuide}>
{t(WEEK_DAYS[0])}
</span>
<Popover.Trigger
aria-label={t("{{value1}}年{{value2}}月,选择年月", {
value1: shown.year,
value2: shown.month,
})}
aria-label={`${visibleMonth}, ${t("选择年月")}`}
className={styles.monthTitle}
>
<span>
{shown.year}
{t("年")}
{shown.month}
{t("月")}
</span>
<span>{visibleMonth}</span>
<Icon name="chevron-down" />
</Popover.Trigger>
</h2>
Expand Down Expand Up @@ -200,15 +186,13 @@ function MonthPicker({
>
<strong>{value}</strong>
<small>
{yearCounts.get(value)} {t("条")}
{yearCounts.get(value)}{" "}
{t("条", { count: yearCounts.get(value) })}
</small>
</button>
))}
</div>
<ol
aria-label={t("{{value1}} 年的月份", { value1: year })}
className={styles.pickerMonths}
>
<ol aria-label={String(year)} className={styles.pickerMonths}>
{cells}
</ol>
</Popover.Popup>
Expand Down Expand Up @@ -244,7 +228,6 @@ export function ArchiveCalendar({
}: ArchiveCalendarProps) {
const { t } = useTranslation();

const { month } = splitMonth(visibleMonth);
const previous = shiftMonth(visibleMonth, -1);
const next = shiftMonth(visibleMonth, 1);
const monthCount = monthCounts.get(visibleMonth) ?? 0;
Expand All @@ -266,11 +249,7 @@ export function ArchiveCalendar({
const count = dayCounts?.get(day) ?? 0;
const isToday = date === today;
const isSelected = date === selectedDay;
const spoken = t("{{value1}}月{{value2}}日{{value3}}", {
value1: month,
value2: day,
value3: isToday ? t(",今天") : "",
});
const spoken = `${date}${isToday ? t(",今天") : ""}`;
cells.push(
<li
className={count > 0 ? styles.calendarDay : styles.calendarEmptyDay}
Expand Down
34 changes: 25 additions & 9 deletions web/src/features/memory/Memory.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -445,22 +445,34 @@

.calendarHeader {
min-block-size: var(--target-size);
display: flex;
display: grid;
grid-template-columns: repeat(7, minmax(0, 1fr));
align-items: center;
justify-content: space-between;
gap: var(--space-2);
}

.calendarTitle {
position: relative;
grid-column: 1;
justify-self: center;
min-inline-size: 0;
flex: 1 1 auto;
margin: 0;
font: inherit;
}

/* Match the first weekday's intrinsic width so the title starts at its text. */
.calendarTitleGuide {
visibility: hidden;
white-space: nowrap;
}

/* The month is a heading and a button: the words are the control. */
.monthTitle {
position: absolute;
inset-block-start: 50%;
inset-inline-start: 0;
transform: translateY(-50%);
min-block-size: var(--target-size);
max-inline-size: 100%;
inline-size: max-content;
display: inline-flex;
align-items: center;
gap: var(--space-1);
Expand Down Expand Up @@ -490,8 +502,7 @@
}
}

/* The words never wrap: a flex heading offers its child its narrowest
width, and a title reading 2026年9 over 月 is a title that broke. */
/* Keep the month label on one line beside its chevron. */
.monthTitle span {
overflow: hidden;
text-overflow: ellipsis;
Expand All @@ -506,8 +517,9 @@
}

.calendarPager {
grid-column: 5 / -1;
justify-self: end;
display: flex;
flex: 0 0 auto;
gap: var(--space-1);
}

Expand Down Expand Up @@ -562,10 +574,14 @@
list-style: none;
}

.calendarTitleGuide,
.weekHeader {
color: var(--text-tertiary);
font-family: var(--font-sans);
font-size: var(--text-xs);
}

.weekHeader {
color: var(--text-tertiary);
text-align: center;
}

Expand Down
Loading
Loading