Default skin complete overhaul draft #12697
Draft
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Notice
This PR is not really even 20% done yet, but I wanted to post it early for a few reasons:
Objectives
Consistent, non-hardcoded colour scheme. Using a mixture of hardcoded colours and theme-provided ones contributes to poor consistency and unification across the theme, makes it harder to modify and see the effects thereof, and splits the scheme across a hundred source files rather than one centralised location. Instead, a unified token-based system, which is standard in many design systems and themes, should be used here, too.
Background-container separation. The purpose of the background is to separate groups of information from each other, not to be the stage on which information is shown. This is the core paradigm on which the layering system rests. Grouping information together naturally makes it easier to parse for humans, and layer containers accomplish just that.
Consistent spacing everywhere. The purpose of spacing is to make information easier to digest, so it needs to be flexible and consistent. For that reason a unit-based solution must be adopted instead of hard-coding padding in floats everywhere. Unciv has an Android-grade font size (18px), so we adopt that as the rem.
Font size standardisation. We currently have two base font sizes, 18px for most text and 24px for headers. But in reality, hardcoded custom font sizes are not uncommon despite often not really being necessary. There's no reason to re-invent the wheel here. We should just adapt a generally accepted typeface scaling equation and stick to sizes from that list; IBM's is a good one that I've been using:
Accessibility. Colour schemes should be designed to be easily usable by the 4%–5% of the population with some form of colour vision deficiency without making it less pleasing for those with typical vision. This involves setting contrast rate targets and carefully choosing colours and designing components such that chromatic aberration, adaption, and simultaneous contrast do not worsen the user experience.
Base colours and background layers
An initial discussion is necessary regarding the background colours. Our colour scheme is firmly rooted in the "darker" category; all of our backgrounds are colour and highly saturated. Disregarding the primary action colour, there is only ever one layer on the background. The colour of this layer varies and its relation to the base colour is not clear; in fact, even its hue differs.
For these reasons, I propose generating base colours algorithmically. Specifically, we should start with a sensible default and model the progression as a nonlinear function. We require background colours that reflect the customary hue while remaining neutral enough to support layering, transparency, and especially text. For this reason, lower saturation is generally desirable. Here it must be recognised that, due to the Helmholtz–Kohlrausch effect, even lower-saturation blue backgrounds will appear brighter than equivalent grey backgrounds would; to compensate for this effect, I have chosen a base lightness value slightly below the average of professionally designed dark themes.
The most obvious way to generate lighter versions of a base colour would be to simply linearly divide the spectrum into a number of equal segments. I belive this approach to be misguided for a few reasons. First, a linear progression of stimulus intensity will practically never be perceived as linear by a human observer due to Stevens' power law; second, the brighter end of such a spectrum is far more uncommonly used in dark themes, and the opposite is true in light themes.
Instead, I have hand-picked the colour #161721 and modelled its lightness spectrum according to the following function:
which, in comparison to a linear function:
furnishes us a sensible set of colours for any given base. Additionally, it grants us future flexibility, because it's far easier to change the base and re-generate colours or to simply change the base a layer uses than to go through every section of code with a toothcomb again.
Black and white
In the typical case pure black should not be used. It tends to cause an extreme and jarring contrast, and, when paired with high-saturation colours, contributes to an illusion of depth; for these reasons, black elements should be represented by the darkest available grey. The more prudent discussion is regarding the use of pure white. Pure white in dark themes is used either often or occasionally depending on the type of content, the desired contrast, and the designer's own whims. I believe that in interactive media, it is best to rely on it when the best possible contrast is actually desirable; and to emphasise that effect, it should be restriced to that usage.
If all text has the highest possible contrast, we lose one way to communicate emphasis. For these reasons, I believe our text should be, by default, either an off-white colour or a transparent white colour. In this case, I have chosen some sensible defaults for the former based on my knowledge and first-hand experience, which are as follows:
Components
The appearance of components is by far the most multifaceted and complicated aspect of the theme. Unlike backgrounds and text, components are interactive and communicate state and behaviour through colour. They require hierarchy, interactive states, alternative forms, and other idiomatic patterns to act in their full capacity.
Hierarchy. For the majority of buttons, a neutral colour from our main family is appropriate, and such components should make up the majority of the total. It is nevertheless very useful to have two variants: high-emphasis variant, and a low-emphasis variant. Typically high-emphasis components have contrasting saturation and hue (but not excessively so), whereas low-emphasis components differentiate themselves by the design of the component itself.
An appropriate base colour for medium-emphasis components in our scheme is Base 50. Both it and its interactive states conform to contrast standards and work well on any layer. For high-emphasis components, I have chosen to shift the hue of the medium-emphasis component and adjust its saturation and luminance to compensate for the fact that wavelengths around green and yellow produce much weaker manifestations of the Helmholtz–Kohlrausch effect in people with typical colour vision.
Therefore, the base component colours are as follows:
Interactive states. Components' interactive states should follow a consistent guideline based on the established tokens. A hovered button should be one step lighter than default, and a pressed or "down" button should be one steps darker than the default. Finally, disabled components should be in the darkest available non-layer shade, with an appropriate transparency.
Negative colours. The negative colours, used for "destructive" elements like the "exit game" button are more complicated. They need to clearly communicate the destructive aspect, and red is an appropriate choice for this—it is well-understood by Western audiences and generally colourblind-friendly. The current colour, however, is so intense that it causes severe chromostereopsis for the non-colourblind. For this reason, it should be significantly muted and its hue shifted slightly towards burgundy. Because only three shades are needed, it is reasonable to hand-pick them. Of course, they must also respect contrast accessibility standards.
Subdued colours. Some elements need to support a "subdued" or "weaker" text colour. Placeholder text and group labels for some controls are examples of such. Instead of the current grey, it should be a special transparent version of the lightest available colour; this adjusts the contrast without the harsh mismatch of dark grey on Oxford blue.
Special
There are several static colours that we need for recognisable game elements. These include gold, culture, faith, and the like. Because they are occasionally used on components, like the "next turn" button, they must likewise be chosen to contrast thereagainst. Much like the negative colours, their hue and saturation must be chosen with some care to avoid the effects of chromostereopsis. Otherwise, the choice is largely a matter of preference. These are yet to be chosen.
Miscellaneous
Okay, but will it look good? What's it look like now?
Well, whether you think it looks good isn't exactly up to me to decide, but here are some of the places that I've been focusing on converting with the first set of changes: