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
12 changes: 6 additions & 6 deletions data/assets/styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -10422,33 +10422,33 @@ body.ios>iframe {
color: #fff;
}

#user-pref>ul {
#user-pref ul {
margin-bottom: .55em;
padding-bottom: .5em;
}

Comment on lines +10425 to 10429
#user-pref>ul li.btn-group {
#user-pref ul li.btn-group {
width: 100%;
display: block;
margin-bottom: .75em;
}

#user-pref>ul li.btn-group:last-child {
#user-pref ul li.btn-group:last-child {
margin-bottom: .35em;
}

#user-pref>ul li.btn-group.option-romanization {
#user-pref ul li.btn-group.option-romanization {
display: none;
}

#user-pref>ul li.btn-group label {
#user-pref ul li.btn-group label {
display: block;
font-weight: 400;
margin-top: 5px;
text-shadow: 1px 1px 0 rgba(238,238,238,.7);
}

#user-pref>ul li.btn-group button {
#user-pref ul li.btn-group button {
float: none;
margin-top: -.4em;
border-radius: 4px !important;
Expand Down
12 changes: 8 additions & 4 deletions src/components/navbar-normal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -614,10 +614,14 @@ export function NavbarNormal({ currentLang }: NavbarNormalProps) {
[closeDictionaryDropdown, navigate],
);

const handlePrefClick = useCallback((e: React.MouseEvent<HTMLAnchorElement>) => {
e.preventDefault();
toggleUserPrefPanel();
}, []);
const handlePrefClick = useCallback(
(e: React.MouseEvent<HTMLAnchorElement>) => {
e.preventDefault();
closeDictionaryDropdown();
toggleUserPrefPanel();
},
[closeDictionaryDropdown],
);

/**
* 語言選項點擊:依照原 press-lang 邏輯計算目標路徑
Expand Down
2 changes: 1 addition & 1 deletion src/utils/media-cdn.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export const ASSET_CDN_BASE = "https://r2-assets.moedict.tw";
* edge-cached stylesheet key (the original unversioned object at 24h, or a
* prior `?v=` version still cached at the 5-minute TTL).
*/
export const LEGACY_STYLESHEET_VERSION = "20260711";
export const LEGACY_STYLESHEET_VERSION = "20260914";

/** 筆畫 JSON:`${STROKE_JSON_BASE_URL}/{codepoint-hex}.json` */
export const STROKE_JSON_BASE_URL = `${ASSET_CDN_BASE}/stroke-json`;
Expand Down
29 changes: 29 additions & 0 deletions tests/e2e/legacy-styles-regression.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,35 @@ test.describe("legacy styles.css \u2014 harness self-verification (controls)", (
).not.toBe(blankDigest);
});

test("pref panel rows stack vertically under the real stylesheet (narrow viewport)", async ({
page,
}) => {
// The React #user-pref markup nests its <ul> inside a wrapper <div>,
// so the legacy `#user-pref>ul ...` child-combinator rules never matched
// and Bootstrap's `.btn-group { display: inline-block }` tiled the rows
// side-by-side (labels merging into one unreadable line) wherever two
// rows fit. The rules are now descendant selectors; every settings row
// must be block-level regardless of viewport width.
await page.setViewportSize({ width: 375, height: 667 });
await blockCssSubresources(page);
await routeStylesCss(page, readWorkingTreeStylesCss);
await page.goto("/%E8%90%8C");
await settle(page, "dictionary-lang");
const displays = await page.evaluate(() => {
const rows = Array.from(document.querySelectorAll("#user-pref li.btn-group"));
return {
count: rows.length,
displays: rows.map((li) => window.getComputedStyle(li).display),
labelDisplays: rows.map(
(li) => window.getComputedStyle(li.querySelector("label")!).display,
),
};
});
expect(displays.count).toBeGreaterThan(2);
expect(displays.displays).toEqual(displays.displays.map(() => "block"));
expect(displays.labelDisplays).toEqual(displays.labelDisplays.map(() => "block"));
});

test("negative control: a deliberately mutated stylesheet changes both the screenshot and the computed-style digest", async ({
page,
}) => {
Expand Down
11 changes: 11 additions & 0 deletions tests/e2e/preferences.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,4 +53,15 @@ test.describe("user preferences (phonetics, pinyin system)", () => {
await page.evaluate(() => window.localStorage.setItem("pinyin_h", "PFS"));
expect(await page.evaluate(() => window.localStorage.getItem("pinyin_h"))).toBe("PFS");
});

test("opening 偏好設定 closes the dictionary dropdown", async ({ page }) => {
await page.goto("/%E8%90%8C");
await waitForAppReady(page);
await expect(page.getByText("草木初生的芽").first()).toBeVisible({ timeout: 30_000 });
await page.locator("ul.nav.navbar-nav > li").first().locator("a").first().click();
const firstOption = page.locator("ul.nav.navbar-nav a.lang-option").first();
await expect(firstOption).toBeVisible({ timeout: 10_000 });
await page.locator("#btn-pref > a").click();
await expect(firstOption).toBeHidden({ timeout: 10_000 });
});
});