Skip to content

Latest commit

 

History

History
141 lines (88 loc) · 6.9 KB

CONTRIBUTING.md

File metadata and controls

141 lines (88 loc) · 6.9 KB

Contributing

Please read EasyPost's general contribution guidelines.

Code of conduct

Please read EasyPost's code of conduct.

Semantic versioning

Easy UI follows semantic versioning. We release patch versions for bug fixes, minor versions for new features, and major versions for breaking changes. When we make breaking changes, we try to introduce deprecation warnings in a minor version along with the upgrade path so that our users learn about the upcoming changes and migrate their code in advance.

The following sections detail what kinds of changes result in each of major, minor, and patch version bumps:

Major

  • Removal of a component
  • Removal of a prop from a component
  • Change to the type accepted for a prop
  • Breaking changes to minimum version of dependencies
  • Breaking changes to public variables, functions, and mixins

Minor

  • New component
  • New prop for a component
  • Additional type accepted for a prop
  • Deprecation of a component, prop, public variable, function, or mixin (ahead of its likely removal in the next major version)

Patch

  • Breaking change to the HTML generated by a component, including addition, removal, or renaming of classes
  • Changes that do not impact public APIs
  • Non-breaking changes to minimum version of dependencies
  • Breaking changes to private variables, functions, and mixins

Your first pull request

Easy UI is a public project so pull requests are welcome. Before working on a large change, it is best to open an issue first to discuss it with the core team.

Sending a pull request

We'll review your pull request and either merge it, request changes to it, or close it with an explanation. We'll do our best to provide updates and feedback throughout the process.

Before submitting a pull request, please:

  1. Review best practices
  2. Fork the repository and create your branch from main
  3. Run npm install in the repository root
  4. If you’ve fixed a bug or added code, make sure to add tests
  5. Ensure the test suite passes with npm test
  6. Format your code with npm run format
  7. Make sure your code lints with npm run lint
  8. Create a changeset by running npm run changes:add. More info.

Changelog

The changelog is created with Changesets.

Adding a changeset

A changeset describes changes made in a branch or commit. It holds three bits of information:

  • What packages we need to release
  • What version we are releasing packages
  • A changelog entry for the released packages

Add a changeset if you have made any changes that will require a package version bump and release:

  1. Run npm run changes:add.
  2. Select the packages you want to include using ↑ and ↓ to navigate to packages, and space to select a package. Hit enter when all desired packages are selected.
  3. Select a bump type for each selected package.
  4. Provide a message to be written into the changelog on the next release.

To check the status of changesets that currently exist run npm run changes:status. If there are changes to packages but no changesets are present, it exits with error status code 1.

Writing a changelog message

Keep the following in mind when authoring your changelog entry (final prompt after running npm run changes:add):

  • Use a positive, conversational tone (for example, use "support" over "allow" and other authoritative verbs)
  • Avoid redundancy when possible (try to phrase a bug fix entry without the word "bug")
  • Use sentence case
  • Use plain language

Out of scope for the changelog

Generally, changes related to these topics can be omitted:

  • Dev dependencies upgrades
  • Chores (infrastructure, release process, etc.)

Component API best practices

If your pull request involves changes to any component APIs, please read over our list of best practices below.

One-offs

  • We define a one-off as a deviation from best practices. We understand that one-offs are virtually inevitable, so when we create them, we should have a good reason for doing so as creating one-offs adds additional context for contributors and users as well as introduces the possibility of creating inconsistent UX.

Intuitive naming

  • Property names should be descriptive and intuitive of what they do. Intuitive names are preferred over descriptive names. For a button, urlLinkDestination is a descriptive name, but href is intuitive.

Consistent naming

  • Properties that have identical purposes across different components should share the same name. Similarly, properties that have identical purposes should also share the same type. If one component has a boolean isValid, other components that intend to control validity should do the same.

Property dependency

  • Although unavoidable at times, we should do our best to not create properties that are dependent upon another. This helps avoid configurations that lead to invalid states. If a component has multiple dependent properties, take a closer look at the overall structure of the component.

Booleans

  • Booleans should be prefixed with simple verbs. For a button, the property name isActive is preferred to active.
  • By default booleans should be false. This makes the notation a bit cleaner for when the boolean is active:
// avoid
<Button isNotDisabled={false} />
// preferred
<Button isDisabled />
  • Avoid creating booleans with hierarchical structure. If an icon component can have more than two possible placements, avoid isIconStart, isIconMiddle, and isIconEnd since we’d have to decide which variant takes precedence. Instead use an enum.

Events

  • For components that process multiple events with the same verb, they should be named with a descriptive noun in between. For a table component that needs to respond to changes to its column and row, use onRowChange and onColumnChange.

Abstractions

  • Abstractions are really difficult to get right and reason about. No abstraction is preferred to clunky abstractions. Ideally we want our components to be as composable as possible.
  • For components that need to render a subcomponent, use the slot paradigm of cloning the React element.

Styling

  • Components should not expose the className property as we run the risk of creating inconsistent UX.