Skip to content

Commit

Permalink
docs: update README and add CONTRIBUTING (#1979)
Browse files Browse the repository at this point in the history
  • Loading branch information
adamstankiewicz authored Feb 1, 2023
1 parent db74c18 commit dc85dae
Show file tree
Hide file tree
Showing 2 changed files with 172 additions and 152 deletions.
13 changes: 13 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Contributing

## Open edX

Please refer to the ["How to Contribute"](https://openedx.org/r/how-to-contribute) documentation and [Code of Conduct](https://openedx.org/code-of-conduct/) from Open edX for general information on contributing to the Open edX project.

## Paragon

The Paragon Working Group accepts bug fixes, new features, documentation, and security patches. You may find open issues [here](https://github.com/openedx/paragon/issues) or by visiting the Paragon Working Group [project board](https://github.com/orgs/openedx/projects/43/views/15). Issues with the "help wanted" or "byte-size" labels may be good candidates to pick up.

If you'd like to contribute a new component or update an existing component, please consider reaching out to the Paragon Working Group via the channels [described in the README](./README.md#getting-help) to propose your changes.

The Paragon Working Group looks forward to your contributions! 💎
311 changes: 159 additions & 152 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
# Paragon

![status](https://img.shields.io/badge/status-Maintained-brightgreen)
[![Build Status](https://github.com/openedx/paragon/actions/workflows/release.yml/badge.svg)](https://github.com/openedx/paragon/actions/workflows/release.yml)
[![npm_version](https://img.shields.io/npm/v/@edx/paragon.svg)](@edx/paragon)
[![codecov](https://codecov.io/gh/edx/paragon/branch/master/graph/badge.svg?token=x1tZmNduy9)](https://codecov.io/gh/edx/paragon)
![status](https://img.shields.io/badge/status-Maintained-brightgreen)
![license](https://img.shields.io/github/license/openedx/paragon.svg)
[![Build Status](https://github.com/openedx/paragon/actions/workflows/release.yml/badge.svg)](https://github.com/openedx/paragon/actions/workflows/release.yml)
[![codecov](https://codecov.io/gh/edx/paragon/branch/master/graph/badge.svg?token=x1tZmNduy9)](https://codecov.io/gh/edx/paragon)
[![NPM downloads](https://img.shields.io/npm/dw/@edx/paragon)](https://www.npmjs.com/package/@edx/paragon)

## Purpose
Expand Down Expand Up @@ -63,135 +63,12 @@ Please reach out to the Paragon Working Group (PWG):
* [Github Issues](https://github.com/openedx/paragon/issues/new?template=blank-issue.md)
* [Weekly PWG Meeting](https://calendar.google.com/calendar/embed?src=c_v86shrnegshsqgp4fj2k94u7bc%40group.calendar.google.com&ctz=America%2FNew_York)

## Contributing & Development

Please refer to the ["How to Contribute"](https://openedx.org/r/how-to-contribute) documentation and [Code of Conduct](https://openedx.org/code-of-conduct/) from Open edX.

The Paragon Working Group accepts fixes, new features, and security patches. If you'd like to contribute a new component or update an existing component, please consider reaching out to the Paragon Working Group via the channels [described above](#getting-help).

#### 1. Start the documentation site development server

The Paragon documentation site serves both as documentation and as a workbench to create your component within. To see your component in action, you need to run the documentation site locally. (Note you need to install dependencies both in the project root and the `www` directory)

```
npm run install-all
cd www
npm start
```

#### 2. Create new component

To create new component run

```
npm run generate-component MyComponent
```

where `MyComponent` is your new component's name.

This will create a directory in `/src/` that will contain templates for all necessary files to start developing the component:
```
MyComponent
├── index.jsx
├── README.md
├── MyComponent.scss
├── _variables.scss
└── MyComponent.test.jsx
```

The script will also automatically export your component from Paragon.

#### 3. Start developing

`/src/MyComponent/index.jsx` is where your component lives, the file is created with the following template, edit it to implement your own component.

``` jsx
import React from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';

const MyComponent = React.forwardRef(({ className, children }, ref) => (
<div ref={ref} className={classNames('png__MyComponent', className)}>
{children}
</div>
));

MyComponent.defaultProps = {
className: undefined,
};

MyComponent.propTypes = {
/** A class name to append to the base element. */
className: PropTypes.string,
/** Specifies contents of the component. */
children: PropTypes.node.isRequired,
};

export default MyComponent;

```

#### 4. (Optional) Add styles to your component.
## Internationalization

If your component requires additional styling (which most likely is the case), edit created SCSS style sheet in your
component's directory `/src/MyComponent/MyComponent.scss` which by default contains an empty class for your component.

If you wish to use SASS variables (which is the preferred way of styling the components since values can be
easily overridden and customized by the consumers of Paragon), add them in `/src/MyComponent/_variables.scss` (this file should contain all variables specific to your component).
This way the variables will also get automatically picked up by documentation site and displayed on your component's page.

**Please note that you need to follow [Paragon's CSS styling conventions](docs/decisions/0012-css-styling-conventions).**

#### 5. Document your component
Paragon supports internationalization for its components out of the box with the support of [react-intl](https://formatjs.io/docs/react-intl/). You may view translated strings for each component on the documentation website by switching languages in the settings.

The documentation for your component lives in `src/MyComponent/README.md`. The documentation site scans this directory for markdown or mdx files to create pages. By default, the file is created with following content:

```` md
---
title: 'MyComponent'
type: 'component'
components:
- MyComponent
status: 'New'
designStatus: 'Done'
devStatus: 'Done'
notes: |
Something special about this component
---

Describe your component here and give usage examples.

### Basic Usage

```jsx live
<MyComponent>
Hello!
</MyComponent>
```

````
Due to Paragon's dependence on ``react-intl``, that means that your whole app needs to be wrapped in its provider, e.g.:

##### Some notes on the format above:

The top part of the markdown file is known as `frontmatter`. This metadata with consumed by the documentation site to control the title of the page and the doc site navigation.
- **title** controls the page title of the generated page
- **components** is a list of react components by displayName. This usually matches the name you define the component as in code. (In our example so far it is MyComponent). Components added to this list will be scanned by react-docgen for code comments and a props api table will be rendered at the bottom of the page.
- **categories** is a list of categories where this page will appear the documentation site menu.
- **status**, **designStatus**, **devStatus**, and **notes** appear in the http://localhost:8000/status page.

JSX code blocks in the markdown file can be made interactive with the live attribute. All paragon components and icons are in scope. (Note: the scope of this code block is controlled by `www/components/CodeBlock.jsx`).

#### 6. Navigate to your component on the doc site and start building

Visit the documentation at [http://localhost:8000](http://localhost:8000) and navigate to see your README.md powered page and workbench. Changes to the README.md file will auto refresh the page.

### Internationalization

Paragon supports internationalization for its components out of the box with the support of [react-intl](https://formatjs.io/docs/react-intl/). You can view translated strings for each component on the docs site after switching language on a settings tab.

#### For consumers

Since we are using ``react-intl`` that means that your whole app needs to be wrapped in its context, e.g.
```javascript
import { IntlProvider } from 'react-intl';
import { messages as paragonMessages } from '@edx/paragon';
Expand All @@ -204,8 +81,7 @@ Since we are using ``react-intl`` that means that your whole app needs to be wra
)
```

Note that if you are using ``@edx/frontend-platform``'s ``AppProvider`` component you don't need a separate context,
you would only need to add Paragon's messages like this
Note that if you are using ``@edx/frontend-platform``'s ``AppProvider`` component, you don't need a separate context as `IntlProvider` is already included; you would only need to add Paragon's i18n messages like this:

```javascript
import { APP_READY, subscribe, initialize } from '@edx/frontend-platform';
Expand Down Expand Up @@ -235,7 +111,46 @@ you would only need to add Paragon's messages like this
});
```

#### For developers
## Contributing

Please refer to the ["How to Contribute"](https://openedx.org/r/how-to-contribute) documentation and [Code of Conduct](https://openedx.org/code-of-conduct/) from Open edX.

The Paragon Working Group accepts bug fixes, new features, documentation, and security patches. You may find open issues [here](https://github.com/openedx/paragon/issues) or by visiting the Paragon Working Group [project board](https://github.com/orgs/openedx/projects/43/views/15).

If you'd like to contribute a new component or update an existing component, please consider reaching out to the Paragon Working Group via the channels [described above](#getting-help) to propose your changes.

The Paragon Working Group looks forward to your contributions! 💎

### Development

#### Developing locally against a micro-frontend (MFE)

If you want to test the changes with local MFE setup, you need to create a "module.config.js" file in your MFE's directory containing local module overrides. After that the webpack build for your application will automatically pick your local version of Paragon and use it. The example of module.config.js file looks like this (for more details about module.config.js, refer to the [frontend-build documentation](https://github.com/openedx/frontend-build#local-module-configuration-for-webpack).):

```javascript
module.exports = {
/*
Modules you want to use from local source code. Adding a module here means that when
your MFE runs its build, it'll resolve the source from peer directories of the app.
moduleName: the name you use to import code from the module.
dir: The relative path to the module's source code.
dist: The sub-directory of the source code where it puts its build artifact. Often "dist".
*/
localModules: [
{ moduleName: '@edx/paragon/scss/core', dir: '../src/paragon', dist: 'scss/core' },
{ moduleName: '@edx/paragon/icons', dir: '../src/paragon', dist: 'icons' },
// Note that using dist: 'dist' will require you to run 'npm build' in Paragon
// to add local changes to the 'dist' directory, so that they can be picked up by the MFE.
// To avoid doing that you can use dist: 'src' to get any local changes hot reloaded on save in the MFE.
{ moduleName: '@edx/paragon', dir: '../src/paragon', dist: 'dist' },
],
};
```

Then, when importing Paragon's core SCSS in your MFE the import needs to begin with a tilde `~` so that path to your local Paragon repository gets resolved correctly: `@import "~@edx/paragon/scss/core";`

#### Internationalization

When developing a new component you should generally follow three rules:
1. The component should not have **any** hardcoded strings as it would be impossible for consumers to translate it
Expand Down Expand Up @@ -319,32 +234,124 @@ When developing a new component you should generally follow three rules:
};
```

### Developing locally against a micro-frontend (MFE)
#### Adding a new component

If you want to test the changes with local MFE setup, you need to create a "module.config.js" file in your MFE's directory containing local module overrides. After that the webpack build for your application will automatically pick your local version of Paragon and use it. The example of module.config.js file looks like this (for more details about module.config.js, refer to the [frontend-build documentation](https://github.com/openedx/frontend-build#local-module-configuration-for-webpack).):
##### 1. Start the documentation site development server

```javascript
module.exports = {
/*
Modules you want to use from local source code. Adding a module here means that when
your MFE runs its build, it'll resolve the source from peer directories of the app.
The Paragon documentation site serves both as documentation and as a workbench to create your component within. To see your component in action, you need to run the documentation site locally. (Note you need to install dependencies both in the project root and the `www` directory)

moduleName: the name you use to import code from the module.
dir: The relative path to the module's source code.
dist: The sub-directory of the source code where it puts its build artifact. Often "dist".
*/
localModules: [
{ moduleName: '@edx/paragon/scss/core', dir: '../src/paragon', dist: 'scss/core' },
{ moduleName: '@edx/paragon/icons', dir: '../src/paragon', dist: 'icons' },
// Note that using dist: 'dist' will require you to run 'npm build' in Paragon
// to add local changes to the 'dist' directory, so that they can be picked up by the MFE.
// To avoid doing that you can use dist: 'src' to get any local changes hot reloaded on save in the MFE.
{ moduleName: '@edx/paragon', dir: '../src/paragon', dist: 'dist' },
],
```
npm run install-all
cd www
npm start
```
##### 2. Create new component
To create new component run
```
npm run generate-component MyComponent
```
where `MyComponent` is your new component's name.
This will create a directory in `/src/` that will contain templates for all necessary files to start developing the component:
```
MyComponent
├── index.jsx
├── README.md
├── MyComponent.scss
├── _variables.scss
└── MyComponent.test.jsx
```
The script will also automatically export your component from Paragon.
##### 3. Start developing
`/src/MyComponent/index.jsx` is where your component lives, the file is created with the following template, edit it to implement your own component.
``` jsx
import React from 'react';
import PropTypes from 'prop-types';
import classNames from 'classnames';
const MyComponent = React.forwardRef(({ className, children }, ref) => (
<div ref={ref} className={classNames('png__MyComponent', className)}>
{children}
</div>
));
MyComponent.defaultProps = {
className: undefined,
};
MyComponent.propTypes = {
/** A class name to append to the base element. */
className: PropTypes.string,
/** Specifies contents of the component. */
children: PropTypes.node.isRequired,
};
export default MyComponent;
```

Then, when importing Paragon's core SCSS in your MFE the import needs to begin with a tilde `~` so that path to your local Paragon repository gets resolved correctly: `@import "~@edx/paragon/scss/core";`
##### 4. (Optional) Add styles to your component.

If your component requires additional styling (which most likely is the case), edit created SCSS style sheet in your
component's directory `/src/MyComponent/MyComponent.scss` which by default contains an empty class for your component.

If you wish to use SASS variables (which is the preferred way of styling the components since values can be
easily overridden and customized by the consumers of Paragon), add them in `/src/MyComponent/_variables.scss` (this file should contain all variables specific to your component).
This way the variables will also get automatically picked up by documentation site and displayed on your component's page.

**Please note that you need to follow [Paragon's CSS styling conventions](docs/decisions/0012-css-styling-conventions).**

##### 5. Document your component

The documentation for your component lives in `src/MyComponent/README.md`. The documentation site scans this directory for markdown or mdx files to create pages. By default, the file is created with following content:

```` md
---
title: 'MyComponent'
type: 'component'
components:
- MyComponent
status: 'New'
designStatus: 'Done'
devStatus: 'Done'
notes: |
Something special about this component
---

Describe your component here and give usage examples.

### Basic Usage

```jsx live
<MyComponent>
Hello!
</MyComponent>
```

````

Some notes on the format above:

The top part of the markdown file is known as `frontmatter`. This metadata with consumed by the documentation site to control the title of the page and the doc site navigation.

- **title** controls the page title of the generated page
- **components** is a list of react components by displayName. This usually matches the name you define the component as in code. (In our example so far it is MyComponent). Components added to this list will be scanned by react-docgen for code comments and a props api table will be rendered at the bottom of the page.
- **categories** is a list of categories where this page will appear the documentation site menu.
- **status**, **designStatus**, **devStatus**, and **notes** appear in the http://localhost:8000/status page.

JSX code blocks in the markdown file can be made interactive with the live attribute. All paragon components and icons are in scope. (Note: the scope of this code block is controlled by `www/components/CodeBlock.jsx`).

##### 6. Navigate to your component on the doc site and start building

Visit the documentation at [http://localhost:8000](http://localhost:8000) and navigate to see your README.md powered page and workbench. Changes to the README.md file will auto refresh the page.

### ESLint

Expand Down

0 comments on commit dc85dae

Please sign in to comment.