Slide 1

Slide 1 text

Ryan Harter @rharter Custom Design Systems in Jetpack Compose

Slide 2

Slide 2 text

Ryan Harter @RHARter Custom Design Systems in Jetpack Compose UI

Slide 3

Slide 3 text

Ryan Harter @RHARter Follow Along https://ryans.link/dsys-compose

Slide 4

Slide 4 text

Ryan Harter @RHARter See Also Compose beyond Material Sebastiano Poggi

Slide 5

Slide 5 text

Compose UI

Slide 6

Slide 6 text

Compose UI Compose UI

Slide 7

Slide 7 text

Compose UI Compose UI Foundation

Slide 8

Slide 8 text

Compose UI Compose UI Foundation Compose Material

Slide 9

Slide 9 text

Compose Material Material Theme Colors Typography Button Text Surface Etc. Shape

Slide 10

Slide 10 text

Compose Material Material Theme Colors Typography Button Text Surface Etc. Shape

Slide 11

Slide 11 text

Sidebar Design System Tokens

Slide 12

Slide 12 text

Sidebar Design System Tokens @Stable class Colors( val primary: Color, val primaryVariant: Color, val secondary: Color, val secondaryVariant: Color, val background: Color, val surface: Color, val error: Color, val onPrimary: Color, val onSecondary: Color, val onBackground: Color, val onSurface: Color, val onError: Color, val isLight: Boolean )

Slide 13

Slide 13 text

Sidebar Design System Tokens @Stable class Colors( val primary: Color, val primaryVariant: Color, val secondary: Color, val secondaryVariant: Color, val background: Color, val surface: Color, val error: Color, val onPrimary: Color, val onSecondary: Color, val onBackground: Color, val onSurface: Color, val onError: Color, val isLight: Boolean ) @Stable class Colors( val : Color, val : Color, val : Color, val : Color, val : Color, val : Color, val : Color, val : Color, val : Color, val : Color, val : Color, val : Color, val : Boolean )

Slide 14

Slide 14 text

Sidebar Design System Tokens @Stable class Colors( val primary: Color, val primaryVariant: Color, val secondary: Color, val secondaryVariant: Color, val background: Color, val surface: Color, val error: Color, val onPrimary: Color, val onSecondary: Color, val onBackground: Color, val onSurface: Color, val onError: Color, val isLight: Boolean ) @Immutable class Typography( val h1: TextStyle, val h2: TextStyle, val h3: TextStyle, val h4: TextStyle, val h5: TextStyle, val h6: TextStyle, val subtitle1: TextStyle, val subtitle2: TextStyle, val body1: TextStyle, val body2: TextStyle, val button: TextStyle, val caption: TextStyle, val overline: TextStyle )

Slide 15

Slide 15 text

Sidebar Design System Tokens @Stable class Colors( val primary: Color, val primaryVariant: Color, val secondary: Color, val secondaryVariant: Color, val background: Color, val surface: Color, val error: Color, val onPrimary: Color, val onSecondary: Color, val onBackground: Color, val onSurface: Color, val onError: Color, val isLight: Boolean ) @Immutable class Typography( val h1: TextStyle, val h2: TextStyle, val h3: TextStyle, val h4: TextStyle, val h5: TextStyle, val h6: TextStyle, val subtitle1: TextStyle, val subtitle2: TextStyle, val body1: TextStyle, val body2: TextStyle, val button: TextStyle, val caption: TextStyle, val overline: TextStyle ) @Immutable class Typography( val : TextStyle, val : TextStyle, val : TextStyle, val : TextStyle, val : TextStyle, val : TextStyle, val : TextStyle, val : TextStyle, val : TextStyle, val : TextStyle, val : TextStyle, val : TextStyle, val : TextStyle )

Slide 16

Slide 16 text

Sidebar Design System Tokens @Stable class Colors( val primary: Color, val primaryVariant: Color, val secondary: Color, val secondaryVariant: Color, val background: Color, val surface: Color, val error: Color, val onPrimary: Color, val onSecondary: Color, val onBackground: Color, val onSurface: Color, val onError: Color, val isLight: Boolean ) @Immutable class Typography( val h1: TextStyle, val h2: TextStyle, val h3: TextStyle, val h4: TextStyle, val h5: TextStyle, val h6: TextStyle, val subtitle1: TextStyle, val subtitle2: TextStyle, val body1: TextStyle, val body2: TextStyle, val button: TextStyle, val caption: TextStyle, val overline: TextStyle )

Slide 17

Slide 17 text

Compose Material Material Theme Colors Typography Button Text Surface Etc. Shape

Slide 18

Slide 18 text

Compose Material Material Theme Button Text Surface Etc. Colors Typography Shape

Slide 19

Slide 19 text

Material Theme

Slide 20

Slide 20 text

Customizing • Customize Material • Extend Material • Implement fully-custom design system Material Theme

Slide 21

Slide 21 text

Material Theme Button Text Surface Etc. Colors Typography Shape Customize Material

Slide 22

Slide 22 text

Material Theme Colors Typography Button Text Surface Etc. Shape Customize Material

Slide 23

Slide 23 text

private val LightColors = lightColors( . .. ) private val DarkColors = darkColors( . .. ) @Composable fun MyTheme(content: @Composable () - > Unit) { MaterialTheme( colors = if (isSystemInDarkTheme()) DarkColors else LightColors, shapes = Shapes( small = RoundedCornerShape(0.dp), medium = RoundedCornerShape(0.dp), large = RoundedCornerShape(0.dp) ), content = content ) } Customize Material

Slide 24

Slide 24 text

private val LightColors = lightColors( . .. ) private val DarkColors = darkColors( . .. ) @Composable fun MyTheme MaterialTheme( colors = if (isSystemInDarkTheme()) DarkColors else LightColors, shapes = Shapes( small = RoundedCornerShape(0.dp), medium = RoundedCornerShape(0.dp), large = RoundedCornerShape(0.dp) ), content = content ) } Customize Material (content: @Composable () - > Unit) {

Slide 25

Slide 25 text

private val LightColors = lightColors( . .. ) private val DarkColors = darkColors( . .. ) @Composable fun MyTheme MaterialTheme( colors = if (isSystemInDarkTheme()) DarkColors else LightColors, shapes = Shapes( small = RoundedCornerShape(0.dp), medium = RoundedCornerShape(0.dp), large = RoundedCornerShape(0.dp) ), content = content ) } : @Composable () -> Unit) { Customize Material (content

Slide 26

Slide 26 text

private val LightColors = lightColors( . .. ) private val DarkColors = darkColors( . .. ) @Composable fun MyTheme MaterialTheme( colors = if (isSystemInDarkTheme()) DarkColors else LightColors, shapes = Shapes( small = RoundedCornerShape(0.dp), medium = RoundedCornerShape(0.dp), large = RoundedCornerShape(0.dp) ), content = content ) } : @Composable () -> Unit) { (content Customize Material content

Slide 27

Slide 27 text

private val LightColors = lightColors( . .. ) private val DarkColors = darkColors( . .. ) @Composable fun MyTheme MaterialTheme( colors = if (isSystemInDarkTheme()) DarkColors else LightColors, shapes = Shapes( small = RoundedCornerShape(0.dp), medium = RoundedCornerShape(0.dp), large = RoundedCornerShape(0.dp) ), content = content ) } private val LightColors = lightColors( . .. ) private val DarkColors = darkColors( . .. ) @Composable fun MyTheme(content: @Composable () - > Unit) { MaterialTheme( colors = if (isSystemInDarkTheme()) DarkColors else LightColors, shapes = Shapes( small = RoundedCornerShape(0.dp), medium = RoundedCornerShape(0.dp), large = RoundedCornerShape(0.dp) ), content = content ) } Customize Material : @Composable () -> Unit) { content (content

Slide 28

Slide 28 text

private val LightColors = lightColors( . .. ) private val DarkColors = darkColors( . .. ) @Composable fun MyTheme MaterialTheme( colors = if (isSystemInDarkTheme()) DarkColors else LightColors, shapes = Shapes( small = RoundedCornerShape(0.dp), medium = RoundedCornerShape(0.dp), large = RoundedCornerShape(0.dp) ), content = content ) } private val LightColors = lightColors( . .. ) private val DarkColors = darkColors( . .. ) @Composable fun MyTheme(content: @Composable () - > Unit) { MaterialTheme( colors = if (isSystemInDarkTheme()) DarkColors else LightColors, shapes = Shapes( small = RoundedCornerShape(0.dp), medium = RoundedCornerShape(0.dp), large = RoundedCornerShape(0.dp) ), content = content ) } Customize Material : @Composable () >

Slide 29

Slide 29 text

private val LightColors = lightColors( . .. ) private val DarkColors = darkColors( . .. ) @Composable fun MyTheme(content: @Composable () - > Unit) { MaterialTheme( colors = if (isSystemInDarkTheme()) DarkColors else LightColors, shapes = Shapes( small = RoundedCornerShape(0.dp), medium = RoundedCornerShape(0.dp), large = RoundedCornerShape(0.dp) ), content = content ) } Customize Material

Slide 30

Slide 30 text

private val LightColors = lightColors( . .. ) private val DarkColors = darkColors( . .. ) @Composable fun MyTheme(content: @Composable () - > Unit) { MaterialTheme( colors = if (isSystemInDarkTheme()) DarkColors else LightColors, shapes = Shapes( small = RoundedCornerShape(0.dp), medium = RoundedCornerShape(0.dp), large = RoundedCornerShape(0.dp) ), content = content ) } Customize Material

Slide 31

Slide 31 text

private val LightColors = lightColors( . .. ) private val DarkColors = darkColors( . .. ) @Composable fun MyTheme(content: @Composable () - > Unit) { MaterialTheme( colors = if (isSystemInDarkTheme()) DarkColors else LightColors, shapes = Shapes( small = RoundedCornerShape(0.dp), medium = RoundedCornerShape(0.dp), large = RoundedCornerShape(0.dp) ), content = content ) } Customize Material

Slide 32

Slide 32 text

private val LightColors = lightColors( . .. ) private val DarkColors = darkColors( . .. ) @Composable fun MyTheme(content: @Composable () - > Unit) { MaterialTheme( colors = if (isSystemInDarkTheme()) DarkColors else LightColors, shapes = Shapes( small = RoundedCornerShape(0.dp), medium = RoundedCornerShape(0.dp), large = RoundedCornerShape(0.dp) ), content = content ) } Customize Material @Composable

Slide 33

Slide 33 text

fun MyApp() { MyTheme { . .. } }

Slide 34

Slide 34 text

Customizing • Customize Material • Extend Material • Implement fully-custom design system Material Theme

Slide 35

Slide 35 text

Extend Material

Slide 36

Slide 36 text

Extend Material (super simple) val Colors.snackbarAction: Color get() = if (isLight) Red300 else Red700 val Typography.textFieldInput: TextStyle get() = TextStyle( / * ... */ ) val Shapes.card: Shape get() = RoundedCornerShape(size = 20.dp) val Colors.snackbarAction: Color get() = if (isLight) Red300 else Red700 val Typography.textFieldInput: TextStyle get() = TextStyle( / * ... */ ) val Shapes.card: Shape get() = RoundedCornerShape(size = 20.dp)

Slide 37

Slide 37 text

Extend Material

Slide 38

Slide 38 text

Sidebar Providing Tokens Material Theme Button Text Surface Etc. Colors Typography Shape

Slide 39

Slide 39 text

Sidebar Surface 1 Material Theme Providing Tokens Button Text Surface Etc. Colors Typography Shape

Slide 40

Slide 40 text

Sidebar Material Theme Colors Typography Shape Surface 1 Providing Tokens Button Text Surface

Slide 41

Slide 41 text

Sidebar Material Theme Colors Typography Shape Surface 1 Providing Tokens Button Text Surface Surface 2 Surface Material Theme 2 Text Text Button Material Theme Colors Typography Shape

Slide 42

Slide 42 text

Sidebar Material Theme Colors Typography Shape Surface 1 Providing Tokens Button Text Surface Surface 2 Surface Material Theme 2 Text Text Button Material Theme Colors Typography Shape

Slide 43

Slide 43 text

Sidebar Material Theme Colors Typography Shape Surface 1 Providing Tokens Button Text Surface Surface 2 Surface Material Theme 2 Text Text Material Theme Colors Typography Shape Button

Slide 44

Slide 44 text

Sidebar Material Theme Colors Typography Shape Surface 1 Providing Tokens Button Text Surface Surface 2 Surface Material Theme 2 Text Text Material Theme Colors Typography Shape Button

Slide 45

Slide 45 text

Sidebar Material Theme Colors Typography Shape Surface 1 Providing Tokens Button Text Surface Surface 2 Surface Material Theme 2 Text Text Material Theme Colors Typography Shape Button

Slide 46

Slide 46 text

Extend Material

Slide 47

Slide 47 text

@Immutable data class ExtendedColors( val tertiary: Color, val onTertiary: Color ) val LocalExtendedColors = staticCompositionLocalOf {

Slide 48

Slide 48 text

@Immutable ExtendedColors( tertiary = Color.Unspecified, onTertiary = Color.Unspecified ) } @Composable

Slide 49

Slide 49 text

fun ExtendedTheme( /* .. . * / content: @Composable () - > Unit ) { val extendedColors = ExtendedColors( tertiary = Color(0xFFA8EFF0), onTertiary = Color(0xFF002021) ) CompositionLocalProvider(LocalExtendedColors provides extendedColors) { MaterialTheme( /* colors = ... , typography = .. . , shapes = .. . */ content = content ) } } Extend Material

Slide 50

Slide 50 text

fun ExtendedTheme( /* .. . * / content: @Composable () - > Unit ) { val extendedColors = ExtendedColors( tertiary = Color(0xFFA8EFF0), onTertiary = Color(0xFF002021) ) CompositionLocalProvider(LocalExtendedColors provides extendedColors) { MaterialTheme( /* colors = ... , typography = .. . , shapes = .. . */ content = content ) } } Extend Material

Slide 51

Slide 51 text

fun ExtendedTheme( /* .. . * / content: @Composable () - > Unit ) { val extendedColors = ExtendedColors( tertiary = Color(0xFFA8EFF0), onTertiary = Color(0xFF002021) ) CompositionLocalProvider(LocalExtendedColors provides extendedColors) { MaterialTheme( /* colors = ... , typography = .. . , shapes = .. . */ content = content ) } } Extend Material

Slide 52

Slide 52 text

fun ExtendedTheme( /* .. . * / content: @Composable () - > Unit ) { val extendedColors = ExtendedColors( tertiary = Color(0xFFA8EFF0), onTertiary = Color(0xFF002021) ) CompositionLocalProvider(LocalExtendedColors provides extendedColors) { MaterialTheme( /* colors = ... , typography = .. . , shapes = .. . */ content = content ) } } Extend Material

Slide 53

Slide 53 text

fun ExtendedTheme( /* .. . * / content: @Composable () - > Unit ) { val extendedColors = ExtendedColors( tertiary = Color(0xFFA8EFF0), onTertiary = Color(0xFF002021) ) CompositionLocalProvider(LocalExtendedColors provides extendedColors) { MaterialTheme( /* colors = ... , typography = .. . , shapes = .. . */ content = content ) } } Extend Material

Slide 54

Slide 54 text

fun ExtendedTheme( /* .. . * / content: @Composable () - > Unit ) { val extendedColors = ExtendedColors( tertiary = Color(0xFFA8EFF0), onTertiary = Color(0xFF002021) ) CompositionLocalProvider(LocalExtendedColors provides extendedColors) { MaterialTheme( /* colors = ... , typography = .. . , shapes = .. . */ content = content ) } } Extend Material

Slide 55

Slide 55 text

fun ExtendedTheme( /* .. . * / content: @Composable () - > Unit ) { val extendedColors = ExtendedColors( tertiary = Color(0xFFA8EFF0), onTertiary = Color(0xFF002021) ) CompositionLocalProvider(LocalExtendedColors provides extendedColors) { MaterialTheme( /* colors = ... , typography = .. . , shapes = .. . */ content = content ) } } Extend Material

Slide 56

Slide 56 text

// Use with eg. ExtendedTheme.colors.tertiary object ExtendedTheme { val colors: ExtendedColors @Composable get() = LocalExtendedColors.current } tertiary = Color(0xFFA8EFF0),

Slide 57

Slide 57 text

object ExtendedTheme { fun ExtendedButton( onClick: () -> Unit, modifier: Modifier = Modifier, content: @Composable RowScope.() -> Unit ) { Button( colors = ButtonDefaults.buttonColors( backgroundColor = ExtendedTheme.colors.tertiary, contentColor = ExtendedTheme.colors.onTertiary /* Other colors use values from MaterialTheme */ ), onClick = onClick, modifier = modifier, content = content ) }

Slide 58

Slide 58 text

object ExtendedTheme { fun ExtendedButton( onClick: () -> Unit, modifier: Modifier = Modifier, content: @Composable RowScope.() -> Unit ) { Button( colors = ButtonDefaults.buttonColors( backgroundColor = ExtendedTheme.colors.tertiary, contentColor = ExtendedTheme.colors.onTertiary /* Other colors use values from MaterialTheme */ ), onClick = onClick, modifier = modifier, content = content ) }

Slide 59

Slide 59 text

object ExtendedTheme { fun ExtendedButton( onClick: () -> Unit, modifier: Modifier = Modifier, content: @Composable RowScope.() -> Unit ) { Button( colors = ButtonDefaults.buttonColors( backgroundColor = ExtendedTheme.colors.tertiary, contentColor = ExtendedTheme.colors.onTertiary /* Other colors use values from MaterialTheme */ ), onClick = onClick, modifier = modifier, content = content ) }

Slide 60

Slide 60 text

object ExtendedTheme { fun ExtendedButton( onClick: () -> Unit, modifier: Modifier = Modifier, content: @Composable RowScope.() -> Unit ) { Button( colors = ButtonDefaults.buttonColors( backgroundColor = ExtendedTheme.colors.tertiary, contentColor = ExtendedTheme.colors.onTertiary /* Other colors use values from MaterialTheme */ ), onClick = onClick, modifier = modifier, content = content ) }

Slide 61

Slide 61 text

object ExtendedTheme { fun ExtendedButton( onClick: () -> Unit, modifier: Modifier = Modifier, content: @Composable RowScope.() -> Unit ) { Button( colors = ButtonDefaults.buttonColors( backgroundColor = ExtendedTheme.colors.tertiary, contentColor = ExtendedTheme.colors.onTertiary /* Other colors use values from MaterialTheme */ ), onClick = onClick, modifier = modifier, content = content ) }

Slide 62

Slide 62 text

Customizing • Customize Material • Extend Material • Implement fully-custom design system Material Theme

Slide 63

Slide 63 text

Fully Custom

Slide 64

Slide 64 text

Fully Custom @Composable fun CustomTheme( /* .. . * / content: @Composable () - > Unit ) { val customColors = ... val customTypography = .. . val customElevation = CustomElevation( default = 4.dp, pressed = 8.dp ) CompositionLocalProvider( LocalCustomColors provides customColors, LocalCustomTypography provides customTypography, LocalCustomElevation provides customElevation, content = content ) }

Slide 65

Slide 65 text

Fully Custom @Composable fun CustomTheme( /* .. . * / content: @Composable () - > Unit ) { val customColors = ... val customTypography = .. . val customElevation = CustomElevation( default = 4.dp, pressed = 8.dp ) CompositionLocalProvider( LocalCustomColors provides customColors, LocalCustomTypography provides customTypography, LocalCustomElevation provides customElevation, content = content ) }

Slide 66

Slide 66 text

Fully Custom @Composable fun CustomTheme( /* .. . * / content: @Composable () - > Unit ) { val customColors = ... val customTypography = .. . val customElevation = CustomElevation( default = 4.dp, pressed = 8.dp ) CompositionLocalProvider( LocalCustomColors provides customColors, LocalCustomTypography provides customTypography, LocalCustomElevation provides customElevation, content = content ) }

Slide 67

Slide 67 text

@Composable fun CustomTheme( /* .. . * / content: @Composable () - > Unit ) { val customColors = ... val customTypography = .. . val customElevation = CustomElevation( default = 4.dp, pressed = 8.dp ) CompositionLocalProvider( LocalCustomColors provides customColors, LocalCustomTypography provides customTypography, LocalCustomElevation provides customElevation, content = content ) } Fully Custom

Slide 68

Slide 68 text

@Composable fun CustomTheme( /* .. . * / content: @Composable () - > Unit ) { val customColors = ... val customTypography = .. . val customElevation = CustomElevation( default = 4.dp, pressed = 8.dp ) CompositionLocalProvider( LocalCustomColors provides customColors, LocalCustomTypography provides customTypography, LocalCustomElevation provides customElevation, content = content ) } Fully Custom

Slide 69

Slide 69 text

@Composable fun CustomTheme( /* .. . * / content: @Composable () - > Unit ) { val customColors = ... val customTypography = .. . val customElevation = CustomElevation( default = 4.dp, pressed = 8.dp ) CompositionLocalProvider( LocalCustomColors provides customColors, LocalCustomTypography provides customTypography, LocalCustomElevation provides customElevation, content = content ) } Fully Custom

Slide 70

Slide 70 text

@Composable fun CustomButton( onClick: () -> Unit, modifier: Modifier = Modifier, content: @Composable RowScope.() -> Unit ) { Button( colors = ButtonDefaults.buttonColors( backgroundColor = CustomTheme.colors.component, contentColor = CustomTheme.colors.content, disabledBackgroundColor = CustomTheme.colors.content .copy(alpha = 0.12f) .compositeOver(CustomTheme.colors.component), disabledContentColor = CustomTheme.colors.content .copy(alpha = ContentAlpha.disabled) ), shape = ButtonShape, LocalCustomColors provides customColors,

Slide 71

Slide 71 text

.copy(alpha = 0.12f) .compositeOver(CustomTheme.colors.component), disabledContentColor = CustomTheme.colors.content .copy(alpha = ContentAlpha.disabled) ), shape = ButtonShape, elevation = ButtonDefaults.elevation( defaultElevation = CustomTheme.elevation.default, pressedElevation = CustomTheme.elevation.pressed ), onClick = onClick, modifier = modifier, content = { ProvideTextStyle( value = CustomTheme.typography.body ) { content() } } ) } Fully Custom

Slide 72

Slide 72 text

@Dropbox

Slide 73

Slide 73 text

Where we started • Already have design system • Color Tokens • Typography Tokens • Components

Slide 74

Slide 74 text

Goals • Get started fast • Easy to use (no cheat sheet) • Access to all of the existing Material composables • Use Compose while implementing design system • Incrementally migrate away from Material

Slide 75

Slide 75 text

• Customize Material • Extend Material • Implement fully-custom design system Customizing Material Theme

Slide 76

Slide 76 text

• Customize Material • Extend Material • Wrap Material • Implement fully-custom design system Customizing Material Theme

Slide 77

Slide 77 text

• Customize Material • Extend Material • Wrap Material • Implement fully-custom design system Customizing Material Theme

Slide 78

Slide 78 text

Wrap Material

Slide 79

Slide 79 text

@Stable class Colors( primary: Color, secondary: Color, accent: Color, buttonPrimaryHover: Color, buttonPrimaryActive: Color, … )

Slide 80

Slide 80 text

/** * Converts the Dig colors to Material colors, so that standard Material * composables use Dig colors out of the box. */ internal fun Colors.toMaterialColors(): MaterialColors = MaterialColors( primary = accent, primaryVariant = accent, secondary = accent, secondaryVariant = accent, background = standard.background, surface = standard.background, error = alert.text, onPrimary = if (isLight) secondary else standard.text, onSecondary = if (isLight) standard.text else secondary, onBackground = standard.text, onSurface = standard.text, onError = if (isLight) secondary else standard.text, isLight = isLight, ) Wrap Material

Slide 81

Slide 81 text

@Immutable data class Typography internal constructor( val titleLarge: TextStyle, val titleStandard: TextStyle, val titleSmall: TextStyle, val labelXLarge: TextStyle, … ) internal fun Typography.toMaterialTypography(): MaterialTypography = MaterialTypography(

Slide 82

Slide 82 text

val titleLarge: TextStyle, defaultFontFamily = DefaultFontFamily, h1 = titleLarge, h2 = titleLarge, h3 = titleLarge, h4 = titleLarge, h5 = titleStandard, h6 = titleStandard.copy(fontWeight = FontWeight.Medium), subtitle1 = paragraphLarge, subtitle2 = paragraphStandard, body1 = paragraphLarge, body2 = paragraphStandard, button = labelLarge.copy(fontWeight = FontWeight.Medium, lineHeight = 24.sp), caption = labelSmall, overline = labelXSmall, ) Wrap Material

Slide 83

Slide 83 text

Wrap Material @Composable fun DigTheme( typography: Typography = DigTheme.typography, colors: Colors = DigTheme.colors, content: @Composable () - > Unit ) { val rememberedColors = … CompositionLocalProvider( LocalColors provides rememberedColors, LocalTypography provides typography ) { MaterialTheme( colors = rememberedColors.toMaterialColors(), typography = typography.toMaterialTypography(), shapes = …, content = content ) } }

Slide 84

Slide 84 text

Wrap Material @Composable fun DigTheme( typography: Typography = DigTheme.typography, colors: Colors = DigTheme.colors, content: @Composable () - > Unit ) { val rememberedColors = … CompositionLocalProvider( LocalColors provides rememberedColors, LocalTypography provides typography ) { MaterialTheme( colors = rememberedColors.toMaterialColors(), typography = typography.toMaterialTypography(), shapes = …, content = content ) } }

Slide 85

Slide 85 text

Wrap Material @Composable fun DigTheme( typography: Typography = DigTheme.typography, colors: Colors = DigTheme.colors, content: @Composable () - > Unit ) { val rememberedColors = … CompositionLocalProvider( LocalColors provides rememberedColors, LocalTypography provides typography ) { MaterialTheme( colors = rememberedColors.toMaterialColors(), typography = typography.toMaterialTypography(), shapes = …, content = content ) } }

Slide 86

Slide 86 text

Wrap Material @Composable fun DigTheme( typography: Typography = DigTheme.typography, colors: Colors = DigTheme.colors, content: @Composable () - > Unit ) { val rememberedColors = … CompositionLocalProvider( LocalColors provides rememberedColors, LocalTypography provides typography ) { MaterialTheme( colors = rememberedColors.toMaterialColors(), typography = typography.toMaterialTypography(), shapes = …, content = content ) } }

Slide 87

Slide 87 text

Wrap Material @Composable fun DigTheme( typography: Typography = DigTheme.typography, colors: Colors = DigTheme.colors, content: @Composable () - > Unit ) { val rememberedColors = … CompositionLocalProvider( LocalColors provides rememberedColors, LocalTypography provides typography ) { MaterialTheme( colors = rememberedColors.toMaterialColors(), typography = typography.toMaterialTypography(), shapes = …, content = content ) } }

Slide 88

Slide 88 text

Wrap Material @Composable fun DigTheme( typography: Typography = DigTheme.typography, colors: Colors = DigTheme.colors, content: @Composable () - > Unit ) { val rememberedColors = … CompositionLocalProvider( LocalColors provides rememberedColors, LocalTypography provides typography ) { MaterialTheme( colors = rememberedColors.toMaterialColors(), typography = typography.toMaterialTypography(), shapes = …, content = content ) } }

Slide 89

Slide 89 text

Wrap Material @Composable fun DigTheme( typography: Typography = DigTheme.typography, colors: Colors = DigTheme.colors, content: @Composable () - > Unit ) { val rememberedColors = … CompositionLocalProvider( LocalColors provides rememberedColors, LocalTypography provides typography ) { MaterialTheme( colors = rememberedColors.toMaterialColors(), typography = typography.toMaterialTypography(), shapes = …, content = content ) } }

Slide 90

Slide 90 text

Wrap Material @Composable fun DigTheme( typography: Typography = DigTheme.typography, colors: Colors = DigTheme.colors, content: @Composable () - > Unit ) { val rememberedColors = … CompositionLocalProvider( LocalColors provides rememberedColors, LocalTypography provides typography ) { MaterialTheme( colors = rememberedColors.toMaterialColors(), typography = typography.toMaterialTypography(), shapes = …, content = content ) } }

Slide 91

Slide 91 text

Wrap Material DigTheme { }

Slide 92

Slide 92 text

Wrap Material DigTheme { Row { Button(onClick = { }) { Text("Button") } Button( onClick = { }, enabled = false ) { Text("Disabled") } } }

Slide 93

Slide 93 text

Wrap Material DigTheme { Row { Button(onClick = { }) { Text("Button") } Button( onClick = { }, enabled = false ) { Text("Disabled") } } }

Slide 94

Slide 94 text

Migration • Not all Material elements perform like we expect • Ex. TopAppBar uses accent color, we use surface color. • Mitigate by creating custom composables • Which implementation to use?

Slide 95

Slide 95 text

Migration Button() TextButton() OutlinedButton() FloatingActionButton() Switch() Checkbox() RadioButton() Text() TextField() LinearProgressIndicator() Card() Button() TextButton() OutlinedButton() FloatingActionButton() Switch() Checkbox() RadioButton() Text() TextField() LinearProgressIndicator() Card() TopAppBar() NavigationBar()

Slide 96

Slide 96 text

dependencies { api(libs.androidx.compose.ui) api(libs.androidx.compose.runtime) api(libs.androidx.compose.foundation) api(libs.androidx.compose.material) implementation(libs.androidx.activity.activity.compose) implementation(libs.androidx.compose.animation) implementation(libs.androidx.lifecycle.lifecycle.viewmodel.compose) implementation(libs.androidx.compose.ui.ui.tooling.preview) debugImplementation(libs.androidx.compose.ui.ui.tooling) } Migration

Slide 97

Slide 97 text

dependencies { api(libs.androidx.compose.ui) api(libs.androidx.compose.runtime) api(libs.androidx.compose.foundation) api(libs.androidx.compose.material) implementation(libs.androidx.activity.activity.compose) implementation(libs.androidx.compose.animation) implementation(libs.androidx.lifecycle.lifecycle.viewmodel.compose) implementation(libs.androidx.compose.ui.ui.tooling.preview) debugImplementation(libs.androidx.compose.ui.ui.tooling) } dependencies { api(libs.androidx.compose.ui) api(libs.androidx.compose.runtime) api(libs.androidx.compose.foundation) implementation(libs.androidx.compose.material) implementation(libs.androidx.activity.activity.compose) implementation(libs.androidx.compose.animation) implementation(libs.androidx.lifecycle.lifecycle.viewmodel.compose) implementation(libs.androidx.compose.ui.ui.tooling.preview) debugImplementation(libs.androidx.compose.ui.ui.tooling) } Migration

Slide 98

Slide 98 text

Progress Implement Theme Audit Components Remove Material

Slide 99

Slide 99 text

Progress Implement Theme Audit Components Remove Material Audit

Slide 100

Slide 100 text

Ryan Harter @RHARter Custom Design Systems in Jetpack Compose UI