Principles
- overwrite or extend basic styling using css prop or
Box
component as escape hatch - merge
className
andstyle
- merge event handlers
- no margin
- forward all props so that users can expect the respective HTML attributes to work
ref
to root for ability to set ref to the underlying DOM node- responsive design by passing an array of values to system props
- overwrite or extend basic styling using css prop
Relations
- What are the possible component relations that a design might often capture
- What is the story of a component?
Components
Box
grow
for use withflex
layout setsflex-grow
to 1high
adds 100% heightwide
adds 100% widthmax
adds 100% height and widthfullscreen
adds 100vh height and 100% width
Flex
Flex
display: flex
Flex.Row
direction: row
Flex.Column
direction: column
Input
Text
ui.components.button
Select
Toggle/Switch
Toast
Stack
- https://arcade.design/docs/utilities/stack/
- https://github.com/component-driven/ui/pull/33/files#diff-6dce92c18d93599f17e15782ef8ab06eedf559a6f4cb7320f610cea346fefb28
- On how to handle Stack children return null on react-native
Tabs
Groups
Primitive
Pattern
Subgroups
ui.layout
Navigation
Data Entry
Data Display
Feedback
References
braid design system
react-native-design-system
- https://github.com/iamshadmirza/react-native-design-system
- Avatar
- ActionButton
- Badge
- Button
- Card
- CheckBox
- CircularProgressBar
- FullScreenLoader
- Header
- Input
- ListItem
- Overlay
- RadioButton
- SearchBar
- Text
- Layout
- Stack
- Inline
- Box
- StackList
- InlineList
- TileList
react-ui
building blocks
Avatar Button Heading Image Input Link Select Spinner Switch Text Textarea
layout
Stack Grid
molecules
Breadcrumb Card Form Menu Paragraph
theme-ui
https://theme-ui.com/components
Box Flex Grid Button Link Text Heading Image Card Label Input Select Textarea Radio Checkbox Slider Field Progress Donut Spinner Avatar Badge Close Alert Divider Embed AspectRatio AspectImage Container NavLink Message IconButton MenuButton
Others
- https://github.com/kripod/react-layout-components
- https://github.com/tenon-io/tenon-ui
- https://github.com/tailwindlabs/headlessui
- https://tailwindui.com/components/
Categorization
avoid the binary notion of "components library components" vs "everything else".
- meaning there is a single place to write components
general taxonomy of responsibilities
- Presentational Components
- Structural Components
- Stateful Components
useful for discovery but not when imposed
useful other conceiving metaphores
- A degree of reusability
- A degree of distance(proximal, distal)
declarations
- dumb/smart
- presentational/container
- stateful/pure
- primitives/pattern
- atoms/molecules/organism
timeless
- Presentational Components
- Structural Components
- Stateful Components
Since the-map-is-not-the-territory to will these seperations into existence will be meat with resistance. It might be better than to view components on being in a spectrum. For example between being most reusable and least reusable.
| least reusable ------------- most reusable|
or
| proximal ------------- distal|
Keeping complexity below a certain treshold is also extremly important.
Little component guide
All components live under the folder components
. This helps to void
the notion of "component library components" vs "everything else" which
allows us to have all components at our fingertips for an efficient
overview and liberates to easily compose and adapt.
Some directories hold multiple components. This allows us to keep
related components together and don't unnecessary clutter /src/components
.
Nested components will never be used outside.
Other than that this approach does not have explicit rules for component categorization. I think this is good because its actually hard to define struct rules and not bump into resistance (the territory is not the map).
Rather I want to provide a vantage point that might be a better fit for the task. I want to point to discoverability and self-emerges and self organization
This is an experiment so bear with me.
Components are part of an organic process
First I want to unearth the frame of looking at the ui as having an deep underlying continuity. Through that we can perceive component boundaries like being cell membranes, instead of implying them to be an isolated thing. To further illustrate I add the metaphore of habitat-habitas. A component dwells in (habitas) another component and likewise a component might be a dwelling place (habitat) for other components. It allows us to see components co-evolving with there surroundings and reciprocally affect each other. This way a boundary goes both ways and the relationship comes to the foreground (I think this is one of the main ideas that this relationship directly dictates how compoments will be implemented).
So as the ui grows and evolves, boundaries emerge and change and some boundaries might not feel right anymore. From here on we can think of components having a dispositional state which are micro configurations (more on this below) that can reach certain tresholds. Once above a certain treshold a component might move into a disregulated state with the danger of becoming disassotiated from its surroundings. It than feels uncomfortable to work with and more a burden then being helpful. (Since we mentioned the boundary relationship before it is important to look also to the surrounding compoments that migh also contribute to the disposition of the component.) We than could say a component (or a set of components) became "bad" and needs some refactoring.
An probably obvious but I think still important sidenote is that since components are not inherently alive, they "become" alive through our participation. Its our participation and by that getting intimate with them, is what allows this organic process to happen.
So how can we conceive or identify dispositional states of components?
Responsibilities
Here we look at general tendencies or inclinations that a component might be working out. Lets define the following:
- Presentational
- components are looking for being reusable and purely presentational. They will be agnostic to API data and application state they are rendered with. They may abstract our stylings and theming, concern themselves about user's interactions with the app, and provice a thin API layer to be used in other components.
- Structural
- components are looking for orchestrating different aspects of the app. They will most often be the habitat of presentational or other structural inclined components and play the crucial role of mapping out business logic with application state and data.
- Stateful
- components that are looking to integrate backend data and business logic.
Reusability
Here we look at the degree of reusability.
┌─── <Modal> <AnalyticsDashboard>
│ ──┐
│ │
│ <LoginForm> │
<Button> ───────────┐ │ ──┐ │
│ │ │ │
│ │ │ │
│ │ │ │
│ │ │ │
┌┼─┼──────────────────────────────┼──────────────────────────────────────────┼─────┐
└─┼─────────┼────────────────────────┼──────────────────────────────────────────┼──┘
│ │ │ │
│ │ │ │
│ └────────┐ │ │
│ │ │ └─ <App>
<Slider> ───────────┘ │ └─── <UserProfileCard>
│
<SearchIconButton>
On the right side of the spectrum with find components with a lower level of reusability, which we can map to components inclined to have stateful responsibilities. The are likely appearing only once in the component tree and are very much purpose-built.
On the left side of the spectrum we find the most reusable components. They will very likely be presentational components. When working with a component library then the components in it will certainly be reuseable and therefore located there.
Other components will be more located in the middle and can be mapped for having structural tendencies. They are specific enough to accept some state or API data and pass it on. They also might be used in several places since they are not responsible for retrieving state or data themselves.
And some components might also have "mixed" responsibilities. This can be the case when components are still working out their place or just because of their special nature do this.
When looking at the compoment tree we will find that less reusable compoments will be located at the top while more resuable components at the bottom. This happens naturally due to the affordances a compoment provides.
It is also highly unlikely that a very reusable compoment is the habitat of a not very reusable compoment.
Now that we have defined these we can look tresholds we can point to that might mean that a component slides into a "bad" state.
- To big
- A component may have too many responsibilities.
- This would mean that a component occupies a breath of component axis that is too wide. For example by incorporating both structural and presentational responsibilities, or stateful and structural responsibilities.
- Poorly Split
- The boundaries of a set of components have been split awkwardly.
- For example after a split a component might still not provide helpful affordances.
- Poorly Nested
- A component might be "surrouned" by others that feel off by how they are located to them.
- For example a presentational inclined component renders a stateful or structual inclined component, making it harder to reuse it.
These are not easy to figure out and as mentioned above require getting intimate with the components. When we do that before we reach to solutions such as Prop drilling and React Context our compoments will stay in a healthy place.
For the rest of this guide I have planned to provide more specific pointers. Like how best to style, working with theme scales, use external component libraries, best practices, etc. Maybe I do that on the go and point to them in our async meetings.
But I hope this vantage point already provides a good sense of what it means to build good compoments.
Takeaways
- Compoments live in a co-evolving way aka habitat-habitas
- Components boundaries are like cell-membranes, meaning there are the relationship rather than have a relationship
- Compoments have dispositional states that can be described by
- spectrum of reusablity
- general tendencies or inclinations aka responsabilities
- being presentational
- being structural
- being stateful
- A component can become unhelpful ("bad") when its dispositional state reaches the treshold of feeling uncomfortable to work with.
- It becomes too big (e.g. too many responsabilities)
- It was poorly split (e.g. still being unhelpful after splitting)
- Poorly Nested (e.g. poorly composed components)
- General rules
- All components live under the folder
src/components
.
- All components live under the folder
Scratchpad
- Choosing boundaries is hard but a first hunch can be made by feeling into its purpose (category) and where to best locate it (hierarchy, component tree).
- no explicit seperation/categorization/organization
- by technical concers
- by features
- nesting is ok
Sources
- https://formidable.com/blog/2021/react-components/
- https://courses.joshwcomeau.com/joy-of-react/04-component-design/01-spectrum-of-components
- https://courses.joshwcomeau.com/joy-of-react/04-component-design/02-component-libraries
- https://bonnittaroy.substack.com/p/a-new-theory-of-the-body-habitat
- https://www.gabe.pizza/notes-on-component-libraries/
- https://www.youtube.com/watch?v=mVVNJKv9esE
tools
Libraries
See
Links
- A blog trying to be a pattern library. All about designing inclusive web interfaces, piece by piece.
- Primitive elements to build isomorphic user interfaces in React.
- Reach UI seeks to become the accessible foundation of your React-based design system.
- Build accessible rich web apps with React
- https://jxnblk.com/blog/components
- https://medium.freecodecamp.org/introducing-the-single-element-pattern-dfbd2c295c5d
- https://varun.ca/styled-system/
- https://medium.com/styled-components/build-better-component-libraries-with-styled-system-4951653d54ee
- https://components.ai/
- https://github.com/ccontrols/component-controls/tree/master/ui/components
- https://formidable.com/blog/2021/react-components/
- https://open-ui.org/
- Building ui components using svg and css
- The component gallery
- Let's talk about Native HTML Tabs
- Good intro into components thinking
- fast, portable, and extensible cmd+k interface for your site
- React first GUI components
- Prioritise content over components | simeonGriggs.dev
- https://www.gabe.pizza/notes-on-component-libraries/
- https://formidable.com/blog/2021/react-components/
- HTML-first, framework-agnostic implementation of shadcn/ui - franken/ui
- React components naming convention | Charly Poly naming