|
| 1 | +# A Playground to investigate a good third-party React UI Lib Architecture |
| 2 | + |
| 3 | +My goal is to find an architecture which could be common ground a base for quality React UI libraries. A consistent theming/styling API would make the lives of many developers way more comfortable. |
| 4 | + |
| 5 | +HELP/FEEDBACK/YOUR OPINION WANTED! :) |
| 6 | + |
| 7 | +## How to setup & run |
| 8 | + |
| 9 | +``` |
| 10 | +npm install |
| 11 | +cd app |
| 12 | +npm install |
| 13 | +npm start |
| 14 | +``` |
| 15 | + |
| 16 | +## Basic Ideas |
| 17 | + |
| 18 | +#### Class based |
| 19 | + |
| 20 | +Component styles should be class based. It's more performant & responsive styling doesn't work with server-side rendering. I myself went down the inline-styles path in the past, but switched back to classes. Your thoughts? |
| 21 | + |
| 22 | +#### react-themeable |
| 23 | + |
| 24 | +Leverage react-themeable. It's a nice way of providing many styling classes to a single component. |
| 25 | +I believe establishing this as a convention would benefit the React community due the consistent API over many libs. |
| 26 | + |
| 27 | +#### Self-contained |
| 28 | + |
| 29 | +Make components self contained (no global UI lib dependencies) so you can import them and avoid importing the whole library e.g. |
| 30 | + |
| 31 | +``` |
| 32 | +// import the whole lib and get Toggle |
| 33 | +import { Toggle } from 'ui-lib'; |
| 34 | +
|
| 35 | +// just import toggle without importing the whole library |
| 36 | +import Toggle from 'ui-lib/Toggle'; |
| 37 | +``` |
| 38 | + |
| 39 | +#### Ship without a theme |
| 40 | + |
| 41 | +Ship without a global theme (so people don't have to import the styling code). |
| 42 | + |
| 43 | +#### Global theming utility |
| 44 | + |
| 45 | +Provide a simple & handy way to apply a global theme for all the imported components. |
| 46 | + |
| 47 | +## Global Theming |
| 48 | + |
| 49 | +While react-themeable is super useful I believe having a way to set a default styling is a crucial feature for a UI library. Most of the time you will use the default theme specific to your product. This avoids adding a lot of theme props through the whole application. |
| 50 | + |
| 51 | +#### Module export |
| 52 | + |
| 53 | +https://github.com/nikgraf/future-react-ui/tree/master/ui-lib |
| 54 | + |
| 55 | +In this version the defaultTheme is exported through a named module export. On line 9, 10, 11 you can see how the default theme is patched with custom classes. (https://github.com/nikgraf/future-react-ui/blob/master/app/index.js#L8) Since this is not so hand it might be useful to have utility function for each library to apply a theme. |
| 56 | + |
| 57 | +#### Static property |
| 58 | + |
| 59 | +https://github.com/nikgraf/future-react-ui/blob/master/ui-lib/StaticProperty/Hint.js |
| 60 | + |
| 61 | +In this version the defaultTheme is attached to the component itself as static property. Compared to the 'Module export' this is a bit more flexible as you can overwrite the whole `theme` object in one go. See line 13-20 for usage. (https://github.com/nikgraf/future-react-ui/blob/master/app/index.js#L13) |
| 62 | + |
| 63 | +#### Theme Component leveraging Context |
| 64 | + |
| 65 | +https://github.com/nikgraf/future-react-ui/blob/master/ui-lib/Context/Hint.js |
| 66 | + |
| 67 | +In this version we leverage context to build a `<Theme />` component that takes a theme as property and passes it down to all child components via React's context. A theme is still a simple JS object as can be seen on line 25-30. (https://github.com/nikgraf/future-react-ui/blob/master/app/index.js#L22). See how it's used here: https://github.com/nikgraf/future-react-ui/blob/master/app/index.js#L94. On one hand this approach is powerful, because you can apply different themes various nesting levels in the render tree. |
| 68 | + |
| 69 | +``` |
| 70 | +<Theme theme={baseTheme}> |
| 71 | + <Theme theme={headerTheme}> |
| 72 | + <Menu items=['Home', 'About'] /> |
| 73 | + </Theme> |
| 74 | + <Hint isOpen>Basic open hint without styling.</Hint> |
| 75 | +</Theme> |
| 76 | +``` |
| 77 | + |
| 78 | +There is one obvious concern with this approach. There could be name-clashing between libraries that use the same key in the `theme` object. This could be solved by following a namespace convention like prefixing the keys with the npm package name. |
| 79 | + |
| 80 | +## Conclusion |
| 81 | + |
| 82 | +While the Theme component based idea is pretty powerful it's issues make me not having this as a default way of doing things. I'm not sure if there are some up/downsides between Module export vs Static property, but currently I'm leaning more to the static property implementation. If you have some ideas/feedback please reach out to me and let's discuss. (Github Issues might be best, but Twitter, Email, Skype, Hangout works as well) |
| 83 | + |
| 84 | +## License |
| 85 | + |
| 86 | +MIT |
0 commit comments