style: refine responsive topbar and auth sheet
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user