Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Andromeda - Jetpack Compose open source Design system

Andromeda - Jetpack Compose open source Design system

This talk emphasizes the thought process one can employ to build a design system, with Jetpack Compose - which gets even easier now.
It takes a huge investment to build a design system in-house which can get very time-consuming, and a team would need dedicated member/s of the team to always keep things updated, documented, and answer any questions that may arise during the development lifecycle.

This talk would introduce and explain the reasons and learnings from building a brand new library - Andromeda - an open-source design system with custom components and a customizable theme. This talk would focus on how to set up a custom theme with custom colors typography and what all goes into making a design system framework

Adit Lal

April 19, 2022
Tweet

More Decks by Adit Lal

Other Decks in Programming

Transcript

  1. Android GDE
 🛠 Individual Consultant
 🔊 Speaker
 🌎 Globe Trotter


    🍻 Beer enthusiast 🎯https:/ /androiddev.social/@aditlal 🔗aditlal.dev
  2. 12 Ingredients The famous nani’s recipe Oven of course Time

    and patience Assembly line Story and marketing Customer support Ever baked a cake?
  3. A design system is a collection of reusable components, guided

    by clear standards, that can be assembled together to build any number of applications. Design system
  4. Style Guide: Colours, Typography, Icons, Illustrations, etc Component Library: Buttons,

    Forms, Menu, Navigation, etc Content Guide: Principles, Common De fi nitions, Voice and Tone, etc Patterns Guide: User and Business Flows, etc Reference Site: Documentation and Best Practices to use it all correctly Design system
  5. Style Guide: Colours, Typography, Icons, Illustrations, etc Component Library: Buttons,

    Forms, Menu, Navigation, etc Content Guide: Principles, Common De fi nitions, Voice and Tone, etc Patterns Guide: User and Business Flows, etc Reference Site: Documentation and Best Practices to use it all correctly Design system
  6. 21 Design 
 System Design Guidelines Document Guidelines Design system

    No Guidelines Chaos 😱 No feedback loop Hard to edit Asset automation
 Feedback loop 🥳
  7. “A design system is a set of interconnected patterns and

    shared practices coherently organised.” “A design system is a collection of reusable components, guided by clear standards, that can be assembled together to build any number of applications.” Design system
  8. • Consistency • Higher quality • Faster builds, through reusable

    components and shared rationale. • Improved maintenance and scalability • Stronger focus on product - concentrate on solving user needs • More and better communication between teams Design system Pros
  9. Planners Can decide on UX fl ow decision faster Can

    focus on more business goals Design system
  10. Developers Can concentrate on the core logic Can improve UI

    ef fi ciently and consistently Can decrease the cost of QA Can reduce project size Design system
  11. Design system Common doubts "Won't it be too restricting?" "I

    won't be able to explore a new style” "What if something doesn't work?"
  12. Making a List Getting a buy-in Form a team Re

    fl ect back on your recent projects Audit and focus on pain points Components, Principles - de fi ne work fl ows Design system Preparing should be..
  13. Making a List Getting a buy-in Form a team Get

    people excited - may be not so straightforward Identify what’s the reward Do a 1-1 with the team - maybe? Look at other examples Run a quick case study Final Approvals Design system Preparing should be..
  14. Making a List Getting a buy-in Form a team Designers

    - de fi ne the visual components Front-end developers - Coders duh!! Product Managers - align with requirements, and set up necessary steps to help the team. Researchers - to discover user needs Quality Engineers - smooth tested system. Leaders - align the vision and allocate resources. Design system Preparing should be..
  15. • Always keep users’ expectations in mind and focus on

    patterns to build a clean design. • Clear primary task - Users want to USE an app if the design is simple yet effective, so make it clear. • Find the best middle ground! • Give enough controls Andromeda - Design Principles
  16. AndromedaTheme - defining the base theme @Composable fun AndromedaTheme( shapes:

    AndromedaShapes = DefaultShapes.default, fontFamily: FontFamily = AndromedaFonts, colors: AndromedaColors = AndromedaTheme.colors, typography: AndromedaTypography = textStyles(fontFamily = fontFamily), content: @Composable () - > Unit, ) { CompositionLocalProvider( LocalColors provides colors, LocalTypography provides typography, LocalShapes provides shapes, LocalContentEmphasis provides ContentEmphasis.Normal, ) { content() } }
  17. AndromedaTheme - defining the base theme @Composable fun AndromedaTheme( shapes:

    AndromedaShapes = DefaultShapes.default, fontFamily: FontFamily = AndromedaFonts, colors: AndromedaColors = AndromedaTheme.colors, typography: AndromedaTypography = textStyles(fontFamily = fontFamily), content: @Composable () - > Unit, ) { CompositionLocalProvider( LocalColors provides colors, LocalTypography provides typography, LocalShapes provides shapes, LocalContentEmphasis provides ContentEmphasis.Normal, ) { content() } }
  18. AndromedaTheme - defining the base theme @Composable fun AndromedaTheme( shapes:

    AndromedaShapes = DefaultShapes.default, fontFamily: FontFamily = AndromedaFonts, colors: AndromedaColors = AndromedaTheme.colors, typography: AndromedaTypography = textStyles(fontFamily = fontFamily), content: @Composable () - > Unit, ) { CompositionLocalProvider( LocalColors provides colors, LocalTypography provides typography, LocalShapes provides shapes, LocalContentEmphasis provides ContentEmphasis.Normal, ) { content() } }
  19. AndromedaTheme - important bits @Composable fun AndromedaTheme( shapes: AndromedaShapes =

    DefaultShapes.default, fontFamily: FontFamily = AndromedaFonts, colors: AndromedaColors = AndromedaTheme.colors, typography: AndromedaTypography = textStyles(fontFamily = fontFamily), content: @Composable () - > Unit, ) { CompositionLocalProvider( LocalColors provides colors, LocalTypography provides typography, LocalShapes provides shapes, LocalContentEmphasis provides ContentEmphasis.Normal, ) { content() } }
  20. AndromedaTheme object AndromedaTheme { public val colors: AndromedaColors @Composable @ReadOnlyComposable

    get() = LocalColors.current public val typography: AndromedaTypography @Composable @ReadOnlyComposable get() = LocalTypography.current public val shapes: AndromedaShapes @Composable @ReadOnlyComposable get() = LocalShapes.current }
  21. AndromedaTheme object AndromedaTheme { public val colors: AndromedaColors @Composable @ReadOnlyComposable

    get() = LocalColors.current public val typography: AndromedaTypography @Composable @ReadOnlyComposable get() = LocalTypography.current public val shapes: AndromedaShapes @Composable @ReadOnlyComposable get() = LocalShapes.current }
  22. Andromeda Foundation @Stable class AndromedaColors( val primaryColors: PrimaryColors, val secondaryColors:

    SecondaryColors, val tertiaryColors: TertiaryColors, val borderColors: BorderColors, val iconColors: IconColors, val contentColors: ContentColors, isDark: Boolean ) { var isDark: Boolean by mutableStateOf(isDark, structuralEqualityPolicy()) internal set fun copy( . . ) : AndromedaColors = AndromedaColors( . . ) } Colors
  23. Andromeda Foundation Colors @Stable class AndromedaColors( val primaryColors: PrimaryColors, val

    secondaryColors: SecondaryColors, val tertiaryColors: TertiaryColors, val borderColors: BorderColors, val iconColors: IconColors, val contentColors: ContentColors, isDark: Boolean ) { var isDark: Boolean by mutableStateOf(isDark, structuralEqualityPolicy()) internal set fun copy( . . ) : AndromedaColors = AndromedaColors( . . ) }
  24. Andromeda Foundation - Fill Colors import androidx.compose.ui.graphics.Color as ComposeColor interface

    FillColors { val background: ComposeColor val active: ComposeColor val error: ComposeColor val mute: ComposeColor val pressed: ComposeColor val alt: ComposeColor }
  25. Andromeda Foundation - Fill Colors import androidx.compose.ui.graphics.Color as ComposeColor interface

    FillColors { val background: ComposeColor val active: ComposeColor val error: ComposeColor val mute: ComposeColor val pressed: ComposeColor val alt: ComposeColor }
  26. Andromeda Foundation - Primary Fill Colors @Stable class PrimaryColors( background:

    ComposeColor, active: ComposeColor, error: ComposeColor, mute: ComposeColor, pressed: ComposeColor, alt: ComposeColor ) : FillColors { override var background: ComposeColor by mutableStateOf(background, structuralEqualityPolicy()) internal set override var active: ComposeColor by mutableStateOf(active, structuralEqualityPolicy()) internal set override var error: ComposeColor by mutableStateOf(error, structuralEqualityPolicy()) internal set override var mute: ComposeColor by mutableStateOf(mute, structuralEqualityPolicy()) internal set override var pressed: ComposeColor by mutableStateOf(pressed, structuralEqualityPolicy()) internal set override var alt: ComposeColor by mutableStateOf(alt, structuralEqualityPolicy()) internal set fun copy(…) }
  27. Andromeda Foundation - Primary Fill Colors @Stable class PrimaryColors( background:

    ComposeColor, active: ComposeColor, error: ComposeColor, mute: ComposeColor, pressed: ComposeColor, alt: ComposeColor ) : FillColors { override var background: ComposeColor by mutableStateOf(background, structuralEqualityPolicy()) internal set override var active: ComposeColor by mutableStateOf(active, structuralEqualityPolicy()) internal set override var error: ComposeColor by mutableStateOf(error, structuralEqualityPolicy()) internal set override var mute: ComposeColor by mutableStateOf(mute, structuralEqualityPolicy()) internal set override var pressed: ComposeColor by mutableStateOf(pressed, structuralEqualityPolicy()) internal set override var alt: ComposeColor by mutableStateOf(alt, structuralEqualityPolicy()) internal set fun copy(…) }
  28. Andromeda Foundation - Primary Fill Colors @Stable class PrimaryColors( background:

    ComposeColor, active: ComposeColor, error: ComposeColor, mute: ComposeColor, pressed: ComposeColor, alt: ComposeColor ) : FillColors { override var background: ComposeColor by mutableStateOf(background, structuralEqualityPolicy()) internal set override var active: ComposeColor by mutableStateOf(active, structuralEqualityPolicy()) internal set override var error: ComposeColor by mutableStateOf(error, structuralEqualityPolicy()) internal set override var mute: ComposeColor by mutableStateOf(mute, structuralEqualityPolicy()) internal set override var pressed: ComposeColor by mutableStateOf(pressed, structuralEqualityPolicy()) internal set override var alt: ComposeColor by mutableStateOf(alt, structuralEqualityPolicy()) internal set fun copy(…) }
  29. Andromeda Foundation - Secondary Colors @Stable class SecondaryColors( background: ComposeColor,

    active: ComposeColor, error: ComposeColor, mute: ComposeColor, pressed: ComposeColor, alt: ComposeColor ) : FillColors { override var background: ComposeColor by mutableStateOf(background, structuralEqualityPolicy()) internal set override var active: ComposeColor by mutableStateOf(active, structuralEqualityPolicy()) internal set override var error: ComposeColor by mutableStateOf(error, structuralEqualityPolicy()) internal set override var mute: ComposeColor by mutableStateOf(mute, structuralEqualityPolicy()) internal set override var pressed: ComposeColor by mutableStateOf(pressed, structuralEqualityPolicy()) internal set override var alt: ComposeColor by mutableStateOf(alt, structuralEqualityPolicy()) internal set fun copy() }
  30. Andromeda Foundation - Content Colors @Stable class ContentColors( normal: ComposeColor,

    minor: ComposeColor, subtle: ComposeColor, disabled: ComposeColor, ) { var normal: ComposeColor by mutableStateOf(normal, structuralEqualityPolicy()) internal set var minor: ComposeColor by mutableStateOf(minor, structuralEqualityPolicy()) internal set var subtle: ComposeColor by mutableStateOf(subtle, structuralEqualityPolicy()) internal set var disabled: ComposeColor by mutableStateOf(disabled, structuralEqualityPolicy()) internal set fun copy() : ContentColors }
  31. fun customLightColors( primaryColors: PrimaryColors = customPrimaryLightColors(), secondaryColors: SecondaryColors = customSecondaryLightColors(),

    tertiaryColors: TertiaryColors = customTertiaryLightColors(), borderColors: BorderColors = customBorderLightColors(), iconColors: IconColors = customtIconsLightColors(), contentColors: ContentColors = customContentLightColors() ) : AndromedaColors = AndromedaColors( primaryColors = primaryColors, secondaryColors = secondaryColors, tertiaryColors = tertiaryColors, borderColors = borderColors, iconColors = iconColors, contentColors = contentColors, isDark = false ) Andromeda Foundation - Colors
  32. fun customLightColors( primaryColors: PrimaryColors = customPrimaryLightColors(), secondaryColors: SecondaryColors = customSecondaryLightColors(),

    tertiaryColors: TertiaryColors = customTertiaryLightColors(), borderColors: BorderColors = customBorderLightColors(), iconColors: IconColors = customtIconsLightColors(), contentColors: ContentColors = customContentLightColors() ) : AndromedaColors = AndromedaColors( primaryColors = primaryColors, secondaryColors = secondaryColors, tertiaryColors = tertiaryColors, borderColors = borderColors, iconColors = iconColors, contentColors = contentColors, isDark = false ) Andromeda Foundation - Colors
  33. val AndromedaFonts = FontFamily( Font(R.font.andromeda_black, FontWeight.Black), Font(R.font.andromeda_bold, FontWeight.Bold), Font(R.font.andromeda_extrabold, FontWeight.ExtraBold),

    Font(R.font.andromeda_light, FontWeight.Light), Font(R.font.andromeda_medium, FontWeight.Medium), Font(R.font.andromeda_regular, FontWeight.W400), Font(R.font.andromeda_semibold, FontWeight.SemiBold), Font(R.font.andromeda_thin, FontWeight.Thin) ) Andromeda Foundation - Fonts
  34. /** * Contains all the typography we provide for our

    components. * * / class AndromedaTypography( val titleHeroTextStyle: TextStyle, val titleModerateBoldTextStyle: TextStyle, val titleModerateDemiTextStyle: TextStyle, val titleSmallDemiTextStyle: TextStyle, val bodyModerateDefaultTypographyStyle: TextStyle, val bodySmallDefaultTypographyStyle: TextStyle, val captionModerateBookDefaultTypographyStyle: TextStyle, val captionModerateDemiDefaultTypographyStyle: TextStyle ) Andromeda Foundation - Text Styles
  35. /** * Builds the default typography set for our theme.

    * * / @Composable fun textStyles(fontFamily: FontFamily) : AndromedaTypography { return AndromedaTypography( titleHeroTextStyle = TitleHeroTypographyStyle(fontFamily) .getComposeTextStyle(), titleModerateBoldTextStyle = TitleModerateBoldTypographyStyle(fontFamily) .getComposeTextStyle(), titleModerateDemiTextStyle = TitleModerateDemiTypographyStyle(fontFamily) .getComposeTextStyle(), titleSmallDemiTextStyle = TitleSmallDemiTypographyStyle(fontFamily) .getComposeTextStyle(), bodyModerateDefaultTypographyStyle = BodyModerateTypographyStyle(fontFamily) .getComposeTextStyle(), bodySmallDefaultTypographyStyle = BodySmallTypographyStyle(fontFamily) .getComposeTextStyle(), captionModerateBookDefaultTypographyStyle = CaptionModerateBookTypographyStyle(fontFamily) .getComposeTextStyle(), captionModerateDemiDefaultTypographyStyle = CaptionModerateDemiTypographyStyle(fontFamily) .getComposeTextStyle() ) } Andromeda Foundation - Text Styles
  36. /** * Builds the default typography set for our theme.

    * * / @Composable fun textStyles(fontFamily: FontFamily) : AndromedaTypography { return AndromedaTypography( titleHeroTextStyle = TitleHeroTypographyStyle(fontFamily) .getComposeTextStyle(), titleModerateBoldTextStyle = TitleModerateBoldTypographyStyle(fontFamily) .getComposeTextStyle(), titleModerateDemiTextStyle = TitleModerateDemiTypographyStyle(fontFamily) .getComposeTextStyle(), titleSmallDemiTextStyle = TitleSmallDemiTypographyStyle(fontFamily) .getComposeTextStyle(), bodyModerateDefaultTypographyStyle = BodyModerateTypographyStyle(fontFamily) .getComposeTextStyle(), bodySmallDefaultTypographyStyle = BodySmallTypographyStyle(fontFamily) .getComposeTextStyle(), captionModerateBookDefaultTypographyStyle = CaptionModerateBookTypographyStyle(fontFamily) .getComposeTextStyle(), captionModerateDemiDefaultTypographyStyle = CaptionModerateDemiTypographyStyle(fontFamily) .getComposeTextStyle() ) } Andromeda Foundation - Text Styles
  37. interface BaseTypography { val fontFamily: FontFamily val fontSize: TextUnit val

    fontWeight: FontWeight val lineHeight: TextUnit } Andromeda Foundation - Typography
  38. private fun toTextStyle(typographyStyle: BaseTypography) : TextStyle { return TextStyle( fontSize

    = typographyStyle.fontSize, fontFamily = typographyStyle.fontFamily, lineHeight = typographyStyle.lineHeight, fontWeight = typographyStyle.fontWeight, ) } fun BaseTypography.getComposeTextStyle() : TextStyle { return toTextStyle(this) } internal val LocalTypography = compositionLocalOf<AndromedaTypography> { error( "No typography provided! Make sure to wrap all usages of components in a " + "AndromedaTheme." ) } Andromeda Foundation - Text Styles
  39. private fun toTextStyle(typographyStyle: BaseTypography) : TextStyle { return TextStyle( fontSize

    = typographyStyle.fontSize, fontFamily = typographyStyle.fontFamily, lineHeight = typographyStyle.lineHeight, fontWeight = typographyStyle.fontWeight, ) } fun BaseTypography.getComposeTextStyle() : TextStyle { return toTextStyle(this) } internal val LocalTypography = compositionLocalOf<AndromedaTypography> { error( "No typography provided! Make sure to wrap all usages of components in a " + "AndromedaTheme." ) } Andromeda Foundation - Text Styles
  40. private fun toTextStyle(typographyStyle: BaseTypography) : TextStyle { return TextStyle( fontSize

    = typographyStyle.fontSize, fontFamily = typographyStyle.fontFamily, lineHeight = typographyStyle.lineHeight, fontWeight = typographyStyle.fontWeight, ) } fun BaseTypography.getComposeTextStyle() : TextStyle { return toTextStyle(this) } internal val LocalTypography = compositionLocalOf<AndromedaTypography> { error( "No typography provided! Make sure to wrap all usages of components in a " + "AndromedaTheme." ) } Andromeda Foundation - Text Styles
  41. private fun toTextStyle(typographyStyle: BaseTypography) : TextStyle { return TextStyle( fontSize

    = typographyStyle.fontSize, fontFamily = typographyStyle.fontFamily, lineHeight = typographyStyle.lineHeight, fontWeight = typographyStyle.fontWeight, ) } fun BaseTypography.getComposeTextStyle() : TextStyle { return toTextStyle(this) } internal val LocalTypography = compositionLocalOf<AndromedaTypography> { error( "No typography provided! Make sure to wrap all usages of components in a " + "AndromedaTheme." ) } Andromeda Foundation - Text Styles
  42. AndromedaTheme - typography provider /** * Useful static object to

    access currently conf i gured Theme properties. * / object AndromedaTheme { /** * These represent the default ease - of - use accessors for colors, typography. * * / public val colors: AndromedaColors @Composable @ReadOnlyComposable get() = LocalColors.current public val typography: AndromedaTypography @Composable @ReadOnlyComposable get() = LocalTypography.current public val shapes: AndromedaShapes @Composable @ReadOnlyComposable get() = LocalShapes.current }
  43. Icons @Composable public fun Icon( painter: Painter, contentDescription: String?, modif

    i er: Modif i er = Modif i er, onClick: IconClickHandler? = null, emphasis: ContentEmphasis = LocalContentEmphasis.current, tint: Color = AndromedaTheme.colors.contentColors.normal.applyEmphasis(emphasis), ) { val colorFilter = if (tint = = Color.Unspecif i ed) null else ColorFilter.tint(tint) val semantics = if (contentDescription ! = null) { Modif i er.semantics { this.contentDescription = contentDescription this.role = Role.Image } } else { Modif i er } val iconClickRipple = rememberRipple(
  44. Icons @Composable public fun Icon( painter: Painter, contentDescription: String?, modif

    i er: Modif i er = Modif i er, onClick: IconClickHandler? = null, emphasis: ContentEmphasis = LocalContentEmphasis.current, tint: Color = AndromedaTheme.colors.contentColors.normal.applyEmphasis(emphasis), ) { . . . } @Composable public fun Icon( painter: Painter, contentDescription: String?, modif onClick: IconClickHandler? = null, emphasis: ContentEmphasis = LocalContentEmphasis.current, tint: Color = AndromedaTheme.colors.contentColors.normal.applyEmphasis(emphasis), ) { val colorFilter = if (tint val semantics = if (contentDescription Modif this.contentDescription = contentDescription this.role = Role.Image } } else { Modif }
  45. Icons @Composable public fun Icon( painter: Painter, contentDescription: String?, modif

    i er: Modif i er = Modif i er, onClick: IconClickHandler? = null, emphasis: ContentEmphasis = LocalContentEmphasis.current, tint: Color = AndromedaTheme.colors.contentColors.normal.applyEmphasis(emphasis), ) { . . . }
  46. Icons @Composable public fun Icon( painter: Painter, contentDescription: String?, modif

    i er: Modif i er = Modif i er, onClick: IconClickHandler? = null, emphasis: ContentEmphasis = LocalContentEmphasis.current, tint: Color = AndromedaTheme.colors.contentColors.normal.applyEmphasis(emphasis), ) { . . . }
  47. Icons @Composable public fun Icon( . . ) { val

    colorFilter = if (tint = = Color.Unspecif i ed) null else ColorFilter.tint(tint) val semantics = if (contentDescription ! = null) { Modif i er.semantics { this.contentDescription = contentDescription this.role = Role.Image } } else { Modif i er } . . . }
  48. Icons @Composable public fun Icon( . . ) { val

    colorFilter = if (tint = = Color.Unspecif i ed) null else ColorFilter.tint(tint) val semantics = if (contentDescription ! = null) { Modif i er.semantics { this.contentDescription = contentDescription this.role = Role.Image } } else { Modif i er } . . . }
  49. Andromeda - Buttons Design and code synced reusable components 


    
 Bu tt ons are vital for almost every screen.
  50. Buttons @Composable fun Button( onClick: () - > Unit, modif

    i er: Modif i er = Modif i er, backgroundColor: ComposeColor = AndromedaTheme.colors.primaryColors.active, contentColor: ComposeColor = contentColorFor(backgroundColor = backgroundColor), interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }, elevation: ButtonElevation = ButtonDefaults.elevation(), shape: Shape = AndromedaTheme.shapes.small, border: BorderStroke? = null, contentPadding: PaddingValues = ButtonDefaults.ContentPadding, content: @Composable RowScope.() - > Unit ) { Surface( modif i er = modif i er, shape = shape, color = backgroundColor, contentColor = contentColor, border = border,
  51. Buttons @Composable fun Button( onClick: () - > Unit, modif

    i er: Modif i er = Modif i er, backgroundColor: ComposeColor = AndromedaTheme.colors.primaryColors.active, contentColor: ComposeColor = contentColorFor(backgroundColor = backgroundColor), interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }, elevation: ButtonElevation = ButtonDefaults.elevation(), shape: Shape = AndromedaTheme.shapes.small, border: BorderStroke? = null, contentPadding: PaddingValues = ButtonDefaults.ContentPadding, content: @Composable RowScope.() - > Unit ) { . . . } @Composable fun Button( onClick: () modif backgroundColor: ComposeColor = AndromedaTheme.colors.primaryColors.active, contentColor: ComposeColor = contentColorFor(backgroundColor = backgroundColor), interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }, elevation: ButtonElevation = ButtonDefaults.elevation(), shape: Shape = AndromedaTheme.shapes.small, border: BorderStroke? = null, contentPadding: PaddingValues = ButtonDefaults.ContentPadding, content: @Composable RowScope.() ) { Surface( modif shape = shape, color = backgroundColor, contentColor = contentColor, border = border,
  52. Buttons @Composable fun Button( onClick: () - > Unit, modif

    i er: Modif i er = Modif i er, backgroundColor: ComposeColor = AndromedaTheme.colors.primaryColors.active, contentColor: ComposeColor = contentColorFor(backgroundColor = backgroundColor), interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }, elevation: ButtonElevation = ButtonDefaults.elevation(), shape: Shape = AndromedaTheme.shapes.small, border: BorderStroke? = null, contentPadding: PaddingValues = ButtonDefaults.ContentPadding, content: @Composable RowScope.() - > Unit ) { . . . }
  53. ButtonsDefaults public object ButtonDefaults { private val ButtonHorizontalPadding = 16.dp

    private val ButtonVerticalPadding = 8.dp public val ContentPadding: PaddingValues = PaddingValues( horizontal = ButtonHorizontalPadding, vertical = ButtonVerticalPadding ) public val MinWidth: Dp = 64.dp public val MinHeight: Dp = 44.dp @Composable public fun elevation( defaultElevation: Dp = 2.dp,
  54. ButtonsDefaults private val ButtonHorizontalPadding = 16.dp private val ButtonVerticalPadding =

    8.dp public val ContentPadding: PaddingValues = PaddingValues( horizontal = ButtonHorizontalPadding, vertical = ButtonVerticalPadding ) public val MinWidth: Dp = 64.dp public val MinHeight: Dp = 44.dp @Composable public fun elevation( defaultElevation: Dp = 2.dp, pressedElevation: Dp = 8.dp, / / focused: Dp = 4.dp, / / hovered: Dp = 4.dp, disabledElevation: Dp = 0.dp ) : ButtonElevation { return remember(defaultElevation, pressedElevation, disabledElevation) { DefaultButtonElevation( defaultElevation = defaultElevation, pressedElevation = pressedElevation, disabledElevation = disabledElevation ) } } }
  55. Elevation @Stable interface ButtonElevation { /** * Contract to help

    build Button Elevation based on button's [enabled] and [interactionSource]. * * @param enabled - to decide if button is enabled. * @param interactionSource - [InteractionSource] for the given button. * / @Composable fun elevation(enabled: Boolean, interactionSource: InteractionSource) : State<Dp> }
  56. import androidx.compose.foundation.shape.CornerBasedShape import androidx.compose.ui.graphics.Shape interface BasicShapes { val small: CornerBasedShape

    val normal: CornerBasedShape val large: CornerBasedShape } interface AndromedaShapes : BasicShapes { val bottomSheet: Shape val buttonShape: Shape val dialogShape: Shape } Andromeda - Shapes
  57. public class DefaultShapes( override val bottomSheet: Shape, override val buttonShape:

    Shape, override val dialogShape: Shape, override val small: CornerBasedShape, override val normal: CornerBasedShape, override val large: CornerBasedShape, ) : AndromedaShapes { public companion object { public val default: AndromedaShapes = DefaultShapes( bottomSheet = RoundedCornerShape(topStart = 16.dp, topEnd = 16.dp), buttonShape = RoundedCornerShape(8.dp), dialogShape = RoundedCornerShape(8.dp), small = RoundedCornerShape(4.dp), normal = RoundedCornerShape(6.dp), large = RoundedCornerShape(12.dp), ) } } /** * Local providers for shapes in [AndromedaTheme]. * * / internal val LocalShapes = compositionLocalOf<AndromedaShapes> { error( "No shapes provided! Make sure to wrap all usages of Andromeda components in a " + "AndromedaTheme." ) } Andromeda - Shapes
  58. object AndromedaTheme { /** * These represent the default ease

    - of - use accessors for colors, typography. * * / public val colors: AndromedaColors @Composable @ReadOnlyComposable get() = LocalColors.current public val typography: AndromedaTypography @Composable @ReadOnlyComposable get() = LocalTypography.current public val shapes: AndromedaShapes @Composable @ReadOnlyComposable get() = LocalShapes.current } Andromeda - Shapes
  59. setContent { ProvideWindowInsets { var isLightTheme by remember { mutableStateOf(true)

    } CircularReveal( targetState = isLightTheme, animationSpec = tween(2500) ) { localTheme - > CatalogTheme(isLightTheme = localTheme) { NavGraph( onToggleTheme = { isLightTheme = !isLightTheme }, ) } } } } Andromeda - Result
  60. setContent { ProvideWindowInsets { var isLightTheme by remember { mutableStateOf(true)

    } CircularReveal( targetState = isLightTheme, animationSpec = tween(2500) ) { localTheme - > CatalogTheme(isLightTheme = localTheme) { NavGraph( onToggleTheme = { isLightTheme = !isLightTheme }, ) } } } } Andromeda - Result
  61. @Composable fun CatalogTheme( isLightTheme: Boolean = true, content: @Composable ()

    - > Unit ) { AndromedaTheme( colors = if (isLightTheme) defaultLightColors() else defaultDarkColors(), fontFamily = CatalogAppFonts ) { content() } } val CatalogAppFonts = FontFamily( Font(R.font.catalog_black, FontWeight.Black), Font(R.font.catalog_bold, FontWeight.Bold), Font(R.font.catalog_extrabold, FontWeight.ExtraBold), Font(R.font.catalog_extralight, FontWeight.Light), Font(R.font.catalog_medium, FontWeight.Medium), Font(R.font.catalog_regular, FontWeight.W400), Font(R.font.catalog_semibold, FontWeight.SemiBold), Font(R.font.catalog_thin, FontWeight.Thin) ) Andromeda - Custom Theme extended
  62. Check out https://github.com/aldefy/Andromeda 
 https://bit.ly/3Nic0JF - Sample catalog app 


    
 Andromeda is an open-source Jetpack Compose design system. A collection of guidelines and components can be used to create amazing compose app user experiences. Foundations introduce Andromeda tokens and principles while Components provide the bolts and nuts that make Andromeda Compose wrapped apps tick.
  63. 102 Tips Just do it Scope appropriately Iterate Make it

    usable Keep it lean Encourage whole-team ownership
  64. 103

  65. GOAT- http:/ /bit.ly/3FkrYjA https:/ /airbnb.design/ https:/ /www.kickstartds.com - Starter pack

    https:/ /mobile.ant.design/ https:/ /thedesignsystem.guide/ Examples