diff --git a/web/app.js b/web/app.js index ab92a30..e9a77ec 100644 --- a/web/app.js +++ b/web/app.js @@ -126,6 +126,7 @@ const I18N = { hDivision: (s) => `interval ${s}`, hCapped: 'enlarged', hCappedTitle: 'The chosen division would exceed 300 intervals over this range: it has been enlarged.', hUnzoom: '× Reset zoom', unitDay: 'd', + toTop: 'Back to top', colRcv: 'Received', colMt: 'Message time', colSev: 'Severity', colHost: 'Host', colApp: 'App', colMsg: 'Message', colGrip: 'Drag to resize, double-click for the automatic width', resetCols: 'Reset column widths', colsReset: 'Column widths reset', @@ -254,6 +255,7 @@ const I18N = { hDivision: (s) => `intervalle ${s}`, hCapped: 'élargi', hCappedTitle: 'La division choisie dépasserait 300 intervalles sur cette plage : elle a été élargie.', hUnzoom: '× Annuler le zoom', unitDay: 'j', + toTop: 'Revenir en haut', colRcv: 'Réception', colMt: 'Heure message', colSev: 'Sévérité', colHost: 'Hôte', colApp: 'App', colMsg: 'Message', colGrip: 'Glisser pour redimensionner, double-clic pour la largeur automatique', resetCols: 'Réinitialiser les colonnes', colsReset: 'Largeurs de colonnes réinitialisées', @@ -1517,6 +1519,15 @@ $('#newPill').addEventListener('click', () => { }); window.addEventListener('scroll', debounce(() => { if (window.scrollY <= 80) flushPending(); }, 150), { passive: true }); +// "Back to top" button, shown once the page has scrolled a little. +const syncToTop = () => { $('#toTop').hidden = window.scrollY < 400; }; +window.addEventListener('scroll', syncToTop, { passive: true }); +$('#toTop').addEventListener('click', () => { + const smooth = !matchMedia('(prefers-reduced-motion: reduce)').matches; + window.scrollTo({ top: 0, behavior: smooth ? 'smooth' : 'auto' }); +}); +syncToTop(); + $('#live').addEventListener('click', () => { state.live = !state.live; store.set('live', state.live ? '1' : '0'); diff --git a/web/index.html b/web/index.html index 69a02d5..a8ea7f7 100644 --- a/web/index.html +++ b/web/index.html @@ -115,6 +115,9 @@ diff --git a/web/style.css b/web/style.css index 2592aa7..a9bc9c7 100644 --- a/web/style.css +++ b/web/style.css @@ -425,6 +425,10 @@ mark.hit { background: var(--hit); color: inherit; border-radius: 3px; padding: .conn.ok::before { color: var(--sev-info); } .conn.ko::before { color: var(--sev-err); } #stats .bad { color: var(--sev-err); } +/* "Back to top", at the right end of the status bar: never over a log row */ +.to-top { width: 24px; height: 24px; margin: -5px -6px -5px auto; flex: none; } /* no taller bar */ +.to-top svg { width: 16px; height: 16px; } +.to-top[hidden] { display: none; } .toast { position: fixed; bottom: 48px; left: 50%; transform: translateX(-50%); z-index: 50;