feat: refonte mobile de la section Configurations #114
CI / lint (push) Successful in 2m1s
CI / security (push) Successful in 1m26s
CI / test (push) Successful in 4m50s
CI / build (push) Successful in 1m22s
CI / e2e (push) Successful in 15m34s

This commit is contained in:
2026-09-24 08:43:18 -04:00
parent d142049216
commit 9fb094f505
18 changed files with 784 additions and 101 deletions
+272 -38
View File
@@ -3164,6 +3164,23 @@ select {
margin-right: 8px;
}
.help-hamburger:hover { color: var(--accent); border-color: var(--accent); }
/* #114: close button for the mobile TOC drawer (hidden on desktop where the
nav is always visible). Scoped to #config-modal so the help modal — which
has no such button — is unaffected. */
.help-toc-close {
display: none;
width: 44px;
height: 44px;
padding: 0;
border: 1px solid var(--border);
border-radius: 6px;
background: transparent;
color: var(--text-secondary);
cursor: pointer;
align-items: center;
justify-content: center;
flex-shrink: 0;
}
.help-nav {
width: 260px;
min-width: 260px;
@@ -4777,22 +4794,204 @@ body.resizing-v {
}
}
/* BUG-071: Configurations modal — mobile usability (viewport ≤ 768px).
#config-nav shares the .help-nav rule that hides it, but the config modal
had no toggle (unlike the help modal): the header hamburger
(#config-hamburger, same .help-hamburger treatment) reveals it as a
collapsible top block. Two-column grids and fixed-width add-rows are
stacked/wrapped so nothing overflows a 360px viewport. */
/* --- #114: Configurations modal — mobile UX refonte (viewport ≤ 768px).
Builds on BUG-071 (which stacked grids/wrapped rows): the TOC becomes a
left slide-over drawer with a backdrop, the modal goes full-screen with
100dvh, every interactive control gets a ≥44px touch target, inputs are
≥16px to stop iOS auto-zoom, and the backend Save row sticks to the
bottom of its scroll container. The drawer is opened by JS toggling
.config-toc-open on #config-modal (backdrop + nav visibility) plus an
inline display on #config-nav (kept for the display-reset contract). */
@media (max-width: 768px) {
/* TOC as a collapsible top block (JS toggles inline display flex/none,
which wins over the hiding rule); the list scrolls within a capped nav. */
#config-modal #config-nav {
/* Full-screen modal with dynamic viewport height (mobile browser chrome). */
#config-modal {
padding: 0;
align-items: stretch;
}
#config-modal .editor-container {
max-width: 100%;
width: 100%;
height: 100vh;
height: 100dvh;
max-height: 100vh;
max-height: 100dvh;
border-radius: 0;
border: none;
overflow: hidden;
}
/* Hamburger: 44px touch target (shared .help-hamburger rule in the help
modal media query also sets 44px; this scopes it to the config modal
in case rule order changes). */
#config-modal .help-hamburger {
display: inline-flex;
width: 44px;
height: 44px;
min-width: 44px;
}
/* Close button in the TOC drawer header. */
#config-modal .help-toc-close {
display: inline-flex;
align-items: center;
justify-content: center;
}
#config-modal .help-nav-header {
padding: 12px 12px 8px;
gap: 8px;
}
/* Close (X) in the modal header. */
#config-modal .editor-btn {
width: 44px;
height: 44px;
min-width: 44px;
}
/* Anti-zoom: ≥16px font on text fields inside the config modal. Never
target input[type=text] globally — it would clobber .mfa-code-input. */
#config-modal .config-input,
#config-modal .config-select,
#config-modal .help-nav-search,
#config-modal .profile-field .config-input,
#config-modal .profile-field .config-select {
min-height: 44px;
font-size: 16px;
}
#config-modal .config-input--num {
width: 100%;
text-align: left;
}
#config-modal .help-nav-search-wrap {
padding: 0 12px 10px;
}
#config-modal .help-search-clear {
min-width: 44px;
min-height: 44px;
}
#config-modal .help-nav-link {
min-height: 44px;
display: flex;
align-items: center;
box-sizing: border-box;
}
/* Sticky Save row inside #cfg-backend-settings (its scroll container is
#config-scroll.help-content, which is the overflow ancestor). */
#config-modal .config-actions-row {
position: sticky;
bottom: 0;
z-index: 5;
display: flex;
flex-direction: column;
gap: 8px;
margin-top: 16px;
margin-bottom: 0;
padding: 10px 0 calc(10px + env(safe-area-inset-bottom, 0));
background: var(--bg-primary);
border-top: 1px solid var(--border);
}
#config-modal .config-actions-row .config-btn-save,
#config-modal .config-actions-row .config-btn-secondary,
#config-modal .config-actions-row .config-btn-primary,
#config-modal .config-actions-row .config-btn-danger {
flex: 1 1 auto;
width: 100%;
min-height: 44px;
box-sizing: border-box;
}
#config-modal .config-btn-save,
#config-modal .config-btn-secondary,
#config-modal .config-btn-primary,
#config-modal .config-btn-danger,
#config-modal .config-btn-add,
#config-modal .config-btn-sm,
#config-modal .mfa-link-btn,
#config-modal .theme-action-btn,
#config-modal .profile-avatar-actions .config-btn-secondary,
#config-modal .editor-btn {
min-height: 44px;
box-sizing: border-box;
}
#config-modal .config-btn-sm,
#config-modal .mfa-link-btn,
#config-modal .theme-action-btn {
min-width: 44px;
padding-left: 12px;
padding-right: 12px;
}
/* Profile avatar row: wrap instead of overflowing a 360px viewport. */
#config-modal .profile-avatar-row {
flex-wrap: wrap;
gap: 12px;
}
#config-modal .profile-form {
max-width: 100%;
}
/* MFA: one-column recovery list, wrapping action rows, full-width code
input with a readable letter-spacing (12px overflows 360px). */
#config-modal .mfa-recovery-list {
grid-template-columns: 1fr;
gap: 6px;
}
#config-modal .mfa-verify-section,
#config-modal .mfa-recovery-actions,
#config-modal .mfa-disable-actions {
flex-wrap: wrap;
}
#config-modal .mfa-verify-section .config-input,
#config-modal .mfa-verify-section .config-btn-primary {
flex: 1 1 100%;
width: 100%;
min-width: 0;
max-width: 100%;
border-right: none;
border-bottom: 1px solid var(--border);
max-height: 46vh;
box-sizing: border-box;
}
#config-modal .mfa-recovery-actions .config-btn-secondary,
#config-modal .mfa-disable-actions .config-btn-danger {
flex: 1 1 auto;
min-height: 44px;
box-sizing: border-box;
}
#config-modal .mfa-code-input {
width: 100%;
max-width: 320px;
min-height: 52px;
font-size: 24px;
letter-spacing: 6px;
}
#config-modal .mfa-secret-code {
display: block;
word-break: break-all;
overflow-wrap: anywhere;
}
#config-modal .mfa-code-input-group {
flex-wrap: wrap;
justify-content: flex-start;
}
/* WebAuthn key rows: wrap instead of clipping the remove button. */
#config-modal .webauthn-key-item {
flex-wrap: wrap;
gap: 8px;
}
#config-modal .webauthn-key-label {
flex: 1 1 100%;
min-width: 0;
}
#config-modal .webauthn-key-item .config-btn-sm {
min-height: 44px;
min-width: 44px;
}
#config-modal .hidden-files-add-row {
flex-wrap: wrap;
}
#config-modal .hidden-files-add-row .config-input {
flex: 1 1 100%;
max-width: none;
min-width: 0;
}
#config-modal .config-diag-row {
flex-wrap: wrap;
gap: 4px 8px;
}
/* AI keys sticky footer: clear the mobile toolbar + home indicator. */
#config-modal .ai-keys-footer {
padding-bottom: calc(12px + env(safe-area-inset-bottom, 0));
bottom: 0;
}
/* Two-column grids → single column. */
#config-modal .ai-default-grid,
@@ -4851,6 +5050,61 @@ body.resizing-v {
min-width: 0;
overflow-wrap: anywhere;
}
/* Drawer: left slide-over above a dimming backdrop. Higher specificity
than the generic .help-nav rules (body .help-nav / .help-nav) that hide
the nav on mobile. JS toggles .config-toc-open on #config-modal. */
#config-modal #config-nav {
position: fixed;
top: 0;
left: 0;
bottom: 0;
width: min(320px, 88vw);
min-width: 0;
max-width: 88vw;
max-height: 100dvh;
height: 100%;
box-sizing: border-box;
z-index: 40;
background: var(--bg-secondary);
border-right: 1px solid var(--border);
border-bottom: none;
box-shadow: none;
backdrop-filter: none;
display: none;
overflow: hidden;
animation: config-toc-slide-in 200ms ease-out;
}
#config-modal.config-toc-open #config-nav {
display: flex;
max-height: 100dvh;
}
#config-modal .help-nav-list {
padding-bottom: calc(20px + env(safe-area-inset-bottom, 0));
}
/* Backdrop: covers the full modal, sits above the content (z-index auto)
and below the drawer (z-index 40). Clicks on the pseudo-element are
attributed to #config-modal, so the existing e.target === modal handler
closes the drawer first; it also blocks taps reaching the content. */
#config-modal.config-toc-open::before {
content: "";
position: absolute;
inset: 0;
z-index: 35;
background: rgba(0, 0, 0, 0.45);
}
@keyframes config-toc-slide-in {
from {
transform: translateX(-100%);
}
to {
transform: translateX(0);
}
}
/* Content area gets a bottom pad so the sticky Save row never covers the
last controls while the virtual keyboard is open. */
#config-modal #config-scroll .config-content {
padding-bottom: 80px;
}
}
/* --- Toast notifications --- */
@@ -5819,28 +6073,6 @@ body.resizing-v {
font-size: 0.9rem;
}
.config-btn-add {
padding: 6px 12px;
background: var(--accent);
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
font-size: 0.875rem;
font-weight: 500;
transition: all 150ms ease;
white-space: nowrap;
}
.config-btn-add:hover {
background: color-mix(in srgb, var(--accent) 85%, black);
transform: translateY(-1px);
}
.config-btn-add:active {
transform: translateY(0);
}
/* ---------------------------------------------------------------------------
Utility — hidden class
--------------------------------------------------------------------------- */
@@ -7907,7 +8139,6 @@ body.popup-mode .content-area {
.webhook-events { color: var(--text-muted); font-size: 0.7rem; }
.webhook-delete { background: none; border: none; color: var(--text-error); cursor: pointer; font-size: 1rem; padding: 2px 6px; }
.config-add-row { display: flex; gap: 8px; margin-top: 8px; }
.config-btn-add { padding: 6px 14px; background: var(--accent); color: #fff; border: none; border-radius: 6px; cursor: pointer; font-size: 0.8rem; }
/* ── API/MCP tokens UI (#107) ── */
.token-item {
@@ -8506,9 +8737,13 @@ body.desktop-mode .editor-container {
.help-hamburger {
display: inline-flex;
width: 44px;
height: 44px;
min-width: 44px;
}
/* TOC: collapsible block at top (not slide-over) */
/* TOC drawer: collapsible block for the help modal; the config modal
(#114) overrides this with a fixed left drawer + backdrop. */
.help-nav {
position: static;
width: 100%;
@@ -10763,7 +10998,6 @@ body.desktop-mode .editor-container {
}
.mfa-link-btn:hover { opacity: 0.8; }
.mfa-error { color: #e74c3c; font-size: 13px; margin-top: 8px; }
.mfa-recovery-input { width: 200px; font-size: 20px; letter-spacing: 4px; }
/* MFA Settings (Security tab) */
.mfa-status-section { padding: 16px 0; }