Skip to content

[WIP] Migrate Design System components in Jetsnack to use Styles#1669

Draft
riggaroo wants to merge 2 commits intomainfrom
feature/styles
Draft

[WIP] Migrate Design System components in Jetsnack to use Styles#1669
riggaroo wants to merge 2 commits intomainfrom
feature/styles

Conversation

@riggaroo
Copy link
Collaborator

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request begins the significant architectural shift in the Jetsnack application by migrating its custom Design System components to leverage the new Compose Styles API. This change aims to streamline UI development, improve maintainability, and provide a more robust and flexible styling mechanism for various UI elements, laying the groundwork for a more scalable design system implementation.

Highlights

  • Migration to Compose Styles API: Initiated the migration of Design System components in Jetsnack to utilize the new Compose Styles API, centralizing styling definitions and improving consistency across UI elements.
  • Introduction of JetsnackText: A new JetsnackText composable was introduced to wrap BasicText and apply styling via the Style API, specifically addressing a known issue where textStyle alone doesn't set fontFamily correctly.
  • Refactored Core UI Components: Key UI components such as JetsnackButton, JetsnackCard, JetsnackDivider, and JetsnackSurface have been refactored to accept and apply styling through the Style API, reducing boilerplate and enhancing customization.
  • Centralized App Styles: A new AppStyles data class and LocalAppStyles CompositionLocal were added to JetsnackTheme, providing a centralized location for defining and accessing application-wide component styles.
  • Experimental API Opt-in: The project now opts into ExperimentalFoundationStyleApi to enable the use of the new Compose Styles API features.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Changelog
  • Jetsnack/app/build.gradle.kts
    • Added opt-in for ExperimentalFoundationStyleApi to the Kotlin compiler arguments.
  • Jetsnack/app/src/main/java/androidx/compose/material3/CompositionLocals.kt
    • Added CompositionLocals.kt to reflect internal Material 3 theming locals (LocalShapes, LocalColorScheme, LocalTypography) using reflection as a temporary workaround.
  • Jetsnack/app/src/main/java/com/example/jetsnack/ui/components/Button.kt
    • Refactored JetsnackButton to use the Style API, removing direct styling parameters like shape, border, backgroundGradient, contentColor, and contentPadding.
    • Replaced Text composables with JetsnackText.
  • Jetsnack/app/src/main/java/com/example/jetsnack/ui/components/Card.kt
    • Refactored JetsnackCard to use the Style API, removing direct styling parameters like shape, color, contentColor, border, and elevation.
    • Replaced Text composables with JetsnackText.
  • Jetsnack/app/src/main/java/com/example/jetsnack/ui/components/Divider.kt
    • Refactored JetsnackDivider to use the Style API for background, height, and fillWidth.
    • Removed the DividerAlpha constant.
  • Jetsnack/app/src/main/java/com/example/jetsnack/ui/components/Filters.kt
    • Opted into ExperimentalFoundationStyleApi.
    • Refactored FilterChip to use the Style API for shape, background, contentColor, and border, including animated states for pressed and selected.
    • Replaced Text composables with JetsnackText.
  • Jetsnack/app/src/main/java/com/example/jetsnack/ui/components/Gradient.kt
    • Removed animateColorAsState and composed imports.
    • Renamed diagonalGradientTint to contentTintDiagonalGradient.
    • Removed the fadeInDiagonalGradientBorder extension function.
  • Jetsnack/app/src/main/java/com/example/jetsnack/ui/components/GradientTintedIconButton.kt
    • Opted into ExperimentalFoundationStyleApi.
    • Refactored JetsnackGradientTintedIconButton to use the Style API for shape, clip, border, background, and pressed states.
    • Maintained contentTintDiagonalGradient for blend mode functionality due to current Style API limitations.
  • Jetsnack/app/src/main/java/com/example/jetsnack/ui/components/QuantitySelector.kt
    • Opted into ExperimentalFoundationStyleApi.
    • Replaced Text composables with JetsnackText and applied styling via the Style API for textStyle, contentColor, fontWeight, fontSize, and textAlign.
  • Jetsnack/app/src/main/java/com/example/jetsnack/ui/components/Snacks.kt
    • Opted into ExperimentalFoundationStyleApi.
    • Replaced Text composables with JetsnackText and applied styling via the Style API for textStyle and contentColor.
    • Updated SnackItem and HighlightSnackItem to use the Style API for shape.
  • Jetsnack/app/src/main/java/com/example/jetsnack/ui/components/Surface.kt
    • Opted into ExperimentalFoundationStyleApi.
    • Refactored JetsnackSurface to use the Style API, removing direct styling parameters and delegating styling to JetsnackTheme.appStyles.surfaceStyle.
    • Commented out old getBackgroundColorForElevation and Color.withElevation helper functions.
  • Jetsnack/app/src/main/java/com/example/jetsnack/ui/components/Text.kt
    • Added new file Text.kt.
    • Introduced JetsnackText composable, a wrapper around BasicText that applies styling using the Style API.
    • Added jetsnackTextStyle extension function to StyleScope to correctly apply TextStyle and fontFamily.
  • Jetsnack/app/src/main/java/com/example/jetsnack/ui/home/DestinationBar.kt
    • Opted into ExperimentalFoundationStyleApi.
    • Replaced Text composables with JetsnackText and applied styling via the Style API for textStyle, contentColor, and textAlign.
    • Updated LocalLocale usage to LocalLocale.current.platformLocale.
  • Jetsnack/app/src/main/java/com/example/jetsnack/ui/home/Feed.kt
    • Updated JetsnackDivider to use the Style API for setting thickness.
  • Jetsnack/app/src/main/java/com/example/jetsnack/ui/home/FilterScreen.kt
    • Replaced Text composables with JetsnackText and applied styling via the Style API for textStyle, textAlign, fontWeight, and contentColor.
  • Jetsnack/app/src/main/java/com/example/jetsnack/ui/home/Home.kt
    • Updated JetsnackSurface to use the Style API for background and contentColor.
    • Updated LocalLocale usage to LocalLocale.current.platformLocale.
    • Replaced Text composables with JetsnackText and applied styling via the Style API for contentColor and textStyle.
  • Jetsnack/app/src/main/java/com/example/jetsnack/ui/home/Profile.kt
    • Replaced Text composables with JetsnackText and applied styling via the Style API for textStyle and textAlign.
  • Jetsnack/app/src/main/java/com/example/jetsnack/ui/home/cart/Cart.kt
    • Replaced Text composables with JetsnackText and applied styling via the Style API for textStyle, contentColor, and textAlign.
    • Updated LocalContext.current.resources to LocalResources.current.
    • Updated JetsnackButton to use the Style API for shape and contentPadding.
  • Jetsnack/app/src/main/java/com/example/jetsnack/ui/home/search/Categories.kt
    • Replaced Text composables with JetsnackText and applied styling via the Style API for textStyle and contentColor.
  • Jetsnack/app/src/main/java/com/example/jetsnack/ui/home/search/Results.kt
    • Replaced Text composables with JetsnackText and applied styling via the Style API for textStyle and contentColor.
    • Updated JetsnackButton to use the Style API for shape and contentPadding.
  • Jetsnack/app/src/main/java/com/example/jetsnack/ui/home/search/Search.kt
    • Updated JetsnackSurface to use the Style API for background, contentColor, and shape.
    • Replaced Text composables with JetsnackText and applied styling via the Style API for contentColor.
  • Jetsnack/app/src/main/java/com/example/jetsnack/ui/home/search/Suggestions.kt
    • Replaced Text composables with JetsnackText and applied styling via the Style API for textStyle and contentColor.
  • Jetsnack/app/src/main/java/com/example/jetsnack/ui/snackdetail/SnackDetail.kt
    • Replaced Text composables with JetsnackText and applied styling via the Style API for textStyle, contentColor, fontStyle, fontSize, textAlign, contentPaddingHorizontal, contentPaddingTop, and fillWidth.
  • Jetsnack/app/src/main/java/com/example/jetsnack/ui/theme/Styles.kt
    • Added new file Styles.kt.
    • Defined AppStyles data class containing Style definitions for buttonStyle, cardStyle, dividerStyle, gradientIconButtonStyle, filterChipStyle, defaultTextStyle, and surfaceStyle.
    • Used LocalJetsnackColors, LocalShapes, LocalTypography, and LocalTextStyle within AppStyles for theme integration.
  • Jetsnack/app/src/main/java/com/example/jetsnack/ui/theme/Theme.kt
    • Opted into ExperimentalFoundationStyleApi.
    • Integrated AppStyles into JetsnackTheme by creating an instance and providing it via CompositionLocalProvider.
    • Exposed LocalAppStyles through the JetsnackTheme object.
  • Jetsnack/gradle/libs.versions.toml
    • Updated androidx-compose-foundation version to 1.11.0-beta01.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@riggaroo riggaroo marked this pull request as draft March 13, 2026 18:22
Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request refactors various UI components (Button, Card, Divider, FilterChip, GradientTintedIconButton, QuantitySelector, Snack-related components, and Surface) in the Jetsnack app to adopt a new experimental Compose Foundation Style API. This involves introducing a Style parameter to these components and migrating their visual properties (like shape, background, content color, padding, and text styles) into Style objects. A new JetsnackText composable is introduced to facilitate text styling within this system. Additionally, a temporary CompositionLocals.kt file is added to access internal Material 3 theming locals via reflection, and AppStyles is introduced to centralize default styles. Review comments highlight critical issues where StyleScope functions like contentPaddingHorizontal, contentPaddingTop, and fillWidth are incorrectly used, leading to compilation errors. There's also a high-severity concern regarding the use of reflection for internal Material 3 APIs, which is brittle, and a suggestion to use more specific exception handling. Finally, an issue with ButtonDefaults.ContentPadding.calculateTopPadding() being incorrectly passed to contentPadding is noted.

Comment on lines +312 to +316
style = {
jetsnackTextStyle(LocalTypography.currentValue.headlineMedium)
contentColor(LocalJetsnackColors.currentValue.textHelp)
contentPaddingHorizontal(24.dp)
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

The function contentPaddingHorizontal is not a valid function on StyleScope. This will cause a compilation error. You should use the contentPadding function with named arguments.

Suggested change
style = {
jetsnackTextStyle(LocalTypography.currentValue.headlineMedium)
contentColor(LocalJetsnackColors.currentValue.textHelp)
contentPaddingHorizontal(24.dp)
}
style = {
jetsnackTextStyle(LocalTypography.currentValue.headlineMedium)
contentColor(LocalJetsnackColors.currentValue.textHelp)
contentPadding(horizontal = 24.dp)
}

Comment on lines +323 to +327
style = {
jetsnackTextStyle(LocalTypography.currentValue.bodyLarge)
contentColor(LocalJetsnackColors.currentValue.textHelp)
contentPaddingHorizontal(24.dp)
},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

The function contentPaddingHorizontal is not a valid function on StyleScope. This will cause a compilation error. You should use the contentPadding function with named arguments.

Suggested change
style = {
jetsnackTextStyle(LocalTypography.currentValue.bodyLarge)
contentColor(LocalJetsnackColors.currentValue.textHelp)
contentPaddingHorizontal(24.dp)
},
style = {
jetsnackTextStyle(LocalTypography.currentValue.bodyLarge)
contentColor(LocalJetsnackColors.currentValue.textHelp)
contentPadding(horizontal = 24.dp)
},

Comment on lines +341 to +347
style = {
jetsnackTextStyle(LocalTypography.currentValue.labelLarge)
contentColor(LocalJetsnackColors.currentValue.textLink)
textAlign(TextAlign.Center)
contentPaddingTop(15.dp)
fillWidth()
},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

The functions contentPaddingTop and fillWidth are not valid on StyleScope. This will cause a compilation error. You should use contentPadding(top = 15.dp) and fillMaxWidth() instead.

Suggested change
style = {
jetsnackTextStyle(LocalTypography.currentValue.labelLarge)
contentColor(LocalJetsnackColors.currentValue.textLink)
textAlign(TextAlign.Center)
contentPaddingTop(15.dp)
fillWidth()
},
style = {
jetsnackTextStyle(LocalTypography.currentValue.labelLarge)
contentColor(LocalJetsnackColors.currentValue.textLink)
textAlign(TextAlign.Center)
contentPadding(top = 15.dp)
fillMaxWidth()
},

Comment on lines +31 to +41
private fun <T> getInternalLocal(className: String, methodName: String, readableName: String): ProvidableCompositionLocal<T> {
try {
val clazz = Class.forName(className)
val method: Method = clazz.getDeclaredMethod(methodName)
method.isAccessible = true
@Suppress("UNCHECKED_CAST")
return method.invoke(null) as ProvidableCompositionLocal<T>
} catch (e: Exception) {
throw RuntimeException("Failed to access internal $readableName via reflection", e)
}
} No newline at end of file
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

Using reflection to access internal library APIs is highly discouraged as it's brittle and can break without warning on any library update, even minor ones. This makes the app fragile.

Also, catching a generic Exception is too broad. It would be safer to catch specific reflection-related exceptions like ClassNotFoundException, NoSuchMethodException, etc., to have a better understanding of what went wrong.

shape( RoundedCornerShape(percent = 50))
background(Brush.linearGradient(LocalJetsnackColors.currentValue.interactivePrimary))
contentColor(LocalJetsnackColors.currentValue.textInteractive)
contentPadding( ButtonDefaults.ContentPadding.calculateTopPadding()) // todo file issue to support padding values
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The contentPadding function is being called with a single Dp value returned by calculateTopPadding(). This will set the padding for all four sides to be the value of the top padding, which is likely not the intended behavior. To apply the default button content padding, you should pass the PaddingValues object directly.

Suggested change
contentPadding( ButtonDefaults.ContentPadding.calculateTopPadding()) // todo file issue to support padding values
contentPadding(ButtonDefaults.ContentPadding)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant