Changeset 0dba092 in Klonkt for src/views/pages/post.ejs


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@…>

File:
1 edited

Legend:

Unmodified
Added
Removed
  • 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>
Note: See TracChangeset for help on using the changeset viewer.