-
Notifications
You must be signed in to change notification settings - Fork 6
UI Component Architecture
We want UI elements to be built as self-contained modules which can easily be published separately to the main app and used in other projects.
It's useful to document what we feel is important for our component implementation as opinions do differ...
Theming should be done via the style layer. Against use of React context
:
[...] putting everything into your single point of context is just like making a big global variable which is pretty much what all the new CSS/CSS-in-JS solutions are trying to fix.
https://github.com/elementalui/elemental/issues/53#issuecomment-143745987
Given this, a factory pattern for injecting styles seems the only viable approach. Rethemeable and react-css-themr are common solutions which use context for theming, but passing themes in this fashion should be achievable with some creating scripting of the node module API.
Theming should output real CSS stylesheets instead of inline styles. Against inline JS styles:
- No style fallbacks can be used (you can't define the same property twice). We want something like autoprefixer to run automatically as well.
- Media & element queries don't work well.
- CSS classes are faster than inline styles.
- Stylehsheets lever browser caching, download parallelisation and reduce FOUC. Inline styles break caching & make initial download times longer.
Custom themes should be easily injectable:
React-themeable currently seems like the best approach for achieving this.
Default theme should be easily customisable:
We need to split up the style layer so that we can inject configuration into it to easily change pallete styles & other simple reconfigurations.
Should be agnostic to style language / CSS preprocessor:
The app currently implements cssnext via PostCSS plugins, but could easily support SASS, LESS or a combination thereof via additional PostCSS plugins. We've tried to configure things in such a way as to allow use of other preprocessors in future if desirable.
- Create each UI view component in its own folder.
- Keep all dependencies (styles, images, fonts) bundled in the same folder as the component.
- Include tests for the component within the folder as well (test framework still needs to be finalised- see #7)
- Include a base version of the component that can be included without styles, a version that can be easily themed by overriding some control variables, and a version that has a full theme pre-bundled with it.
Here's a blueprint for your component folder:
-
Component
- this will be the name of your component as included by other files.-
Component.js
- an unstyled component which accepts a react-themeable themes key. -
Component.css
- base cssnext stylesheet, without configuration vars. This allows child themes to reuse the base styles but include their own variable overrides for simple theming. -
index.js
- a fully styled component as the default export. Should take the compiled class name mappings fromindex.css
and apply the theme to the component, seesrc/components/themed.js
. -
index.css
- full theme styles for the component. Will mostly just load base theme variables & component-specific variables before bringing in styles fromComponent.css
. -
vars.css
- if your component has theme-related configuration variables, separate them into their own file here so that child themes can include their own version. -
Component.test.js
- unit tests for the component. At minimum a single 'render' test should be provided.
-
:TODO: document react-storybook
config
- https://speakerdeck.com/vjeux/react-css-in-js
- https://github.com/nikgraf/future-react-ui
- https://github.com/nikgraf/future-react-ui/issues/1
- https://github.com/elementalui/elemental/issues/53
- https://github.com/theme-standard/spec
- https://byjoeybaker.com/react-inline-styles
- http://jamesknelson.com/why-you-shouldnt-style-with-javascript/
About this codebase
For new contributors