Ask HN: In your experience, what are sound conventions for e-ink UI development?
I'm developing a UI for an e-ink device and realizing that many standard interaction patterns assume a high refresh rate and no ghosting. I'm looking for conventions that account for the limitations of e-ink, such as slow refresh and ghosting, to create a user experience that feels intentional and minimizes frustration. Specifically, I'm interested in how to handle streaming content, like LLM responses, and interactions like resizing, in a way that avoids disruptive refreshes and makes the UI feel responsive despite the hardware constraints.
Layout has to become as monotonic as possible, especially in the absence of user interaction; in other words, the app itself should never be doing anything to disrupt prior renders on its own unless you are clearing the whole page. When it is the user interacting with the app, try to minimize the number of intermediate states their interactions produce. This does NOT mean "just don't render those intermediate states", however. It means make the interactions themselves not require intermediate feedback. Essentially, users (and developers) are so accustomed to just being able to manipulate things with no side effects that you have to make every possible interaction as intentional as possible, leaving them less frustrated when they do see a refresh.
If an operation is going to cause a refresh, it should happen at a moment the user already understands as a semantic boundary. You obviously cannot always avoid this, so when there is a hard requirement for continuous feedback, use a degraded/cheap transient representation and refresh at commit of that action. With E-Ink, every interaction has to be a trade off between ghosting and latency. One common pattern I ended up coming back to is intermediate states that optimize for latency at the expense of ghosting until the UI action is 'complete'. This will allow refreshes to be associated with the satisfaction of finality.
When resizing, I simply draw the outline of the shape with a fast update mode that tolerates more ghosting until the user releases their finger or stylus, at which point, after a small lag to account for an 'oops, just a tiny bit bigger/smaller', I do a localized refresh of the union of the old + new area. The outline itself is deliberately faint, so the refresh doesn't have to be as intense if its a small delta.
For your streaming LLM case, I would recommend doing it in chunks, like you said, perhaps doing a hard refresh of everything but the input box + moving the tail of last sent message + beginning of stream to the top upon send. Of course, this implies that you know exactly how long the response will be, which you don't. The challenge will be coming up with a UI paradigm that doesn't make it look awkward if the response only goes down to the middle of the screen while also nicely doing a clean refresh pre-emptively if it's clear it will overflow and need to move to the top.
For the actual streaming, you'll have to ensure that your text alignment works in such a way that once a line is rendered to the screen, its placement is final (in other words, no streaming intra-word, as you need to know if the word will fit in remaining space on the line before rendering it). Basically, avoid retroactive reflow like a PDF document with a fixed layout, not like this text box I am typing in with a resize handle at the lower right. You'll also probably want to disable scrolling during generation as well, or at least make some sort of discrete pagination mechanism for going back and forth.
- freeone3000
I’d focus more on print usability and readability guidelines than computer guidelines. 5Hz eink is closer to a moving newspaper than a slow computer.
https://www.mediapoint.com.au/design-tips/composition-layout... might be moderately helpful.
But my advice: do not count on anything refreshing ever. Do not have animations, or transitions. Preload things to the correct spaces, then fill in. Reserve fixed white areas for output, and then fill in with black. (This works much better than the reverse!)
For quite long running processes, it might be worth having it behind a second page load.
- philosopherNoob
Spitballing an idea. I don’t use e-ink stuff but had my hands on it back when personal readers were new to the market.
When scrolling arbitrary text on a computer via keyboard, I generally become mildly frustrated hitting Spacebar, PageUp, and/or PageDown because I lose continuity with what I’m reading. (Perhaps the momentary 60hz blur makes it worse?) I attribute that to having a hard time identifying where I last read.
If there’s a dedicated button to scrolling, consider having an adjustable distance. EX: 100% screen height down, 95% screen width down (keeps a sliver of the last page), or 80% screen width down (keeps a chunk of the last page).
If you’re working with a touch display, perhaps a hold-and-drag-to-scroll feature could work? Have no indicator when pressed and only refresh the screen when the user lifts their finger. (It’s certainly not ideal to provide no feedback that it’s being used. But it may be useful to a user aware of how it works. Would probably need a training demonstration in-device like what older operating systems had.)
Perhaps a dedicated scroll undo button? For when one makes a mis-input and wants it back where it was. I know I’ve seen my grandma get frustrated at that sort of thing on desktop/phone where it’s quick to fix.
- longnguyen
Not a web UI, but I recently built this[0] for my Boox Note Air 5c tablet. You may find it useful (check the source code in GitHub)
[0]: https://inka.page