Contributing
March 28, 2026 · View on GitHub
Before submitting a pull request (PR), consider filing an issue to gain clarity and direction.
Prerequisites
Codebase
Project set-up
Fork the repo and clone your fork:
git clone <YOUR_FORK>
cd carbon-components-svelte
Set the original repository as the upstream:
git remote add upstream git@github.com:carbon-design-system/carbon-components-svelte.git
# verify that the upstream is added
git remote -v
Install
Install all dependencies (root and docs) and generate TypeScript definitions and docs/src/COMPONENT_API.json:
bun setup
This single command runs bun install in both the project root and docs/, then runs bun build:docs.
Documentation set-up
Component documentation is located in the docs folder. The site uses Vite, Routify 3, Svelte 5, and MDsveX. The Vite config resolves carbon-components-svelte to the repository root, so edits under src/ are picked up without a separate package link.
After running bun setup, start the docs dev server:
cd docs
bun dev
The site should be served at http://localhost:5173/ (or the next available port).
Development workflow
Create a topic branch from master. Keep your PR focused and branch up-to-date with upstream master.
git checkout -b new-feature
Preview changes to components from the src folder in the documentation website located in docs/.
Component Format
Each component should adopt the following structure:
src/Component
│
└───Component.svelte // main component
└───ComponentSkeleton.svelte // Skeleton component (if applicable)
└───index.js // export components
Type definitions (*.svelte.d.ts and src/index.d.ts) are generated by bun build:docs (sveld) into src/ and are gitignored.
Editing a component
If adding or editing an exported component prop, be sure to annotate its value using JSDoc conventions.
/**
* Specify the size of the component
* @type {"sm" | "default" | "lg"}
*/
export let size = "default";
Creating a component
First, submit an issue.
If creating a new component, don't forget to add it to src/index.js:
export { CopyButton } from "./CopyButton";
export { ComboBox } from "./ComboBox";
+ export { FixedComboBox } from "./FixedComboBox";
export {
ComposedModal,
ModalHeader,
ModalBody,
ModalFooter,
} from "./ComposedModal";
Run bun run build:docs
Run the following command to re-generate TypeScript definitions in src/ and docs/src/COMPONENT_API.json.
bun run build:docs
Checks
bun run lint— run Biome linterbun run test— run unit testsbun run test:e2e— run Playwright E2E testsbun test:src-types— type-checksrc/(usestsconfig.types.json)bun test:types— runsvelte-checkon*.svelteand.tsfiles intests/
Testing
Unit tests
Unit tests live in tests/ and use Vitest with @testing-library/svelte. Run them with bun run test.
E2E testing with Playwright
E2E tests run in a real browser against HTML fixtures served by Vite. The Playwright config is in playwright.config.ts; the Vite config for fixtures is in e2e/vite.config.ts.
Run the full suite:
bun run test:e2e
Run a focused component or pattern:
# Single test file
bunx playwright test e2e/breakpoint.test.ts
# Tests matching a grep pattern (e.g. "Breakpoint" or "sm breakpoint")
bunx playwright test --grep "Breakpoint"
Adding a new E2E test — use the Breakpoint example as a template. Create these files:
| File | Purpose |
|---|---|
e2e/fixtures/MyComponentFixture.svelte | Svelte component that renders the component under test. Use data-testid on elements you want to query. |
e2e/fixtures/my-component.ts | Entry script that mounts the fixture into #app. Use the shared mount() utility from ./mount. |
e2e/fixtures/my-component.html | HTML page with <div id="app"></div> and a script tag loading the entry module. |
e2e/my-component.test.ts | Playwright tests. Use page.goto("/my-component.html") in beforeEach, then page.getByTestId(...) to assert. |
Example fixture mount (my-component.ts):
import MyComponentFixture from "./MyComponentFixture.svelte";
import { mount } from "./mount";
mount(MyComponentFixture);
Notes:
- Visibility assertions: For components that hide content with CSS (e.g. ComposedModal),
toBeVisible()can be unreliable because the element stays in the DOM. PrefertoHaveClass(/is-visible/)on the container, or assert onaria-hidden/inertinstead. - Strict mode:
getByText("Row 1")matches "Row 10", "Row 11", etc. UsegetByRole("cell", { name: "Row 1", exact: true })or more specific selectors when content can match multiple elements. - Add a link to
e2e/fixtures/index.htmlso the fixture is reachable from the index page.
Submit a Pull Request
Sync Your Fork
Before submitting a pull request, make sure your fork is up to date with the latest upstream changes.
git fetch upstream
git checkout master
git merge upstream/master
Submit a PR
After you've pushed your changes to remote, submit your PR. Make sure you are comparing <YOUR_USER_ID>/feature to origin/master.
Maintainer guide
The following items only apply to project maintainers.
Release
This library is published to NPM with provenance via a GitHub workflow.
The workflow is automatically triggered when pushing a tag that begins with v (e.g., v0.81.1). It uses Bun to run bun ci, bun build:docs, and bunx culls --preserve=svelte before publishing to NPM.
However, maintainers must perform a few things in preparation for a release.
Locally, while on master and the branch is clean, run bun run release. This command will:
- Bump the semantic version in
package.json - Generate notes in
CHANGELOG.md - Run
bun run build:docsto update the generated documentation
This command will not create a commit nor tag. Afterwards, perform the following manually:
# 1. Commit the changes using the new version as the commit message.
git commit -am "v0.81.1"
# 2. Create a tag.
git tag v0.81.1
# 3. Push the tag to the remote.
# This will trigger the `release.yml` workflow to publish a new package to NPM (with provenance).
git push origin v0.81.1
If all goes as expected, the release.yml workflow should trigger a new run and publish the new version to NPM.
Post-release checklist
After confirming that the new release is published to NPM, perform the following:
-
Create a new release on GitHub. Click "Generate release notes" to automatically list changes by commit with the relevant Pull Request and author metadata. You may manually remove notes that are not relevant to the release (e.g., CI changes).
-
Publish the release as the latest release.
-
As good practice, visit the Pull Request and/or issue for each commit and manually confirm that it's been released. This is helpful for future readers to understand what version includes the new feature or fix.
Released in [v0.81.1](https://github.com/carbon-design-system/carbon-components-svelte/releases/tag/v0.81.1).