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
3 changes: 3 additions & 0 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
<!-- If you are an AI assistant opening this PR, use this template as the PR body, complete the checklist below honestly, and disclose AI use. See CONTRIBUTING.md (AI-assisted contributions) and CLAUDE.md. -->

Closes <!-- Github issue # here -->

Expand All @@ -8,6 +9,8 @@ Closes <!-- Github issue # here -->
- [ ] Filled out test instructions.
- [ ] Updated documentation (if it already exists for this component).
- [ ] Looked at the Accessibility Practices for this feature - [Aria Practices](https://www.w3.org/WAI/ARIA/apg/)
- [ ] I understand every change in this PR and can explain why it's there.
- [ ] If AI-assisted, I followed our [AI contribution guidance](https://github.com/adobe/react-spectrum/blob/main/CONTRIBUTING.md#ai-assisted-contributions) and pointed my assistant at [CLAUDE.md](https://github.com/adobe/react-spectrum/blob/main/CLAUDE.md).

## 📝 Test Instructions:

Expand Down
60 changes: 60 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# CLAUDE.md

Guidance for working in the react-spectrum monorepo.

## Repo layout

The repo is layered. Changes flow up from the lowest level:

- **`@internationalized/*` and `@react-stately/*`** — the two lowest levels (i18n utilities and state management).
- **`@react-aria/*`** — behavior and accessibility hooks built on the above.
- **`react-aria-components` (RAC)** and some **React Spectrum v3 (RSP)** — component layer built on the hooks.
- **RSP S2 (`@react-spectrum/s2`)** — the Spectrum 2 design system, the highest level.

Test suites are split by type:

- **Jest tests** — `yarn test`
- **SSR tests** — `yarn test:ssr`
- **Browser tests** — `yarn test:browser`
- **Visual regression tests (VRT)** — `yarn chromatic`
- **High-contrast-mode VRT** — `yarn chromatic:forced-colors`

Maintainers run the Chromatic VRT suites themselves — don't run `yarn chromatic` / `yarn chromatic:forced-colors`. You can still start the VRT Storybooks locally to verify visual state: `yarn start:chromatic` and `yarn start:chromatic-fc`.

All commonly used commands live in the root `package.json` scripts.

Tests are **not** co-located with source — each package keeps them in a sibling `test/` directory. The file suffix routes the test to a runner: `*.ssr.test.*` → `yarn test:ssr`, `*.browser.test.*` → `yarn test:browser`, plain `*.test.*` → `yarn test` (Jest). Shared test helpers live in `@react-aria/test-utils` / `@react-spectrum/test-utils` (the `User` event abstraction and per-component testers).

## Tooling

This repo does **not** use the conventional JS toolchain — reach for these, and don't hand-format code or swap in defaults:

- **Format** — `oxfmt` (`yarn format`), not Prettier. The style is opinionated (single quotes, no bracket spacing → `{foo}`, no trailing commas). Always run the tool rather than formatting by hand.
- **Lint** — `oxlint` plus repo-local rules, not ESLint. `yarn lint` bundles format-check, type-check, `oxlint`, and Yarn `constraints` (which enforce cross-package dependency versions).
- **Type-check** — `tsgo` (`yarn check-types`), the native TypeScript compiler — not `tsc`. A `tsc` fallback exists as `yarn check-types:tsc`.
- **Build** — Parcel driven by `make` (`yarn build`), not plain `tsc`/rollup.
- **Yarn 4 workspaces** monorepo; use `yarn workspaces foreach` for cross-package operations.

## Writing tests

- **Run the full suite before committing.** Do not write PR descriptions that list a subset of specific passing tests — run everything (`yarn test`, and `yarn test:browser` when relevant).
- **Run lint and formatting before committing** (`yarn lint`, `yarn format`).
- **Test at the right level.** For any change at the RAC level or below (including hooks), write the test at the RAC level ideally. If the change lives at a higher level, test at that level.
- **Move to browser tests when needed.** If a test requires mocking specific browser behavior, consider moving it to the browser run (`yarn test:browser`).
- **Cover the reported issue.** When fixing a reported issue, add a test that reproduces the specific example given in the issue.
- **Check whether the test already exists.** Find a home for it near other similar tests.
- **Check code coverage** to help decide whether a new test adds value — this is subjective.
- **In unit tests, prefer** fake timers, our test utils, and user event. Aside from those, prefer not mocking other modules, instead, move the test to a higher level.
- **Combine tests** that share the same setup before an assertion.
- **Ground test titles in the goal**, not the implementation — double-check they are accurate.

## Contributing

- **Match the surrounding code** — follow the naming, structure, and patterns of neighboring files.
- **Limit comments** — let the code speak for itself. Provide a holistic summary of how the changes work and why this approach was used in the description. If a particular section of code is complex, then prefer a higher level description of multiple lines over explaining a single line.
- **Commit format** — use conventional-commit prefixes (`fix:`, `feat:`, `chore:`, `docs:`) as seen in the git history.
- **Opening a PR** — use `.github/PULL_REQUEST_TEMPLATE.md` as the PR body (e.g. `gh pr create --body-file .github/PULL_REQUEST_TEMPLATE.md`), don't hand-write a body. Fill out the checklist honestly and disclose AI use.
- **Storybook** is the main way to develop and view components: `yarn start` (v3/RAC) and `yarn start:s2` (S2).
- **S2 styling** — style with the `style` macro (`import {style} from '../style' with {type: 'macro'};` — the `with {type: 'macro'}` attribute is required). Pass typed style objects to it; don't write CSS files or hand-rolled className strings for S2.
- **User-facing strings** — add the key to the package's `intl/en-US.json` (ICU MessageFormat) and read it via the localized string hook. Never hardcode UI text, and don't hand-edit the other locale files (translators own those).
- **Generated code** — v3 icon components are generated (`yarn build:icons`) and s2 are handled through a parcel transformer, not hand-written, and `postinstall` runs `patch-package`, so run install on a fresh clone.
46 changes: 46 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,52 @@ Read [GitHub's pull request documentation](https://help.github.com/articles/abou

Lastly, please follow the pull request template when submitting a pull request!


## AI-assisted contributions
Setting expectations: the AI doesn't contribute to React Spectrum or Quarry, you do. The AI is a tool, but you are still the author, and you own every line, every decision, and every explanation.

If you use an AI assistant, point it at our [CLAUDE.md](CLAUDE.md), which captures the repo conventions we expect it to follow.

### Aligning on a solution

Open an issue or discussion, or at minimum, describe the problem and intended solution in the PR description. Otherwise, we have to reverse-engineer both the problem and the intended solution before we can even begin reviewing. An issue with: "here's what I'm seeing, here's what I plan to do, does that sound right?" really helps.

### Give us the intent, not just the fix

Tell us what you want and why, separately from how you did it. Then if we need to make a change to the PR, we can be confident that we're satisfying the goal you had. This framing helps when prompting the AI as well.

### Tell us what you tested

* mouse / touch / keyboard / screen reader
* LTR / RTL
* light / dark / high-contrast
* disabled / loading / error / empty
* narrow / wide / truncated / very long / wrapping text
* component sizes and zoom levels

Even if you haven't tested all of these, it's hugely helpful to us to know where to focus efforts.

### Beware false confidence

One of the biggest issues we face with the rise of AI contributions is the wrong root cause but with a lot of details asserting why it is, in fact, the issue. Press the AI, and ask both it and yourself "is this the root cause, or a symptom?" and "what else could cause this?" before committing to a solution.

### Keep a human in the loop of the conversation

When you iterate between reviews, be sure you can say what changed and why, one sentence is enough. A PR that transforms completely between every review without explanation is exhausting to follow and makes us feel like we're arguing with a machine instead of collaborating with a person.


#### Requirements of front end code

These can be useful constraints or reminders as AI is not inherently good at these things.

* **Small** — everything you add ships across the network to the client, so more code means slower load times.
* **Fast** — must run well on constrained CPU and memory, not just the latest MacBook Pro. Many users are on years-old, low-end Android devices.
* **Mindful of the shared environment** — keep the global namespace clean, don't hog resources or throw uncaught errors, avoid CSS that leaks across boundaries, and keep ids unique.
* **Stable** — RSP and Quarry are libraries with many downstream dependents who upgrade on their own schedule, so avoid breaking them.
* **Accessible** — accessibility is still a relatively new web requirement, so strong examples are scarce and bad ones are common. use other examples in the repo or the APG examples first.
* **Cross-environment** — works across browsers, assistive technologies, and devices.


### Contributor License Agreement
All third-party contributions to this project must be accompanied by a signed contributor license agreement. This gives Adobe permission to redistribute your contributions as part of the project. [Sign our CLA](https://opensource.adobe.com/cla.html). You only need to submit an Adobe CLA one time, so if you have submitted one previously, you are good to go!

Expand Down