I have a question on how you are supposed to use m...
# compose
d
I have a question on how you are supposed to use multiple text colors in Material 3 on the same surface. đź§µ
So let's say you have a primary surface. The text on top of the primary surface will have an onPrimary. Let's say I want to have maybe 3 different text colors of shades of black/white on top of a Surface. So depending on the Surface color it would be specific colors that our designer chose for the different surface. It should automatically work with dark mode per the theme. All options I would think would be hacky. I have how this works well with 1 text color automatically but multiple I am not clear.
I could of course just use a color directly on the Text but that is not going to play well if I change the surface color or use dark mode. Basically I want to say I can have 3 text styles on any surface and apply them something like MaterialTheme.typography.displayLarge MaterialTheme.typography.displayLarge.Light MaterialTheme.typography.displayLarge.Dark Where the above 3 colors change per the surface.
c
Is your designer adhering to the Material3 color system/roles?
d
Not yet. Work in progress. Realistically its going to be MaterialTheme.typography.body3 MaterialTheme.typography.body3.Light Where body3 are extension functions. All kind of hacky right now
I would imagine having multiple different colors on a surface is pretty common. Not sure how people solve it. Like alphas, wrapping everything that I want light color with a different theme, hacking around surfaces and wrap everything light with surface with background and I change the onBackground color as currently background and surface are the same in my project. All seem pretty hacky
k
M3 spec already does that. See the tab spec, using
primary
for active tab text and
onSurfaceVariant
for inactive tab text
Also, don't add Light or Dark to typography tokens. Typography is about font size, family, weight, line height, character spacing. Very much not about color.
As for the core of your question, it should be answered by your designer. How do they want it to look like? Do you use a fixed theme, or the device dynamic theme? If it's a fixed theme, you can do something simple like hardcoded colors. If it's a dynamic theme, it's not shades of grey. It would need to come from one of the tonal pallettes, much like primary and on surface variant do.
d
I am going to give more of a concrete example and I think that will help with discussion. https://github.com/DavidCorrado/Material3TextColoring/blob/main/app/src/main/java/com/example/textcoloring/MainActivity.kt So you can see I have 2 surfaces. One primary and one background. Then right below that the same 2 surfaces with theme dark. I have 3 colors on each surface and my goal is to allow each of those 3 colors to be different in every one of the situations as shown in the screenshot. So you can see the theming automatically changes the Colors for every single surface for 1 color. I am looking to repeat that for 2 more colors on each surface. @Kirill Grouchnikov you mention using surfaceVariant. Which means I would apply a surface around "Color 2". Which would work for "Color 2" but not "Color 3". Also the problem with that is if I change onSurfaceVariant it will have side effects such as affecting the tab inactive text color like you referenced which I don't want. Also another problem is that would not work on top of the primary surface as there is no primaryVariant. Hopefully thats clear.
k
Looking at the basics first, every M3 tonal palette looks like this
From a single key color, M3 generates a palette with tonal stops, from 0 (darkest) to 100 (lightest)
Every base combination of M3
X
and
onX
is a pair of two tonal stops:
So
primary
which is mapped to P40 (darker tonal stop) and then
onPrimary
which is mapped to P90 (lighter tonal stop). With enough “spread” between the two stops, you should get good contrast for text on background, no matter what was the seed color that generated the whole tonal palette
What you can do for your particular case? Multiple options, depending on what your design “envisions”.
Option 1 - choose adjacent tonal stops from the same palette. So if your surface fill is P95 (light fill), your text colors can be P10, P20 and P30. And the other way around for light texts on dark fill.
Option 2 - choose the same tonal stop from the three accent palettes (primary, secondary, tertiary). So for the surface fill of P95, your text colors would be P20, S20 and T20.
Option 3 - use a single tonal stop, and apply alpha. So for the surface fill of P95, your text colors would be P20, P20 at 90% alpha, P20 at 80% alpha.
What you and your designer need to decide is how you want it to look like, and then based on that, choose one of these options, along with specific tonal stops or alphas as relevant.
Don’t expect M3 to have these tokens or mappings out of the box. M3 has `X`/`onX` pairs for a few values of
X
if you will - such as
surface
,
surfaceVariant
,
background
,
primary
,
primaryContainer
, etc. What you are looking for is
onX1
,
onX2
,
onX3
for every
X
defined in M3, and that is something that is up to you to figure out - in terms of what kind of color harmony / coherence you are looking for.
d
Is there examples out there to demo the 3 ways you expressed above? I am going to give my understanding 1. So my understanding of this is 3 colors you can define on top of a primary surface. The way I understand that is using the color directly on Text composable would not be good as it would not work well with dark mode. So how would this work? 2. I am not sure this will work for me as I want 3 colors on the same surface and I think this involves 1 color per surface. 3. How would this work as I would think you would want a different alpha if you are in dark mode or not I think my problem is that X and onX is a 1:1 relationship. A surface has only 1 text color. You can override a specific composable Text color but it will not automatically change the color per the theme. I could maybe add another custom surface I create that is the same surface color and change the onSurface color. I think that would require me to completely rebuild ColorScheme and many other classes to add more surface colors?
c
require me to completely rebuild ColorScheme and many other classes to add more surface colors
Not necessarily - if you are looking to just add more color parameters to
colorScheme
, you can extend
MaterialTheme
: https://developer.android.com/jetpack/compose/designsystems/custom#extending-material
d
Interesting and I do think the ability to add colors to colorScheme would essentially be what I want. I will explore that
k
Also, there is no magic in dark mode. It’s just a different mapping for
X
and
onX
. So for light mode, your fill (X) might be P90 and your text (onX) might be P20. And for dark mode, the same X would be P10 and onX would be P80. Light mapping goes to
values
and dark mapping goes to
values-night
And you don’t have to tie yourself to specific Xs from M3 (such as
surface
). Indeed, it’s a 1:1 relationship for those Xs in M3, so you have two options: 1. Add
onX2
and
onX3
for the relevant Xs in your color scheme extension 2. Define your own X - such as let’s say
mySurface
and then matching
onMySurface1
,
onMySurface2
and
onMySurface3
for light and dark modes.