-
Notifications
You must be signed in to change notification settings - Fork 12
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Systems: The Core of a Component Library #3
Comments
cc'ing @diegohaz <3 |
Thank you for sharing this! ❤️ I agree with almost everything. I only have two observations:
I agree that Framer Motion looks better, but if I had to choose between Framer Motion and React Spring to use in a component library, I would probably go for the one that has the most flexible API and gives me more control. So, in this case, I would use React Spring internally and maybe expose an API similar to Framer Motion to my consumers. If we ever need to build something different, Framer Motion may not have a prop that supports it. Whereas with a lower level API like the one React Spring exposes, we have more power over what we can do. But I don't know Framer Motion enough to discard it. Maybe it exposes some lower level APIs just like Emotion.
Not really important, but I think these components would actually be classified as atoms. Some of them are even mentioned as atoms in the Brad Frost's Atomic Design blog post. But the fact that this is confusing and we have to discuss it is just a signal that Atomic Design has failed in structuring design systems, at least when it comes to code. I've received a lot of feedback while working on Atomic React, and I could see that the time people were wasting trying to decide whether a component is an atom, molecule or organism wasn't worth the benefit that the methodology was providing. I tried to remedy it (Do not worry), but it turns out that Atomic Design is another problem. 😅 |
Ah yes! I agree with you there. Ultimately, at the core/library level, I'd want maximum control. But for consumers, simple API. That may be something like... Framer Motion throughout.
I recognize that those are typically considered atoms 😊 . I think what I was attempting to illustrate is that components that are often considered to be lowest level elements (e.g. They're often composed of many smaller components. For context, I'm not 100% subscribed to Atomic Design philosophy. I like it as a guideline and a way to imagine things. The discoveries from your Arc project are invaluable! Like you had mentioned, I think getting caught up in semantics for semantics sake can cause problems 🙈 . I suppose the TLDR is... Low level/core systems are hugely important. ✌️ |
Oo! This is fun. Below is an illustration of a flow chart, detailing the various systems and mechanics for an Example: https://g2-components.xyz/?path=/story/components-alert--default |
Closing this up as we now have a blog to express and share ideas: |
I've been thinking deeply about design systems, specifically component libraries, for a while now. An indicator of a successful library is something that...
Just Works.
Meaning, the person using the library can plop things in and hit the ground running, with minimal configuration, prop "massaging", and setup.
The components are self-aware.
They're aware of each other.
Accessibility, styles, animations, and gestures are built-in by default.
It. Just. Works.
How a library can achieve this workflow is for it to recognize and craft high-quality core systems.
Core Systems Overview
Above is a rough diagram that illustrates a high-level overview of the various core systems.
These systems would exist at the lowest level of the library. They can be exposed to consumers, however, their interfaces (APIs) should be greatly simplified.
Note: There are even smaller sub-systems in these core systems. For example, Reakit (❤️), uses Popper.js for Popover positioning. Popper.js is a dedicated positioning engine (system).
From a development perspective, I would break it down into 3 levels (lowest to highest)
Core
These systems can exist within the project or as 3rd party dependencies, like Reakit (a11y) or Framer Motion (Animation/Gesture). The APIs for working with these parts should be thoughtful and well defined.
If we're thinking about this from an Atomic Design perspective (in the context of a component library)...
These would be electrons, neutrons, and photons (not even atoms!!!!)
Library
This is where our components live. I would split these into 2 categories:
Primitives
Primitives are the base-levels components. In terms of Atomic Design, these are the atoms. The best example of this would be the
BaseView
orBox
component.Box
interfaces directly with the core systems. Beyond that, everything else usesBox
.Other examples of primitives may include:
Surface
Text
Core system features can be exposed with simplified APIs (aka. component props)
Non-Primitives
Non-Primitives (lol, I need a better name), are elements people most often think about when it comes to Component libraries. These are your
Card
,Button
,TextInput
, etc... In terms of Atomic Design, these are the molecules.They are mostly composed of primitives and work relatively closely with the core systems.
They can be composed together to create larger components (or "molecules").
For example, a ColorPicker would be composed of many elements, like:
TextInput
Text
Flex
Grid
Card
Popover
Button
It may also interface with some of the core systems. (e.g. gestures for dragging).
Consumer
This level exists outside of the library. This is where developers grab our components and build their UIs.
They should be able to compose components together with ease. If needed, they should be able to easily make refinements to styles (style system/theme system) or maybe animation feels (animation system). The APIs for making these adjustments should be incredibly minimal.
Below would be an example of minimal consumer friendly APIs.
Let's say we want to make something draggable.
Here is
react-spring
/react-use-gesture
:Here is
framer-motion
Framer Motion feels much more approachable. It's easier to read, also, it feels easier to write and modify.
It does a ton of things under-the-hood, but all of that should be taken care of at the core/library level.
It should feel invisible to the consumer.
I understand this may feel a little abstract. To get a (slightly) better sense of things, it may help to explore this repo a bit!
That's it for now :). I'll add to these notes as I continue my exploration and research ✌️
The text was updated successfully, but these errors were encountered: