Welcome and thank you for contributing! The Recipe team is committed to maintaining consistent, quality components and guidelines. We welcome all feedback, designs, or ideas to produce the best possible experience for our users. Below are the contribution guidelines for contributing.
Never be shy about reporting a bug or challenge with Recipe. The system can only get better if we understand how its being used in the real world by downstream applications.
The process for fixing bugs is simpler than for evolving the system, and we really encourage squads to help fix bugs instead of working around them or waiting for the Recipe team to fix. Workarounds are brittle and only help your team in the short term. Contributing a fix makes Recipe better for everyone.
Please start by filing a GitHub issue against the Recipe project. After filing we hope that you'll consider contributing a fix.
src/unreleased.md
with a summary of the changes made, following our versioning guidance to categorize changes into appropriate headings.Recipe follows a changesets workflow allowing contributors to declare how their changes should be released alongside their code commits, such that updating package versions, changelogs and publishing can all be automated.
When a contributor is preparing a branch to submit as a pull request, we need to capture the "semver bump type" (i.e. Major, Minor, Patch) with a summary of the changes made. In order to capture this information, the contributor should run:
yarn changeset
and answer the provided questions. The changeset command will be write a Markdown file that contains the summary and metadata to store data about the package(s) that will be released and the semver bump types for them. This file should then be committed to git. Committing the changeset file within the same commit the summarized change was applied is ideal, as it will associate the changeset with the commit sha of the actual change. We recommend following following our versioning guidance for the format of the changeset message in order to help communicate what impact the changeset contents have on the next version.
When a release is cut, we use this changeset metadata to version bump Recipe to an appropriate number, combining multiple changesets into a single coordinated release.
Write usage documentation. Document the design decisions you’ve made and explain how this new component should be used. Some good questions to answer are:
All components belong in src/components
within their own folder.
Component names should be in the singular form and should be prefixed with Ez
.
Example:
📦 recipe┗ 📂 src┗ 📂 components┗ 📂 EzExample┣ 📂 __tests__┃ ┗ 📜 EzExample.test.tsx┣ 📂 Implementations┃ ┣ 📜 EzExampleImplementation.tsx┃ ┗ 📜 index.ts┣ 📜 EzExample.tsx┣ 📜 EzExample.md┣ 📜 EzExample.preview.md┣ 📜 EzExample.types.ts┗ 📜 index.ts
Index files should NOT contain any logic and should only be used to provide exports of named components.
In order to create a consistent directory structure, Recipe provides tooling to help you get started creating components.
Recipe uses plop to quickly generate boiler plate code for a new React component that follows our folder structure and naming scheme.
To generate a new component, run yarn create-component
inside packages/recipe
or use the workspace command via yarn workspace @ezcater/recipe create-component
. You'll see a CLI that guides you through the process. Alternatively, you can simply run yarn create-component EzExample
, where EzExample is the name of your new component.
If your component needs a preview image for the doc site, you will also need to run yarn create-preview ../recipe/src/components/EzExample/EzExample.preview.md
from packages/snapshot
.
New component requirements:
Recipe's documentation is generated from its source code. To supplement this autogenerated documentation, you'll need to create and modify a markdown file associated with your component. By default, the markdown file is created for you when you create your component and provides the structure you need to document your component and provided live examples.
Inside the markdown file, any fenced code block decorated with the jsx
language identifier will be enhanced with a live editor on the doc site. You should use fenced code blocks to provide examples of your components in various supported states in order to document the component's features.
Example:
### Basic ButtonsEzButton supports `filled` (default), `outlined`, and `text` variants.```jsx<EzLayout><EzButton>Filled</EzButton><EzButton variant="outlined">Outlined</EzButton><EzButton variant="text">Text</EzButton></EzLayout>```
When a change to a property, feature, or component in Recipe requires a breaking change, we can give users more time to react to these changes by deprecating these features before entirely removing or overhauling them at a later time.
Add a deprecation warning alert to the appropriate doc site page to let users know the feature has been deprecated. Also note what major version we expect to remove the deprecated feature to minimize confusion and encourage action.
If the deprecation is related to a theming change, add a reference to it in src/themes/deprecated.ts
.
export const deprecatedColors = {set: new Set(['green', 'white']),warning: `*Recipe Deprecation*. The colors 'green' and 'white' are deprecated and will be removed in a future version of Recipe. Use 'common.green' and 'common.white' instead.`,};
Then add a console log warning in the affected component if it detects a deprecated property was used. This will help developers become aware of new deprecations so they can address them.
import warning from 'tiny-warning';import {deprecatedColors} from '../../../../themes/deprecated';...warning(!deprecatedColors.set.has(color), deprecatedColors.warning);...
Finally, you can add a test for the affected component to verify the warning is being output correctly.
import warning from 'tiny-warning';jest.mock('tiny-warning');const warningMock = warning as jest.Mock<typeof warning>;describe('EzIcon', () => {beforeEach(() => {warningMock.mockReset();});it('should log a warning if a deprecated color is used', () => {render(<EzIcon icon={SVG_ICON_BURGER} color="green" />);expect(warningMock).toHaveBeenCalledWith(false,"*Deprecated*. The colors 'green' and 'white' are deprecated and will be removed in a future version of Recipe. Use 'common.green' and 'common.white' instead.");});});
When the deprecated feature is ready to be removed, remove the feature along with all associated alerts and warnings. Be sure to note the breaking change in the migration guide for the major version release.
Clone the repository and install dependencies:
yarn install
The doc site provides live examples to demonstrate the various states of your components, and explain how each state is used.
We strongly encourage using documentation to drive your component design. Having detailed usage guidelines and a complete API promotes clear systems thinking and is a huge timesaver for preventing churn in the PR.
The doc site is a great environment to start developing your component as the environment has hot reloading and components can be added on the fly through various doc files. Any file in the src/components
folder with an .md
extension and corresponding front matter (including name
, title
and path
) will run in the doc site automatically. Any JSX examples will turned into a live playground for your component.
You can run the doc site as follows:
yarn develop
This command will start a server and open your browser to http://localhost:8000/ to see the doc site. The server will watch your local file system and will hot reload the doc site as you make changes.
If you want to test your local component code from within your application, you'll need to setup a link.
First setup the link from the recipe package you wish to use (such as packages/recipe
):
yarn link
Then setup the link in the root of your application:
cd my-application-directoryyarn link @ezcater/recipe
You may need to rebuild recipe to see your changes.
yarn develop # or `yarn workspace @ezcater/recipe develop` to just run the recipe build script
NOTE: When using yarn link
, a common issue is having multiple instances of React, which results in the error hooks can only be called inside the body of a function component
. This isn't a Recipe specific issue, but rather specific to React hooks and yarn link. See the following link for help with this issue.
Alternatively, you can open a draft PR with your changes, then add the deploy
label to your PR on github. A github action will build a canary release of your branch and add a comment to the PR with the version info. Update your application to use this version and you can test your changes. If you push more changes to your recipe branch and need a new canary build, just remove and add the deploy
label to get a new release.
Testing in recipe is extremely important to ensure the quality of our downstream products. We therefore expect components to have 100% code coverage.
To run tests, run:
yarn test
This command will run the full test suite and output code-coverage statistics using istanbul. To view a breakdown of the coverage (statements, branches, functions and lines covered), you can view the coverage report (found in /recipe/coverage/lcov-report/index.html
) in your browser.
To continuously watch and run tests, run:
yarn test:watch
After contributing updates to recipe, you'll need to publish the recipe package for changes to take effect in downstream projects.
Recipe uses the Changesets Release github action to automate the process of creating a pull request for an up-versioned Recipe release. This process uses the semantic versioning metadata captured as part of our development process. When an automated versioning PR is merged, a new Recipe release will be published to npm on your behalf.