Changeset 0dba092 in Klonkt


Ignore:
Timestamp:
06/24/2026 03:09:22 PM (3 months ago)
Author:
Robin Genis <roboburr@…>
Branches:
main
Children:
914eb9f
Parents:
749c183
Message:

style(activitypub): reply field as a floating popover (zero layout shift)

The address field now opens as an absolutely-positioned popover below the button
(appended to body) instead of inline — so neither the post CTA nor a comment row
reflows. Closes on outside-click, Escape, scroll, or cancel; toggles on re-click.

Co-Authored-By: Claude <noreply@…>

Location:
src
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • src/assets/css/style.css

    r749c183 r0dba092  
    44194419
    44204420/* Reply-via-fediverse CTA on post pages */
    4421 .post-fediverse-cta { margin: 1.75rem 0; display: flex; align-items: center; min-height: 2.4rem; }
     4421.post-fediverse-cta { margin: 1.75rem 0; }
    44224422.fedi-remote-reply-btn { display: inline-flex; align-items: center; gap: .45rem; }
    44234423.post-fediverse-cta .fedi-remote-reply-btn {
     
    44324432
    44334433/* Inline "reply via fediverse" address form (replaces the browser prompt) */
    4434 .fedi-remote-form { display: inline-flex; align-items: center; gap: .4rem; margin: 0; flex-wrap: wrap; }
     4434.fedi-remote-form {
     4435  position: absolute; z-index: 60; display: inline-flex; align-items: center; gap: .4rem;
     4436  padding: .4rem; border-radius: 999px;
     4437  background: var(--paper-2, var(--paper, #fff));
     4438  border: 1px solid color-mix(in srgb, var(--ink, #000) 12%, transparent);
     4439  box-shadow: 0 10px 30px rgba(0,0,0,.28);
     4440}
    44354441.fedi-remote-form input {
    44364442  height: 2.2rem; padding: 0 .9rem; border-radius: 999px; font: inherit; min-width: 230px;
  • src/views/pages/post.ejs

    r749c183 r0dba092  
    102102  (function(){
    103103    if (window.__fediRemoteWired) return; window.__fediRemoteWired = true;
     104    var current = null, currentBtn = null;
     105    function close(){ if (current) { current.remove(); current = null; currentBtn = null; } }
    104106    function go(raw, uri){
    105107      var d = (raw||'').trim().replace(/^@?[^@\s]*@/, '').replace(/^https?:\/\//i, '').replace(/\/.*$/, '').trim();
    106108      if (d) location.href = 'https://' + d + '/authorize_interaction?uri=' + encodeURIComponent(uri||'');
    107109    }
    108     function closeForm(f){ if (!f) return; if (f._btn) f._btn.style.display = ''; f.remove(); }
     110    function place(f, b){
     111      var r = b.getBoundingClientRect();
     112      f.style.top = (r.bottom + window.scrollY + 6) + 'px';
     113      f.style.left = Math.max(8, Math.min(r.left + window.scrollX, window.scrollX + window.innerWidth - 340)) + 'px';
     114    }
    109115    document.addEventListener('click', function(e){
    110       var cancel = e.target.closest && e.target.closest('.fedi-remote-cancel');
    111       if (cancel) { closeForm(cancel.closest('.fedi-remote-form')); return; }
     116      if (e.target.closest && e.target.closest('.fedi-remote-cancel')) { close(); return; }
     117      if (current && e.target.closest && e.target.closest('.fedi-remote-form')) return; // click inside → keep
    112118      var b = e.target.closest && e.target.closest('.fedi-remote-reply-btn');
    113       if (!b) return;
    114       e.preventDefault();
    115       closeForm(document.querySelector('.fedi-remote-form')); // close any open one (restores its button)
    116       var f = document.createElement('form');
    117       f.className = 'fedi-remote-form';
    118       f.dataset.uri = b.getAttribute('data-fedi-uri') || '';
    119       f._btn = b;
    120       f.innerHTML = '<input type="text" autocomplete="off" spellcheck="false">'
    121         + '<button type="submit" class="btn btn-primary fedi-remote-go" aria-label="ok">&rarr;</button>'
    122         + '<button type="button" class="fedi-remote-cancel" aria-label="x">&times;</button>';
    123       var inp = f.querySelector('input');
    124       inp.placeholder = b.getAttribute('data-fedi-ph') || '@name@server.social';
    125       b.style.display = 'none';                  // replace the button in place → no layout jump
    126       b.parentNode.insertBefore(f, b.nextSibling);
    127       inp.focus();
     119      if (b) {
     120        e.preventDefault();
     121        if (currentBtn === b) { close(); return; }   // toggle off
     122        close();
     123        var f = document.createElement('form');
     124        f.className = 'fedi-remote-form';
     125        f.dataset.uri = b.getAttribute('data-fedi-uri') || '';
     126        f.innerHTML = '<input type="text" autocomplete="off" spellcheck="false">'
     127          + '<button type="submit" class="btn btn-primary fedi-remote-go" aria-label="ok">&rarr;</button>'
     128          + '<button type="button" class="fedi-remote-cancel" aria-label="x">&times;</button>';
     129        f.querySelector('input').placeholder = b.getAttribute('data-fedi-ph') || '@name@server.social';
     130        document.body.appendChild(f);            // floating popover → no layout reflow
     131        place(f, b); current = f; currentBtn = b;
     132        f.querySelector('input').focus();
     133        return;
     134      }
     135      if (current) close(); // click anywhere else closes it
    128136    });
    129137    document.addEventListener('submit', function(e){
    130138      var f = e.target.closest && e.target.closest('.fedi-remote-form');
    131       if (!f) return;
    132       e.preventDefault();
     139      if (!f) return; e.preventDefault();
    133140      go(f.querySelector('input').value, f.dataset.uri);
    134141    });
     142    document.addEventListener('keydown', function(e){ if (e.key === 'Escape') close(); });
     143    window.addEventListener('scroll', close, true);
    135144  })();
    136145  </script>
  • src/views/shell.ejs

    r749c183 r0dba092  
    175175
    176176<!-- v9 stylesheet (full palette system) -->
    177 <link rel="stylesheet" href="/assets/css/style.css?v=43">
     177<link rel="stylesheet" href="/assets/css/style.css?v=44">
    178178
    179179<!-- Audio player styles: loaded on every page so the mini-player works
Note: See TracChangeset for help on using the changeset viewer.