├── .babelrc
├── .eslintignore
├── .eslintrc
├── .gitignore
├── .jscsrc
├── .npmignore
├── .travis.yml
├── LICENSE
├── README.md
├── app
├── README.md
├── components
│ ├── HintCssModulesExample
│ │ ├── index.js
│ │ └── styles.css
│ ├── HintExample
│ │ └── index.js
│ └── HintJssExample
│ │ ├── index.js
│ │ └── styles.js
├── index.html
├── index.js
├── package.json
├── server.js
└── webpack.config.js
├── global-theming.md
├── package.json
└── ui-lib
├── Context
├── Hint.js
└── Theme.js
├── Factory
├── belle
│ └── Hint.js
├── elemental
│ └── Hint.js
├── react-themeable
│ └── createComponent.js
└── ui-core
│ └── Hint.js
├── ModuleExport
└── Hint.js
└── StaticProperty
└── Hint.js
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": ["react", "es2015", "stage-0"],
3 | "env": {
4 | "development": {
5 | "presets": ["react-hmre"]
6 | }
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/.eslintignore:
--------------------------------------------------------------------------------
1 | **/node_modules/**
2 | lib/**
3 | app/**
4 |
--------------------------------------------------------------------------------
/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "airbnb",
3 | "env": {
4 | "mocha": true
5 | },
6 | "rules": {
7 | "react/prop-types": 0
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Dependency directory
2 | # Commenting this out is preferred by some people, see
3 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git-
4 | node_modules
5 |
6 | .DS_Store
7 |
8 | # Webpack cache & build files
9 | bundle.js
10 | .bundle.js
11 |
12 | # Build
13 | /lib/
14 |
15 | # NPM debug
16 | npm-debug.log
17 | npm-debug.log*
18 |
--------------------------------------------------------------------------------
/.jscsrc:
--------------------------------------------------------------------------------
1 | {
2 | "preset": "airbnb",
3 | "validateQuoteMarks": null,
4 | "excludeFiles": [
5 | "coverage/**",
6 | "node_modules/**",
7 | "app/**",
8 | "lib/**"
9 | ]
10 | }
11 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | # Dependency directory
2 | # Commenting this out is preferred by some people, see
3 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git-
4 | node_modules
5 |
6 | # Webpack cache & build files
7 | bundle.js
8 | .bundle.js
9 |
10 | # Sources
11 | /app/
12 |
13 | # NPM debug
14 | npm-debug.log
15 |
16 | tests
17 | docs
18 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 | node_js:
3 | - "4.1"
4 | sudo: false
5 | script:
6 | - npm test
7 | - npm run lint
8 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2015 Nik Graf
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4 |
5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6 |
7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
8 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
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 | Feel free to join the ongoing discussion [here](https://github.com/nikgraf/future-react-ui/issues/1) or open up a new issue.
7 |
8 | ## How to setup & run
9 |
10 | ```
11 | npm install
12 | cd app
13 | npm install
14 | npm start
15 | ```
16 |
17 | ## Basic Ideas
18 |
19 | #### Self-contained
20 |
21 | Make components self contained (no global UI lib dependencies) so you can import them and avoid importing the whole library e.g.
22 |
23 | ```
24 | // import the whole lib and get Toggle
25 | import { Toggle } from 'ui-lib';
26 |
27 | // just import toggle without importing the whole library
28 | import Toggle from 'ui-lib/Toggle';
29 | ```
30 |
31 | #### react-themeable
32 |
33 | Leverage react-themeable. It's a nice way of providing many styling classes to a single component.
34 | I believe establishing this as a convention would benefit the React community due the consistent API over many libs.
35 |
36 | #### ClassName based
37 |
38 | 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. A component using react-themeable could actually work with both (class-names & inline-styles), but I believe this is an unnecessary overhead. Your thoughts?
39 |
40 | #### Ship without a theme
41 |
42 | Ship without a global theme so people don't have to import the styling code. This might not be relevant to company internal or in general libraries that a opinionated about styling.
43 |
44 | #### Global theming utility
45 |
46 | Provide a simple & handy way to apply a global theme for all the imported components.
47 |
48 | ## Global Theming
49 |
50 | 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.
51 |
52 | ### Factory Pattern
53 |
54 | https://github.com/nikgraf/future-react-ui/tree/master/ui-lib/Factory
55 |
56 | In this version we assume there is a package which includes a completely unstyled version of the UI kits while there is a second one which takes all the needed components and return themed components buy leveraging a factory function.
57 |
58 | ```
59 | /**
60 | * Returns a the provided component as themed component.
61 | *
62 | * Note: defaultProps could be useful for default special behavioural in
63 | * different ui libraries.
64 | */
65 | export default (Component, theme, defaultProps) => (props) => {
66 | return ;
67 | };
68 | ```
69 |
70 | For example these UI
71 |
72 | #### Not themed kits & components
73 |
74 | - material-ui-core (unstyled kit)
75 | - belle-core (unstyled kit)
76 | - elemental-core (unstyled kit)
77 | - react-toolbox-core (unstyled kit)
78 | - react-select (unstyled component)
79 | - react-autocomplete (unstyled component)
80 | - react-modal (unstyled component)
81 |
82 | #### Themed UI kits
83 |
84 | - material-ui (themed with material ui style and based on material-ui-core)
85 | - belle (themed with belle style and based on belle-core)
86 | - belle-flat (themed with a flat theme and based on belle-core)
87 | - elemental (themed with the elemental theme and based on elemental-core)
88 | - react-toolbox (themed with the material theme and based on react-toolbox-core)
89 | - your-product-ui-lib (themed with your company style and based on belle-core[Toggle, Rating] & react-select & react-modal)
90 | - your-friends-product-ui-lib (themed with their company style and based on react-select & react-modal & react-autocomplete)
91 |
92 | Usage:
93 | ```
94 | import Hint from 'elemental/Hint';
95 |
96 | const customTheme = {
97 | questionMark: 'custom-class-for-question-mark-gold',
98 | visibleContent: 'custom-class-visible-content',
99 | };
100 |
101 | export default (props) => {
102 | return (
103 |
104 | {/* Globally theme component */}
105 |
106 | {/* Overwriting the theme locally for this case */}
107 |
108 |
109 | );
110 | };
111 | ```
112 |
113 | ### Other Global Theming Patterns
114 |
115 | other patterns can be found here: https://github.com/nikgraf/future-react-ui/blob/master/global-theming.md
116 |
117 | ## Temporary Conclusion
118 |
119 | While the Theme component based idea is pretty powerful the issues make me not like it as a default. For some time I was convinced that Module export or Static property would be one of the winners. Right now I'm pretty convinced the Factory Pattern is the clear winner. It is super flexible and allows people to create their own company UI kits. They can easily provide their own styling as well as set other props as default suited to their needs. Another benefit is that you can easily get started with prototyping by using an already style version (e.g. belle-flat) and replace it later with your custom product style.
120 |
121 | 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)
122 |
123 | ## License
124 |
125 | MIT
126 |
--------------------------------------------------------------------------------
/app/README.md:
--------------------------------------------------------------------------------
1 | Examples Playground for Development
2 | ================
3 |
4 | ## Install
5 |
6 | ```
7 | npm install
8 | ```
9 |
10 | Make sure you ran `npm install` in the root folder.
11 |
12 | ## Run
13 |
14 | ```
15 | npm start
16 | ```
17 |
18 | The app will run with hot reloading on `http://localhost:3000`.
19 |
--------------------------------------------------------------------------------
/app/components/HintCssModulesExample/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import Hint from 'ui-lib/StaticProperty/Hint';
3 | import styles from './styles.css';
4 |
5 | const HintExample = () => {
6 | return (
7 |