To submit changes to Nimble, the first step is to build the monorepo which requires the following to be setup:
- Sync down a copy of the nimble repository
- Note: For one-off small contributions you can consider using a fork-pull workflow. However fork-pull workflows are not yet supported for substantial development. For substantial development you should be added as a Contributor to the repository. See the
README.md
Community section to get in touch if you need Contributor permissions.
- Note: For one-off small contributions you can consider using a fork-pull workflow. However fork-pull workflows are not yet supported for substantial development. For substantial development you should be added as a Contributor to the repository. See the
- Install Node.js version 22+ (run
node --version
) and npm version 10+ (runnpm --version
) which can be downloaded from https://nodejs.org/en/download/ - Install .NET 8 SDK (
8.0.403
or higher) which can be downloaded from https://dotnet.microsoft.com/en-us/download- Run
dotnet --info
to verify the required version of the SDK is installed. Av8
install is required, but it's fine if later versions are installed too.
- Run
From the nimble
directory:
-
Run
npm install
-
Run
npm run build
-
Run
npm run storybook
to view the components in StorybookNote: As you make style changes to components you will need to refresh your browser window to see the effect.
For Visual Studio Code users, after running npm install
you can:
- Use
Terminal » Run Task…
to see a list of available tasks. - Use
Terminal » Run Build Task…
to do a full build of the Nimble monorepo.- Alternatively, you can run a full build using the shortcuts
cmd+shift+B
on Mac /ctrl+shift+B
on Windows.
- Alternatively, you can run a full build using the shortcuts
Now that you can build the monorepo see the CONTRIBUTING.md
for the packages you would like to contribute to.
This repository uses the following tooling. See below for more info.
- A monorepo containing multiple packages managed via NPM workspaces.
- Linting via ESLint following the NI JavaScript and TypeScript Styleguide
- Testing via Karma, Jasmine, bUnit, and Playwright
- Releases via beachball
- Pipelines automating the above via GitHub Actions
- Automated dependency updates via Renovate
- Nimble architecture
- Nimble Components XD Library
- Nimble Components Figma Library
- Nimble technologies walkthrough video (NI internal)
- Follow the instructions in component specs to approve the direction and create specs for interaction design, visual design, and implementation.
- Ensure base tokens and icons are available. See instructions for contributing to Nimble Tokens.
- Build the web component, including adding theme-aware tokens, documentation, and component logic. See instructions for contributing to Nimble Components.
- Add wrappers for each framework. See instructions for adding Angular wrappers. See instructions for adding Blazor wrappers.
- Publish and use! 🎉
- Documentation for consumers of Nimble should go in
README.md
files. - Documentation for contributors should go in
CONTRIBUTING.md
files. - Documentation is hierarchical throughout the repo:
- repo-wide documentation exists at the root
- package-specific documentation exists for each package
- documentation of specific utilities or components can exist next to the source or in dedicated
docs
folders throughout the repo. Be sure to link to lower-level documents from higher-level ones to aid in discovery.
- Links in documentation within the repo should use relative paths from the root of the repo (i.e.
/packages/nimble-components/docs/
, not../nimble-components/docs
). This ensures links across packages will work both on GitHub and onnpmjs.org
.
This repo generally follows the NI JavaScript and TypeScript Styleguide. Some packages list additional conventions in their CONTRIBUTING.md
.
Each pull request should add a small increment of high-quality well-tested value to Nimble. To keep PRs small you can add functionality incrementally but each PR should contain appropriate tests for the functionality being added and shouldn't introduce technical debt to be fixed later.
This repository uses beachball to automate publishing its packages to NPM. The basic workflow is as follows:
- Every pull request that affects a published package must contain a "change file" which specifies how it affects the versions of each package and includes a description of the change. Developers generate this change file by running
npm run change
before creating the pull request. - After the pull request completes, a CI pipeline will inspect the change files to generate changelogs, bump versions in package.json files, and create git tags for the updated package versions.
- A pipeline will run for each newly created git tag and invoke the
npm run publish
command for the associated package.
When generating a change file, follow these guidelines:
- Follow semantic versioning when choosing the change type. Components that are marked as incubating may use
patch
version bumps even for breaking changes. - Write a brief but useful description with Nimble clients in mind. If making a major (breaking) change, explain what clients need to do to adopt it. The description can be plain text or markdown, with newlines specified via
\n
if needed. - If you prefer not to expose your email address to the world, configure GitHub to "Keep my email address private" before generating the change file.
If a beachball publish command fails on the pipeline so packages are partially published, perform the following steps to get the repo in a good state:
- Create a branch from main which should still have change files from the failed publish and, if applicable, fix the underlying issue in the branch.
- In the repo root run
npm run sync
. Beachball will:- Find the latest packages that were published successfully to npm.
- Update the
package.json
for each of those packages to align with the latest published version. It also handles cross-dependencies, i.e. angular shows the latest version of components as its dependency. - Note: It does not handle packages that are not published to npm at all. For example, you need to manually check nuget.org for
NimbleBlazor
's published version and update thepackage.json
.
- Commit the changes from
npm run sync
and runnpm run change
for those changes. - Submit a PR for the branch and merge.
The repository runs the Dependency Review action to prevent submissions if any dependencies have known vulnerabilities. This can occur during on a PR that introduces a new dependency version or on an unrelated PR if a vulnerability was recently reported on an existing dependency. If this check fails, our options include:
- Update the direct dependency which brings in the vulnerability to a version that addresses the issue.
- If the actual issue is with a sub-dependency which has published a fix, we can update that sub-dependency via
npm audit fix
. This should be accompanied by appropriate testing of the new version. We should also ensure there is an issue on the direct dependency's repository asking them to uptake the fixed sub-dependency.
If a fix for the vulnerability isn't available or if it isn't practical to uptake the fix, our options include:
- Remove the vulnerable dependency and find a different way to achieve the same functionality.
- Dismiss the alert in the GitHub Security - Dependabot dashboard, and document your rationale for doing so. We should ensure there is an issue on the dependency's repository asking them to fix the vulnerability and also file an issue against this repository to track fixing the vulnerability and restoring strict auditing.
This repository uses Chromatic to facilitate visual component review, and adds GitHub status checks to the build pipeline. The workflow is as follows:
- The
UI Tests
status check is designed to highlight any visual changes included in the changeset. The developer (that's you!) should review theUI Tests
status check in Chromatic, and if all changes are intentional or expected, mark the components as approved. If you approve an initial build and then make further changes to a snapshot, this check will show the difference between those revisions, not between main and the latest revision. - The
UI Review
status check is designed to collect feedback from UX and visual designers. It shows the difference between the latest revision and main. Rather than blocking PR completion on this feedback, you can also approve this check by validating the story changes yourself. However, you should still demo your changes to relevant designers either in a team meeting or one-on-one. This can happen either before or after the PR completes, as long as designer feedback is addressed promptly. If you don't have access to a designer, please reach out to Nimble team members for help.
The PR pipeline also generates a live Storybook site for each PR. Developers, designers, and PR reviewers can also use this to inspect component appearance and behavior.
This repository uses automated linting and automated lint formatting. Use npm run lint
to confirm that your changes match style guidelines. If there are rules that can be autofixed they can be cleaned up by running npm run format
.
To enable linting and formatting during development, install the recommended VS Code extensions. The list of recommended VS Code extensions can be found in .vscode/extensions.json
.
The default formatter for the workspace should be already configured by .vscode/settings.json
. To configure it manually go to File >> Preferences >> Settings >> Workspace >> Text Editor >> Default Formatter
and select Prettier ESLint
. The Prettier ESLint
option assumes that the recommended VS Code extensions are installed.
You may wish to have the formatter run every time you save a file. This would help ensure you don't forget to run the formatter and end up with a failing PR build. If you want this behavior, turn it on in your user settings: File >> Preferences >> Settings >> User >> Text Editor >> Format On Save
. We leave this option unset in the workspace settings so that it does not override the user setting.
When creating a new component in the nimble-components
package, it's often sufficient to run the npm run storybook -w @ni/nimble-components
command to preview the component during development. However, when integration components with Angular or when modifying multiple packages, it's necessary to rebuild multiple components as you modify them. To run *:watch
scripts for all packages simultaneously, this repository uses VS Code Tasks to automatically launch the scripts in configured terminal tabs.
To launch the watch scripts, open View»Command palette… and type run task
. Select Tasks: Run Task
and then select Create Watch Terminals
and press enter.
You can also configure this task to execute via a keyboard shortcut by configuring the keybindings.json file to include the following:
{
"key": "ctrl+shift+\\",
"command": "workbench.action.tasks.runTask",
"args": "Create Watch Terminals"
}
This repo follows the NI code submission workflow (NI internal link) with some modifications. The general submission flow is:
- When your code is ready to submit, create a Draft pull request.
- Perform a self review of the changes. Ensure they follow conventions and that the status checks are passing.
- Add a local peer reviewer. If you are new to Nimble, also add the contact from the Nimble team who has been helping you get familiar with the repo.
- Once those reviewers have approved, mark the PR as "Ready for review". This will add owners to the review.
- Each file in a pull request requires the approval of at least one of its code owners (though in general for interesting changes we wait for everyone to review). Owners for different files are listed in
CODEOWNERS
.
If a PR requires significant refactoring at any point in this process, please move it back to Draft and re-do the steps before exiting draft.
Some of these steps may be skipped for trivial changes; please use good judgement.
Thanks for following this process! It helps reduce the burden on owners to catch smaller issues.
When completing Pull Requests, use squash merges and copy the PR description into the squash commit message. Including the PR description makes it easier to see relevant history at a glance.
Install packages using the workflow you would expect for npm workspaces and a slightly different workflow for adding Angular libraries.
To install npm packages start from the root of the repository and use npm install <new-package> --workspace=<target-package-name>
.
Example: Install five
in an npm workspace project:
npm install five --workspace=@ni/nimble-tokens
Example: Install five
in an angular-workspace project (requires peer dependency):
npm install five --save-peer --workspace=@ni/nimble-angular
Example: Add a monorepo package nimble-tokens
as a dependency to another monorepo package:
npm install @ni/nimble-tokens --workspace=@ni/nimble-components
This repository uses Renovate to automatically create pull requests that bump the version of dependencies on a schedule. Renovate is configured via renovate.json
.
Code owners are responsible for completing or rejecting Renovate PRs. Completing a PR may require manually adding a beachball change file to the branch. The change type
will typically be patch
if any package.json
or .csproj
is changing. The comment
should summarize which set of dependencies are being updated. To complete a PR you may need to manually trigger a rebase by clicking the checkbox in the PR description. Note: prefer the checkbox over GitHub's "Update branch" button so that Renovate can remain in control of all commits to its branch.
Intermittent test failures can be a huge drain on productivity as they can cause unrelated failures in builds and block merging PRs or creating releases. Particularly when accepting contributions from different timezones and from contributors outside of the Nimble team without the tribal knowledge of what tests fail intermittently.
The general policy is that intermittent failures that can fail a build, such as jasmine unit tests or chromatic status checks, should be addressed in main immediately.
Some resolutions for an intermittent test are:
- Immediately submit a PR to address the underlying issue causing the failure. This can be done if the change can be approved and merged by the end of the day that the issue was discovered and if there is high confidence in the change.
- If the underlying issue is not well-known or the fix does not give high confidence in resolving the intermittent test then the test should be disabled with
xit
and a tech debt issue created to handle the intermittent test. The disabled test should include a comment linking to the corresponding issue. Then the new issue itself must be handled as follows.
The policy is that intermittent test tech debt issues should be actively assigned and worked on. Intermittent tests should not be disabled and allowed to be unaddressed for extended periods of time.
Some ways to make progress on an intermittent test tech debt issue are:
- In a branch a developer can try and re-enable the test and reproduce the failure by including additional logging, etc. Creating a PR is not necessary to queue a build in nimble; every commit has an associated build and will re-run the tests.
- If the failure is too intermittent to detect by manually queuing builds in a branch and needs additional logging and executions in main, then modify the test so that it will not fail the test suite and add the additional logging needed to make it run in main. Actively monitor the change and have a pre-defined date to disable the test and re-evaluate how to handle the issue.