summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorojacobson <ojacobson@noreply.codeberg.org>2025-05-16 02:15:05 +0000
committerojacobson <ojacobson@noreply.codeberg.org>2025-05-16 02:15:05 +0000
commit630cbc2b70309ae5d2ece01861b9fe3983ab5278 (patch)
treefe93a375a8e4ffb17d2133dd0adfab55fb456abb
parent6eb8487d89ab14f8f11a40b78d7db72e3266840d (diff)
parenta4ad808eb804e32edf3b848c229542b759db0102 (diff)
Merge pull request 'prop/text-input-no-quill-plus' (#2) from prop/text-input-no-quill-plus into prop/text-input-no-quill
Reviewed-on: https://codeberg.org/ojacobson/pilcrow/pulls/2 Reviewed-by: Kit <wlonk@noreply.codeberg.org>
-rw-r--r--ui/lib/components/MessageInput.svelte42
-rw-r--r--ui/styles/forms.css8
-rw-r--r--ui/styles/textarea.css8
3 files changed, 44 insertions, 14 deletions
diff --git a/ui/lib/components/MessageInput.svelte b/ui/lib/components/MessageInput.svelte
index 71b7b8f..cdb855e 100644
--- a/ui/lib/components/MessageInput.svelte
+++ b/ui/lib/components/MessageInput.svelte
@@ -1,40 +1,64 @@
<script>
let { sendMessage = async (message) => {} } = $props();
- let form = $state(null);
let value = $state('');
- // This doesn't seem to work with a contenteditable two-way bound svelte
- // thing:
let disabled = $state(false);
+ // Entering and removing text from the input area leaves a stray line break behind. This effect
+ // looks for that scenario and removes it, restoring the "empty" state (and bringing the
+ // placeholder back again in the process).
+ $effect(() => {
+ const trimmed = value.trim();
+ if (trimmed !== value && trimmed === '') {
+ value = trimmed;
+ }
+ });
+
async function onsubmit(event) {
event.preventDefault();
disabled = true;
try {
await sendMessage(value);
- value = '';
+ event.target.closest('form')?.reset();
} finally {
disabled = false;
}
}
function onkeydown(event) {
+ if (disabled) {
+ event.preventDefault();
+ return;
+ }
+
let modifier = event.shiftKey || event.altKey || event.ctrlKey || event.metaKey;
if (!modifier && event.key === 'Enter') {
event.preventDefault();
- form?.requestSubmit?.();
+ event.target.closest('form')?.requestSubmit();
+ }
+ }
+
+ function onpaste(event) {
+ if (disabled) {
+ event.preventDefault();
}
}
</script>
-<form {onsubmit} bind:this={form}>
+<form {onsubmit}>
+ <textarea bind:value class="hidden" {disabled}></textarea>
<div
+ role="textbox"
+ tabindex="0"
contenteditable="plaintext-only"
- class="textarea"
+ class={{
+ textarea: true,
+ disabled
+ }}
bind:innerText={value}
{onkeydown}
- {disabled}
- placeholder="Say something..."
+ {onpaste}
+ data-placeholder="Say something..."
></div>
<button type="submit">&raquo;</button>
</form>
diff --git a/ui/styles/forms.css b/ui/styles/forms.css
index eb98743..98fd43e 100644
--- a/ui/styles/forms.css
+++ b/ui/styles/forms.css
@@ -22,3 +22,11 @@ form.form > button {
border: 1px solid var(--colour-input-border);
margin: 0.25rem;
}
+
+.disabled {
+ color: var(--light-text);
+}
+
+.hidden {
+ display: none;
+}
diff --git a/ui/styles/textarea.css b/ui/styles/textarea.css
index 4dc804a..d315bcf 100644
--- a/ui/styles/textarea.css
+++ b/ui/styles/textarea.css
@@ -6,11 +6,9 @@
align-items: stretch;
}
-/* The second selector is more generally useful, but it doesn't seem to work,
- * so I added in the first selector. */
-.textarea:empty:before,
-[contenteditable='true']:empty:before {
- content: attr(placeholder);
+[data-placeholder]:empty:before {
+ content: attr(data-placeholder);
+ color: var(--light-text);
pointer-events: none;
display: block; /* For Firefox */
}