Skip to main content

Types of Props

The Components page details how to declare a component and its props as standard val properties. This page covers two more ways for a parent component to configure its children with props: Common props and Tree props.

Common Props​

note

A common prop is one of a set of properties that can be applied to any primitive component.

Common props are supported by all primitive components. They include View properties like onClick and background, visibility events like onVisible, as well as layout parameters like margin.

Common props are specified using the Style API, which enables one or more common props to be chained together into a Style object that is passed to the components as a prop, as shown in the following example:

val 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? = null). 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 primitive component (for example, Text or Row). All common props end up being materialized by primitive components, as shown in the following example:

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

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

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

Combining a Style from above with a local Style​

The following 'more advanced' example shows how you can combine a Style taken from above 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? = null) : 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:

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:

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.

Java - Kotlin compatibility​

If you need to pass down a style from a Java class to a Kotlin component, use StyleCompat:

@LayoutSpec
class OuterStyleComponentSpec {

@OnCreateLayout
static Component onCreateLayout(ComponentContext c) {
return new InnerTextComponent(StyleCompat.marginDip(YogaEdge.ALL, 8).build());
}
}

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 OuterStyleComponent.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.