MaterialTheme(colorScheme, typography, shapes) { ... } provides three objects through composition locals, read below with MaterialTheme.colorScheme, .typography and .shapes. A nested MaterialTheme restyles one subtree, as a CSS custom property set on an element overrides the one on :root.
A ColorScheme holds 48 named color roles, not a palette of shades:
| Role family | Examples | Used for |
|---|---|---|
| Accent | primary, secondary, tertiary | filled buttons, active states |
| On-color | onPrimary, onSurface | text and icons on the matching role |
| Container | primaryContainer, secondaryContainer | tonal buttons, selected chips, app bars |
| Surface | surface, surfaceContainerHighest | screens, cards, sheets, menus |
| Utility | outline, error, scrim | borders, errors, dimming |
Roles come in pairs: a component that draws on primary sets LocalContentColor to onPrimary, so the Text("Buy") inside a Button is white without being told. Hard-code Color.Black on a text instead and it vanishes in dark mode.
Typography has 15 styles: display, headline, title, body and label, each Large, Medium and Small. Components choose theirs (a Button uses labelLarge), and your text should pick a style rather than a raw font size, so theme changes reach it. BookNest keeps Roboto for reading and gives titles a serif face, which Android maps to Noto Serif:
private val base = Typography()
val BookNestTypography = base.copy( // serif titles, default sans body
headlineSmall = base.headlineSmall.copy(fontFamily = FontFamily.Serif),
titleLarge = base.titleLarge.copy(fontFamily = FontFamily.Serif),
titleMedium = base.titleMedium.copy(fontFamily = FontFamily.Serif,
fontWeight = FontWeight.SemiBold),
)
val BookNestShapes = Shapes(medium = RoundedCornerShape(16.dp)) // cards: 12 dp -> 16 dpcopy() keeps the type scale and changes only what you name; a brand font goes in res/font/ as a FontFamily(Font(R.font.x)). Cards use the medium of five Shapes.