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

Kirill Grouchnikov

11/12/2020, 9:58 PM
I have a case where I want to "tag" a certain subtree as a "logical" grouping of content. For example, in Office you have the ribbon "group", the footer "group", the taskpane "group". One option is to use an ambient to wrap that group, but it feels too heavyweight. And the other option is to use a modifier, but it looks like a modifier only gets "applied" to the specific composable. If I have another composable down the tree and I want to check which logical group it belongs to, there doesn't seem to be a way (by design?) to walk the modifiers of my parent chain. Should I go with ambients?
z

Zach Klippenstein (he/him) [MOD]

11/12/2020, 10:00 PM
Another way is to explicitly pass the group identifier to the children, maybe using a receiver on your child composables
👆 1
k

Kirill Grouchnikov

11/12/2020, 10:01 PM
Would that need to be done explicitly however many nested levels I have in my hierarchy of composables?
z

Zach Klippenstein (he/him) [MOD]

11/12/2020, 10:10 PM
Depends on how your composables are structured, you might be able to take advantage of lambdas and lexical scope
a

Adam Powell

11/12/2020, 10:49 PM
an ambient for this kind of metadata could be fine; I suppose it depends on what the group is used for and what the defined behavior is if something isn't in a group
👎 1
j

jim

11/12/2020, 11:04 PM
(1) why do you want to know which group the widget belongs to? There are some valid reasons, but at first glance it sounds suspicious. (2) why can't you just pass the group in as a parameter to the widget(s) that need it?
k

Kirill Grouchnikov

11/12/2020, 11:05 PM
I think of the UI hierarchy as a tree. Every node has a color. A child node inherits the parent color, unless that child is explicitly overriding it. So an application hierarchy can be seen as "red" toolbar, "blue" footer, "green" sidebar, etc, but at any level you can tweak the color, like yellow group of buttons in a blue footer. And there's the default color set on the root.
j

jim

11/12/2020, 11:05 PM
Are we literally talking about color here? Or are you still trying to ask the question in the abstract?
k

Kirill Grouchnikov

11/12/2020, 11:08 PM
Passing this indication around is cumbersome. In my particular case, application UI is partitioned into functional areas, each with its own theme. So a footer button looks different from a toolbar button. It's not a color. It's the functional area type, which then is used to query the area theme.
It's the fill color, the icon tint, the border color, the checkmark color, the rollover highlight color, etc. All queried based on which area the control is in.
j

jim

11/12/2020, 11:09 PM
But usually you would use
FooterButton
to build the footer and
Toolbarbutton
to build the toolbar. Unless you would sometimes put buttons that are normally in the footer into the toolbar?
k

Kirill Grouchnikov

11/12/2020, 11:11 PM
Why would the UI builder need to know where the button goes. If it's a button that boldens the text, that's what the button is. The look shouldn't be a part of the button creation, imo
a

Adam Powell

11/12/2020, 11:12 PM
one might similarly say that the button shouldn't concern itself with the group it's in
💯 1
👆 1
k

Kirill Grouchnikov

11/12/2020, 11:13 PM
Exactly. It's only at the draw time that it queries the colors and draws itself. Because that needs to happen at some point. Otherwise how do you create visual separation?
j

jim

11/12/2020, 11:13 PM
A button concerning its self with how it looks is literally THE thing a button should be doing.
a

Adam Powell

11/12/2020, 11:13 PM
"group" is still kind of vague here in terms of its intent and the data involved
k

Kirill Grouchnikov

11/12/2020, 11:14 PM
Toolbar is a group, but then a search field in it is a subgroup
Let me find a screenshot
This is one example. Buttons pinned to the taskbar up top area automatically tinted the right way, including the icons. And the search box is a different nested grouping.
a

Adam Powell

11/12/2020, 11:27 PM
so for theming, then?
j

jim

11/12/2020, 11:27 PM
it would be a stretch to call that theming
k

Kirill Grouchnikov

11/12/2020, 11:27 PM
I see a world where the button adapts to the area when it draws itself, instead of doing that at creation time. This way you can have metadata that captures what the button is, and let the button figure out how to draw itself wherever it is in the application hierarchy.
j

jim

11/12/2020, 11:28 PM
That inverts the decision making in a way that is antithetical to Compose.
k

Kirill Grouchnikov

11/12/2020, 11:28 PM
At least this is the design system that I'm porting to compose desktop from swing
j

jim

11/12/2020, 11:29 PM
Children should not know about their parents, because that prevents reuse in contexts that the Child wasn't originally expecting but that the parent knows about
you always want the parent to be the one in direct control, telling the child how it should behave
k

Kirill Grouchnikov

11/12/2020, 11:30 PM
That's the whole point of ambient "overriding" of colors, text styles, etc already today
I don't see how applying typography to a specific app area with ambient is any different
j

jim

11/12/2020, 11:32 PM
Ambients are like nuclear weapons, you really shouldn't use them unless you absolutely must, and even then you should feel bad.
🍄 2
☁️ 1
They are intended for situations where they are consumed by hundreds or thousands of widgets in a tree, through deep hierarchies, and thus infeasible to pass to each child explicitly.
k

Kirill Grouchnikov

11/12/2020, 11:33 PM
That's exactly my use case
j

jim

11/12/2020, 11:34 PM
it is not, those ribbons are small and relatively flat
k

Kirill Grouchnikov

11/13/2020, 12:20 AM
Here's a few examples of desktop apps with clear logical separation of complex UI surfaces into functional areas. And on desktop, controls such as buttons have many more states (and combinations of thereof) than what is right now available for app customizations via https://android.googlesource.com/platform/frameworks/support/+/refs/heads/androidx-master-dev/compose/material/material/src/commonMain/kotlin/androidx/compose/material/Button.kt#295
j

jim

11/13/2020, 12:21 AM
I'm not saying that apps don't have clear logical separation of complex UI into functional areas.
I'm saying that different functional areas should use widgets that are built for those functional areas
k

Kirill Grouchnikov

11/13/2020, 12:21 AM
There's enabled bit, selected bit, pressed bit, rollover bit - and highly customized UIs provide distinct visuals for different combinations of these bits.
The ribbon can host literally thousands of commands, depending on the complexity of the app (office, autocad, etc). Passing dozens of colors into each composable seems a lot of overhead at the creation point.
j

jim

11/13/2020, 12:24 AM
We are diverging pretty substantially from your original ask. Are you trying to build a design system, or trying to build some panels using an existing design system?
If the former, a design system might introduce an ambient (like Material introduces
MaterialTheme
). If the later, you should probably find a different solution (like use 
FooterButton
 to build the footer and 
Toolbarbutton
 to build the toolbar).
Creating widgets (like a new button type) that are specific to a particular region of an app is not an antipattern. It is in fact an idiomatic pattern.
k

Kirill Grouchnikov

11/13/2020, 2:08 AM
It's the former