First time playing around with creating a composab...
# compose
c
First time playing around with creating a composable that has a "slot". (took me way longer than I'd like to admit that I had to call
content()
and not just
content
🙃 Does this seem fairly idiomatic?
Copy code
@Composable
fun MyCustomContainer(header: String = "", content: @Composable () -> Unit) {
    Column() {
        if (header.isNotBlank()) {
            Text(text = header)
        }
        content()
    }
}
a
Add a
modifier
parameter that defaults to the empty
Modifier
and pass it to the root
Column
then consider propagating the
ColumnScope
receiver to
content
c
@Adam Powell
consider propagating the 
ColumnScope
 receiver to 
content
You lost me there.
a
Copy code
@Composable fun MyCustomContainer(
  modifier: Modifier = Modifier,
  header: String = "",
  content: @Composable ColumnScope.() -> Unit
) = Column(modifier) {
  if (header.isNotBlank()) {
    Text(header)
  }
  content()
}
the
ColumnScope
receiver will let callers use any of the usual
ColumnScope
child modifiers
c
Oh. You did that via
content: @Composable ColumnScope.() -> Unit
?
👍 1
👌 1
When I was looking at Button source (in order to reference a slot api) I saw
content: @Composable RowScope.() -> Unit
and I wasn't sure what it was doing, so I just left it as () -> Unit.
a
you don't have to, but it does pass along the capabilities and tells the caller a little bit about what to expect around the content's layout
c
Okay. This is basically my commented code as to what I'm doing.
Copy code
//Key points
//1. Modifier goes first as per convention and we pass it down to internal column so those modifiers are propagated to that layout
//2. This uses a "slot api" in order to pass in content for the container
//3. Marking "content" as a Type of ColumnScope allows us to any ColumnScope child modifiers (not sure what this means yet)
@Composable
fun Container(modifier: Modifier = Modifier, header: String = "", content: @Composable ColumnScope.() -> Unit) {
    Column(modifier) {
        if (header.isNotBlank()) {
            Text(text = header)
        }
        content()
    }
}
@Adam Powell if you get a chance. I tried looking up more info/docs on ColumnScope.() and I'm not really sure what it does. You said "you don't have to, but it does pass along the capabilities and tells the caller a little bit about what to expect around the content's layout" What capabilities are we talkin'?
a
It puts column-specific modifiers like
Modifier.weight
into scope
c
Aha. So without that, I wouldn't be able to use column specific modifiers since its "type" safe here. Not like xml where you could always set an attribute and 🤞 that the layout will take it into account?
a
Right. The layout scope is an explicit parameter to the modifier factory by way of the receiver.
c
Thanks for teaching @Adam Powell 👍