Question/feedback on supporting non-Material desig...
# compose
b
Question/feedback on supporting non-Material design systems and future compatibility: Why are all of the components in
androidx.compose.material
named as though they are the the canonical implementation, when the messaging so far is that Material is an implementation of a specific design system?
Text
is a great example- it’s name alone ensures that it will be the first text Composable that most engineers reach for, but that presents two problems in my mind: • Today, any project with its own design system has the burden of ensuring its engineers use their design system’s text instead of the innocent and generic sounding
Text
• When a new Android-default design system inevitably comes along in the future, we have a similar problem- does the new design system create a
HoloText
, create its own Composable named
Text
, or does Material rename
Text
to something else? Contrast that with the Material Components library with
View
s, which explicitly labels the material-themed components e.g.
MaterialRadioButton
. There are some tricks under the hood to swap them in for framework components in some cases, but they still get a clear name in the library.
👍 1
👀 1
i
If you are building your own design system, wouldn't you just also use
Text
in your own package namespace? Not including the material library (as it is a purposefully a separate artifact) would be enough to prevent confusion.
m
other libraries (e.g., third-party) are likely to pull in
material
by transitive dependencies
i
But should they?
☝️ 1
b
I definitely have been considering calling our text Composable
Text
as well, but I see a few challenges there- first is that if developers are searching for documentation on a
Text
composable they may not realize which package it is coming from so differences in the public API may cause unneeded confusion
z
Yea, if that’s the case then they’re unnecessarily bloating your APK anyway (i.e. there’s other problems than just namespacing)
b
Another challenge is that it is fairly likely that we will be pulling in Material in our design system library so that we can wrap some components that we don’t want to completely re-implement ourselves. While that’s a bit more bearable since I expect fewer engineers to be working in that library, it is still more cognitive overhead
As another example, while I want my engineers using my
Button
instead of the Material button, I don’t necessarily want to stop them from using a
RippleIndication
from Material
(And I very much do not want to fork
RippleIndication
)
m
Going back to my third-party library point, it is possible that the library itself needs Material. Ideally, they would make that dependency be
implementation
and not
api
. Ideally, I would have hair. 👴🏼 My guess is that there will be a cottage industry for Lint rules to enforce usage of the right composables.
b
My guess is that there will be a cottage industry for Lint rules to enforce usage of the right composables.
Absolutely. We already have one, and @Alexjlockwood has made one for his team as well
a
@Bryan Herbst there was an earlier discussion about this hidden away in a thread regarding the
TextField
vs.
MaterialTextField
component names. @Louis Pullen-Freilich [G]’s response:
That used to be the case, but then we heard the opposite feedback - developers would intuitively reach for
TextField
first, and be confused because it has no opinionated UX or styling, and requires a lot of work to look like a Material TextField. The current rename was to point developers to the opinionated component first, as this is usually the desired component.
link to thread: https://kotlinlang.slack.com/archives/CJLTWPH7S/p1599499510158400?thread_ts=1599494195.155900&cid=CJLTWPH7S
regarding the usage of `RippleIndication`… i believe there was some discussion about possibly moving that into a separate artifact outside of material, which i tend to agree with… at least it would allow me to remove the
implementation
dependency on material entirely (cc @matvei)
also not sure if it needs to be said, but i’ve been maintaining a list of exclusions i don’t want to show up in auto-complete and committed it to source control in
.idea/codeInsightSettings.xml
. here’s what i have so far (note this currently hides
RippleIndication
from auto-complete… i havent fixed that yet 😅)
Copy code
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
  <component name="JavaProjectCodeInsightSettings">
    <excluded-names>
      <name>android.graphics.drawable.Icon</name>
      <name>android.inputmethodservice.Keyboard.Row</name>
      <name>android.preference.PreferenceActivity.Header</name>
      <name>android.preference.SwitchPreference</name>
      <name>android.provider.CalendarContract.Colors</name>
      <name>android.text.Layout.Alignment</name>
      <name>android.view.Surface</name>
      <name>android.widget.Button</name>
      <name>android.widget.CheckBox</name>
      <name>android.widget.GridLayout.Alignment</name>
      <name>android.widget.RadioButton</name>
      <name>android.widget.Switch</name>
      <name>android.widget.ToggleButton</name>
      <name>androidx.compose.foundation.AmbientContentColor</name>
      <name>androidx.compose.foundation.AmbientTextStyle</name>
      <name>androidx.compose.foundation.Icon</name>
      <name>androidx.compose.foundation.ProvideTextStyle</name>
      <name>androidx.compose.foundation.Text</name>
      <name>androidx.compose.foundation.contentColor</name>
      <name>androidx.compose.foundation.layout.Spacer</name>
      <name>androidx.compose.material.*</name>
      <name>androidx.compose.material.icons.*</name>
      <name>androidx.compose.ui.text.input.KeyboardType.Text</name>
      <name>java.lang.reflect.Modifier</name>
      <name>java.nio.file.WatchEvent.Modifier</name>
      <name>java.time.format.TextStyle</name>
      <name>org.w3c.dom.Text</name>
    </excluded-names>
  </component>
</project>
m
Yeah, we have ongoing discussions around the extraction of the Ripples in general and RippleIndication to the separate, material independent library, so any design system that don't want material components, but wants ripples might just depend on the small piece 🙂 Stay tuned
🎉 13
💥 10
z
j
If you are building your own design system, wouldn't you just also use 
Text
 in your own package namespace? Not including the material library (as it is a purposefully a separate artifact) would be enough to prevent confusion.
Well, if that would be usable practically, Compose foundations wouldn't have BasicText and the same the TextField should be without prefix, shouldn't be? The reality is that including material (at least the compose's) is a must and we and probably majority of others build upon it. Personally, this is one of my open questions if I should (re)name my components with prefix our let them just namespaced. At the same time, we know we wouldn't wrap everything, so it seems pretty weird to have TextField and CompanyButton.
a
FWIW i started out prefixing all of our design system components… eventually i dropped them, and code has gotten a lot cleaner looking as a result. it’s definitely grown on me over time 😄
👍 6
blob thinking upside down 1
b
I’m leaning that direction too- I’m hoping that after using it a bit devs will get used to it and won’t have to think about it. That, coupled with lint checks to guide you in the right direction should help. I’m structuring my lint check so it offers replacements (
androidx.compose.material.Button
->
com.target.design.Button
)
m
The general motto we're using in compose team is that material is just a design system that is build on top of the public building blocks in foundation; Material is the same as
YourCompanyDesignSystem
, just build by compose team. Therefore, using
YourCompanysDesignSystem
should feel as natural as using material or any other design system, without prefixes like
MyCompanyLibrary
. This way the code is cleaner and the right practices are being promoted. We don't want anyone to end up there:
Copy code
fun C() {
    Column(Modifier.materialClickable(...)) {
        MaterialButton(onClick = {}) {
             MaterialText("Click me")
        }
        MaterialText("Click this button")
    }
}
j
I think if you are mixing material and normal composables in your library, you can use a typealias in your imports
Copy code
import foundation.Text
import material.Text as MaterialText