| Commit message (Collapse) | Author | Age |
| | |
|
| | |
|
| |
|
|
| |
The hidden `textarea` used to attach the form value to the DOM was being included in the ARIA accessibility tree, at least in testing (I didn't check in a browser). While we could suppress this iwth `aria-role="hidden"`, the WHATWG recommendation is to Not Do That, and to find another way to hide the element, instead. Marking the element as hidden accomplishes that goal, _and_ gets rid of a style rule.
|
| |
|
|
|
|
| |
modification.
This also avoids using `placeholder` on elements where it's nonstandard, like `<div>`s.
|
| |
|
|
|
| |
* Give the input `div` a marker to tell screen readers &c that it is a textbox.
* Ensure that it participates in tab order. (Zero is a sentinel value, see <https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Global_attributes/tabindex>.)
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
| |
|
|
|
| |
* Suppress input (including paste) while the input is disabled.
* Style the input to make it visible that it's not accepting input.
|
| |
|
|
| |
For whatever reason, `innerText` captures interior line breaks, while `textContent` does not. Wild. DOM APIs.
|
| | |
|
| | |
|
| |
|
|
|
|
|
|
|
|
|
| |
There is a subtle race conditon in this code, which is likely not fixable without a protocol change:
* Ghost messages can disappear before their "real" message replacement shows up, if the client finishes sending (i.e., receives an HTTP response on the POST) before the server delivers the real message.
* Ghost messages can be duplicated briefly, if the client receives the real message before the client finishes sending.
Both happen in practice; we make no ordering guarantees between requests.
To aviod this, we'd to give clients a way to correlate pending sends with received messages. This would require fundamentally the same capabilities, like per-operation nonces, that preventing duplicate operations will require.
|
| |
|
|
|
|
| |
A `MessageRun` is a visual container with a specific layout - bordered, with a drop shadow, with a name badge on the top-left, which is either positioned to the left (`other-message`) or right (`own-message`). It is content-agnostic.
This facilitates putting things besides live messages inside of a message run. As a side effect, this gets rid of ActiveChannel; most of what it was doing makes more sense living in the channel view's `+page.svelte`.
|
| |
|
|
| |
Only once on load, then once per new message.
|
| |
|
|
|
|
|
|
| |
Access to "global" (maybe "external?") state is now handled at the top level of the component hierarchy, in `+page.svelte`, `+layout.svelte`, and their associated scripts. State is otherwise passed down through props, and changes are passed up through callbacks.
This is - hopefully - groundwork for refactoring state management a bit. I wanted to move access to state out to a smaller number of places, so that I have fewer places to update to implement reconnect logic. My broader goal is to make it easier to refactor these kinds of external side effects, as well, though no such changes are in this branch.
This change also makes testing a mile easier, since tests can interact with props and callbacks instead of emulating the whole HTTP request stack and the Pilcrow API. This change removes do-very-little tests.
|
| | |
|
| |
|
|
| |
Browsers cope with weird nestings mostly fine, but there's no upside for us in testing that.
|
| | |
|
| | |
|
| | |
|
| | |
|
| |
|
|
| |
own/other messages.
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| |\ |
|
| | |
| |
| |
| | |
I dunno, I like the fleuron. Maybe it's too twee?
|
| | |
| |
| |
| |
| |
| | |
This includes jamming the "at" of a message into a data- attribute on
the Message component, so that it can later be used by parent components
via Plain Old Javascript and the .dataset attribute of an HTML node.
|
| | | |
|
| |\| |
|
| | |
| |
| |
| | |
Svelte's lint complains if you add interaction to a div but don't give that div an ARIA role.
|
| | |
| |
| |
| | |
If you're setting it to a static value, use set.
|
| | |
| |
| |
| | |
Just use state, don't derive from a non-state local variable.
|
| | |
| |
| |
| |
| |
| | |
rendered.
~16% of the `hi development` channel's rendering time was taken up on this.
|
| |\| |
|
| | |
| |
| |
| | |
This also fixes some rendering jank with the message timestamp chip.
|
| | | |
|
| | | |
|
| |/
|
|
| |
But it's not working. Why?
|
| | |
|
| | |
|
| | |
|
| | |
|
| | |
|
| |
|
|
| |
I've also refactored how runs are processed, to avoid re-splitting runs every time the channel view is rendered. They're generated when messages are ingested into the `$messages` store, instead.
|
| | |
|
| | |
|