Skip to content

Commit 81d4c53

Browse files
committed
feat(web): migrate settings header to shared contract
1 parent 01e114c commit 81d4c53

4 files changed

Lines changed: 20 additions & 61 deletions

File tree

packages/web/src/features/settings/components/settings-page.test.tsx

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -941,19 +941,24 @@ describe("SettingsPage", () => {
941941
expect(routerMocks.navigate).toHaveBeenCalledWith("/");
942942
});
943943

944-
it("renders a compact desktop header with only the settings title", async () => {
944+
it("renders the desktop settings header through the shared PageHeader contract", async () => {
945945
const sendCommand = vi.fn().mockResolvedValue({});
946946
const store = createConnectedStore(sendCommand);
947947

948948
renderSettingsPage(store);
949949

950-
const desktopHeader = document.querySelector(".settings-header__desktop") as HTMLElement | null;
950+
const desktopHeader = document.querySelector(
951+
".settings-header .page-header"
952+
) as HTMLElement | null;
951953
const mobileHeader = document.querySelector(
952954
".settings-header .mobile-page-header"
953955
) as HTMLElement | null;
954-
const headerCopy = document.querySelector(".settings-header__copy") as HTMLElement | null;
956+
const headerCopy = document.querySelector(
957+
".settings-header .page-header__copy"
958+
) as HTMLElement | null;
955959

956960
expect(desktopHeader).not.toBeNull();
961+
expect(desktopHeader).toHaveClass("page-header--secondary");
957962
expect(mobileHeader).toBeNull();
958963
expect(screen.getByRole("heading", { name: "设置" })).toBeInTheDocument();
959964
expect(
@@ -962,7 +967,7 @@ describe("SettingsPage", () => {
962967
expect(headerCopy).not.toBeNull();
963968
expect(within(headerCopy as HTMLElement).queryByText("Coder Studio")).toBeNull();
964969
expect(within(headerCopy as HTMLElement).queryByText("设置已自动保存")).toBeNull();
965-
expect(document.querySelector(".settings-header__section-pill")).toBeNull();
970+
expect(document.querySelector(".settings-header__desktop")).toBeNull();
966971
});
967972

968973
it("renders a mobile category list and returns from detail content to the settings root", async () => {

packages/web/src/features/settings/components/settings-page.tsx

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ import {
2222
resolveSupervisorRetryOnTimeout,
2323
} from "@coder-studio/core";
2424
import { useAtom, useAtomValue, useSetAtom, useStore } from "jotai";
25-
import { Check, ChevronLeft, ChevronRight } from "lucide-react";
25+
import { Check, ChevronRight } from "lucide-react";
2626
import { useEffect, useId, useRef, useState } from "react";
2727
import { useNavigate } from "react-router-dom";
2828
import { localeAtom, themeAtom } from "../../../atoms/app-ui";
@@ -38,6 +38,7 @@ import { useTranslation } from "../../../lib/i18n";
3838
import { getThemeById, resolveStoredThemeId, THEMES } from "../../../theme";
3939
import { notificationPreferencesAtom } from "../../notifications/atoms";
4040
import { MobilePageHeader } from "../../shared/components/mobile-page-header";
41+
import { PageHeader } from "../../shared/components/page-header";
4142
import {
4243
getTerminalFontSizePreference,
4344
hasExplicitTerminalFontSizeSetting,
@@ -610,19 +611,13 @@ export function SettingsPage() {
610611
backLabel={t("action.back")}
611612
/>
612613
) : (
613-
<div className="settings-header__desktop">
614-
<button
615-
type="button"
616-
className="page-header__back settings-header__back"
617-
onClick={handleBack}
618-
>
619-
<ChevronLeft size={16} />
620-
<span>{t("action.back")}</span>
621-
</button>
622-
<div className="settings-header__copy">
623-
<h1 className="page-title settings-header__title">{t("settings.title")}</h1>
624-
</div>
625-
</div>
614+
<PageHeader
615+
title={t("settings.title")}
616+
titleAs="h1"
617+
level="secondary"
618+
onBack={handleBack}
619+
backLabel={t("action.back")}
620+
/>
626621
)}
627622
</header>
628623

packages/web/src/styles/components.css

Lines changed: 0 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -743,36 +743,6 @@
743743
border-bottom: 1px solid var(--border);
744744
}
745745

746-
.settings-header__desktop {
747-
width: 100%;
748-
margin: 0;
749-
display: flex;
750-
align-items: center;
751-
justify-content: flex-start;
752-
gap: var(--sp-3);
753-
}
754-
755-
.settings-header__back {
756-
flex-shrink: 0;
757-
min-height: 30px;
758-
font-size: var(--text-xs);
759-
}
760-
761-
.settings-header__copy {
762-
min-width: 0;
763-
display: flex;
764-
flex: 0 1 auto;
765-
flex-direction: column;
766-
justify-content: flex-start;
767-
gap: 0;
768-
}
769-
770-
.settings-header__title {
771-
margin: 0;
772-
font-size: 18px;
773-
line-height: 1.05;
774-
}
775-
776746
.settings-body {
777747
display: flex;
778748
flex: 1;

packages/web/src/styles/components.theme.test.ts

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -725,9 +725,7 @@ describe("components.css theme-sensitive surfaces", () => {
725725
it("keeps settings navigation aligned with desktop editor chrome on both desktop and mobile", () => {
726726
const settingsPage = getLastRuleBlock(".settings-page");
727727
const baseSettingsHeader = getRuleBlocksFrom(stylesheet, ".settings-header")[0];
728-
const desktopSettingsHeader = getLastRuleBlock(".settings-header__desktop");
729-
const desktopSettingsCopy = getLastRuleBlock(".settings-header__copy");
730-
const desktopSettingsTitle = getLastRuleBlock(".settings-header__title");
728+
const desktopSettingsHeader = getLastRuleBlock(".page-header--secondary");
731729
const settingsBody = getLastRuleBlock(".settings-body");
732730
const settingsSidebar = getLastRuleBlock(".settings-sidebar");
733731
const settingsContent = getLastRuleBlock(".settings-content");
@@ -757,16 +755,7 @@ describe("components.css theme-sensitive surfaces", () => {
757755
expect(baseSettingsHeader).toContain("background: var(--bg-surface)");
758756
expect(baseSettingsHeader).toContain("border-bottom: 1px solid var(--border)");
759757
expect(baseSettingsHeader).toContain("padding: var(--sp-1) var(--sp-4)");
760-
expect(desktopSettingsHeader).toContain("width: 100%");
761-
expect(desktopSettingsHeader).toContain("margin: 0");
762-
expect(desktopSettingsHeader).toContain("display: flex");
763-
expect(desktopSettingsHeader).toContain("align-items: center");
764-
expect(desktopSettingsHeader).toContain("justify-content: flex-start");
765-
expect(desktopSettingsCopy).toContain("justify-content: flex-start");
766-
expect(desktopSettingsCopy).toContain("flex: 0 1 auto");
767-
expect(desktopSettingsCopy).toContain("gap: 0");
768-
expect(desktopSettingsTitle).toContain("font-size: 18px");
769-
expect(desktopSettingsTitle).toContain("line-height: 1.05");
758+
expect(desktopSettingsHeader).toContain("min-height: 48px");
770759
expect(settingsBody).toContain("align-items: stretch");
771760
expect(settingsBody).toContain("background: var(--bg-page)");
772761
expect(settingsSidebar).toContain("background: var(--bg-panel)");

0 commit comments

Comments
 (0)