style: refine responsive topbar and auth sheet

This commit is contained in:
kris
2026-03-22 12:22:17 +08:00
parent 37709d37b7
commit 7500d02730
2 changed files with 134 additions and 76 deletions

View File

@@ -169,6 +169,7 @@ function ensureAuthUi() {
modal.className = "auth-modal-backdrop hidden";
modal.innerHTML = `
<div class="auth-modal">
<form class="auth-form" data-role="auth-form">
<div class="auth-head">
<div>
<h3>连接 StoryForge</h3>
@@ -178,15 +179,15 @@ function ensureAuthUi() {
</div>
<div class="field-stack">
<label>后端地址</label>
<input type="text" data-auth-field="backendUrl" placeholder="${DEFAULT_BACKEND_URL}" />
<input type="text" data-auth-field="backendUrl" placeholder="${DEFAULT_BACKEND_URL}" autocomplete="url" />
</div>
<div class="field-stack">
<label>用户名</label>
<input type="text" data-auth-field="username" placeholder="kris" />
<input type="text" data-auth-field="username" placeholder="kris" autocomplete="username" />
</div>
<div class="field-stack">
<label>密码</label>
<input type="password" data-auth-field="password" placeholder="输入密码" />
<input type="password" data-auth-field="password" placeholder="输入密码" autocomplete="current-password" />
</div>
<div class="field-stack">
<label>已有 Token</label>
@@ -195,8 +196,9 @@ function ensureAuthUi() {
<div class="helper-text" data-role="auth-message"></div>
<div class="auth-actions">
<button class="btn btn-secondary" type="button" data-action="auth-refresh">刷新数据</button>
<button class="btn btn-primary" type="button" data-action="submit-auth">登录并加载</button>
<button class="btn btn-primary" type="submit" data-action="submit-auth">登录并加载</button>
</div>
</form>
</div>
`;
document.body.appendChild(modal);
@@ -2442,17 +2444,8 @@ document.addEventListener("click", async (event) => {
return;
}
if (name === "submit-auth") {
setBusy(true, "正在登录并加载...");
try {
await loginWithForm();
closeAuthModal();
await bootstrap();
} catch (error) {
const message = document.querySelector('[data-role="auth-message"]');
if (message) message.textContent = error.message;
} finally {
setBusy(false, "");
}
// Auth form submission is handled centrally so clicking the submit
// button and pressing Enter share the same code path.
return;
}
if (name === "auth-refresh" || name === "refresh-data") {
@@ -2610,6 +2603,23 @@ document.addEventListener("input", (event) => {
}
});
document.addEventListener("submit", async (event) => {
const form = event.target;
if (!(form instanceof HTMLFormElement) || form.dataset.role !== "auth-form") return;
event.preventDefault();
setBusy(true, "正在登录并加载...");
try {
await loginWithForm();
closeAuthModal();
await bootstrap();
} catch (error) {
const message = document.querySelector('[data-role="auth-message"]');
if (message) message.textContent = error.message;
} finally {
setBusy(false, "");
}
});
navButtons.forEach((button) => {
button.addEventListener("click", () => {
const next = button.dataset.screenTarget;

View File

@@ -213,6 +213,16 @@ select {
min-width: 0;
}
.topbar-left {
flex: 1 1 auto;
}
.topbar-right {
flex: 1 1 auto;
justify-content: flex-end;
flex-wrap: wrap;
}
.workspace-switch,
.search,
.mini-card {
@@ -234,6 +244,8 @@ select {
.workspace-switch span {
font-size: 12px;
color: var(--muted);
display: block;
line-height: 1.4;
}
.search {
@@ -279,6 +291,7 @@ select {
display: flex;
align-items: center;
gap: 10px;
flex-wrap: wrap;
}
.auth-status {
@@ -314,6 +327,11 @@ select {
padding: 22px;
}
.auth-form {
display: grid;
gap: 0;
}
.action-modal-backdrop {
position: fixed;
inset: 0;
@@ -1144,18 +1162,37 @@ tbody tr:hover {
border-radius: 18px;
}
.topbar-left .chip-row,
.topbar-right {
width: 100%;
}
.topbar-left .chip-row {
flex-wrap: nowrap;
overflow-x: auto;
padding-bottom: 2px;
scrollbar-width: none;
}
.topbar-left .chip-row::-webkit-scrollbar {
display: none;
}
.top-pill {
padding: 7px 10px;
}
.auth-inline {
flex-wrap: wrap;
width: 100%;
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 8px;
}
.auth-status {
max-width: none;
width: 100%;
grid-column: 1 / -1;
}
.auth-modal-backdrop,
@@ -1332,6 +1369,7 @@ tbody tr:hover {
.topbar-right {
gap: 8px;
align-items: stretch;
}
.search {
@@ -1339,7 +1377,53 @@ tbody tr:hover {
}
.action-row .btn,
.btn {
.auth-actions .btn {
width: 100%;
}
.workspace-switch {
padding: 10px 12px;
}
.workspace-switch strong {
font-size: 12px;
}
.workspace-switch span {
font-size: 11px;
}
.topbar-left .chip-row {
gap: 6px;
}
.topbar-left .chip,
.top-pill {
font-size: 11px;
}
.topbar-right > :not(.avatar) {
width: 100%;
}
.topbar-right .search {
order: 2;
}
.topbar-right .auth-inline {
order: 1;
}
.topbar-right .top-pill {
width: auto;
}
.topbar-right .avatar {
order: 4;
align-self: flex-end;
}
.auth-inline .btn {
width: 100%;
}
@@ -1383,39 +1467,3 @@ tbody tr:hover {
font-size: 12px;
text-align: right;
}
@media (max-width: 1320px) {
.grid-main,
.grid-split,
.grid-5,
.grid-4,
.grid-3,
.three-col,
.two-col {
grid-template-columns: 1fr;
}
.calendar {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
}
@media (max-width: 1080px) {
.app-shell {
grid-template-columns: 1fr;
}
.sidebar {
position: relative;
height: auto;
}
.topbar {
flex-direction: column;
align-items: stretch;
}
.topbar-left,
.topbar-right {
flex-wrap: wrap;
}
.search {
min-width: 0;
}
}