Learn how to contribute, including general guidelines, running the project locally, publishing, and creating new components.
We’re excited that you’d like to contribute to Pluma. We are currently only accepting contributions from Customer.io employees.
Pluma uses pnpm workspaces. To use the expected tool versions, run:
Install dependencies and build the workspace from the repo root:
For day-to-day development, start the full local environment:
For docs-only work, run:
Most changes that affect published packages need a changeset. Create one from the repo root:
Select the changed package, choose the version bump, and commit the generated changeset file with your PR. Changesets will use that file later to update package versions, changelogs, and published packages.
If you need to test a package in another app before release, create a snapshot build after adding a changeset:
Snapshot version changes are local publishing artifacts and should not be committed.
Use the component generator from the repo root:
The generator creates the React and Ember component files, shared styles, docs, stories, and tests, then updates the relevant entrypoints. For a subcomponent, run:
Component docs should live next to the component as {component-name}.docs.mdx. In docs examples, import Pluma modules through @customerio/pluma-components instead of relative source paths so examples match how consumers use the package.
We have some rules around how to design a good API for a component.
When adding a new property or changing an existing one, you should follow these rules:
is or has when affecting state - e.g. isOpen, isHovered, hasErroron for events or callbacks - e.g. onOpen, onClose, onHovershould when affecting behavior - e.g. shouldCloseOnOverlayClick, shouldCloseOnEscapearia when affecting accessibility - e.g. ariaLabel, ariaDescribedBywith when conditionally rendering something - e.g. withIcon, withArrow, withOverlaySpecific names:
isError when affecting the error stateisDanger when the style indicates a destructive actionisDisabled when the component is disabledTo ensure consistency, use semantic names like critical, success, caution, and information instead of raw color names like red, yellow, or blue whenever possible. Colors that don't have a semantic name should use their presentational color name (i.e. plum).
Components should make it easy to get accessibility right. This means:
aria-* attributes when necessaryrole attributetabIndex attributeFollow the ARIA Authoring Practices Guide (APG) when creating a new component.
When designing a component with multiple sizes you should probably use a size property. It should take shorthand values. For example, size="sm" or size="lg". Long hand values (i.e. size="small") are not extensible and should be avoided.
The one exception to this is font weights where we follow browser standards and use size="normal", size="bold", etc.
When designing a component with multiple variants you should probably use a variant property. It should almost always just take the following:
primarysecondarytertiarysubtleDanger variants should be done through a isDanger property, so it can be combined with other variants.
By default, variant should be secondary.
Whenever you are creating a component that can contain multiple parts (i.e. a tooltip has a trigger and content), you should use multiple components that compose together. This allows us to have the same API between React and Ember. If most of the use-cases are strings for one of the parts, add a property that takes a string and does the composition to make it easier for the developer to get right.