version 1.0.0

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:

  1. External dependencies (React, styled-components, ...)
  2. Internal dependencies (utils, other components, ...)
  3. Constants

Please separate these categories with line breaks.

Imports SHALL be sorted alphabetical order.

Exports

Named exports

Named exports are preferred over default exports:

  1. Easier to follow: named export are imported with the same identifier. It is easier to reason on code with stable names.
  2. 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.
  3. 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.

Read more on the topic.

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 component
  • disabled: set to true if you don't want to give access to the page
  • flag: 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. 😉

© Ulule 2021, Built with Gatsby