diff options
| author | Owen Jacobson <owen@grimoire.ca> | 2025-05-13 18:14:04 -0400 |
|---|---|---|
| committer | Owen Jacobson <owen@grimoire.ca> | 2025-05-13 21:11:00 -0400 |
| commit | a0568ada5568bd8d6538e26e003b26c8409e2cb7 (patch) | |
| tree | d5d0a46c5470f8170eb21daf042e5e596eda80a9 /ui | |
| parent | 361623aaccf08063712500a213548a2756dd13c4 (diff) | |
Make the resulting form more amenable to normal DOM operations.
This is purely an aesthetic choice:
* The DOM `reset()` function can be used to clear the form, but can't be used to clear editable DIVs. Binding the editable div to a (hidden) form field allows `reset()` to clear both.
* We can find the target `form` element out of the event, but the API needed to do so differs between events dispatched to form controls and events dispatched to random DOM nodes. Using `closest('form')` works for both kinds of event target.
In practice, there is little need to make sure the message input form uses "normal" DOM APIs for functional reasons. Everything inside `MessageInput` is controllable through the component's script. This change isn't based on a functional need, but rather in the hopes that integrating with the DOM APIs makes it easier for _code we don't control_ - screen readers, password managers, saved-form support in browsers, &c - to integrate with Pilcrow. It is purely speculative.
(This also used to be necessary because Firefox didn't support `contenteditable="plaintext-only"`, but [support was added in March][ff-pto]
[ff-pto]: https://www.mozilla.org/en-US/firefox/136.0/releasenotes/#:~:text=The%20value%20plaintext%2Donly%20can%20now%20be%20specified%20for%20the%20contenteditable%20attribute%2C%20making%20the%20raw%20text%20of%20an%20element%20editable%20but%20without%20supporting%20rich%20text%20formatting.
Diffstat (limited to 'ui')
| -rw-r--r-- | ui/lib/components/MessageInput.svelte | 8 | ||||
| -rw-r--r-- | ui/styles/forms.css | 4 |
2 files changed, 8 insertions, 4 deletions
diff --git a/ui/lib/components/MessageInput.svelte b/ui/lib/components/MessageInput.svelte index 848321d..6c22b29 100644 --- a/ui/lib/components/MessageInput.svelte +++ b/ui/lib/components/MessageInput.svelte @@ -1,7 +1,6 @@ <script> let { sendMessage = async (message) => {} } = $props(); - let form = $state(null); let value = $state(''); let disabled = $state(false); @@ -10,7 +9,7 @@ disabled = true; try { await sendMessage(value); - value = ''; + event.target.closest('form')?.reset(); } finally { disabled = false; } @@ -25,7 +24,7 @@ let modifier = event.shiftKey || event.altKey || event.ctrlKey || event.metaKey; if (!modifier && event.key === 'Enter') { event.preventDefault(); - form?.requestSubmit?.(); + event.target.closest('form')?.requestSubmit(); } } @@ -36,7 +35,8 @@ } </script> -<form {onsubmit} bind:this={form}> +<form {onsubmit}> + <textarea bind:value class="hidden" {disabled}></textarea> <div contenteditable="plaintext-only" class={{ diff --git a/ui/styles/forms.css b/ui/styles/forms.css index 907f1bf..1c1ae5c 100644 --- a/ui/styles/forms.css +++ b/ui/styles/forms.css @@ -30,3 +30,7 @@ form.form > button { .disabled { color: var(--light-text); } + +.hidden { + display: none; +} |
