Is there a pattern for use by libraries of composables, so the library knows how to create composables from the app's design system?I am not worried about simple parent-child relationships, where we can get away with a
composable lambda. I am more worried about cases where the library itself should be calling composable functions for certain roles, but it has no a priori way of knowing what those functions are.For example, if a library wants to render a button, it needs some composable for that. But
is a Compose Material thing, and the argument made here on several occasions is that Compose Material is just one possible design system. Somehow, the library needs a way to know "this is how I build a button", in such a way that it uses the app's chosen design system. Do we have a pattern for doing this? For apps themselves, they can simply use the right composable functions, but published libraries do not have that option, as they will be used by many apps.My fear is that, in the absence of such a pattern, libraries will tend towards "you can have any design system you want, so long as it is Compose Material".
Published libraries that expose UI components need to pick a design system they're based on. There's no such thing as a design system agnostic component. (edit: that emits specific layout/UI elements anyway.)
Material's theming around shapes, colors, and typography is one type of customization that can be imposed from the surrounding environment, but design systems run deep. Ordering of confirm/cancel buttons. Metrics for spacing between different elements. The difference between concepts like raised and ink buttons that are specific to a design system. There's no real end to it.
Once you get to a high enough level of abstraction you can do things like write components that pick between design systems based on one local constraint or another, but those both need to carry a lowest common denominator API surface and have robust implementations per design system that account for those design system specific elements
one thing that can help promote reuse across different composables with different design for the same purpose is to make sure your composables interact with associated hoisted state types in public API-clean ways. Composables written for different design systems can consume the same state types that enforce operational policy.
Avoid things like
properties on those types that establish private communication channels
1 year ago
Take a look at the variety of designs and details...
Agreed. For a component like a date picker, the library itself will basically be the design system for itself, exposing whatever options its authors wish. Teams wishing to use a date picker will choose among existing implementations for which one best fits the rest of their app's design, or they will elect to create their own if needed.However, not all libraries will be exposing something like a date picker. Composables are used for every unit of UI. Should an about screen composable be defining its own design system? Perhaps there aren't enough of these to worry about.I can't help but have this nagging feeling that we're going to run into problems. If the answer is that the app-specific design system is only useful for custom-crafted composables, it feels like we're going to have a lot of conflict between those design systems and libraries.Anyway, thanks!
What kinds of components do you think might be impacted by this mindset?
1 year ago
I suppose that my root concern is that Compose Material is going to be so unavoidable that custom app design systems are going to be a pain. And that if we don't take steps to help library authors make it easy to integrate their components into an app-specific design system, we're going to run into problems.For your date pickers, how are you envisioning that library authors will allow users of their composables to specify things like font details, foreground/background/accent colors, and the like? Even though the look and feel of an individual date picker is highly variable, they pretty much all have text and they pretty much all have colors.
If the answer is "use
", then Compose Material becomes part of the API surface.If the answer is "create your own library-specific thing that kinda resembles
in role but does not impose a Compose Material dependency", that's great, but we're probably going to need examples and evangelism.My guess is that the answer is "accept them all as parameters". Hopefully, that will hold up.
1 year ago
If they're meant to be customized, then as parameters. If the component is meant to be design system-specific, then ambients CompositionLocals from that design system are likely to play a role
Mostly though, any time I've been so much as a spectator to the development of a component where this becomes a question, the agnosticism to the design system is skin deep at most, and supporting customizations ends up being a treadmill of moving goalposts
the other existing pressures to move policy into hoisted state objects (e.g. testability) I think threads the needle nicely. Composables are meant to be cheap to write, cheap to fork.
1 year ago
a treadmill of moving goalposts
The world needs a GIF of this. 😀It would be wonderful if the Compose team could publish guidance for how you are envisioning composable libraries will look. There is quite a bit of expectation that the ecosystem will be filling in all sorts of gaps in the widget set, and the first generation of those libraries are going to be important for establishing community conventions.Again, thanks for your ideas!
I think some of it is likely to come in the form of examples from other jetpack libraries publishing compose-related modules or submodules
we've had some requests for biometric prompt, as one example. Should be interesting 🙂 there I expect at least some domain pressure to be visually and structurally consistent across apps regardless of those apps' design systems
Have ambients been secretly replaced or something?
1 year ago
Nah just renamed
Same mechanism, just called something a bit more descriptive. CompositionLocal => similar to ThreadLocal, only available in composition
1 year ago
I’ve had a few conversations about design systems here, and the place I ended up at (and @Alexjlockwood ended up in a similar camp) is creating my own design system module that is very close to Material, but not.Our design system defines colors and typography that don’t quite line up with Material’s, so we have either forked the Material components or wrapped them in our own Composables. I’m actually very happy with it so far- most of the Composables are pretty small and straightforward to fork/wrap.Here’s the thread that originally led me down that path: https://kotlinlang.slack.com/archives/CJLTWPH7S/p1603291475356800
It also affords our design system a lot of opportunity to grow beyond Material, and to hide Material concepts that don’t make sense (for example, our definition of elevation & shapes isn’t anywhere close to Material’s, even though we’ve historically leaned on Material a lot in the View world).I think we are very used to being able to customize just about every detail of the existing Material Views so that is our initial inclination with Compose.
1 year ago
Wouldn't such a question apply to any UI "platform"? If somebody wants to create a library of components for the web, I don't think there's a solution that would allow creating something like a date picker that feels seamless with every single web framework out there. Library developers have to make the choice on which design system they support.
1 year ago
One of the big differences with Compose vs. the View framework is that we are used to the View framework exposing a ton of configurable attributes (typography, all manner of colors, sometimes even shapes, etc.) because many of those are “optional” and exposing them is relatively easy to do. With Compose, those attributes would all map to function arguments which is a bit more noisy from an API perspective.The end result is that Composables tend to expose fewer attributes and are thus more opinionated from a design perspective.
I think the date picker is a pretty extreme example, and I think you are right there. That being said, in the web world the same jQuery date picker is pretty extensively customizable via CSS attributes
1 year ago
yes, compose leans very hard into using composition to do those things rather than accumulating parameters on "canonical" components
this is conscious; we have many cases of android views that became too big to fail and too big to fork. RecyclerView is the first example that comes to mind, app bars/toolbars/action bars are another one that gathered a lot of feature requests that we just couldn't get to over the years
when those are part of canonical components, the only options to implement your feature are to either upstream new capabilities to the canonical components, or fork them
the former will always be limited by balancing complexity tradeoffs both in API surface and ongoing maintenance, not to mention team prioritization
the latter we've tried to address by making forking a composable fairly cheap. If a composable is made up of other public API composables, dropping down to the layer you need and building back up from there offers more flexibility in the long term
1 year ago
But this still is not addressing the original question. If there are N design systems built on top of Compose, and I have an idea for a component (say, radial menu), what do I do?
Perhaps the idea/assumption/strong guidance is that every design system needs to provide a layered collection of its own composables that is sufficiently flexible and powerful to build on top of.
1 year ago
yes, that's where the flexibility ideally lies in a design system library
A strong design spec, with “top-level” components and subcomponent variations, semantic colours (i.e.
) and interaction guidelines
On top of that, the various layers are built: “primitive” components, “compound” components, etc. These basic ideas are of course Compose agnostic, but it seems as though Compose is infact fundamentally poised to realize these concepts way better than Views.