Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
170 changes: 168 additions & 2 deletions src/reviewer/viz/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -565,6 +565,124 @@
.comment-panel::-webkit-scrollbar-thumb { background: #d1d5db; border-radius: 3px; }
.paper-panel::-webkit-scrollbar-thumb:hover,
.comment-panel::-webkit-scrollbar-thumb:hover { background: #9ca3af; }

/* ── Mobile bottom nav ── */
.mobile-bottom-nav {
display: none;
position: fixed;
bottom: 0; left: 0; right: 0;
height: 56px;
background: var(--surface);
border-top: 1px solid var(--border);
z-index: 200;
box-shadow: 0 -2px 8px rgba(0,0,0,0.06);
}
.mobile-bottom-nav-btn {
flex: 1;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 3px;
font-size: 11px;
font-weight: 500;
font-family: inherit;
color: var(--text-secondary);
background: none;
border: none;
cursor: pointer;
transition: color 0.15s;
position: relative;
}
.mobile-bottom-nav-btn.active { color: var(--accent); }
.mobile-bottom-nav-btn svg { width: 22px; height: 22px; }
.mobile-nav-badge {
position: absolute;
top: 5px;
right: calc(50% - 22px);
font-size: 9px;
font-weight: 700;
background: var(--accent);
color: #fff;
border-radius: 10px;
min-width: 16px;
height: 16px;
line-height: 16px;
text-align: center;
padding: 0 4px;
}

/* ── Mobile responsive ── */
@media (max-width: 768px) {
body {
display: flex;
flex-direction: column;
height: 100vh;
overflow: hidden;
}

/* Header: two-row layout */
.header {
flex-wrap: wrap;
height: auto;
min-height: var(--header-h);
padding: 8px 16px;
gap: 6px;
align-content: center;
flex-shrink: 0;
}
.header .separator { display: none; }
.legend { display: none; }
.paper-select-wrapper { order: 4; max-width: 100%; width: 100%; }

/* Tabs + metrics: don't shrink */
.tabs-bar { flex-shrink: 0; padding: 0 12px; }
.metrics-bar { flex-shrink: 0; padding: 0 12px; font-size: 11px; gap: 10px; }

/* Main: fill remaining space, panels overlap via absolute */
.main {
flex: 1;
min-height: 0;
height: auto;
overflow: hidden;
position: relative;
}

/* Paper panel: full size, visible by default */
.paper-panel {
position: absolute;
top: 0; left: 0; right: 0; bottom: 0;
padding: 20px 16px 72px;
border-right: none;
overflow-y: auto;
}
.paper-panel.mobile-hidden { display: none; }
.paper-panel-inner { max-width: 100%; }

/* Paragraphs: tighter on mobile */
.para { padding: 6px 10px; margin: 0 -10px 2px; }
.para .para-idx { display: none; }

/* Comment panel: full size, hidden by default on mobile */
.comment-panel {
position: absolute;
top: 0; left: 0; right: 0; bottom: 0;
flex: none;
width: 100%;
display: none;
overflow-y: auto;
padding-bottom: 56px;
}
.comment-panel.mobile-active { display: block; }

/* Show the mobile nav */
.mobile-bottom-nav { display: flex; }
}

@media (max-width: 480px) {
.version-badge { display: none; }
.metrics-bar { font-size: 10px; gap: 8px; }
}
</style>
</head>
<body>
Expand All @@ -585,6 +703,18 @@
<div class="comment-panel" id="comment-panel"></div>
</div>

<div class="mobile-bottom-nav" id="mobile-bottom-nav">
<button class="mobile-bottom-nav-btn active" id="mobile-btn-paper" onclick="switchMobilePanel('paper')">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M19.5 14.25v-2.625a3.375 3.375 0 0 0-3.375-3.375h-1.5A1.125 1.125 0 0 1 13.5 7.125v-1.5a3.375 3.375 0 0 0-3.375-3.375H8.25m0 12.75h7.5m-7.5 3H12M10.5 2.25H5.625c-.621 0-1.125.504-1.125 1.125v17.25c0 .621.504 1.125 1.125 1.125h12.75c.621 0 1.125-.504 1.125-1.125V11.25a9 9 0 0 0-9-9Z" /></svg>
Paper
</button>
<button class="mobile-bottom-nav-btn" id="mobile-btn-comments" onclick="switchMobilePanel('comments')">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" d="M7.5 8.25h9m-9 3H12m-9.75 1.51c0 1.6 1.123 2.994 2.707 3.227 1.129.166 2.27.293 3.423.379.35.026.67.21.865.501L12 21l2.755-4.133a1.14 1.14 0 0 1 .865-.501 48.172 48.172 0 0 0 3.423-.379c1.584-.233 2.707-1.626 2.707-3.228V6.741c0-1.602-1.123-2.995-2.707-3.228A48.394 48.394 0 0 0 12 3c-2.392 0-4.744.175-7.043.513C3.373 3.746 2.25 5.14 2.25 6.741v6.018Z" /></svg>
Comments
<span class="mobile-nav-badge" id="mobile-nav-badge" style="display:none"></span>
</button>
</div>

<script>
let INDEX = null;
let paperCache = {};
Expand All @@ -596,6 +726,35 @@
let typesetQueue = Promise.resolve();
let resolvedIds = new Set();
let showOnlyOpen = false;
let mobilePanelActive = 'paper';

function isMobile() { return window.innerWidth <= 768; }

function switchMobilePanel(panel) {
mobilePanelActive = panel;
const paperPanel = document.getElementById('paper-panel');
const commentPanel = document.getElementById('comment-panel');
const btnPaper = document.getElementById('mobile-btn-paper');
const btnComments = document.getElementById('mobile-btn-comments');
if (panel === 'paper') {
paperPanel.classList.remove('mobile-hidden');
commentPanel.classList.remove('mobile-active');
btnPaper && btnPaper.classList.add('active');
btnComments && btnComments.classList.remove('active');
} else {
paperPanel.classList.add('mobile-hidden');
commentPanel.classList.add('mobile-active');
btnPaper && btnPaper.classList.remove('active');
btnComments && btnComments.classList.add('active');
}
}

function updateMobileNavBadge(count) {
const badge = document.getElementById('mobile-nav-badge');
if (!badge) return;
badge.style.display = count > 0 ? '' : 'none';
badge.textContent = count > 99 ? '99+' : count;
}

function resolvedStorageKey(commentId) {
return `oar_resolved:${currentPaperSlug}:${currentMethod}:${commentId}`;
Expand Down Expand Up @@ -705,6 +864,7 @@
currentPaperSlug = sel.value;
activeCommentId = null;
renderedPaperSlug = null;
if (isMobile()) switchMobilePanel('paper');
await loadPaper(currentPaperSlug);
buildMethodTabs();
render();
Expand Down Expand Up @@ -781,6 +941,8 @@

updatePaperHighlights();
renderComments();
const _m = paper && paper.methods[currentMethod];
if (_m) updateMobileNavBadge(getVisibleComments(_m.comments).length);
}

function renderLegend() {
Expand Down Expand Up @@ -966,6 +1128,7 @@
if (comment) {
activeCommentId = comment.id;
render();
if (isMobile()) switchMobilePanel('comments');
const card = document.getElementById('card-' + comment.id);
if (card) card.scrollIntoView({ behavior: 'smooth', block: 'center' });
}
Expand Down Expand Up @@ -1077,11 +1240,14 @@
activeCommentId = id;
render();
if (comment && comment.paragraph_index != null) {
if (isMobile()) switchMobilePanel('paper');
const paraEl = document.getElementById('para-' + comment.paragraph_index);
if (paraEl) paraEl.scrollIntoView({ behavior: 'smooth', block: 'center' });
}
const cardEl = document.getElementById('card-' + id);
if (cardEl) cardEl.scrollIntoView({ behavior: 'smooth', block: 'center' });
if (!isMobile()) {
const cardEl = document.getElementById('card-' + id);
if (cardEl) cardEl.scrollIntoView({ behavior: 'smooth', block: 'center' });
}
};
});
}
Expand Down