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

Kickstarting our Design System

Kickstarting our Design System

As your application, product and team rapidly develops and scales, you will undoubtedly have inconsistent UI components. It’s easy for developers and designers to create new elements that differ in really small specifications. This not only creates a bad branding experience, but also the feeling that there are several apps and styles inside the same app. In this talk, we will show you some design system fundamentals, how to properly map them to the Android framework and how you can build re-usable components on top of it. We will also tackle what are the biggest problems migrating to a design system from nothing, and how you should approach it. By the end of the talk, we just hope that you go and meet your designer and start developing your design system.

Fábio Carballo

September 19, 2019
Tweet

More Decks by Fábio Carballo

Other Decks in Technology

Transcript

  1. • Some Colours • Text Styles • A few Components

    • Not much Documentation • A lot of Colours • No Text Styles • Some Components • No Documentation • A lot of Colours • Text Styles • Some Components • Some Documentation iOS Android Design
  2. That one “Divider” Grey Is this the right grey? I

    thought it was this one? Yeah it should be the grey we used in that other screen :) Hmm, I was using this to be honest
  3. #1B1B1B &color-gray-11 #202020 &color-gray-13 #000000 &color-gray-0 #FFFFFF &color-gray-100 #747474 &color-gray-45

    #E6E6E6 &color-gray-90 #FBFBFB &color-gray-98 Name Value Visualization #2D2D2D &color-gray-18 #333333 &color-gray-20 #BFBFBF &color-gray-75 #2A7E6D &color-teal-49 Value Visualization Name
  4. Spacing Corner Radius Colors Typography Elevation Opacity <attr name="spacingNone" format="reference"

    /> <attr name="spacingTightest" format="reference" /> <attr name="spacingTighter" format="reference" /> <attr name="spacingTight" format="reference" /> <attr name="spacingDefault" format="reference" /> <attr name="spacingLoose" format="reference" /> <attr name="spacingLooser" format="reference" /> <attr name="spacingLoosest" format="reference" />
  5. Spacing Corner Radius Colors Typography Elevation Opacity <attr name="cornerRadiusHard" format="reference"

    /> <attr name="cornerRadiusSoft" format="reference" /> <attr name="cornerRadiusSmooth" format="reference" />
  6. Spacing Corner Radius Colors Typography Elevation Opacity <attr name="colorTypographyDefault" format="reference"

    /> <attr name="colorTypographyDefaultInverted" format="reference" /> <attr name="colorBackgroundDefault" format="reference" /> <attr name="colorBackgroundCard" format="reference" /> <attr name="colorIconographyDefault" format="reference" /> <attr name="colorDividerDefault" format="reference" />
  7. Spacing Corner Radius Colors Typography Elevation Opacity <attr name="colorTypographyDefault" format="reference"

    /> <attr name="colorTypographyDefaultInverted" format="reference" /> <attr name="colorBackgroundDefault" format="reference" /> <attr name="colorBackgroundCard" format="reference" /> <attr name="colorIconographyDefault" format="reference" /> <attr name="colorDividerDefault" format="reference" />
  8. Spacing Corner Radius Colors Typography Elevation Opacity <attr name="colorTypographyDefault" format="reference"

    /> <attr name="colorTypographyDefaultInverted" format="reference" /> <attr name="colorBackgroundDefault" format="reference" /> <attr name="colorBackgroundCard" format="reference" /> <attr name="colorIconographyDefault" format="reference" /> <attr name="colorDividerDefault" format="reference" />
  9. Spacing Corner Radius Colors Typography Elevation Opacity <attr name="colorTypographyDefault" format="reference"

    /> <attr name="colorTypographyDefaultInverted" format="reference" /> <attr name="colorBackgroundDefault" format="reference" /> <attr name="colorBackgroundCard" format="reference" /> <attr name="colorIconographyDefault" format="reference" /> <attr name="colorDividerDefault" format="reference" />
  10. Spacing Corner Radius Typography Elevation Opacity <style name="Nxd" /> <style

    name=“Nxd.BaseTheme" parent="Theme.MaterialComponents.Light.NoActionBar"> </style>
  11. Spacing <style name="Nxd" /> <style name=“Nxd.BaseTheme" parent="Theme.MaterialComponents.Light.NoActionBar"> <item name="spacingNone">@dimen/nxd_spacing_none</item> <item

    name="spacingTightest">@dimen/nxd_spacing_tightest</item> <item name="spacingTighter">@dimen/nxd_spacing_tighter</item> <item name="spacingTight">@dimen/nxd_spacing_tight</item> <item name="spacingDefault">@dimen/nxd_spacing_default</item> <item name="spacingLoose">@dimen/nxd_spacing_loose</item> <item name="spacingLooser">@dimen/nxd_spacing_looser</item> <item name="spacingLoosest">@dimen/nxd_spacing_loosest</item>
  12. Spacing <style name="Nxd" /> <style name=“Nxd.BaseTheme" parent="Theme.MaterialComponents.Light.NoActionBar"> <item name="spacingNone">@dimen/nxd_spacing_none</item> <item

    name="spacingTightest">@dimen/nxd_spacing_tightest</item> <item name="spacingTighter">@dimen/nxd_spacing_tighter</item> <item name="spacingTight">@dimen/nxd_spacing_tight</item> <item name="spacingDefault">@dimen/nxd_spacing_default</item> <item name="spacingLoose">@dimen/nxd_spacing_loose</item> <item name="spacingLooser">@dimen/nxd_spacing_looser</item> <item name="spacingLoosest">@dimen/nxd_spacing_loosest</item>
  13. <item name="spacingNone">@dimen/nxd_spacing_none</item> <item name="spacingTightest">@dimen/nxd_spacing_tightest</item> <item name="spacingTighter">@dimen/nxd_spacing_tighter</item> <item name="spacingTight">@dimen/nxd_spacing_tight</item> <item name="spacingDefault">16dp</item>

    <item name="spacingLoose">@dimen/nxd_spacing_loose</item> <item name="spacingLooser">@dimen/nxd_spacing_looser</item> <item name="spacingLoosest">@dimen/nxd_spacing_loosest</item> Spacing <style name="Nxd" /> <style name=“Nxd.BaseTheme" parent="Theme.MaterialComponents.Light.NoActionBar">
  14. Spacing <style name="Nxd" /> <style name=“Nxd.BaseTheme" parent="Theme.MaterialComponents.Light.NoActionBar"> <item name="spacingNone">0dp/item> <item

    name="spacingTightest">4dp</item> <item name="spacingTighter">8dp</item> <item name="spacingTight">12dp</item> <item name="spacingDefault">16dp</item> <item name="spacingLoose">24dp</item> <item name="spacingLooser">32dp</item> <item name="spacingLoosest">48dp</item>
  15. Spacing <style name="Nxd" /> <style name=“Nxd.BaseTheme" parent="Theme.MaterialComponents.Light.NoActionBar"> Corner Radius <item

    name="cornerRadiusHard">@dimen/nxd_corner_radius_hard</item> <item name="cornerRadiusSoft">@dimen/nxd_corner_radius_soft</item> <item name="cornerRadiusSmooth">@dimen/nxd_corner_radius_smooth</item> <item name="spacingNone">0dp/item> <item name="spacingTightest">4dp</item> <item name="spacingTighter">8dp</item> <item name="spacingTight">12dp</item> <item name="spacingDefault">16dp</item> <item name="spacingLoose">24dp</item> <item name="spacingLooser">32dp</item> <item name="spacingLoosest">48dp</item>
  16. Spacing Corner Radius <item name="cornerRadiusHard">@dimen/nxd_corner_radius_hard</item> <item name="cornerRadiusSoft">@dimen/nxd_corner_radius_soft</item> <item name="cornerRadiusSmooth">@dimen/nxd_corner_radius_smooth</item> <item

    name="spacingTighter">8dp</item> <item name="spacingTight">12dp</item> <item name="spacingDefault">16dp</item> <item name="spacingLoose">24dp</item> <item name="spacingLooser">32dp</item> <item name="spacingLoosest">48dp</item> Opacity <item name=“opacityOpaque">@dimen/nxd_op_opaque</item> <item name=“opacityQuarterTransparent”>@dimen/nxd_op_quarter_transparent</item> <item name=“opacitySemiTransparent">@dimen/nxd_op_semi_transparent</item> <item name="opacityThreeQuarterTransparent">@dimen/nxd_op_tq_transparent</item> <item name=“opacityTransparent">@dimen/nxd_op_transparent</item> </style>
  17. <item name=“opacityTransparent">@dimen/nxd_op_transparent</item> </style> Introducing … Bright Mode! <style name="Nxd.BaseTheme.Bright"> <item

    name="colorTypographyDefault">@color/grey_11</item> <item name="colorTypographyDefaultInverted">@color/grey_100</item> <item name="colorBackgroundDefault">@color/grey_100</item> <item name="colorBackgroundCard">@color/grey_100</item> <item name="colorIconographyDefault">@color/grey_11</item> <item name="colorDividerDefault">@color/grey_90</item> Colors
  18. <style name="Nxd.BaseTheme.Bright"> <item name="colorTypographyDefault">@color/grey_11</item> <item name="colorTypographyDefaultInverted">@color/grey_100</item> <item name="colorBackgroundDefault">@color/grey_100</item> <item name="colorBackgroundCard">@color/grey_100</item>

    <item name="colorIconographyDefault">@color/grey_11</item> <item name="colorDividerDefault">@color/grey_90</item> <style name="Nxd.BaseTheme.Dark" /> <item name="colorTypographyDefault">@color/grey_100</item> <item name="colorTypographyDefaultInverted">@color/grey_11</item> <item name="colorBackgroundDefault">@color/grey_18</item> <item name="colorBackgroundCard">@color/grey_13</item> <item name="colorIconographyDefault">@color/grey_100</item> <item name="colorDividerDefault">@color/grey_20</item>
  19. How to use our theme attributes? XML spacingNone spacingDefault spacingTight

    spacingTightest spacingLoose spacingLoosest <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin=" "/>
  20. How to use our theme attributes? XML spacingNone spacingDefault spacingTight

    spacingTightest spacingLoose spacingLoosest <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin=" "/>
  21. How to use our theme attributes? XML spacingNone spacingDefault spacingTight

    spacingTightest spacingLoose spacingLoosest <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin=" "/> ?attr/
  22. How to use our theme attributes? XML spacingDefault <TextView android:layout_width="wrap_content"

    android:layout_height="wrap_content" android:layout_margin=" "/> ?attr/
  23. How to use our theme attributes? Programatically @AnyRes private fun

    Context.themeResourceId(@AttrRes attrRes: Int, expectedResourceType: String): Int { } val typedValue = TypedValue() theme.resolveAttribute(attrRes, typedValue, true) val resId = typedValue.resourceId val resourceType = resources.getResourceTypeName(resId) if (expectedResourceType != resourceType) { val attributeName = resources.getResourceName(attrRes) throw IllegalArgumentException("No resource found with the given type .......") } return resId
  24. How to use our theme attributes? @AnyRes private fun Context.themeResourceId(@AttrRes

    attrRes: Int, expectedResourceType: String): Int { } Programatically val typedValue = TypedValue() theme.resolveAttribute(attrRes, typedValue, true) val resId = typedValue.resourceId val resourceType = resources.getResourceTypeName(resId) if (expectedResourceType != resourceType) { val attributeName = resources.getResourceName(attrRes) throw IllegalArgumentException("No resource found with the given type .......") } return resId
  25. How to use our theme attributes? @AnyRes private fun Context.themeResourceId(@AttrRes

    attrRes: Int, expectedResourceType: String): Int { } Programatically val typedValue = TypedValue() theme.resolveAttribute(attrRes, typedValue, true) val resId = typedValue.resourceId val resourceType = resources.getResourceTypeName(resId) if (expectedResourceType != resourceType) { val attributeName = resources.getResourceName(attrRes) throw IllegalArgumentException("No resource found with the given type .......") } return resId
  26. How to use our theme attributes? @AnyRes private fun Context.themeResourceId(@AttrRes

    attrRes: Int, expectedResourceType: String): Int { } Programatically val typedValue = TypedValue() theme.resolveAttribute(attrRes, typedValue, true) val resId = typedValue.resourceId val resourceType = resources.getResourceTypeName(resId) if (expectedResourceType != resourceType) { val attributeName = resources.getResourceName(attrRes) throw IllegalArgumentException("No resource found with the given type .......") } return resId
  27. How to use our theme attributes? @AnyRes private fun Context.themeResourceId(@AttrRes

    attrRes: Int, expectedResourceType: String): Int { } Programatically val typedValue = TypedValue() theme.resolveAttribute(attrRes, typedValue, true) val resId = typedValue.resourceId val resourceType = resources.getResourceTypeName(resId) if (expectedResourceType != resourceType) { val attributeName = resources.getResourceName(attrRes) throw IllegalArgumentException("No resource found with the given type .......") } return resId
  28. How to use our theme attributes? @AnyRes private fun Context.themeResourceId(@AttrRes

    attrRes: Int, expectedResourceType: String): Int { } Programatically val typedValue = TypedValue() theme.resolveAttribute(attrRes, typedValue, true) val resId = typedValue.resourceId val resourceType = resources.getResourceTypeName(resId) if (expectedResourceType != resourceType) { val attributeName = resources.getResourceName(attrRes) throw IllegalArgumentException("No resource found with the given type .......") } return resId
  29. How to use our theme attributes? Programatically @ColorRes fun Context.themeColorResId(@AttrRes

    attrRes: Int) = themeResourceId(attrRes, "color") // Example val colorResId = context.themeColorResId(R.attr.colorBackgroundDefault)
  30. How to use our theme attributes? Programatically fun Context.themeDimensionPixelSize(@AttrRes attrRes:

    Int) = resources.getDimensionPixelSize(themeResourceId(attrRes, "dimen"))
  31. How to use our theme attributes? Programatically fun Context.themeDimensionPixelSize(@AttrRes attrRes:

    Int) = resources.getDimensionPixelSize(themeResourceId(attrRes, "dimen"))
  32. How to use our theme attributes? Programatically fun Context.themeDimensionPixelSize(@AttrRes attrRes:

    Int) = resources.getDimensionPixelSize(themeResourceId(attrRes, "dimen")) val defaultPadding = context.themeDimensionPixelSize(R.attr.spacingDefault) setPadding(defaultPadding, 0, defaultPadding 0)
  33. How to use our theme attributes? Programatically fun Context.themeDimensionPixelSize(@AttrRes attrRes:

    Int) = resources.getDimensionPixelSize(themeResourceId(attrRes, "dimen")) val defaultPadding = context.themeDimensionPixelSize(R.attr.spacingDefault) setPadding(defaultPadding, 0, defaultPadding 0)
  34. Building Components class TransactionContainer: FrameLayout { fun bind(viewEntity: ViewEntity) {

    title = viewEntity.title subtitle = viewEntity.title amount.bind(AmountViewEntity(amount, currency)) setOnClickListener { clickAction() } } data class ViewEntity( val title: String, val subtitle: String, val amount: Money, val currency: Currency, val clickAction: () -> Unit) }
  35. Building Components class TransactionContainer: FrameLayout { fun bind(viewEntity: ViewEntity) {

    title = viewEntity.title subtitle = viewEntity.title amount.bind(AmountViewEntity(amount, currency)) setOnClickListener { clickAction() } } data class ViewEntity( val title: String, val subtitle: String, val amount: Money, val currency: Currency, val clickAction: () -> Unit) }
  36. Building Components class TransactionContainer: FrameLayout { fun bind(viewEntity: ViewEntity) {

    title = viewEntity.title subtitle = viewEntity.title amount.bind(AmountViewEntity(amount, currency)) setOnClickListener { clickAction() } } data class ViewEntity( val title: String, val subtitle: String, val amount: Money, val currency: Currency, val clickAction: () -> Unit) }
  37. val color = context.themeColor(R.attr.colorTypographyInteractive) <TextView android:textColor="?attr/colorTypographyInteractive" /> Static Analysis Migration

    Detekt Lint val color = context.getColor(R.color.nxd_teal_91) <TextView android:textColor=“@color/nxd_teal_91" />
  38. TransactionContainer ViewEntity SectionHeader ViewEntity SubSectionHeader ViewEntity ButtonContainer ViewEntity InfoCard ViewEntity

    RecyclerView NXDRecyclerView Adapter System Level ViewEntity to ViewHolder/Binder TransactionContainer ViewHolder/Binder SectionHeader ViewHolder/Binder SubSectionHeader ViewHolder/Binder ButtonContainer ViewHolder/Binder InfoCard ViewHolder/Binder
  39. TransactionContainerViewEntity( "From Main Account", " to Home", Money(BigDecimal(5), Euro)), TransactionContainerViewEntity(

    "From Main Account", "Last one ... ", Money(BigDecimal(4.50), Euro)), TransactionContainerViewEntity( "From Main Account", "Just one more ", Money(BigDecimal(5), Euro)), TransactionContainerViewEntity( "From Main Account", "Money for drinks!", Money(BigDecimal(5), Euro)))) SectionHeaderViewEntity("Transactions"), listOf( SubSectionHeaderViewEntity(“Today”),
  40. Server elements: [ { type: “sectionHeader”, ... }, { type:

    “subSectionHeader”, ... }, { type: "transaction", ... }, { type: “transaction", ... } ] App
  41. Server elements: [ { type: “sectionHeader”, ... }, { type:

    “subSectionHeader”, ... }, { type: "transaction", ... }, { type: “transaction", ... } ] App Transformer Transaction ViewEntity SubSectionHeader ViewEntity SectionHeader ViewEntity RecyclerView
  42. Feature Design Conceptualisation Does the design contain a new component

    that is not in NXD? Check the NXD Glossary App and look for conceptually similar components Can the new component be replaced with something that exists in NXD? Create proposal for why we need the new component inline with the NXD contribution guidelines Submit Proposal Replace Component No Action Required YES NO YES NO