fix(frontend): refine settings dialog layout
Independent Staging Quality Gate / validate (push) Failing after 8m47s
Independent Staging Quality Gate / publish (push) Skipped

Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
jesse-ux
2026-09-19 11:32:27 +08:00
co-authored by Claude Code
parent c2ecbc74cd
commit eb8f5147f4
12 changed files with 135 additions and 48 deletions
+25 -19
View File
@@ -1831,23 +1831,21 @@ button:disabled { cursor: default; opacity: .45; }
.account-modal-overlay { position: fixed; z-index: 40; inset: 0; display: grid; place-items: center; padding: var(--space-4); background: var(--color-scrim); animation: account-overlay-enter 180ms ease-out both; }
.account-modal { width: min(100%, 560px); max-height: min(84vh, 760px); overflow-y: auto; padding: var(--space-8); border: 1px solid var(--color-border); border-radius: var(--radius-xl); background: var(--color-canvas); box-shadow: var(--shadow-elevated); animation: account-dialog-enter 180ms var(--ease-out) both; }
.settings-modal { width: min(100vw - 32px, 880px); height: min(84vh, 640px); max-height: min(84vh, 640px); overflow: hidden; display: grid; grid-template-rows: auto 1fr; }
.account-settings-shell { display: grid; grid-template-columns: 176px minmax(0, 1fr); min-height: 0; overflow: hidden; align-items: stretch; }
.settings-dialog-nav { display: grid; align-content: start; gap: var(--space-1); overflow: hidden; }
.settings-dialog-nav-item { min-height: 44px; display: grid; grid-template-columns: 18px minmax(0, 1fr) 16px; align-items: center; gap: var(--space-2); padding: 0 var(--space-3); border: 0; border-radius: var(--radius-md); background: transparent; color: var(--color-ink-secondary); cursor: pointer; text-align: left; }
.account-settings-shell { display: grid; grid-template-columns: 200px minmax(0, 1fr); min-height: 0; overflow: hidden; align-items: stretch; }
.settings-dialog-nav { display: grid; align-content: start; gap: var(--space-1); overflow: hidden; padding-right: var(--space-4); border-right: 1px solid var(--color-border); }
.settings-dialog-nav-item { min-height: 44px; display: grid; grid-template-columns: 18px minmax(0, 1fr); align-items: center; gap: var(--space-2); padding: 0 var(--space-3); border: 0; border-radius: var(--radius-md); background: transparent; color: var(--color-ink-secondary); cursor: pointer; text-align: left; }
.settings-dialog-nav-item:hover { background: color-mix(in srgb, var(--color-canvas-muted) 55%, transparent); color: var(--color-ink-secondary); }
.settings-dialog-nav-item[aria-current="page"] { background: var(--color-canvas-muted); color: var(--color-ink); }
.settings-dialog-nav-item > svg { width: 18px; height: 18px; color: var(--color-ink-tertiary); }
.settings-dialog-nav-item > svg:last-child { width: 15px; height: 15px; margin-left: auto; }
.settings-dialog-content { min-width: 0; min-height: 0; overflow-y: auto; }
/* Form panes (个人资料 / 通用设置) read as one column, so they are capped and left
aligned instead of stretching across the ~690px content area. The cap lives on the
children, never on the scroll container or the dialog box: .settings-modal keeps its
fixed width/height, so the four panes still cannot change the dialog size (BUG-554 /
BUG-698). List panes (星盘资料 / 账户与点数) stay full-bleed. */
.settings-dialog-content--form > * { max-width: 440px; margin-right: auto; }
.settings-dialog-copy { margin: 0 0 var(--space-5); color: var(--color-ink-secondary); font-size: var(--type-body-sm); line-height: 1.6; }
.settings-dialog-content { min-width: 0; min-height: 0; overflow-y: auto; padding: 0 var(--space-8) var(--space-8); }
/* Form panes (个人资料 / 通用设置) use a comfortable reading width instead of
leaving the content stranded in a narrow 440px column. The cap stays on pane
children, never on the scroll container or dialog box, so pane switches keep the
same frame (BUG-554 / BUG-698). List panes remain full-bleed within this inset. */
.settings-dialog-content--form > * { max-width: 560px; margin-right: auto; }
.settings-dialog-copy { max-width: 760px; margin: 0 0 var(--space-5); color: var(--color-ink-secondary); font-size: var(--type-body-sm); line-height: 1.6; }
.avatar-section { padding-top: 0; }
.avatar-editor { display: grid; grid-template-columns: 48px minmax(0, 1fr); align-items: center; gap: var(--space-5); margin-top: var(--space-5); }
.avatar-editor { display: grid; grid-template-columns: 56px minmax(0, 1fr); align-items: center; gap: var(--space-5); margin-top: var(--space-5); }
.avatar-editor-controls { min-width: 0; display: grid; gap: var(--space-4); }
.avatar-palette-list { display: grid; grid-template-columns: repeat(4, minmax(48px, 1fr)); gap: var(--space-2); }
.avatar-palette { min-width: 0; height: 34px; overflow: hidden; display: flex; padding: 3px; border: 1px solid var(--color-border); border-radius: var(--radius-md); background: var(--color-canvas); cursor: pointer; transition: border-color 120ms ease-out, box-shadow 120ms ease-out, transform 120ms ease-out; }
@@ -1864,6 +1862,8 @@ button:disabled { cursor: default; opacity: .45; }
.logout-modal { width: min(100%, 400px); }
.account-modal h2, .auth-panel h1 { font-family: var(--font-display); font-weight: 500; letter-spacing: -.5px; text-wrap: balance; }
.account-modal h2 { margin: 0; font-size: var(--type-display-sm); letter-spacing: -.025em; }
.account-modal-heading { min-width: 0; display: grid; gap: var(--space-1); }
.account-modal-eyebrow { color: var(--color-ink-tertiary); font-size: var(--type-overline); font-weight: 600; letter-spacing: .08em; text-transform: uppercase; }
.account-modal-header { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--space-4); padding-bottom: var(--space-5); }
.dialog-close { width: 44px; height: 44px; display: grid; flex: 0 0 auto; place-items: center; border: 0; cursor: pointer; transition: background-color 120ms ease-out, transform 120ms ease-out; border-radius: var(--radius-md); background: var(--color-canvas-muted); }
.redeem-balance { display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-4); padding: var(--space-4) 0; border-top: 1px solid var(--color-border); border-bottom: 1px solid var(--color-border); }
@@ -1890,6 +1890,8 @@ button:disabled { cursor: default; opacity: .45; }
.chart-library-panel { display: grid; gap: var(--space-5); margin-top: var(--space-5); }
.chart-library-group { display: grid; gap: var(--space-3); }
.chart-library-group-heading { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); }
.chart-library-group-heading > div:first-child { min-width: 0; }
.chart-library-group-heading-actions { display: flex; align-items: center; flex: 0 0 auto; gap: var(--space-2); }
.chart-library-group-heading b, .chart-library-group-heading small { display: block; }
.chart-library-group-heading b { color: var(--color-ink); font-size: var(--type-caption); font-weight: 600; }
.chart-library-group-heading small { margin-top: 3px; color: var(--color-ink-secondary); font-size: var(--type-caption); font-weight: 400; }
@@ -1899,6 +1901,7 @@ button.chart-library-item { cursor: pointer; text-align: left; }
.chart-library-item-chevron { width: 16px; height: 16px; flex: 0 0 auto; color: var(--color-ink-tertiary); }
.chart-library-back { min-height: 44px; display: inline-flex; align-items: center; gap: var(--space-2); margin: 0 0 var(--space-4); padding: 0; border: 0; background: transparent; color: var(--color-ink-secondary); cursor: pointer; font-size: var(--type-body-sm); }
.chart-library-add { margin-top: var(--space-4); }
.chart-library-add--heading { margin-top: 0; white-space: nowrap; }
.chart-library-item-main { min-width: 0; }
.chart-library-item strong, .chart-library-item small { display: block; }
.chart-library-item strong { color: var(--color-ink); font-size: var(--type-body-md); font-weight: 500; }
@@ -2025,13 +2028,16 @@ input:not([type="radio"]):not([type="checkbox"]):not([class^="ant-"]):not([class
.account-modal { width: 100%; max-height: 100vh; min-height: 100vh; border-radius: 0; padding: var(--space-6); }
.settings-modal { width: 100%; height: 100vh; max-height: 100vh; }
.account-settings-shell { grid-template-columns: 1fr; grid-template-rows: auto 1fr; gap: var(--space-4); }
.settings-dialog-nav { position: static; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--space-1); padding-bottom: var(--space-3); border-bottom: 1px solid var(--color-border); }
.settings-dialog-nav-item { min-height: 40px; grid-template-columns: 1fr; justify-items: center; gap: 2px; padding: var(--space-2); text-align: center; font-size: var(--type-caption); }
.settings-dialog-nav-item > svg:last-child { display: none; }
.settings-dialog-content { min-height: 0; overflow-y: auto; }
.avatar-editor { grid-template-columns: 48px minmax(0, 1fr); gap: var(--space-4); }
.avatar-editor > .user-avatar { width: 48px !important; height: 48px !important; }
.settings-dialog-nav { position: static; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--space-1); padding-bottom: var(--space-3); border-right: 0; border-bottom: 1px solid var(--color-border); }
.settings-dialog-nav-item { min-height: 44px; grid-template-columns: 1fr; justify-items: center; gap: 2px; padding: var(--space-2); text-align: center; font-size: var(--type-caption); }
.settings-dialog-content { min-height: 0; overflow-y: auto; padding: 0 var(--space-4) var(--space-6); }
.settings-dialog-content--form > * { max-width: none; }
.avatar-editor { grid-template-columns: 56px minmax(0, 1fr); gap: var(--space-4); }
.avatar-editor > .user-avatar { width: 56px !important; height: 56px !important; }
.avatar-palette-list { grid-template-columns: repeat(2, minmax(64px, 1fr)); }
.chart-library-group-heading { align-items: flex-start; }
.chart-library-group-heading-actions { align-items: flex-end; flex-direction: column; gap: var(--space-1); }
.chart-library-add--heading { min-height: 40px; padding-inline: var(--space-3); }
.auth-page { height: 100vh; overflow-x: hidden; overflow-y: auto; -webkit-overflow-scrolling: touch; padding: 0; }
.auth-shell { min-height: 100%; overflow: visible; align-content: start; grid-template-columns: 1fr; grid-template-rows: auto auto; border-radius: 0; box-shadow: none; }
.auth-story { min-height: 0; justify-content: flex-start; gap: var(--space-3); padding: var(--space-6) var(--space-6) var(--space-5); }
@@ -1,6 +1,6 @@
"use client";
import { ChevronRight, Settings, UserRound, Users, WalletCards, X } from "lucide-react";
import { Settings, UserRound, Users, WalletCards, X } from "lucide-react";
import { memo, type MutableRefObject, type ReactNode } from "react";
import { createPortal } from "react-dom";
@@ -72,7 +72,10 @@ export const AccountDialogOverlay = memo(function AccountDialogOverlay({
onMouseDown={(event) => event.stopPropagation()}
>
<header className="account-modal-header">
<h2 id="account-dialog-title">{model.title}</h2>
<div className="account-modal-heading">
{isSettingsDialog ? <span className="account-modal-eyebrow">设置</span> : null}
<h2 id="account-dialog-title">{model.title}</h2>
</div>
<button
className="dialog-close"
ref={model.closeButtonRef}
@@ -97,7 +100,6 @@ export const AccountDialogOverlay = memo(function AccountDialogOverlay({
>
<Icon aria-hidden="true" />
<span>{label}</span>
<ChevronRight aria-hidden="true" />
</button>
))}
</nav>
+17 -15
View File
@@ -323,24 +323,26 @@ export function ChartLibraryPanel({
<div className="chart-library-group">
<div className="chart-library-group-heading">
<div><b>其他人</b><small>亲友、伴侣或客户资料</small></div>
<span className="chart-library-count">{otherCharts.length}</span>
<div className="chart-library-group-heading-actions">
<span className="chart-library-count">{otherCharts.length}</span>
<button
className="button-secondary chart-library-add chart-library-add--heading"
type="button"
onClick={() => {
setOtherProfileDraft(emptyProfile);
setOtherChartRelationship("other");
setEditingChartId(null);
setAccountError("");
setProfileNotice("");
setView({ kind: "add" });
}}
>
添加其他人
</button>
</div>
</div>
{otherCharts.length === 0 && <p className="empty-library-copy">还没有其他星盘,先添加一份资料。</p>}
{otherCharts.map(listRow)}
<button
className="button-secondary chart-library-add"
type="button"
onClick={() => {
setOtherProfileDraft(emptyProfile);
setOtherChartRelationship("other");
setEditingChartId(null);
setAccountError("");
setProfileNotice("");
setView({ kind: "add" });
}}
>
添加其他人
</button>
</div>
</div>
);
+3 -3
View File
@@ -27,11 +27,11 @@ export function ProfilePanel({
{account.avatar && (
<section className="sheet-section avatar-section" aria-labelledby="avatar-section-title">
<div className="section-heading">
<b id="avatar-section-title">头像</b>
<small>Beam 形象由随机种子生成,刷新和换设备后保持一致</small>
<b id="avatar-section-title">账户头像</b>
<small>Beam 形象会在刷新和换设备后保持一致</small>
</div>
<div className="avatar-editor">
<UserAvatar avatar={account.avatar} size={48} label="当前头像预览" />
<UserAvatar avatar={account.avatar} size={56} label="当前头像预览" />
<div className="avatar-editor-controls">
<div className="avatar-palette-list" role="radiogroup" aria-label="头像配色">
{beamAvatarPalettes.map((palette, index) => (