# Racine

<p align="left">
  <a href="https://github.com/storybooks/storybook"><img src="/docs/assets/storybook.svg" alt=""></a>
  <a href="https://seeds-storybook.netlify.com"><img src="https://api.netlify.com/api/v1/badges/29cdfd47-e0ce-4af0-bda9-b6d3f7ad38e5/deploy-status" alt=""></a>
  <a href="https://github.com/styled-components/styled-components"><img src="https://img.shields.io/badge/style-%F0%9F%92%85%20styled--components-orange.svg?colorB=daa357&colorA=db748e" alt=""></a>
  <a href="https://github.com/sproutsocial/seeds/blob/main/seeds-react/racine/LICENSE"><img src="https://flat.badgen.net/badge/license/MIT/blue" alt=""></a>
</p>

## Installation

Install Racine using npm or yarn:

```sh
$ yarn add @sproutsocial/racine react styled-components
# or
$ npm install @sproutsocial/racine react styled-components
```

You may also require specific peer dependencies when starting a new project or sandbox environment:

```js
@sproutsocial/seeds-border
@sproutsocial/seeds-color
@sproutsocial/seeds-depth
@sproutsocial/seeds-motion
@sproutsocial/seeds-networkcolor
@sproutsocial/seeds-space
@sproutsocial/seeds-typography
moment
prop-types
react
react-dates
styled-components
```

Then, wrap your app's React root in Racine's `ThemeProvider` component:

```js
import { ThemeProvider } from "@sproutsocial/racine";

const App = (props) => (
  <ThemeProvider>
    <div>your app here</div>
  </ThemeProvider>
);
```

## Local development

Racine uses [Storybook](https://storybook.js.org) for local development. Please refer to the root README for more information on [getting started](https://github.com/sproutsocial/seeds?tab=readme-ov-file#seeds) before continuing.

### Testing Racine changes in another project

Spin up a draft PR immediately for two reasons:

1. We'll cache your build making all subsequent builds super fast
2. Add the "📦 create test versions" label to your PR to generate a snapshot version of the package to use for testing in other projects.
3. You'll need to be sure to add a changeset or a bot will comment on your PR prompting you to do so before a snapshot can be created.

_Note: the snapshot will post as a comment on the PR once it has been generated._

## Documentation

[Racine is documented on the Seeds reference site](https://sproutsocial.com/seeds/components)

Racine uses [Storybook](https://storybook.js.org) as a local development environment, and for running tests against components. Every component has a `.stories.js` file where developers can write "stories" to test components in isolation. Running `yarn storybook` will open the Racine Storybook in your browser so that you can see changes live as you make them. [You can read more about writing stories on the Storybook website](https://storybook.js.org/docs/basics/writing-stories/).

## Contributing

Contributions to Racine are welcomed from any member of the wider Sprout org. Whether you're adding a new component or simply fixing a bug, every improvement to the library is future leverage for our peers, our product, and our customers.

When writing code for Racine, please refer to the `code-guidelines.mdx` story in Storybook.

### **🔍 Step 1: Find a way to contribute**

There are a few ways to get involved:

- Join #design-systems on Slack to participate in discussions about Racine's development.
- The Design Systems team [uses Jira to track our backlog, in-flight changes, and future changes](https://sprout.atlassian.net/jira/software/c/projects/DS/boards/601/backlog). It's a great way to get a broad look at what's happening in Racine, and tracks the squad's work from sprint to sprint, and release to release.

### **🗺 Step 2: Find your way around**

Racine's file structure is set up like this:

- `codemods` - For major updates to Racine that have breaking changes, codemods are included for automatically handling component API updates. Codemods are also discovered from other `@sproutsocial/seeds-react-*` packages automatically.
- `src`
  - `ComponentName` - Deprecated components that won't get added to the monorepo have a folder within the `src` directory.

Most components in Racine are exported at the root from their own packages. Each package typically structures its files similarly to how they appeared in Racine:

- `src`
  - `index.js` - This file should contain all necessary exports for the component.
  - `index.stories.js` - Storybook stories can be written here.
  - `index.test.js` - All component tests live inside this file.
  - `styles.js` - Any style-specific components live here.

And you can interact with Racine via the command line with these commands:

- `yarn start` - This will watch the Racine package for changes, and also run Storybook locally so that you can see your changes as you go.
- `yarn change` - This command will generate a changeset file that is used to document changes to the Racine package. If you are making a PR to Racine that should result in a version bump to the package, you will need to run this command to add a changeset. You can [learn more about this command](#-step-3-make-your-changes) in step 3.
- `yarn build` - Generate production builds for the Racine package.
- `yarn test` - Run Racine's test suite. **Note:** `yarn start` must be run before `yarn test` to build generated files and directories
- `yarn clean` - Delete all generated files and directories.
- `yarn release` - This will trigger the release process for creating a new version of the Racine package on npm. **Only Racine administrators can perform the release process.**

### **🔄 Running Codemods**

Codemods are automated scripts that help migrate code when component APIs change. They're available via the `racine-codemod` CLI tool and are automatically discovered from both racine and other `@sproutsocial/seeds-react-*` packages.

**List available codemods:**

```bash
racine-codemod
```

**View codemod documentation:**

```bash
racine-codemod <codemod-name>
```

**Run a codemod:**

```bash
racine-codemod <codemod-name> <path-to-files>
```

**Example:**

```bash
racine-codemod badge-1.x-to-2.x src --parser=tsx --quote=double
```

After running a codemod, you should run Prettier to fix any formatting issues:

```bash
yarn format
```

For more information on codemods, see the [migration documentation](https://sproutsocial.com/seeds/components/migration) on the Seeds reference site.

### **✅ Step 3: Make your changes**

Cut a feature branch off `main` and start coding! As updates are merged into `main` by other developers over time you'll want to pull those updates into your branch, ideally via rebase, to avoid any conflicts when you open a pull request.

We use a [visual regression testing](https://seeds-storybook.netlify.app/?path=/story/welcome-visual-regression-testing--page) suite to capture any unintended changes during development. After running `yarn build` you can run the suite locally with `yarn test:visual-regression`, which will open a report in your browser to show you what passed and what failed. If any fails are actually intentional visual changes you can add the `update-failed-snapshots 📸` label to your PR and rerun the VRT workflow to approve those changes as new reference images and include them in your PR.

As you develop you'll want to track the scope of the changes you make. Racine supports this with a tool called [changesets](https://github.com/atlassian/changesets) to automatically pick new version numbers and update the changelog whenever we publish a new version of the package.

**Run `yarn change` at the root of the Seeds repo to generate a changeset that will be used to derive the next version number for Racine from your changes.**

We use semantic versioning for the Racine package, which allows users to understand the scope of a package's changes based on the version number, which is in the format `major.minor.patch`.

When running this command, you will be asked to select whether your change is a **patch**, **minor**, or **major** change.

- **patch** changes are for bug fixes, and they bump the last digit in the version number (`x.x.0`)
- **minor** changes are for new features or improvements, and they bump the middle digit in the version number (`x.0.x`)
- **major** changes are _breaking changes_, and they bump the first digit (`0.x.x`). These types of changes are rare and should be coordinated in advance with the Design Systems team.

The changeset CLI will also ask you to input a message detailing your changes. The completion of the command will generate a new changeset markdown file. You are more than welcome to edit this file after it has been generated, so don't get hung up on trying to write the perfect text from the command line. Aim to make the text of the changeset file(s) as descriptive and informative as possible, as they will be used to build a changelog file when the new version is released. Check out our documentation for the [Seeds Release Process](https://sprout.atlassian.net/wiki/spaces/SEEDS/pages/3522756609/DS+Seeds+Release+Process#Changesets) for examples of what makes a good or bad changeset.

**You can add as many changesets to a PR as you would like.** If your PR makes several distinct changes to Racine, you should create a changeset detailing each one individually.

### **🗣 Step 4: Create a pull request**

Once you're ready to submit your changes for review, open a PR against the `main` branch. A few things will happen:

- The Design Systems team will be tagged to review your code. Feel free to additionally tag any specific individuals who you think should take a look.
- Visual regression testing will run against your PR, and the results can be found in the "Report" artifact on the summary page for the associated Github Action run. `html_report/index.html` in `Report.zip` will show you what passed and what failed.
- Racine's test suite will run via CI, and the status will be reported on the PR. You can run `yarn test` to run these tests locally. If there are any issues, they will need to be resolved before the PR can be merged.
- Netlify will create a preview deploy of Racine's Storybook and include a link to it in a comment on the PR so you can see your changes and share them with others.

You may be asked to make changes to match Racine's contribution guidelines, so expect to keep attention on your PR for a little bit. Once your tests are passing and you have at least one approving Design Systems review, you're welcome to merge your PR. It may sometimes take a little while to get an approval from the DS team since a merge queues your contribution into the next release and the DS team needs to make sure they have the bandwidth to validate any contribution before it releases.

### **☁️ Step 5: Changes get published to Code Artifact**

When the Design Systems team prepares the next Racine release, changsets will generate a PR called `Version Packages`. This PR will detail all of the changes that have been made to the package since the last publish. Merging this PR will release a new version of Racine.

When the PR is merged, [GitHub will kick off a publish of the new version](https://github.com/sproutsocial/seeds/actions?query=workflow%3ARelease). There will be a notification in #design-systems in Slack when the new version is available.

### **✍ Step 6: Document your changes**

Racine components are documented in [Seeds](https://sproutsocial.com/seeds/components), Sprout's design system. You can open a PR to the [reference site app](https://github.com/sproutsocial/seeds/tree/main/apps/reference-site) to add or edit component documentation. It's a good idea to have documentation changes ready to go at the same time your Racine contributions are deployed, so start early! Reach out to the Design Systems team if you need help getting started.

### **🔧 Adding Codemods**

When making breaking changes to a component API, you should create a codemod to help users migrate their code. Codemods should be added to the package that needs migration (not racine), and will be automatically discovered by the `racine-codemod` CLI.

**When to create a codemod:**

- Removing or renaming props
- Changing prop types or values
- Breaking API changes that affect multiple files

**Initial Setup** (for packages adding their first codemod):

1. **Update `tsup.config.ts`**:

   - Add a separate config entry for codemods:

   ```typescript
   export default defineConfig([
     // Main package build
     { entry: ["src/index.ts"], format: ["cjs", "esm"] /* ... */ },
     // Codemods build (CJS only)
     { entry: ["codemods/**/*.ts"], format: ["cjs"], dts: false /* ... */ },
   ]);
   ```

2. **Update `package.json`**:

   - Add `exports` field for codemods:

   ```json
   {
     "exports": {
       ".": {
         /* existing exports */
       },
       "./codemods/*": {
         "require": "./dist/codemods/*.js"
       }
     },
     "files": ["dist", "codemods"]
   }
   ```

   - Add `@types/jscodeshift` and `jscodeshift` to devDependencies (if not already present)

3. **Update `tsconfig.json`**:
   - Add `codemods/**/*` to the `include` array

**Creating a New Codemod:**

1. Create codemod file in `codemods/` directory (e.g., `codemods/my-codemod.ts`)
2. Write in TypeScript - use proper types from `jscodeshift` (avoid `any` types)
3. Export as CommonJS: `module.exports = transformer;`
4. Add tests in `codemods/__tests__/my-codemod.test.ts`
5. Add documentation entry to `racine/codemods/codemod-docs.js`
6. Build process handles compilation automatically (`yarn build` or `turbo build`)
7. Codemod will be discoverable via `racine-codemod` CLI after package is built

**Testing codemods locally:**

- Run `yarn build` to compile codemod to JavaScript
- Run `yarn test` to run codemod tests
- Test codemod execution: `racine-codemod my-codemod path/to/test/files`

**Example structure:**

```
my-package/
  codemods/
    my-codemod.ts
    __tests__/
      my-codemod.test.ts
  dist/
    codemods/
      my-codemod.js  (built automatically)
```
