Slide 1

Slide 1 text

How does the Relay connect Android app development and Design?
 ZOZO, Inc.
 Technology Division Technology Strategy Department CTO Section
 Ryosuke Horie Copyright © ZOZO, Inc. 1 2023/6/1 
 Recap: Google I/O 2023


Slide 2

Slide 2 text

© ZOZO, Inc. ZOZO, Inc.
 Technology Division 
 Technology Strategy Department
 CTO Section
 Ryosuke Horie
 2

Slide 3

Slide 3 text

© ZOZO, Inc. 3 https://io.google/2023/program/bac078a1-4c65-4566-b200-71e8cbe14601/

Slide 4

Slide 4 text

© ZOZO, Inc. 4 What is Relay?
 ● Figma to Composables


Slide 5

Slide 5 text

© ZOZO, Inc. 5 What is Relay?
 ● Easy to build apps with Figma's UI components


Slide 6

Slide 6 text

© ZOZO, Inc. 6 Relay workflow
 Figma Components

Slide 7

Slide 7 text

© ZOZO, Inc. 7 Relay workflow
 Figma Relay for Figma Plugin Components

Slide 8

Slide 8 text

© ZOZO, Inc. 8 Create UI Packages from Component with Relay Plugin


Slide 9

Slide 9 text

© ZOZO, Inc. 9 What is UI Packages?
 ● Intermediate representation of UI shared between Figma and Android Studio
 https://developer.android.com/jetpack/compose/tooling/relay/create-ui-packages

Slide 10

Slide 10 text

© ZOZO, Inc. 10 What is UI Packages?
 ● Intermediate representation of UI shared between Figma and Android Studio
 ● The UI package contains the following information:
 ○ Layout Information
 ○ UI Package Summary
 ○ Content and interaction parameters
 ○ Styling information
 ○ Font and image assets
 https://developer.android.com/jetpack/compose/tooling/relay/create-ui-packages

Slide 11

Slide 11 text

© ZOZO, Inc. 11 Relay workflow
 Figma Relay for Figma Plugin UI Packages Components

Slide 12

Slide 12 text

© ZOZO, Inc. 12 Relay workflow
 Figma Relay for Figma Plugin UI Packages Android Studio Relay for Android Studio Plugin Components Android Studio icon from: https://developer.android.com/studio

Slide 13

Slide 13 text

© ZOZO, Inc. ● UI Package is fetched by entering the Figma source URL
 13 Import UI Package with Relay for Android Studio Plugin
 
 


Slide 14

Slide 14 text

© ZOZO, Inc. ● UI Package is fetched by entering the Figma source URL
 ● Fetched UI Packages are placed under ui-packages
 14 Import UI Package with Relay for Android Studio Plugin
 
 


Slide 15

Slide 15 text

© ZOZO, Inc. 15 Relay workflow
 Figma Relay for Figma Plugin UI Packages Android Studio Relay for Android Studio Plugin Components Android Studio icon from: https://developer.android.com/studio

Slide 16

Slide 16 text

© ZOZO, Inc. 16 Relay workflow
 Figma Relay for Figma Plugin UI Packages Android Studio Relay for Android Studio Plugin Components Relay Gradle Plugin Android Studio icon from: https://developer.android.com/studio

Slide 17

Slide 17 text

© ZOZO, Inc. 17 Generate code from UI package with Relay Gradle Plugin
 
 
 
 
 ● Generate Composables in Android project build


Slide 18

Slide 18 text

© ZOZO, Inc. 18 Generate code from UI package with Relay Gradle Plugin
 
 
 
 
 ● Generate Composables in Android project build
 ● The following two gradle tasks are defined:
 ○ generateRelayCode
 ○ generateRelayRuntimeCode
 ● Perform these tasks if you only want to build UI packages


Slide 19

Slide 19 text

© ZOZO, Inc. 19 Relay workflow
 Figma Relay for Figma Plugin UI Packages Relay Gradle Plugin Relay for Android Studio Plugin Composables Components @Composable fun EventCard(modifier: Modifier = Modifier) { TopLevel(modifier = modifier) { Thumbnail() Title() Description() } } Android Studio Android Studio icon from: https://developer.android.com/studio

Slide 20

Slide 20 text

© ZOZO, Inc. 20 Relay workflow
 Figma Relay for Figma Plugin UI Packages Relay Gradle Plugin Relay for Android Studio Plugin Composables Components @Composable fun EventCard(modifier: Modifier = Modifier) { TopLevel(modifier = modifier) { Thumbnail() Title() Description() } } Android Studio Android Studio icon from: https://developer.android.com/studio

Slide 21

Slide 21 text

© ZOZO, Inc. 21 Make and propagate design updates


Slide 22

Slide 22 text

© ZOZO, Inc. 22 Make and propagate design updates
 ● Update design and save named version


Slide 23

Slide 23 text

© ZOZO, Inc. 23 Make and propagate design updates
 ● Update UI package in Android Studio
 ● Rebuild Android project to reflect updates


Slide 24

Slide 24 text

© ZOZO, Inc. 24 What should I do in these cases?


Slide 25

Slide 25 text

© ZOZO, Inc. 25 What should I do in these cases?
 ● Dynamically change text and images
 ● Handling Components with Multiple UI Patterns
 ● Handling clicks and other interactions


Slide 26

Slide 26 text

© ZOZO, Inc. 26 Content parameters


Slide 27

Slide 27 text

© ZOZO, Inc. 27 Content parameters
 ● Annotate where to parameterize the component


Slide 28

Slide 28 text

© ZOZO, Inc. 28 Content parameters
 ● UI package updated to include parameters


Slide 29

Slide 29 text

© ZOZO, Inc. 29 Content parameters
 ● Composable is generated to receive parameters


Slide 30

Slide 30 text

© ZOZO, Inc. 30 Handling Design Variants


Slide 31

Slide 31 text

© ZOZO, Inc. 31 Handling Design Variants
 ● Create Design Variants with Figma
 ● Relay can handle Variants
 ○ Switching Composables with enum


Slide 32

Slide 32 text

© ZOZO, Inc. 32 Handling Design Variants
 ● Switching Composable with enum
 // Design to select for EventComponents enum class View { EventCard, ListItem } /** * This composable was generated from the UI Package 'event_components'. * Generated code; do not edit directly */ @Composable fun EventComponents( modifier: Modifier = Modifier, view: View = View.EventCard ) { when (view) { View.EventCard -> TopLevelViewEventCard(modifier = modifier) { ThumbnailViewEventCard() TitleViewEventCard() DescriptionViewEventCard() } View.ListItem -> TopLevelViewListItem(modifier = modifier) { ThumbnailViewListItem() TextsViewListItem { TitleViewListItem() DescriptionViewListItem() OptionsViewListItem { OptionViewListItem() } } } }

Slide 33

Slide 33 text

© ZOZO, Inc. 33 Handling Design Variants
 ● Switching Composable with enum
 // Design to select for EventComponents enum class View { EventCard, ListItem } /** * This composable was generated from the UI Package 'event_components'. * Generated code; do not edit directly */ @Composable fun EventComponents( modifier: Modifier = Modifier, view: View = View.EventCard ) { when (view) { View.EventCard -> TopLevelViewEventCard(modifier = modifier) { ThumbnailViewEventCard() TitleViewEventCard() DescriptionViewEventCard() } View.ListItem -> TopLevelViewListItem(modifier = modifier) { ThumbnailViewListItem() TextsViewListItem { TitleViewListItem() DescriptionViewListItem() OptionsViewListItem { OptionViewListItem() } } } }

Slide 34

Slide 34 text

© ZOZO, Inc. 34 Handling Design Variants
 ● Switching Composable with enum
 // Design to select for EventComponents enum class View { EventCard, ListItem } /** * This composable was generated from the UI Package 'event_components'. * Generated code; do not edit directly */ @Composable fun EventComponents( modifier: Modifier = Modifier, view: View = View.EventCard ) { when (view) { View.EventCard -> TopLevelViewEventCard(modifier = modifier) { ThumbnailViewEventCard() TitleViewEventCard() DescriptionViewEventCard() } View.ListItem -> TopLevelViewListItem(modifier = modifier) { ThumbnailViewListItem() TextsViewListItem { TitleViewListItem() DescriptionViewListItem() OptionsViewListItem { OptionViewListItem() } } } }

Slide 35

Slide 35 text

© ZOZO, Inc. 35 Handling Design Variants
 ● Switching Composable with enum
 // Design to select for EventComponents enum class View { EventCard, ListItem } /** * This composable was generated from the UI Package 'event_components'. * Generated code; do not edit directly */ @Composable fun EventComponents( modifier: Modifier = Modifier, view: View = View.EventCard ) { when (view) { View.EventCard -> TopLevelViewEventCard(modifier = modifier) { ThumbnailViewEventCard() TitleViewEventCard() DescriptionViewEventCard() } View.ListItem -> TopLevelViewListItem(modifier = modifier) { ThumbnailViewListItem() TextsViewListItem { TitleViewListItem() DescriptionViewListItem() OptionsViewListItem { OptionViewListItem() } } } }

Slide 36

Slide 36 text

© ZOZO, Inc. 36 Content Parameters in Design Variants
 ● Add content parameters to entire Design Variants


Slide 37

Slide 37 text

© ZOZO, Inc. 37 /** * This composable was generated from the UI Package 'event_components'. * Generated code; do not edit directly * * @param thumbnail Event thumbnail image * @param title Event title * @param description Event description */ @Composable fun EventComponents( modifier: Modifier = Modifier, view: View = View.EventCard, thumbnail: Painter = EmptyPainter(), title: String = "", description: String = "" ) { when (view) { View.EventCard -> TopLevelViewEventCard(modifier = modifier) { ThumbnailViewEventCard(thumbnail = thumbnail) TitleViewEventCard(title = title) DescriptionViewEventCard(description = description) } View.ListItem -> TopLevelViewListItem(modifier = modifier) { ThumbnailViewListItem(thumbnail = thumbnail) TextsViewListItem { TitleViewListItem(title = title) DescriptionViewListItem(description = description) OptionsViewListItem { OptionViewListItem() } } } }

Slide 38

Slide 38 text

© ZOZO, Inc. 38 /** * This composable was generated from the UI Package 'event_components'. * Generated code; do not edit directly * * @param thumbnail Event thumbnail image * @param title Event title * @param description Event description */ @Composable fun EventComponents( modifier: Modifier = Modifier, view: View = View.EventCard, thumbnail: Painter = EmptyPainter(), title: String = "", description: String = "" ) { when (view) { View.EventCard -> TopLevelViewEventCard(modifier = modifier) { ThumbnailViewEventCard(thumbnail = thumbnail) TitleViewEventCard(title = title) DescriptionViewEventCard(description = description) } View.ListItem -> TopLevelViewListItem(modifier = modifier) { ThumbnailViewListItem(thumbnail = thumbnail) TextsViewListItem { TitleViewListItem(title = title) DescriptionViewListItem(description = description) OptionsViewListItem { OptionViewListItem() } } } }

Slide 39

Slide 39 text

© ZOZO, Inc. 39 Interaction Handlers


Slide 40

Slide 40 text

© ZOZO, Inc. 40 Interaction Handlers
 ● Add Interaction Handlers to entire Design Variants


Slide 41

Slide 41 text

© ZOZO, Inc. 41 @Composable fun EventComponents( modifier: Modifier = Modifier, view: View = View.EventCard, thumbnail: Painter = EmptyPainter(), title: String = "", description: String = "", onTapped: () -> Unit = {} ) { when (view) { View.EventCard -> TopLevelViewEventCard( onTapped = onTapped, modifier = modifier ) { ThumbnailViewEventCard(thumbnail = thumbnail) TitleViewEventCard(title = title) DescriptionViewEventCard(description = description) } View.ListItem -> TopLevelViewListItem( onTapped = onTapped, modifier = modifier ) { ThumbnailViewListItem(thumbnail = thumbnail) TextsViewListItem { TitleViewListItem(title = title) DescriptionViewListItem(description = description) OptionsViewListItem { OptionViewListItem() } } } } }

Slide 42

Slide 42 text

© ZOZO, Inc. 42 @Composable fun EventComponents( modifier: Modifier = Modifier, view: View = View.EventCard, thumbnail: Painter = EmptyPainter(), title: String = "", description: String = "", onTapped: () -> Unit = {} ) { when (view) { View.EventCard -> TopLevelViewEventCard( onTapped = onTapped, modifier = modifier ) { ThumbnailViewEventCard(thumbnail = thumbnail) TitleViewEventCard(title = title) DescriptionViewEventCard(description = description) } View.ListItem -> TopLevelViewListItem( onTapped = onTapped, modifier = modifier ) { ThumbnailViewListItem(thumbnail = thumbnail) TextsViewListItem { TitleViewListItem(title = title) DescriptionViewListItem(description = description) OptionsViewListItem { OptionViewListItem() } } } } }

Slide 43

Slide 43 text

© ZOZO, Inc. 43 Partially add Interaction Handlers
 ● Add interactions only for specific components


Slide 44

Slide 44 text

© ZOZO, Inc. 44 @Composable fun EventComponents( modifier: Modifier = Modifier, view: View = View.EventCard, thumbnail: Painter = EmptyPainter(), title: String = "", description: String = "", onTapped: () -> Unit = {}, onMenuTapped: () -> Unit = {} ) { when (view) { View.EventCard -> TopLevelViewEventCard( onTapped = onTapped, modifier = modifier ) { ThumbnailViewEventCard(thumbnail = thumbnail) TitleViewEventCard(title = title) DescriptionViewEventCard(description = description) } View.ListItem -> TopLevelViewListItem( onTapped = onTapped, modifier = modifier ) { ThumbnailViewListItem(thumbnail = thumbnail) TextsViewListItem { TitleViewListItem(title = title) DescriptionViewListItem(description = description) OptionsViewListItem { OptionViewListItem(onMenuTapped = onMenuTapped) } } } } }

Slide 45

Slide 45 text

© ZOZO, Inc. 45 @Composable fun EventComponents( modifier: Modifier = Modifier, view: View = View.EventCard, thumbnail: Painter = EmptyPainter(), title: String = "", description: String = "", onTapped: () -> Unit = {}, onMenuTapped: () -> Unit = {} ) { when (view) { View.EventCard -> TopLevelViewEventCard( onTapped = onTapped, modifier = modifier ) { ThumbnailViewEventCard(thumbnail = thumbnail) TitleViewEventCard(title = title) DescriptionViewEventCard(description = description) } View.ListItem -> TopLevelViewListItem( onTapped = onTapped, modifier = modifier ) { ThumbnailViewListItem(thumbnail = thumbnail) TextsViewListItem { TitleViewListItem(title = title) DescriptionViewListItem(description = description) OptionsViewListItem { OptionViewListItem(onMenuTapped = onMenuTapped) } } } } }

Slide 46

Slide 46 text

© ZOZO, Inc. 46 Add state and interaction
 ● UI package is stateless
 ● Wrap your generated package in a custom Composable function for state management
 ● For example, if the DropdownMenu is displayed by clicking on the menu


Slide 47

Slide 47 text

© ZOZO, Inc. 47 @Composable fun EventListItemController( event: Event, onTapped: () -> Unit, ) { var expanded by remember { mutableStateOf(false) } Box { EventComponents( … view = View.ListItem, onTapped = onTapped, onMenuTapped = { expanded = true } ) DropdownMenu( expanded = expanded, onDismissRequest = { expanded = false }, ) { DropdownMenuItem( text = { Text(text = "menu1") }, onClick = { /*TODO*/ } ) … } } }

Slide 48

Slide 48 text

© ZOZO, Inc. 48 @Composable fun EventListItemController( event: Event, onTapped: () -> Unit, ) { var expanded by remember { mutableStateOf(false) } Box { EventComponents( … view = View.ListItem, onTapped = onTapped, onMenuTapped = { expanded = true } ) DropdownMenu( expanded = expanded, onDismissRequest = { expanded = false }, ) { DropdownMenuItem( text = { Text(text = "menu1") }, onClick = { /*TODO*/ } ) … } } }

Slide 49

Slide 49 text

© ZOZO, Inc. 49 What should I do in these cases?
 ● Dynamically change text and images
 ● Handling Components with Multiple UI Patterns
 ● Handling clicks and other interactions


Slide 50

Slide 50 text

© ZOZO, Inc. 50 What should I do in these cases?
 ● Dynamically change text and images
 → Content Parameters
 ● Handling Components with Multiple UI Patterns
 → Switching in Design Variants
 ● Handling clicks and other interactions
 → Interaction Handlers


Slide 51

Slide 51 text

© ZOZO, Inc. 51

Slide 52

Slide 52 text

© ZOZO, Inc. 52 Other Features
 ● Mapping Figma’s Styles to Compose theme
 ● Mapping components to existing code


Slide 53

Slide 53 text

© ZOZO, Inc. 53 Pros & Cons
 ● Composables generated from design files are considered accurate
 ● Easy Android app development with UI package
 ● Need to design with the generated code in mind, for better or worse
 ● Roles of designers and engineers need to be reconsidered
 


Slide 54

Slide 54 text

© ZOZO, Inc. 54 Conclusion
 ● Design and Android app development are closely connected
 ● It is exciting to see Composable being generated from Figma!
 ○ This is an α release and I look forward to future updates
 ● A lot of thinking to ask into the development process, but much potential for productivity improvement.
 


Slide 55

Slide 55 text

© ZOZO, Inc. 55 How to study Relay?
 ● Watch “Build a complete app with Relay and Compose”
 ● Do Codelab
 ● Read the Android Developers documentation
 ● Hands on (good if you can do it with a designer)


Slide 56

Slide 56 text

No content