Things I've learned building a modern TUI framework
I’m a little disappointed to see no mention of the problems of colour. Perhaps Textual is just too firmly in the camp of overriding <i>everything</i>, so that these problems don’t appear (and it just feels extremely heavily out of place instead). As a user of a light, high-contrast terminal, I will state that <i>most</i> TUIs that I use are badly executed, featuring awful ugliness, complete inaccessibility, or both, due to incorrect assumptions about colour.<p>Terminals just have the wrong primitives for colour. It’s irredeemably broken, needing complete replacement with an altogether different approach to colours, and I don’t even know quite what that approach would be, quite apart from the improbability of convincing people to implement it.<p>There are default foreground and background colours, and they could be black and white, white and black, or just about anything, really. (People speak of 16- and 256-colour terminals, but they’re actually 18- and 258-colour.)<p>You want to make your text stronger? Have fun. You’ll look at your terminal that does #ccc-on-#000 or similar, and try bold. One some terminals, this will also change the colour to #fff, but on others it won’t. You kind of want to, because bold-but-the-same-colour isn’t drawing the attention you want, so you figure you’ll set the colour to bright white. Well, now your text is <i>completely invisible</i> for may light terminal users. So you begrudgingly roll that back and decide to try yellow. Eh, it’s a bit dull, but not <i>too</i> bad. You’ll still get complaints from light terminal users, though, because although it does have the advantage of distinctiveness, it’s <i>much</i> lower contrast. Don’t even think of bright yellow, because that’s back to being almost invisible in most light terminals.<p>Light terminal themes have to decide whether colours 8–15 mean “bright” (increase lightness and perhaps saturation) or “higher contrast” (where you <i>decrease</i> lightness). Having played the game, I can report that both choices will break some things, but that “bright” is <i>probably</i> the more reasonable of the two. But know that you can’t rely on any particular direction in the relationship between colours 0–7 and 8–15.<p>You think you’ll get around all of this by setting background colours? Please don’t, this just guarantees that your app will feel <i>completely</i> out of place, and probably be unpleasant to use.<p>You’re fed up with light terminal considerations? Well then, perhaps you’d like some blue in your dark terminal. Pity that there are still widely-used terminals out there where blue so dark that it’s almost invisible and <i>extremely</i> hard to read. And even bright blue is commonly mildly painful to read. So blue’s out for any length of text.<p>My advice ends up: by default, you should not set <i>any</i> background colours, and for foregrounds you can use the default colour and colours 1 (red), 2 (green), 5 (purple) and 6 (teal), and I will graciously permit you to use colours 3 (yellow) and 4 (blue) for no more than one word at a time (e.g. “warning:” in yellow). Seriously. Until the user opts into anything else, treat the entire thing as a five-and-a-bit-colour terminal, because you’ll cause misery if you go any further. <i>Never</i> use colours 0, 7, 8 or 15 by default without determining what they and the default colours are, because they may be high contrast or <i>zero</i> contrast. You can also use bold, which <i>may</i> give brighter colours, whatever that means, but shouldn’t use colours 7–15 directly.<p>In many terminals it is possible to determine what the default background and foreground colours and other colours are, and if you have a <i>really</i> good reason why you want to use a bunch more colours you can try reading them and at least doing something simple like switching between a light and dark theme, but I recommend against that, because setting backgrounds is still just generally… <i>non-native</i> is probably a decent way of putting it. Stay colour-neutral by default, fit in rather than standing out.<p>This is hardly the only place terminals are using a fundamentally bad model. The article does talk about the problems of column widths, seen especially in emoji. We seriously need to burn the current scheme of terminals down and build something <i>sound</i> in its place. Of course, this is extraordinarily unlikely to happen, and only stands any chance whatsoever if compatibility can be maintained in some way.