feat: LS.modal — общий компонент модалок + миграция /exam9 + /my-students
Новый общий компонент LS.modal (api.js) — companion к LS.confirm.
Универсальная form/content-модалка с консистентным поведением:
LS.modal({
title, content, size: 'sm'|'md'|'lg',
actions: [{label, primary, danger, onClick}],
onClose,
});
// Returns { close, root, body, setBody, setActions, setError }
Стандартное поведение:
- ESC и backdrop-click закрывают (опциональный dismissible:false)
- z-index 9000 (тот же что LS.confirm — без конфликтов)
- Auto-focus первого input/select/textarea/button в body
- prevFocus restore при закрытии
- Анимация scale+translateY .22s
- Адаптив: на мобилках padding уменьшается
CSS-классы .ls-mov / .ls-mod / .ls-mod-hdr / .ls-mod-body / .ls-mod-act
впрыскиваются один раз из api.js (id=ls-modal-style), как и стили
toast/confirm.
Миграция exam9 «Назначить вариант»:
- Убран inline <div class="ex-overlay" id="assign-overlay">…</div>
- Убраны .ax-actions, .ax-btn, .ax-btn-primary, .ax-error, .ax-success
CSS (теперь в общих .ls-mod-* стилях)
- openAssignModal → LS.modal({ title, content: form, actions: [...] })
- Удалены closeAssignModal/onAssignOverlayClick/onAssignEsc — теперь
handle'ит LS.modal
- Удалена unused переменная assignVariantNum (closure теперь над varNum)
exam9.html: −53 строк (CSS + HTML модалки)
app.js: переписан 90 строк → 70 строк
Миграция my-students «Убрать ученика»:
- native confirm() → LS.confirm() с danger-стилизацией
- alert() → LS.toast() для согласованности
Сохранён классroom-овский «ex-overlay»/«ex-panel» CSS (используется
для picker'а вариантов в exam9). Не трогаем classroom.html — у него
своя ecosystem cr-*-overlay.
Дальше — postupенная миграция модалок в textbooks/classes/admin
по мере касания этих страниц. Шаблон установлен.
This commit is contained in:
@@ -225,32 +225,6 @@
|
||||
font-family:'Manrope',sans-serif; font-size:.9rem;
|
||||
}
|
||||
.ax-input:focus { outline:none; border-color:var(--violet); }
|
||||
.ax-actions {
|
||||
display:flex; gap:10px; justify-content:flex-end; margin-top:6px;
|
||||
}
|
||||
.ax-btn {
|
||||
padding:9px 18px; border-radius:10px; border:1.5px solid var(--border-h);
|
||||
background:transparent; color:var(--text);
|
||||
font-family:'Manrope',sans-serif; font-size:.88rem; font-weight:700;
|
||||
cursor:pointer; transition:all .15s;
|
||||
}
|
||||
.ax-btn:hover { border-color:var(--text-2); }
|
||||
.ax-btn-primary { background:var(--violet); border-color:var(--violet); color:#fff; }
|
||||
.ax-btn-primary:hover { background:#7e3eca; border-color:#7e3eca; }
|
||||
.ax-btn-primary:disabled { opacity:.5; cursor:not-allowed; }
|
||||
.ax-error {
|
||||
padding:9px 12px; border-radius:8px; background:rgba(241,91,68,.1);
|
||||
border:1px solid rgba(241,91,68,.3); color:#F94144;
|
||||
font-size:.84rem; display:none;
|
||||
}
|
||||
.ax-error.visible { display:block; }
|
||||
.ax-success {
|
||||
padding:9px 12px; border-radius:8px; background:rgba(6,214,160,.1);
|
||||
border:1px solid rgba(6,214,160,.3); color:#06D6A0;
|
||||
font-size:.84rem; display:none;
|
||||
}
|
||||
.ax-success.visible { display:block; }
|
||||
|
||||
@media (max-width: 600px) {
|
||||
.ex-wrap { padding:20px 16px 60px; }
|
||||
.ex-title { font-size:1.15rem; }
|
||||
@@ -311,33 +285,6 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="ex-overlay" id="assign-overlay" onclick="onAssignOverlayClick(event)">
|
||||
<div class="ex-panel" onclick="event.stopPropagation()" style="width:min(520px,94vw)">
|
||||
<div class="ex-panel-head">
|
||||
<h2 id="assign-title">Назначить вариант</h2>
|
||||
<button class="ex-panel-close" onclick="closeAssignModal()" title="Закрыть">
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>
|
||||
</button>
|
||||
</div>
|
||||
<form class="ax-form" id="assign-form" onsubmit="event.preventDefault(); submitAssign()">
|
||||
<div class="ax-field">
|
||||
<label>Классы</label>
|
||||
<div class="ax-classes" id="ax-classes-list">Загрузка…</div>
|
||||
</div>
|
||||
<div class="ax-field">
|
||||
<label>Срок сдачи (опционально)</label>
|
||||
<input type="datetime-local" class="ax-input" id="ax-deadline" />
|
||||
</div>
|
||||
<div class="ax-error" id="ax-error"></div>
|
||||
<div class="ax-success" id="ax-success"></div>
|
||||
<div class="ax-actions">
|
||||
<button type="button" class="ax-btn" onclick="closeAssignModal()">Отмена</button>
|
||||
<button type="submit" class="ax-btn ax-btn-primary" id="ax-submit">Назначить</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/lucide@0.469.0/dist/umd/lucide.min.js"></script>
|
||||
<script src="/js/api.js"></script>
|
||||
<script src="/js/sidebar.js"></script>
|
||||
|
||||
Reference in New Issue
Block a user