Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@
**/PublicAPI-test.js @carbon-design-system/developers-system-admins @carbon-design-system/monorepo-reviewers
**/PublicAPI-test.js.snap @carbon-design-system/developers-system-admins @carbon-design-system/monorepo-reviewers

# Admins and leads should be notified of changes to CI/CD workflows
# codeowners, and any other config present in .github.
# Admins and leads should be notified of changes to these.
# This should always be the last entry in this file.
/.github/ @carbon-design-system/developers-system-admins @carbon-design-system/monorepo-reviewers
/.github/CODEOWNERS @carbon-design-system/developers-system-admins @carbon-design-system/monorepo-reviewers
**/AGENTS.md @carbon-design-system/developers-system-admins @carbon-design-system/monorepo-reviewers
42 changes: 42 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -476,3 +476,45 @@ jobs:
echo "- Storybook deploy preview: ${{ env.storybookUrl }}" >> $GITHUB_STEP_SUMMARY
echo "- Commit: ${{ github.event.pull_request.head.sha }}" >> $GITHUB_STEP_SUMMARY
echo "- Chromatic build URL: ${{ env.buildUrl }}" >> $GITHUB_STEP_SUMMARY

flag-agents-md-changes:
runs-on: ubuntu-latest
steps:
- name: Detect AGENTS.md changes
id: changes
uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2
with:
filters: |
added_or_modified:
- added|modified: '**/AGENTS.md'

- name: Post PR comment (if not already present)
if: steps.changes.outputs.added_or_modified == 'true'
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
with:
script: |
const marker = "<!-- agents-md-comment -->";

const body = `${marker}
⚠️ An AGENTS.md was added or updated in this PR. The length of these files directly correlate with token usage, increased instruction length, and spend. Please follow [best practices](https://www.aihero.dev/a-complete-guide-to-agents-md) and leave a comment explaining why this change is needed.
`;

const { data: comments } = await github.rest.issues.listComments({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
per_page: 100
});

const alreadyCommented = comments.some(comment =>
comment.body?.includes(marker)
);

if (!alreadyCommented) {
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body
});
}
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ lib
dist
umd
css
docs/generated

# Netlify deploy folder
/demo/*
Expand Down
66 changes: 66 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
<!--
HUMAN MAINTAINERS:
This file should be as short as possible. More length = more tokens used.
-->

This is a monorepo for IBM's Carbon Design System that contains React
components, web components, Sass styles, foundational elements (colors, grid,
icons, pictograms, layout, motion, themes, type), and tooling.

# Repository Guidelines

- The correct Node version to use is present in `.nvmrc`
- Yarn workspaces manage dependencies and package relationships
- `package.json` scripts make use of Lerna for build and task sequencing

## Workflow details

- Avoid scanning the entire repo as a first step. Start from the most necessary
surface for the task and expand or drill down only when necessary
- Follow the coding style guide, see `docs/style.md`
- Follow the developer guide, see `docs/developer-handbook.md`
- Project decisions are recorded through Architecture Decision Records (ADRs) in
`docs/decisions/`
- For procedural instructions on various tasks for maintainers, see
`docs/guides/`
- The approach for delivering experimental, feature-flagged, "preview" code:
`docs/experimental-code.md`, `docs/feature-flags.md`, `docs/preview-code.md`
- Linting, formatting, build and tests should all pass before committing
- Before opening or reviewing a pull request (PR), follow the instructions:
`docs/guides/reviewing-pull-requests.md`

## Package relationships

- The packages contained within this monorepo and published to NPM are
intentionally layered on top of each other. Higher-level packages re-export or
wrap lower-level packages.
- A directory-to-package mapping is generated from the build:
`docs/generated/package-structure.json`
- A detailed graph of packages and their relationships is generated from the
build: `docs/generated/package-structure-graph.json`

## Package-specific details

- A dual-flagship model is followed for `@carbon/react` and
`@carbon/web-components`. These two are intended to provide an equal
experience for consumers choosing to build with either library. Visual and
functional parity are paramount, though the implementations themselves are
allowed to diverge as necessary. Opportunities to unify logic between the two
can be considered and surfaced as an option when appropriate. Framework
conventions should be prioritized over logic unification when beneficial to
either/both packages in areas included, but not limited to, performance
optimization and ease of maintenance.
- `carbon-components` is a deprecated package that re-exports `@carbon/styles`
- `carbon-components-react` is a deprecated package that re-exports
`@carbon/react`

## End user/practitioner guidance

If the task is complicated and specialized enough to require it, there is
external documentation focused towards end users of the system (designers,
developers, product managers)

- Detailed design and usage information for the system as a whole:
https://github.com/carbon-design-system/carbon-website/tree/main/src/pages
- Developer-focused, component-specific usage docs are surfaced through
storybook and housed in colocated `.mdx` files.
52 changes: 52 additions & 0 deletions docs/package-structure.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# Package structure

The packages contained within this monorepo and published to NPM are
intentionally layered on top of each other. Higher-level packages re-export or
wrap lower-level packages. This sometimes paints a confusing picture of what
packages exist, which to use, and what others' purpose is relative to the ones
currently in use.

## Layer 0: Elements

These packages have minimal or zero dependency on the rest of the design system.
They use the IBM Design Language as foundational guidance and a single source of
truth.

- `packages/colors` -> `@carbon/colors`
- `packages/grid` -> `@carbon/grid`
- `packages/icons` -> `@carbon/icons`
- `packages/pictograms` -> `@carbon/pictograms`
- `packages/layout` -> `@carbon/layout`
- `packages/motion` -> `@carbon/motion`
- `packages/themes` -> `@carbon/themes`
- `packages/type` -> `@carbon/type`

This may not be an exhaustive/current list.

## Layer 1: Primitives

These packages import and use the elements packages to provide low level
building blocks, helpers, and tooling.

- `packages/styles` -> `@carbon/styles`
- `packages/icons-react` -> `@carbon/icons-react`
- `packages/icons-vue` -> `@carbon/icons-vue`
- `packages/pictograms-react` -> `@carbon/pictograms-react`
- `packages/upgrade` -> `@carbon/upgrade`
- `packages/utilities` -> `@carbon/utilities`
- `packages/utilities-react` -> `@carbon/utilities-react`

This may not be an exhaustive/current list.

## Layer 2: Components

These are the canonical design system component implementations that incorporate
packages in the lower layers. In some cases, lower layer packages are exposed
directly through these, removing the need for consumers to install the lower
level packages. One example is how `@carbon/react` makes available
`@carbon/styles` and `@carbon/icons-react` assets.

- `packages/react` -> `@carbon/react`
- `packages/web-components` -> `@carbon/web-comonents`

This may not be an exhaustive/current list.
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
"www"
],
"scripts": {
"build": "lerna run build --stream --prefix",
"build": "lerna run build --stream --prefix && node tasks/generate-repo-structure.js",
"ci-check": "carbon-cli ci-check",
"clean": "lerna run clean && lerna clean --yes && rimraf node_modules",
"doctoc": "doctoc --title '## Table of Contents'",
Expand All @@ -24,10 +24,10 @@
"lint": "eslint actions config packages www",
"lint:fix": "eslint --cache --fix --max-warnings 0 actions config packages www",
"lint:styles": "stylelint '**/*.scss' --report-needless-disables --report-invalid-scope-disables",
"postinstall": "husky",
"telemetry:config": "lerna run telemetry:config",
"test": "cross-env BABEL_ENV=test jest",
"test:e2e": "cross-env BABEL_ENV=test jest -c jest.e2e.config.js",
"postinstall": "husky"
"test:e2e": "cross-env BABEL_ENV=test jest -c jest.e2e.config.js"
},
"resolutions": {
"@types/react": "~19.2.0",
Expand Down
38 changes: 38 additions & 0 deletions packages/react/AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# `packages/react`

This package houses the canonical react component implementations.
`@carbon/react` is intended to be a single point of entry for most everything a
consumer needs to build a React app with the Carbon Design System. Styles are
re-exported from `packages/styles` and icons are re-exported from
`packages/icons-react`.

## Guidelines

- Follow React best practices and common conventions
- Prefer composable declarative solutions over inheritable or imperative ones
- Don't query the DOM directly, use refs where possible
- You might not need a `useEffect` when updating state based on props or state,
caching expensive calculations, resetting all state when a prop changes,
adjusting some state when a prop changes, sharing logic between event
handlers, sending a POST request, chains of computations, initializing the
application, notifying parent components about state changes, passing data to
the parent, subscribing to an external store, and fetching data. Refer to
https://react.dev/learn/you-might-not-need-an-effect only when unable to
determine a clean non-effect approach.

## Component folder structure

For `packages/react/src/components/`:

```
ComponentName/
├── index.tsx // Re-exports
├── ComponentName.tsx // Main component
├── ComponentName.stories.js // Storybook stories
├── component-name-story.scss // Styling for storybook stories
├── ComponentName.mdx // Storybook mdx docs
└── __tests__/
│ └── ComponentName-test.js // Unit tests
└── docs/
└── overview.mdx // Demo file consumed by external documentation
```
17 changes: 17 additions & 0 deletions packages/styles/AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# `packages/styles`

This package houses a hierarchy of Sass files that have a main entrypoint of
`packages/styles/index.scss`. It `@use`'s, `@forward`'s, `@include`'s and
re-exports style modules/files built in all the elements packages to provide
consumers a single entrypoint for all areas of the design system: colors, grid,
icons, pictograms, layout, motion, themes, type. In addition it houses primary
styles that are used with component implementations in `packages/react`,
`packages/web-components`. It makes use of the Sass module system to ensure
styles are only included once and not duplicated.

## Guidelines

- Use current Sass authoring practices such as `@use`
- Stylelint must pass, config in `config/stylelint-config-carbon`
- Testing files: `__tests__/`, though most all tests are housed upstream in the
elements packages
24 changes: 24 additions & 0 deletions packages/web-components/AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# `packages/web-components`

This package houses the canonical web component implementation of the design
system components.

## Guidelines

- Follow best practices and common conventions for Web Components

## Component folder structure

For `packages/web-components/src/components/`:

```
component-name/
├── index.ts // Re-exports
├── component-name.ts // Main component
├── component-name.scss // Web-component-specific styling
├── component-name.stories.ts // Storybook stories
├── component-name-story.scss // Styling for storybook stories
├── component-name.mdx // Storybook mdx docs
└── __tests__/
│ └── component-name-test.ts // Unit tests
```
46 changes: 46 additions & 0 deletions tasks/generate-repo-structure.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/**
* Copyright IBM Corp. 2026
*
* This source code is licensed under the Apache-2.0 license found in the
* LICENSE file in the root directory of this source tree.
*/
import { execSync } from 'node:child_process';
import { writeFileSync, mkdirSync } from 'node:fs';
import { relative, dirname } from 'node:path';

// Resolve repo root so paths are always relative to it
const repoRoot = execSync('git rev-parse --show-toplevel', {
encoding: 'utf8',
}).trim();

// ---- Packages ----
const structureOutputPath = 'docs/generated/package-structure.json';
const rawPackages = execSync('yarn lerna list --all --long --json', {
encoding: 'utf8',
});

const packages = JSON.parse(rawPackages)
.map((pkg) => ({
name: pkg.name,
path: relative(repoRoot, pkg.location),
private: pkg.private,
}))
.sort((a, b) => a.name.localeCompare(b.name));

// Ensure the directory exists
mkdirSync(dirname(structureOutputPath), { recursive: true });
writeFileSync(structureOutputPath, JSON.stringify(packages, null, 2) + '\n');
console.log(`✓ wrote ${structureOutputPath}`);

// ---- Graph ----
const graphOutputPath = 'docs/generated/monorepo-internal-graph.json';
const rawGraph = execSync('yarn lerna list --all --graph', {
encoding: 'utf8',
});

mkdirSync(dirname(graphOutputPath), { recursive: true });
writeFileSync(
graphOutputPath,
JSON.stringify(JSON.parse(rawGraph), null, 2) + '\n'
);
console.log(`✓ wrote ${graphOutputPath}`);