Changeset 8f6a61d in Klonkt


Ignore:
Timestamp:
06/17/2026 01:52:53 AM (3 months ago)
Author:
roboburr <roboburr@…>
Branches:
main
Children:
d5b9d2a
Parents:
9611f31
Message:

Prutter composer: clear after send + Enter behaviour + auto-grow

  • Text is now cleared after a successful send (inline hx-on wasn't reliable → done in JS via htmx:afterRequest).
  • Desktop: Enter = send, Shift+Enter = new line.
  • Touch (mobile/tablet, pointer:coarse): Enter = new line; send via the Send button.
  • Textarea grows automatically (up to 40vh, then internal scroll).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@…>

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/views/pages/prutter-conversation.ejs

    r9611f31 r8f6a61d  
    2828  </ol>
    2929
    30   <form class="prutter-composer"
     30  <form class="prutter-composer" id="prutter-composer"
    3131        method="post"
    3232        action="<%= siteUrlBase %>/prutter/<%= conversation.id %>/send"
    3333        hx-post="<%= siteUrlBase %>/prutter/<%= conversation.id %>/send"
    3434        hx-target="#prutter-thread"
    35         hx-swap="beforeend"
    36         hx-on::after-request="this.querySelector('textarea').value=''; window.__prutterScroll && window.__prutterScroll();">
     35        hx-swap="beforeend">
    3736    <textarea name="content" rows="1" maxlength="2000" placeholder="Bericht…" required></textarea>
    3837    <button type="submit" class="btn btn-primary">Stuur</button>
     
    8382    console.warn('Prutter WS unavailable:', e);
    8483  }
     84
     85  // ── Composer: invoer-gedrag + auto-groei + wissen na versturen ──────────
     86  var form = document.getElementById('prutter-composer');
     87  var ta = form ? form.querySelector('textarea') : null;
     88  if (form && ta) {
     89    var MAXH = function () { return Math.round(window.innerHeight * 0.4); };
     90    function autoGrow() {
     91      ta.style.height = 'auto';
     92      ta.style.height = Math.min(ta.scrollHeight, MAXH()) + 'px';
     93    }
     94    function isTouch() {
     95      return window.matchMedia && window.matchMedia('(pointer: coarse)').matches;
     96    }
     97    function submit() {
     98      if (!ta.value.trim()) return;
     99      if (form.requestSubmit) form.requestSubmit();
     100      else form.dispatchEvent(new Event('submit', { bubbles: true, cancelable: true }));
     101    }
     102
     103    ta.addEventListener('input', autoGrow);
     104    ta.addEventListener('keydown', function (e) {
     105      if (e.key !== 'Enter' || e.isComposing) return;   // IME-invoer met rust laten
     106      // Touch (mobiel/tablet): Enter = nieuwe regel, versturen via de Stuur-knop.
     107      if (isTouch()) return;
     108      // Desktop: Shift+Enter = nieuwe regel, gewone Enter = versturen.
     109      if (e.shiftKey) return;
     110      e.preventDefault();
     111      submit();
     112    });
     113
     114    // Wissen + terug naar één regel ná een geslaagde verzending.
     115    form.addEventListener('htmx:afterRequest', function (e) {
     116      if (e.detail && e.detail.successful) {
     117        ta.value = '';
     118        autoGrow();
     119        scrollToBottom();
     120        ta.focus();
     121      }
     122    });
     123
     124    autoGrow();
     125  }
    85126})();
    86127</script>
     
    211252  resize: none;
    212253  min-height: 44px; max-height: 40vh;
     254  overflow-y: auto;   /* scrollt intern zodra de auto-groei de max raakt */
    213255}
    214256.prutter-composer .btn { flex: 0 0 auto; min-height: 44px; }
Note: See TracChangeset for help on using the changeset viewer.