mirror of
https://github.com/CyberSecurityUP/NeuroSploit.git
synced 2026-09-30 04:51:50 +02:00
fix(web): responsive pass — real device sizes, scroll in the right containers
Audited at 390×844, 844×390 (phone landscape), 768×1024, 1024×768, 1440×900
and ≥1600px. What was actually broken:
- **The run header collapsed.** `justify-content: space-between` let the two
action buttons take the whole row, so at 390px the title wrapped one
character per line ("Test AspNe / t") and the facts line wrapped one word per
line. It now stacks below 680px, with the title block sized to its content
instead of stretching (the desktop `flex: 1` was what left a 180px void above
the buttons in the stacked layout).
- **The terminal header overflowed** its dock at 390px (557px of content in a
390px box) — it wraps now, and the status text drops out on narrow screens
where the coloured dot already carries it.
- **`100vh` is wrong on mobile.** It measures the viewport without the
collapsing address bar, so the wizard footer and its CTA sit underneath it.
Switched to `dvh` with the `vh` line kept as the fallback.
- **The dock took 82% of a phone in landscape** at its fixed 320px. It now
tracks the viewport (`clamp(180px, 42dvh, 340px)`, tighter still under
500px of height).
- **The off-canvas drawer had no way out but the button that opened it.**
Added a scrim that closes it, Esc, and auto-close when a run is picked —
and it closes itself if the window grows past the breakpoint, which
otherwise left a scrim over a sidebar that was no longer a drawer.
- **The stepper scrolls horizontally on a phone**, so advancing to an
off-screen step looked like nothing happened; the active step is scrolled
into view.
Device-type rules rather than width alone: `pointer: coarse` gets 38-44px hit
targets and 16px inputs (under 16px, iOS zooms the page on focus and breaks the
layout the user is typing into); `prefers-reduced-motion` drops the drawer
slide and the progress animation, which are decoration.
Scrolling stays where it belongs — one scroller per pane (`.wizard-body`,
`.run-body`, `.dash-body`, `.sb-groups`, `.modal-body`, `.term-host`), wide
tables scroll inside `.table-wrap`, and the page itself never scrolls
horizontally at any tested size.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
6475dba752
commit
4f277838c6
+23
-4
@@ -138,6 +138,10 @@ function goToStep(n) {
|
||||
show($('#btnLaunch'), state.step === STEP_COUNT - 1);
|
||||
if (state.step === STEP_COUNT - 1) renderReview();
|
||||
updateWizardSummary();
|
||||
// The stepper scrolls horizontally on a phone; advancing to a step that is
|
||||
// off-screen would look like nothing happened.
|
||||
const active = $('.step-tab.active');
|
||||
if (active?.scrollIntoView) active.scrollIntoView({ block: 'nearest', inline: 'center', behavior: 'smooth' });
|
||||
}
|
||||
|
||||
// Errors land next to the field they belong to. A modal alert forced the
|
||||
@@ -1902,6 +1906,7 @@ document.addEventListener('keydown', (e) => {
|
||||
if (!$('#findingModal').hidden) return show($('#findingModal'), false);
|
||||
if (!$('#leadModal').hidden) return closeLeadModal();
|
||||
if (!$('#authModal').hidden) return show($('#authModal'), false);
|
||||
if ($('#sidebar').classList.contains('open')) return setSidebar(false);
|
||||
if (!$('#termDock').hidden) termClose();
|
||||
});
|
||||
|
||||
@@ -2250,12 +2255,26 @@ $('#runFilter').addEventListener('input', (e) => { state.runFilter = e.target.va
|
||||
// boot
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
// Below 768px the sidebar slides off-canvas. It previously had no way back:
|
||||
// Below 900px the sidebar slides off-canvas. It previously had no way back:
|
||||
// the CSS hid it and nothing could set .open.
|
||||
$('#btnSidebarToggle').addEventListener('click', () => $('#sidebar').classList.toggle('open'));
|
||||
$('#sbGroups').addEventListener('click', () => {
|
||||
if (window.matchMedia('(max-width: 768px)').matches) $('#sidebar').classList.remove('open');
|
||||
const NARROW = '(max-width: 900px)';
|
||||
function setSidebar(open) {
|
||||
$('#sidebar').classList.toggle('open', open);
|
||||
show($('#sidebarScrim'), open && window.matchMedia(NARROW).matches);
|
||||
$('#btnSidebarToggle').setAttribute('aria-expanded', String(open));
|
||||
}
|
||||
$('#btnSidebarToggle').addEventListener('click', () => setSidebar(!$('#sidebar').classList.contains('open')));
|
||||
$('#sidebarScrim').addEventListener('click', () => setSidebar(false));
|
||||
// Picking a run is the drawer's whole purpose — it should get out of the way
|
||||
// once you have.
|
||||
$('#sbGroups').addEventListener('click', (e) => {
|
||||
if (e.target.closest('.sb-run') && window.matchMedia(NARROW).matches) setSidebar(false);
|
||||
});
|
||||
$('#btnDashboard').addEventListener('click', () => { if (window.matchMedia(NARROW).matches) setSidebar(false); });
|
||||
$('#btnNewEngagement').addEventListener('click', () => { if (window.matchMedia(NARROW).matches) setSidebar(false); });
|
||||
// Growing the window past the breakpoint leaves a scrim over a sidebar that is
|
||||
// no longer a drawer.
|
||||
window.matchMedia(NARROW).addEventListener('change', (m) => { if (!m.matches) setSidebar(false); });
|
||||
|
||||
async function boot() {
|
||||
applyTheme();
|
||||
|
||||
Reference in New Issue
Block a user