https://kotlinlang.org logo
#compose
Title
# compose
j

Jan Skrasek

08/29/2020, 10:10 PM
I'd like to style my "components". Let's say I have specific color for my button. Ideally, I like to call
Button(backgroundColor = Color.MyColor)
, but of course, also content color has to be handled. Explicit passing of such seems to be pretty verbose, but there is not probably any way to modify contentColorFor() behavior for my color. Other options is to create own Button implementation but that's not much elegant.
j

Josh Feinberg

08/29/2020, 10:12 PM
so you want them to be styled separately from your app theme?
you could probably wrap your button in a new theme with all those colors defined
🤔 1
j

Jan Skrasek

08/29/2020, 10:13 PM
Interesting, thanks for the idea!
l

Louis Pullen-Freilich [G]

08/29/2020, 10:20 PM
In general, it can be helpful to think of a 'style' as a new function, providing different defaults / values to the underlying component. This is actually how internally some components are implemented, for example,
OutlinedButton
(https://cs.android.com/androidx/platform/frameworks/support/+/androidx-master-dev:compose/material/material/src/commonMain/kotlin/androidx/compose/material/Button.kt;l=167) just calls
Button
with some different defaults - and the same works well in application code as well. So something like:
Copy code
@Composable 
fun LoginButton(
    onClick: () -> Unit,
    modifier: Modifier = Modifier,
    enabled: Boolean = true,
    content: @Composable RowScope.() -> Unit
) {
    Button(
        onClick = onClick,
        modifier = modifier,
        enabled = enabled,
        backgroundColor = Color.MyColor,
        contentColor = Color.contentColorFor(backgroundColor)
        content = content
    )
}
Is the expected / recommended pattern here. This also allows you to only expose the parameters / customization your
LoginButton
actually needs, so you don't need to expose color customization if you want to ensure it will always be the same color, or you can even provide a higher level API that accepts some object (like a
String
) that will be internally converted to text, instead of a
content
lambda. The other benefit is having semantically named components, rather than everything just being a
Button
with different theme / style configurations, that make it harder to understand what the component actually represents / how it appears.
✔️ 1
👆 2
z

Zhelyazko Atanasov

08/30/2020, 6:13 AM
On the topic of theming, in the view-based theming, it was possible to modify all instances of a view by applying a default theme style - e.g. I could add a
paddingBottom
to all Buttons in the app. We were able to modify any View attribute's value. Now in Compose this doesn't seem to be possible? We have to implement our own wrapper around the composable (e.g. the Button) that specifies the custom values (the padding) - same as the example above with
LoginButton
. Well, if we want to modify the color, typography or shape, we can use MaterialTheming, but then this will be applied to all composables that depends on MaterialTheming. I'm not able to say something like
buttonStyle = funkyMaterialTheme
. So if I have a relatively large app built with Compose and the UI designer wants to change the background of all the Buttons in the app, without affecting the rest of the components, I have to first create
MyFunkyButton
composable and replace all Button instances with it, right? If that's indeed the case, probably it's worth creating those semantically named "wrapper" composables that follow the company's design system, saving us the headaches later when the company's design system changes and it doesn't 100% follow the Material guidelines 🙂
☝️ 3
j

Jan Skrasek

08/30/2020, 9:20 AM
Yes yes...this is exactly why I am trying to understand it now. If it is needed to introduce wrappers for (almost?) everything now to avoid issues later.
l

Louis Pullen-Freilich [G]

08/30/2020, 1:13 PM
There's certainly value in eagerly creating wrapping functions - it means that sweeping changes such as changing 'default' colors / padding / size become one line. At the same time though, since components are just functions, generic IDE tools for refactoring and renaming should make it pretty easy to extract something later on, and there are probably a few things we can do specifically for this use case in tooling, such as alt+enter intentions to extract a function into a wrapper and replace usages 🙂
🧐 2
👍 1
z

Zhelyazko Atanasov

08/30/2020, 5:14 PM
Now that you mention it, indeed with having everything as a function it's going to be a lot more easier to extract and replace a component. 👍
5 Views