- When does a component go in the design system?
- Release Process
- Prerelease Process
- Maintaining Assets
- Git Strategy
- Code Standards
- Code Style
- Rules
- Build process
- ES Modules
Thanks to changeset, we can generate version bumps automatically.
- Ensure that
develop
branch is up to date withmaster
. Run these commands ondevelop
branch - Run
pnpm changeset
in the root of the repository and follow CLI instructions to generate a new changeset. - Run
pnpm changeset version
command. This will bump the versions of the packages previously specified with pnpm changeset (and any dependents of those) and update the changelog files. - Run
pnpm install
. This will update the lockfile and rebuild packages. - Commit the changes. (e.g
git add .
andgit commit -m "chore: bump version X.X.X"
) - Push your changes.
- Raise a pull request from
develop
intomaster
. - Obtain at least 1 approval.
- Click the "Merge Pull Request" button to trigger an automatic release, monitoring progress in CircleCI.
- Tag a version and push your tag (
git tag vX.X.X
andgit push && git push --tags
) - Communicate the release to the team!
You might want to release a version of your packages before you do an actual release, Changesets lets you do this but there are some caveats because of the complexity that monorepos add that are important to understand.
When you want to do a prerelease, you need to enter prerelease mode. You can do that with the pre enter . The tag that you need to pass is used in versions(e.g. 1.0.0-beta.0) and for the npm dist tag.
A prerelease workflow might look something like this:
pnpm changeset pre enter alpha
pnpm changeset
pnpm changeset version
pnpm install
git checkout -b "feat/prerelease"
git add .
git commit -m "Enter prerelease mode and version packages"
pnpm changeset publish
git push --follow-tags
pnpm changeset pre exit
Icons are exported from Figma and stored in the adjacent svg
directory.
Each icon must:
- have it's own
32×32
artboard.- in other words, a
viewBox
that is at least32
on one axis:- good:
viewBox="0 0 32 18"
,viewBox="0 0 32 32"
. - bad:
viewbox="0 0 20 34"
.
- good:
- in other words, a
- contain only one exportable layer, which has:
- a single path or group.
- a kebab-case layer name prefixed with
icon-
- this is essential for the build step.
- the export format defined as "SVG".
- have its color fill set to
#DE1E7E
(remember "DELETE") if you want the color to be modified.
Any changes to this Sketch file should be committed as well as the Sketch-generated SVGs. To export all SVGs in Sketch, select File > Export
and in the next step choose the svg
directory as the output location.
For performance benefits (such as code-splitting) we opted for creating individual React components for each icon, rather than one single component.
We make use of SVGR, to transform the above SVG icons in assets
to React components in moon-icons
.
To update/add icons run: yarn assets build
- Runs SVGR based on the config options.
- Builds React
.tsx
files for each component with the template.
Commits follow the Angular Commit Message Format. When committing changes, make use of the Commitizen CLI to generate consistent commit messages:
pnpn run commit
As a developer, you will you be branching and merging from develop
, our base branch.
Consider origin/master
to always represent the latest code deployed to production.
Use supporting branches for all new features and bug fixes. Unlike the base branch, these branches have a limited life-time and should be removed after merging.
The different types of branches should be named as follows:
- Feature:
feature/feature-name
- Bug fix:
fix/fix-name
-
Create the branch locally and then push to GitHub if it does not exist yet.
A branch should always be 'publicly' available, and should never exist in just one developer's local repo.
-
Make a pull request.
-
Add the
in progress
tag until ready for review. -
Periodically, keep changes up to date with develop via
git rebase develop
. -
Grab a review and remove the
in progress
tag. -
One approved, it's down to you to merge the branch into
develop
. Code can only be contributed todevelop
via using pull requests. -
Delete your branch.
git checkout develop
git pull
git checkout your-branch
git rebase develop
Long-lived feature branches present problems when you need to build code on top of unfinished work. Merge unfinished features into the develop
branch (following the steps outline above) so others can build off their work, but keep them hidden from your users and testers behind feature flags. Enable the flag in development to use the feature without the changes affecting anyone else. Once the feature is finished, you can remove the flags or use them to roll out to selected users and testers.
All features should attempt to conform to as many items on The A11Y Project's Web Accessibility Checklist as possible. If a checkbox can't be completed, the justification should be documented for future reference.
As part of our TypeScript linting process, we make use of react-a11y
rules (surfaced via tslint-microsoft-contrib
) to catch any common issues. react-a11y-role-has-required-aria-props
is currently disabled for incorrect results.
Mobile devices are the most commonly used methods of browsing the web. When it comes to designing and developing your component, always build with mobile in mind first.
Need to modify the style at specific breakpoints? Scale your changes upwards; build for mobile by default and then add media queries for changes on larger sizes.
Want to use CSS Grid? Set your component to display: block;
by default to stack items on mobile and other unsupported devices, then implement your grid at larger breakpoints.
Code formatting is handled automatically via Prettier on pre-commit. However, you could install an IDE extension or run manually via yarn format <prettier-args>
.
Linting will catch any further non-formatting issues:
- TSLint
- Config: tslint.json
- Note: As TSLint does not yet support TypeScript project
references
(palantir/tslint#4137), TSLint must be executed vialerna run
to treat each package correctly.
Before contributing new component in design system need to determine should it be put to core package or should be created new package for this component. For this you need follow the rule: if the components has complicated logic or some external dependencies - for it should be created new package.
Please stick to a directory style to make things visually easier to track new component:
- the new component should be placed in separate folder and be given corresponding name (more details about the naming below);
- styled component shoud be placed in
styles
folder. But only the ones used for this folder component. If any component down the tree needs styled stuff, they should have their own folder for it; - all component's logic better to moove to the hook and create a folder or file with the hook name;
- all the nested components should be placed in folder
private
; - from the main file should be exported outside, only one component and it's interface;
For a basic component, the directory structure would look something like this:
+————————————+
│ Badge │
+————————————+
components
├── badge
│ ├── styles
│ ├── Container.ts
│ └── Badge.tsx
└── …
For larger components, consider breaking down into smaller partials:
components
├── singleSelect
│ ├── private
│ ├── styles
│ ├── SearchWrapper.ts
│ ├── Options.tsx
│ ├── SingleSelectWithContext.tsx
│ ├── styles
│ ├── Container.ts
│ ├── SelectLabel.ts
│ └── SingleSelect.tsx
└── …
!! Any styled components created should be .ts and not .tsx. The same goes for custom hooks, if you need to make them .tsx, it means they are not just styled components anymore.
!! All what was placed in private
and styled
folders exlude from export outside, baced on barrelsby config.
-
Components should be defined in PascalCase.
For example:
<ComponentName/>
-
Component partials should be prefixed by the component name:
For example:
<ComponentNameTitle/>
-
Each component feature must have a corresponding description page in next-docs/pages/components
with code exepmples of all possible states.
- All your files should be named after the actual component. So the component
GroupIconCurrency
is inside the fileGroupIconCurrency.tsx
. - All your components should export a single default React component. This is only so we can enable tree shaking.
- All first level subfolders inside
/src/
are considered public. People will useimport { } from @heathmont/moon-package-name/folder
to import files from those folders directly. - You are required to auto-generate an index file to for each subfolder which uses named exports to re-export all exports inside the folder + sub folders. This is required for tree shaking.
- You are required to auto-generate an index file to for your package which uses named exports to re-export all exports. This is required to allow lerna to import the project proeprly.
All packages are built in 2 separate formats, commonjs
and es
.
All code belongs in /src
folder. When running yarn build, it will automatically generat a lib
folder based on the code
inside src
.
First we transpile commonjs
format modules into the lib
folder directly.
Second we transpile es
format modules into the lib/es
folder.
Third we generated typescript definitions into the lib
folder directly.
Before we release, we will:
- Copy all files from
lib
folder into the root folder. - Update the
files
,main
,module
andtypings
fields in package.json
After we release, we will:
- Remove all the files we copied over from
lib
. - Undo the changes to
files
,main
,module
andtypings
fields in package.json