Skip to main content

Common Props

The Components page details how to declare a component and its props as standard val properties. This page covers another way for a parent component to configure its children with props: Common props, aka the Style API.

Common Props​

Common props are props that can be applied to any component and are defined by the Style API. They include View properties like onClick and background, visibility events like onVisible, as well as layout parameters like margin.

A Style object can be constructed by chaining multiple Styles together, as shown in the following example:

import com.facebook.litho.view.backgroundColor

MyComponent(
style = Style.margin(all = 4.px)
.backgroundColor(Color.RED)
.viewTag("my_view")
)

For a component to be configured with a Style, it should declare a Style prop (such as val style: Style = Style). It should then pass that Style object to one of the components it renders to, usually the root component it returns from render. In this way, the Style will eventually end up on a PrimitiveComponent (for example, Text or Row). All common props end up being materialized by PrimitiveComponents, as shown in the following example:

class StyledHelloComponent(private val name: String, private val style: Style = Style) :
KComponent() {

override fun ComponentScope.render(): Component {
return Text(style = style, text = "Hello $name!")
}
}

val componentWithOnClick: StyledHelloComponent =
StyledHelloComponent(name = "Common Props", style = Style.onClick { log("clicked!") })

Combining a Style from a Parent with a Local Style​

The following example shows how you can combine a Style passed from a parent with the Style the component itself wants to define:

class OuterTextComponent : KComponent() {
override fun ComponentScope.render(): Component {
return InnerTextComponent(style = Style.margin(all = 8.dp))
}
}

class InnerTextComponent(private val style: Style = Style) : KComponent() {
override fun ComponentScope.render(): Component {
return Text(
style = Style.padding(all = 8.dp).alpha(.5f) + style,
text = "I accept style from a parent!",
)
}
}

Working with Style​

In the above example, you may have noticed the use of + to combine the Style passed from OuterTextComponent and the styles that InnerTextComponent defines. The + operator combines two Styles into a single Style without mutating either:

import com.facebook.litho.Style

val alphaStyle = Style.alpha(1f)
val combinedStyle = alphaStyle + Style.padding(all = 8.dp).margin(all = 8.dp)

// Result:
// alphaStyle: (alpha: 1f)
// combinedStyle: (alpha: 1f) <- (padding-all: 8.dp) <- (margin-all: 8.dp)

Note that ordering around + matters: if a Style property is defined twice, the last definition takes precendence:

import com.facebook.litho.Style
import com.facebook.litho.core.padding

val alphaStyle = Style.alpha(1f)
val combinedStyle = alphaStyle + Style.padding(all = 8.dp).alpha(.5f)

// Result:
// combinedStyle will apply padding of 8.dp and alpha of .5f

Generally, Style objects are immutable: any time you combine styles or add new properties to a style, you get a new Style instance that contains all the properties of the previous style plus the new properties.

Interoperability with Legacy Components​

For passing style from Kotlin code to a Java Spec component, you can use .kotlinStyle(), which is equivalent to setting all the common props the Style defines:

class OuterStyleKComponent : KComponent() {
override fun ComponentScope.render(): Component {
val style = Style.margin(all = 8.dp)
return PlaygroundComponent.create(context).kotlinStyle(style).build()
}
}

See also​

  • Tree Props - provides a way to give access to contextual objects, like a theme or logging utility, to all components in a sub-tree without having to manually pass them.