You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: packages/components/CONTRIBUTING.md
+273-6Lines changed: 273 additions & 6 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -4,12 +4,279 @@ Thank you for taking the time to contribute.
4
4
5
5
The following is a set of guidelines for contributing to the `@wordpress/components` package to be considered in addition to the general ones described in our [Contributing Policy](/CONTRIBUTING.md).
6
6
7
-
## Examples
7
+
## Core principles
8
8
9
-
Each component needs to include an example in its README.md file to demonstrate the usage of the component.
9
+
Contributions to the `@wordpress/components` package should follow a set of core principles and technical requirements.
10
10
11
-
These examples can be consumed automatically from other projects in order to visualize them in their documentation. To ensure these examples are extractable, compilable and renderable, they should be structured in the following way:
11
+
This set of guidelines should apply especially to newly introduced components. It is, in fact, possible that some of the older components don't respect some of these guidelines for legacy/compatibility reasons.
12
12
13
-
- It has to be included in a `jsx` code block.
14
-
- It has to work out-of-the-box. No additional code should be needed to have working the example.
15
-
- It has to define a React component called `My<ComponentName>` which renders the example (i.e.: `MyButton`). Examples for the Higher Order Components should define a `MyComponent<ComponentName>` component (i.e.: `MyComponentWithNotices`).
13
+
### Compatibility
14
+
15
+
The `@wordpress/components` package includes components that are relied upon by many developers across different projects. It is, therefore, very important to avoid introducing breaking changes.
16
+
17
+
In these situations, one possible approach is to "soft-deprecate" a given legacy API. This is achieved by:
18
+
19
+
1. Removing traces of the API from the docs, while still supporting it in code.
20
+
2. Updating all places in Gutenberg that use that API.
21
+
3. Adding deprecation warnings (only after the previous point is completed, otherwise the Browser Console will be polluted by all those warnings and some e2e tests may fail).
22
+
23
+
When adding new components or new props to existing components, it's recommended to prefix them with `__unstable` or `__experimental` until they're stable enough to be exposed as part of the public API.
24
+
25
+
Learn more on [How to preserve backward compatibility for a React Component](/docs/how-to-guides/backward-compatibility/README.md#how-to-preserve-backward-compatibility-for-a-react-component) and [Experimental and Unstable APIs](/docs/contributors/code/coding-guidelines.md#experimental-and-unstable-apis).
26
+
27
+
### Components composition
28
+
29
+
<!-- ### Polymorphic Components (i.e. the `as` prop)
30
+
31
+
The primary way to compose components is through the `as` prop. This prop can be used to change the underlying element used to render a component, e.g.:
32
+
33
+
```tsx
34
+
function LinkButton( { href, children } ) {
35
+
return <Button variant="primary" as="a" href={href}>{ children }</Button>;
36
+
}
37
+
```
38
+
39
+
### Composition patterns
40
+
41
+
TBD — E.g. Using `children` vs custom render props vs arbitrary "data" props
42
+
43
+
### (Semi-)Controlled components
44
+
45
+
TBD
46
+
47
+
### Layout "responsibilities"
48
+
49
+
TBD — Components' layout responsibilities and boundaries (i.e., a component should only affect the layout of its children, not its own) -->
50
+
51
+
#### Components & Hooks
52
+
53
+
One way to enable reusability and composition is to extract a component's underlying logic into a hook (living in a separate `hook.ts` file). The actual component (usually defined in a `component.tsx` file) can then invoke the hook and use its output to render the required DOM elements. For example:
54
+
55
+
```tsx
56
+
// in `hook.ts`
57
+
function useExampleComponent( props:PolymorphicComponentProps< ExampleProps, 'div' > ) {
A couple of good examples of how hooks are used for composition are:
91
+
92
+
- the `Card` component, which builds on top of the `Surface` component by [calling the `useSurface` hook inside its own hook](/packages/components/src/card/card/hook.js);
93
+
- the `HStack` component, which builds on top of the `Flex` component and [calls the `useFlex` hook inside its own hook](/packages/components/src/h-stack/hook.js).
94
+
95
+
<!-- ### APIs Consinstency
96
+
97
+
[To be expanded] E.g.:
98
+
99
+
- Boolean component props should be prefixed with `is*` (e.g. `isChecked`), `has*` (e.g. `hasValue`) or `enable*` (e.g. `enableScroll`)
100
+
- Event callback props should be prefixed with `on*` (e.g. `onChanged`)
101
+
- Subcomponents naming conventions (e.g `CardBody` instead of `Card.Body`)
102
+
- ...
103
+
104
+
### Performance
105
+
106
+
TDB -->
107
+
108
+
### Technical requirements for new components
109
+
110
+
The following are a set of technical requirements for all newly introduced components. These requirements are also retroactively being applied to existing components.
111
+
112
+
For an example of a component that follows these requirements, take a look at [`ItemGroup`](/packages/components/src/item-group).
113
+
114
+
#### TypeScript
115
+
116
+
We strongly encourage using TypeScript for all new components. Components should be typed using the `WordPressComponent` type.
117
+
118
+
<!-- TODO: add to the previous paragraph once the composision section gets added to this document.
119
+
(more details about polymorphism can be found above in the "Components composition" section). -->
120
+
121
+
#### Styling
122
+
123
+
All new component should be styled using [Emotion](https://emotion.sh/docs/introduction).
124
+
125
+
Note: Instead of using Emotion's standard `cx` function, the custom [`useCx` hook](/packages/components/src/utils/hooks/use-cx.ts) should be used instead.
126
+
127
+
#### Context system
128
+
129
+
The `@wordpress/components` context system is based on [React's `Context` API](https://reactjs.org/docs/context.html), and is a way for components to adapt to the "context" they're being rendered in.
130
+
131
+
Components can use this system via a couple of functions:
132
+
133
+
- they can provide values using a shared `ContextSystemProvider` component
134
+
- they can connect to the Context via `contextConnect`
135
+
- they can read the "computed" values from the context via `useContextSystem`
136
+
137
+
An example of how this is used can be found in the [`Card` component family](/packages/components/src/card). For example, this is how the `Card` component injects the `size` and `isBorderless` props down to its `CardBody` subcomponent — which makes it use the correct spacing and border settings "auto-magically".
Please refer to the [JavaScript Testing Overview docs](/docs/contributors/code/testing-overview.md#snapshot-testing).
212
+
213
+
#### Storybook
214
+
215
+
All new components should add stories to the project's [Storybook](https://storybook.js.org/). Each [story](https://storybook.js.org/docs/react/get-started/whats-a-story) captures the rendered state of a UI component in isolation. This greatly simplifies working on a given component, while also serving as an interactive form of documentation.
216
+
217
+
A component's story should be showcasing its different states — for example, the different variants of a `Button`:
A great tool to use when writing stories is the [Storybook Controls addon](https://storybook.js.org/addons/@storybook/addon-controls). Ideally props should be exposed by using this addon, which provides a graphical UI to interact dynamically with the component without needing to write code.
232
+
233
+
The default value of each control should coincide with the default value of the props (i.e. it should be `undefined` if a prop is not required). A story should, therefore, also explicitly show how values from the Context System are applied to (sub)components. A good example of how this may look like is the [`Card` story](https://wordpress.github.io/gutenberg/?path=/story/components-card--default) (code [here](/packages/components/src/card/stories/index.js)).
234
+
235
+
Storybook can be started on a local maching by running `npm run storybook:dev`. Alternatively, the components' catalogue (up to date with the latest code on `trunk`) can be found at [wordpress.github.io/gutenberg/](https://wordpress.github.io/gutenberg/).
236
+
237
+
#### Documentation
238
+
239
+
All components, in addition to being typed, should be using JSDoc when necessary — as explained in the [Coding Guidelines](/docs/contributors/code/coding-guidelines.md#javascript-documentation-using-jsdoc).
240
+
241
+
Each component that is exported from the `@wordpress/components` package should include a `README.md` file, explaining how to use the component, showing examples, and documenting all the props.
242
+
243
+
#### Folder structure
244
+
245
+
As a result of the above guidelines, all new components (except for shared utilities) should _generally_ follow this folder structure:
246
+
247
+
```
248
+
component-name/
249
+
├── component.tsx
250
+
├── context.ts
251
+
├── hook.ts
252
+
├── index.ts
253
+
├── README.md
254
+
├── styles.ts
255
+
└── types.ts
256
+
```
257
+
258
+
In case of a family of components (e.g. `Card` and `CardBody`, `CardFooter`, `CardHeader` ...), each component's implementation should live in a separate subfolder:
Copy file name to clipboardExpand all lines: packages/components/README.md
+5-1Lines changed: 5 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -10,7 +10,7 @@ Install the module
10
10
npm install @wordpress/components --save
11
11
```
12
12
13
-
_This package assumes that your code will run in an **ES2015+** environment. If you're using an environment that has limited or no support for ES2015+ such as IE browsers then using [core-js](https://github.com/zloirock/core-js) will add polyfills for these methods._
13
+
_This package assumes that your code will run in an **ES2015+** environment. If you're using an environment that has limited or no support for such language features and APIs, you should include [the polyfill shipped in `@wordpress/babel-preset-default`](/packages/babel-preset-default#polyfill) in your code._
14
14
15
15
## Usage
16
16
@@ -32,3 +32,7 @@ Many components include CSS to add style, you will need to add in order to appea
32
32
In non-WordPress projects, link to the `build-style/style.css` file directly, it is located at `node_modules/@wordpress/components/build-style/style.css`.
33
33
34
34
<br/><br/><palign="center"><imgsrc="https://s.w.org/style/images/codeispoetry.png?1"alt="Code is Poetry." /></p>
35
+
36
+
## Contributing
37
+
38
+
See [CONTRIBUTING.md](/packages/components/CONTRIBUTING.md) for the contributing guidelines for the `@wordpress/components` package.
0 commit comments