Prodig provides reusable React components. You can also use it in plain HTML via CSS nevertheless.
β οΈ IMPORTANT NOTE: Due to this issue, please use npm instead of Yarn as package manager.
Prerequisites: you need to have NodeJS and npm
- Clone prodig repository
$ git clone git@github.com:kukuhsul/prodig.git
- Install dependencies
$ cd prodig path/to/prodig/$ npm install
Below are the folder structure used in prodig:
βββ src/
β βββ components/
β β βββ MyComponent/
β β β βββ index.tsx
β β β βββ MyComponent.scss
β β βββ MyOtherComponent
β β βββ . . .
β βββ fonts/
β βββ images/
β βββ styles/
β β βββ settings/
β β βββ bases/
β β βββ tools/
β β βββ utilities/
β β βββ index.scss (root style)
β βββ index.ts (Main file: import and exports all assets. Used by `npm run build`)
βββ dist/ (containing bundled files, generated by: `npm run build`)
| βββ fonts/
| βββ images/
β βββ styles/
β | βββ settings/
β | βββ bases/
β | βββ tools/
β β βββ components/ (component-level styles)
β | βββ utilities/
β β βββ styles.scss (root style)
β | βββ styles.css (bundled CSS style)
β βββ index.js (Production main file, containing bundled component)
βββ . . .
Below are the commands list, you can found the command's detail in package.json
file
build
: build allbuild:js
: build and generate bundled JS components into thedist
folderbuild:css
: build and generate CSS into thedist
folderclean
: deletedist
foldercopy-misc
: copy miscellaneous files (e.g.README.md
,package.json
) to thedist
foldercopy-assets
: copy assets files (e.g. images, fonts) to thedist
folderformat:css
: run CSS/SCSS linter and fix error"format:ts
: run TS linter and fix errorlint:css
: run CSS/SCSS linter (check.stylelintrc.json
for configuration)lint:ts
: run TS linter (checktslint.json
for configuration)start
: run development mode using storybook. (http://localhost:9001)
Editor configuration will helps us (as developer) to define and maintain consistent coding styles between different editors and IDEs. Those configuration can be found in .editorconfig file. If you are using VSCode, please install this plugin to automatically override user/workspace settings
CSS/SASS code styles are referring to the most reasonable Airbnb CSS/SASS Styleguide. StyleLint will ensure all css/sass code is conformed with the above styleguide. Those configuration can be found in .stylelintrc
file. StyleLint errors are displayed as warning messages.
We are using sustainable and scalable ITCSS architecture, which contains 5 layer of styles (see the styles/
folder):
- Settings: global SCSS variables and configs (e.g. colors, sizes)
- Tools: global SCSS functions and mixins (e.g. unit conversion)
- Bases: basic styling (e.g. normalize, reset)
- Components: components-level styles, located separately in each component's folder
- Utilities: helper class, high specifity (e.g. text-align)
We are also using BEM naming convention:
- Block (B): standalone entity that is meaningful on its own
- Element (E): a part of a block that has no standalone meaning and is semantically tied to its block
- Modifier (M): A flag on a block or element. Use them to change appearance or behavior
.button { //> B
/* Styles goes here */
&__icon { /* Styles goes here */ } //> E
&--primary { /* Styles goes here */ } //> M
&--secondary { /* Styles goes here */ } //> M
&--disabled { /* Styles goes here */ } //> M
}
Aditional file naming convention:
- Component-level: Use PascalCase and match the component's name. Example:
MyComponent.scss
forMyComponent.tsx
. [NO-LINT
] - Other: use lowercase and dash "
-
" as separator of each word, and also add underscore_
prefix except the root style file. Examples:_tokens-color.scss
,_typography.scss
,index.scss
Typescript and React/TSX code styles are referring to Airbnb: Javascript and Palantir: tslint-react. TSLint will ensure all ts/tsx code is conformed with the styleguide. Those configuration can be found in .tslint.json
file. TSLint errors are displayed as error messages and will stop the building process.
Note: [
NO-LINT
] label means that no linter for the particular style. However, you still have to conform with the style
-
Naming
- Extensions: Use
.tsx
extension for components-level. Use.ts
only for root file that export all components and assets. [NO-LINT
] - Filename: Use PascalCase for filename. E.g.,
SomeFile.tsx
. Use nameindex.tsx
for the component root file, so that can be resolved by./components/MyComponent
. [NO-LINT
] - Reference Naming: Use PascalCase for React components and camelCase for its instances. [
NO-LINT
]// good import MyComponent from './MyComponent'; const myComponent = <MyComponent />;
- Extensions: Use
-
References
- Always use
const
orlet
instead ofvar
. [tslint rule:no-var-keyword
] - Use
const
instead oflet
andvar
if a variable is only assigned to once when it is declared. [tslint:prefer-const
]
- Always use
-
Semicolon
Always use semicolon at the end of every statement [tslint rule:semicolon
] -
Curly
Always use curly braces forif
/for
/do
/while
statements, except for one line flow statements. [tslint rule:curly
]// bad if (x > 0) doStuff(); //good if (x > 0) doStuff(); if (x > 0) { doStuff(); }
-
Quotemark
Use single quote''
for string literals, and use double quote""
for jsx attributes. [tslint rule:quotemark
] -
Trailing Comma
Use trailing comma for multiline objects and array. [tslint rule:trailing-comma
] -
JSX: Formating
- Multiline JSX: Multiline JSx expressions must be wrapped with parentheses. Opening parenthesis must be followed by a newline. Closing parenthesis must be preceded by a newline. [tslint rule:
jsx-wrap-multiline
]// bad const button = <button type="submit"> Submit </button>; // good const button = ( <button type="submit"> Submit </button> );
- JSX: Self Close: JSX elements with no child should be self-closed and have space before the trailing slash [tslint rules:
jsx-self-close
,jsx-space-before-trailing-slash
]// bad <Button text="Proofn Button"></Button> <Button text="Proofn Button"/> // good <Button text="Proofn Button" />
- Alignment: [1] JSX attributes must be indented further than the opening tag, sit on their own line and vertically aligned. JSX element that have only 1 attribute may sit on same line with the opening tag. [2] Tag closing must be on its own line and aligned with opening of tag. [3] Closing tag must be on its own line and aligned with opening tag. [tslint rule:
jsx-alignment
]// bad const hello = ( <Hello name="Proofn Guy" other="nothing" // ----- [1] > Something here</Hello> // ----- [3] ); const otherHello = ( <Hello name="other Proofn Guy" other="nothing"> // ----- [2] Something here </Hello> ); // good const helloOneAttribute = ( <Hello name="Proofn Guy"> Something here </Here> ); const hello = ( <Hello name="Proofn Guy" other="nothing" > Something here </Hello> );
- Curly Spacing: Do not pad JSX curly braces with spaces. [tslint rule:
jsx-curly-spacing
]
- Multiline JSX: Multiline JSx expressions must be wrapped with parentheses. Opening parenthesis must be followed by a newline. Closing parenthesis must be preceded by a newline. [tslint rule:
-
JSX: No Lambda
Creating new anonymous functions (with either the function syntax or ES2015 arrow syntax) inside the render call stack works against pure component rendering. When doing an equality check between two lambdas, React will always consider them unequal values and force the component to re-render more often than necessary. [tslint rule:jsx-no-lambda
]// bad const otherButton = ( <button onClick={function () { /* do something */ }} /> ); const button = ( <button onClick={() => /* do something */}> Click Me </button> ); // good const handleClick = () => { console.log('clicked'); }; const button = ( <button onClick={handleClick}> Click Me </button> );
-
JSX: No Bind
Do not use function binding in JSX attributes. Bind call in the render path creates a brand new function on every single render. Bind event handlers for the render method in the constructor. [tslint rule:jsx-no-bind
]// bad class Button extends React.Component { onClickHandler() { // do something } render() { return <button onClick={this.onClickHandler.bind(this)} />; } } // good export interface Props { name: string; } class Button extends React.Component<Props> { constructor(props) { super(props); this.onClickHandler = this.onClickHandler.bind(this); } onClickHandler() { // do something } render() { return <div onClick={this.onClickHandler} />; } }
Prerequisites: you need to have NodeJS and npm
-
Clone prodig repository (outside the app folder)
$ git clone git@github.com:kukuhsul/prodig.git
-
Inject prodig to the global npm module on your machine
$ npm link
Info: the above command will builds prodig and runs
npm link
to add symbolic link from your βglobal node_modulesβ directory to theprodig/publish
folder. -
Add prodig to the app, asumes app folder is
proofn-frontend-app
$ cd proofn-frontend-app path/to/proofn-frontend-app/$ npm link prodig
Info: the above command will creates a symbolic link from
./node_modules/prodig
to<global_node_modules>/prodig
, so that we can use prodig as dependency of our app
You can use React Component by importing component directly from prodig
import { SomeComponent } from 'prodig';
You can use CSS/SASS by importing styles from prodig/dist/styles
- Improve storybook documentation
- Add testing feature
- Add image optimization pipeline
- Use only PostCSS to compile handle style
- Integrate linter in development mode (storybook)
- Add prodig utilities to align libraris usage between prodig and consumer app
- Fix postcss-modules plugin error on
npm run build:js