Contributing
Organisation
We wanted to build our Design System based on this principle: a Design System should be a collection of composable building blocks.
In this spirit, the library exposes "macro" components, but also smaller "building blocks" used to produce these "macro" components.
./styles
This is where "basic" styled components live: the "building blocks". No JSX allowed, only small styled DOM elements. For instance:
These styles represent the foundation of the Design System, and are exposed to enable consumers of the library to build variations of the macro components if needed.
Macro components are composed of these styles mixed with other React elements.
💡 Example:
The base styles of the <Select>
component are exposed. This allows defining a "custom" select with some variation in style.
./components
This is where "macro" components live. Go nuts with JSX here!
If you want or need to split your component into simpler ones, please export everything. This allows building variants with maximum reuse.
If the component has complex logic, please try to abstract it away in a hook.
💡 Example:
The <Select>
component is composed of a <SelectButton>
and a <SelectDrawer>
, and both are exposed.
./behaviours
This is where complex logic specific to a "class" of component lives. The idea again is to allow custom variation with maximum reuse.
For example, the <Select>
behaviour is exposed through multiple hooks, allowing the user to build a custom component with the same behaviour.
./hooks
When a hook is not specific to some component, but is rather of general purpose (e.g. useLoseFocus
, useDebounce
...), this is where it goes.
./legacy
Hosts components from the previous DS organisation. They don't respect the coding style or current organisation. Use them only if there is no equivalent in ./components
or ./styles
, and don't make improvements (unless you have no other choice). Ideally they should be migrated first to the current organisation before any improvements.
./glyphs
Everything related to SVG Icons. Each glyph is a different component exported in the namespace glpyhs
. So to use the glyph Heart
, you would use <glyphs.stroke.Heart>
.
Coding style
TypeScript vs. JavaScript
Please always write in TypeScript when possible. That being said, the codebase will still accept JavaScript.
Imports
Try to import dependencies in this order:
- External dependencies (React, styled-components, ...)
- Internal dependencies (utils, other components, ...)
- Constants
Please separate these categories with line breaks.
Imports SHALL be sorted alphabetical order.
Exports
Named exports
Named exports are preferred over default exports:
- Easier to follow: named export are imported with the same identifier. It is easier to reason on code with stable names.
- Early errors: if you try to import something by name that is not there, an error will be thrown right of the bat. If you import a default that is not what you expect, you won't know until it blows up in some code path.
- No thinking overload: no need for the importer to think of a name, the name is already set. The less thinking the better. You only have to think of a name if there is conflicts.
Exporting components
To be able to truly benefit from styled-components
, all Design System components should be styled
components, even if no styles are defined:
So please always wrap component exports in the styled()
HoC.
Code Documentation
Props documentation is generated with react-docgen. Thus, you MUST define a type for the props of each component you will expose in the library.
To ensure documentation is correctly generated and clear, please respect the following conventions:
Imported type for props
react-docgen
can't handle imported types (be it PropTypes or plain types). But sometimes we need to extend
a component. When we do so, and in order to have a clear documentation, add a docblock specifying which component is extended.
In this example, only foo
will be documented, but the docblock explains that additional properties can be added, and refers to the documentation of the extended component to have the full list of additional props.
Basic styled components
react-docgen
can't handle basic styled-components natively. Relying on some conventions, it is possible to extend react-docgen
capabilities and handle some cases.
For basic styled
components, you need to manually set the displayName
, because react-docgen
can't infer it for you. You also need to manually set the defaultProps
(even if you're already setting them through default arguments) because react-docgen
doesn't know how to extract them from the interpolations in the template.
Wrapped styled components
react-docgen
can't handle wrapped styled
components natively. Again, we can extend react-docgen
capabilities and handle some cases with conventions. You need to manually set the displayName
for the same reasons, but react-docgen
will find defaultProps
by itself in the function signature. So, don't forget to add them.
Documentation
If you create a new component, create a new MDX file in the fronted/owl-nest/standalone/owl-kit-website/src/docs
folder. The file MUST be named by the component displayName
.
💡Example: the file documenting the <S.image.Avatar />
component would be named S.image.Avatar.mdx
.
You'll need to define some metadata at the beginning of the file:
displayName
: the display name of componentdisabled
: set totrue
if you don't want to give access to the pageflag
: if you want to flag some components (null to disable): e.g. legacy, experimental, deprecated.group
: the name of a component group used for display: e.g. Components, Crowdfunding, Glyphs, Layout, Styles.subgroup
: the name of a subgroup to further categorize components (optional)
A few pre-built components are available to help composing documentation pages:
- ComponentInfo
- Playground
- PropsTable
- CodeBlock
You SHALL at least embed a Playground
and PropsTable
components. Furthermore, you SHOULD showcase the component variants, if any.
Tip
ℹ️ Sometimes when adding a new page, Gatsby needs to be reloaded in order to take it into account.
Netlify
The website is (automatically) deployed on Netlify from the master
branch.
Netlify also offers automatic deployment for open PRs, so take a look at the GitHub checks section in your PR. 😉