# All about theming in Jetpack Compose

> A Jetpack Compose tutorial about how to use themes in your Jetpack Compose app, using Material 3 compose.

Published 23 March 2023 by Alex Styl.

Heya! Happy Thursday. Alex here.

Today's tutorial is going to cover how to use themes in your Jetpack Compose app, using Material 3 compose.

You can still use this tutorial with Material compose. What's different is that they use different theme attributes (such as `colors` instead of `colorScheme`) and different imports, but the main concept is the same.

For a tl;dr what's different between Material and Material 3, [checkout this Twitter thread](https://twitter.com/alexstyl/status/1620459556483768320).

## Thinking in Themes

It all starts with the `MaterialTheme()` composable. This composable is responsible for setting up the look and feel for all the content of its children.

Most of the times, it is going to be the top level composable of your app:

```kotlin
MaterialTheme {
    HomeScreen()
}
```

out of the box, the `MaterialTheme()` composable gives you 3 different attributes which you can pass as parameters:

```kotlin
@Composable
fun MaterialTheme(
    colorScheme: ColorScheme = MaterialTheme.colorScheme,
    shapes: Shapes = MaterialTheme.shapes,
    typography: Typography = MaterialTheme.typography,
    content: @Composable () -> Unit
)
```

The parameters that you pass here are going to be used in any child composable passed to the _content_.

Example of this are [`ModalBottomSheets`](https://composables.com/tutorials/bottomsheet.md) that were recently introduced in Material 3 compose. The value of the _extraLarge_ parameter of the passing `Shapes` object will affect how the bottom sheet is going to look like. More on that in a bit.

The cool thing is `MaterialTheme()`'s children composables will have access to any parameter passed here via the `MaterialTheme` object.
At any point that you need to access, say, the specified `Typography`, you can use the `MaterialTheme` object.

Here is a quick example:

```kotlin
MaterialTheme(
    typography = Typography(
        headlineLarge = TextStyle(
            fontSize = 24.sp
        )
    )
) {
    HomeScreen()
}
```

and here is how to access the `headlineLarge` property from any child:

```kotlin
@Composable
fun HomeScreen() {
    Text("This is my title", style = MaterialTheme.typography.headlineLarge)
}
```

you can use the `MaterialTheme` object to get any color, type style or shape you need, as long as the composable is wrapped with the `MaterialTheme` composable.

In other words: the `MaterialTheme()` composable gives access to the `MaterialTheme` object to all of its children and its children children.

By default, most (if not all) composables that come out of the box with Material 3 will use this object for default values. This means that updating the values passed to your theme will update the look and feel of your app.

## Every `MaterialTheme` property explained

The 3 different attributes you can modify in your MaterialTheme (colorScheme, shapes, typography) are an implementation of how the Material 3 design system works.

Keep reading to learn how each attribute works and how it affects the looks of your app:

### What is `colorsScheme` and how it works in Material 3 compose

Material 3 comes with a list of predefined (named) colors. The main ones are: _primary_, _surface_ and _background_.

Primary is the main highlight of your app (for things like button backgrounds and other interactive elements). Surface sets the color for surfaces such as Cards and Bottom Sheets (a reminder that a surface is a piece of paper in the Material metaphor). Background is, well, the background of your app.

Every color comes with its pair. For each color in the `colorScheme` you will find a `on_` counterpart. For example `primary` comes with `onPrimary`. The `onPrimary` is used for elements that are placed on top of other elements using the `primary` color.

A good example of this are buttons. They use `primary` as their background color. Their text uses the `onPrimary` color.

This works for any color in Material. Need to change the color of text that is used on top of a card? Update the `onSurface` color and the text will magically update to the given `onSurface` color.

#### Do not create `ColorScheme()` via its constructor

Instead of defining a `ColorScheme` from scratch (which requires a ton of constructor arguments) use one of the color scheme functions instead. Those are used as a base to definine your own themes. Those include `lightScheme()` (a base for light themes), `darkScheme()` (a base for dark themes).

`dynamicLightColorScheme()` and `dynamicDarkColorScheme()` are also available. These color schemes will create dynamic colors according to the user's wallpaper.

### What is `typography` and how it works in Material 3 compose

Typography defines the styling of text in your app. All text styles are split in _display_, _headline_, _title_, _body_, and _label_. Each category comes in different size variations: _small_, _medium_ and _large_.

Each combination is a `TextStyle`. Each `TextStyle` can contain anything related to the looks of text. This include the text `fontSize`, `fontWeight`, `fontFamily`, `lineHeight` to name a few.

The type of `TextStyle` your `Text()` composable is going to receive depends on the composable that it is wrapped in. For example, the `TopAppBar()` title uses the `titleLarge` textStyle.

### What is `shapes` and how it works in Material 3 compose

Shape defines the looks (mostly corners) of different elements in your app. This affects composables such as buttons shapes, card and sheets.

Jetpack Compose comes with some predefined shapes you can use depending on your needs such as `CircleShape` and `RectangleShape`.

If you need rounded corners, checkout the `RoundedCornerShape()` function. `CutCornerShape()` is also available.

## How to tell how a composable will be visually affected if I change my theme?

Check the default values of the composable you are interested in. Let's find out which theme value will change the background color of our `Button()`s.

Notice the `colors` default value of the `Button()` composable:

```kotlin
fun Button(
    onClick: () -> Unit,
    modifier: Modifier = Modifier,
    colors: ButtonColors = ButtonDefaults.buttonColors(),
    // ... other parameters
)
```

The `ButtonDefaults.buttonColors()` function is the place where the `Button()` receives all of its colors.

If you check the source code of the `Button()` you will The background color of the button is called `containerColor`

```kotlin
fun buttonColors(
    containerColor: Color = FilledButtonTokens.ContainerColor.toColor(),
    // other parameters
)
```

If you check the `ContainerColor` you will notice its value is `ColorSchemeKeyTokens.Primary`. Digging deeper you will find this value is mapped to `MaterialTheme.colorScheme.primary` color.

Figuring out which value is affected is a bit tricky. You wouldn't need to do this often though as the composables that come out of the box should look and consistent according to your theme.

---

In this tutorial you learnt how to theme your app using Material 3 compose library. You learnt about the `MaterialTheme()` composable and how it grants access to the `MaterialTheme` object to all of its children (and their children). You learnt about the different attributes you can customize: colorScheme, typography and shapes.

---

## ⚡️ Breaking Jetpack Compose news

Jetpack Compose 1.4.0 was released yesterday along with a few others!

Here are all the new Jetpack Compose updates we got:

- 🚀 **Compose UI** 1.4.0 ([changelog](https://developer.android.com/jetpack/androidx/releases/compose-ui#1.4.0))
- 🚀 **Compose UI** 1.5.0-alpha01 ([changelog](https://developer.android.com/jetpack/androidx/releases/compose-ui#1.5.0-alpha01))
- 🎬 **Compose Animation** 1.4.0 ([changelog](https://developer.android.com/jetpack/androidx/releases/compose-animation#1.4.0))
- 🎬 **Compose Animation** 1.5.0-alpha01 ([changelog](https://developer.android.com/jetpack/androidx/releases/compose-animation#1.5.0-alpha01))
- 🧰 **Compose Compiler** 1.4.4 ([changelog](https://developer.android.com/jetpack/androidx/releases/compose-compiler#1.4.4))
- 🧱 **Compose Foundation** 1.4.0 ([changelog](https://developer.android.com/jetpack/androidx/releases/compose-foundation#1.4.0))
- 🧱 **Compose Foundation** 1.5.0-alpha01 ([changelog](https://developer.android.com/jetpack/androidx/releases/compose-foundation#1.5.0-alpha01))
- 🎨 **Compose Material** 1.4.0 ([changelog](https://developer.android.com/jetpack/androidx/releases/compose-material#1.4.0))
- 🎨 **Compose Material** 1.5.0-alpha01 ([changelog](https://developer.android.com/jetpack/androidx/releases/compose-material#1.5.0-alpha01))
- 🎨 **Compose Material 3** 1.1.0-beta01 ([changelog](https://developer.android.com/jetpack/androidx/releases/compose-material3#1.1.0-beta01))
- 🏃‍♂️ **Compose Runtime** 1.4.0 ([changelog](https://developer.android.com/jetpack/androidx/releases/compose-runtime#1.4.0))
- 🏃‍♂️ **Compose Runtime** 1.5.0-alpha01 ([changelog](https://developer.android.com/jetpack/androidx/releases/compose-runtime#1.5.0-alpha01))
- ⌚️ **Wear Compose** 1.2.0-alpha07 ([changelog](https://developer.android.com/jetpack/androidx/releases/wear-compose#1.2.0-alpha07))
- ⌚️🎨 **Wear Compose Material3** material3-1.0.0-alpha01 ([changelog](https://developer.android.com/jetpack/androidx/releases/wear-compose#material3-1.0.0-alpha01))

---

That's all I got for you today.

How did you find this issue? Let me know by replying to this email if you are reading in your inbox.

Until the next one,

Alex
