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 linter
  • bun run test — run unit tests
  • bun run test:e2e — run Playwright E2E tests
  • bun test:src-types — type-check src/ (uses tsconfig.types.json)
  • bun test:types — run svelte-check on *.svelte and .ts files in tests/

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:

FilePurpose
e2e/fixtures/MyComponentFixture.svelteSvelte component that renders the component under test. Use data-testid on elements you want to query.
e2e/fixtures/my-component.tsEntry script that mounts the fixture into #app. Use the shared mount() utility from ./mount.
e2e/fixtures/my-component.htmlHTML page with <div id="app"></div> and a script tag loading the entry module.
e2e/my-component.test.tsPlaywright 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. Prefer toHaveClass(/is-visible/) on the container, or assert on aria-hidden / inert instead.
  • Strict mode: getByText("Row 1") matches "Row 10", "Row 11", etc. Use getByRole("cell", { name: "Row 1", exact: true }) or more specific selectors when content can match multiple elements.
  • Add a link to e2e/fixtures/index.html so 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:docs to 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:

  1. 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).

  2. Publish the release as the latest release.

  3. 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).