# Canvas Kit 12.0 Upgrade Guide

This guide contains an overview of the changes in Canvas Kit v12. Please
[reach out](https://github.com/Workday/canvas-kit/issues/new?labels=bug&template=bug.md) if you have
any questions.

## Why You Should Upgrade

Canvas Kit is transitioning into a
[new way of styling](https://github.com/Workday/canvas-kit/discussions/2265). Theming and building
an in sync Canvas Kit CSS has been at the top of our minds. We've started using our new
[Canvas Tokens Web](https://workday.github.io/canvas-tokens/?path=/docs/docs-getting-started--docs)
package to take advantage of
[CSS variables](https://developer.mozilla.org/en-US/docs/Web/CSS/Using_CSS_custom_properties) and
provide semantic tokens that can translate to theming components.

A note to the reader:

- While we still support our old tokens from `@workday/canvas-kit-react/tokens`, **you must**
  install our new tokens from `@workday/canvas-tokens-web`. You can find more info in our
  [docs](https://workday.github.io/canvas-tokens/?path=/docs/docs-getting-started--docs).
- If your application lives within another application that already imports the CSS variables, **you
  do not need to import these again**.

## Table of contents

- [Canvas Tokens](#canvas-tokens)
- [Codemod](#codemod)
  - [Instructions](#instructions)
- [Styling Updates](#styling-updates)
  - [Compatibility Mode](#compatibility-mode)
- [Deprecations](#deprecations)
  - [Form Field Container](#form-field-container)
- [Removals](#removals)
  - [Input Icon Container](#input-icon-container)
- [Infrastructure](#infrastructure)
  - [TypeScript](#typescript)
- [Component Updates](#component-updates)
  - [Styling API and CSS Tokens](#styling-api-and-css-tokens)
  - [Avatar](#avatar)
  - [Collections](#collections)
  - [Combobox](#combmbox)
  - [Form Field](#form-field)
    - [Form Field Group](#form-field-group)
    - [Form Field Field](#form-field-field)
  - [Menu Item](#menu-item)
  - [MultiSelect](#multiselect)
  - [Search Form](#search-form)
  - [Select](#select)
  - [Text Area](#text-area)
  - [Text Input](#text-input)
- [Utility Updates](#utility-updates)
- [Troubleshooting](#troubleshooting)
- [Glossary](#glossary)
  - [Main](#main)
  - [Preview](#preview)
  - [Labs](#labs)

## Canvas Tokens

In v12, all the components listed in this guide have started using our new
[Canvas Tokens Web](https://workday.github.io/canvas-tokens/?path=/docs/docs-getting-started--docs).
**You must** add `@workday/canvas-tokens-web` to ensure our components are properly styled and the
variables are defined at the root of your application. For more information on installing and using,
please reference our tokens
[docs](https://workday.github.io/canvas-tokens/?path=/docs/docs-getting-started--docs).

> **Note:** If your application lives within another application that already imports the CSS
> variables, **you do not need to import these again**. If you need them for local development
> either add them via a plugin or at the root of the environment, **do not ship code to production
> duplicating the imports**.

## Codemod

We've provided a [codemod](https://github.com/Workday/canvas-kit/tree/master/modules/codemod) to
automatically update your code to work with most of the breaking changes in v12. **Breaking changes
handled by the codemod are marked with 🤖 in the Upgrade Guide.**

> **Note: In v12, we have done some infrastructure updates with moving to Storybook 7, Webpack 5,
> TypeScript 5.0 and Cypress 13 . With these updates has come some formatting issues after running
> our codemods. We recommend running a formatter to address the format issues that have been
> introduced in v12.**

A codemod is a script that makes programmatic transformations on your codebase by traversing the
[AST](https://www.codeshiftcommunity.com/docs/understanding-asts), identifying patterns, and making
prescribed changes. This greatly decreases opportunities for error and reduces the number of manual
updates, which allows you to focus on changes that need your attention. **We highly recommend you
use the codemod for these reasons.**

If you're new to running codemods or if it's been a minute since you've used one, there are a few
things you'll want to keep in mind.

- Our codemods are meant to be run sequentially. For example, if you're using v8 of Canvas Kit,
  you'll need to run the v9 codemod before you run v10 and so on.
- The codemod will update your code to be compatible with the specified version, but it will **not**
  remove outdated dependencies or upgrade dependencies to the latest version. You'll need to upgrade
  dependencies on your own.
  - We recommend upgrading dependencies before running the codemod.
  - Always review your `package.json` files to make sure your dependency versions look correct.
- The codemod will not handle every breaking change in v12. You will likely need to make some manual
  changes to be compatible. Use our Upgrade Guide as a checklist.
- Codemods are not bulletproof.
  - Conduct a thorough PR and QA review of all changes to ensure no regressions were introduced.
  - As a safety precaution, we recommend committing the changes from the codemod as a single
    isolated commit (separate from other changes) so you can roll back more easily if necessary.

We're here to help! Automatic changes to your codebase can feel scary. You can always reach out to
our team. We'd be very happy to walk you through the process to set you up for success.

### Instructions

The easiest way to run our codemod is to use `npx` in your terminal.

```sh
npx @workday/canvas-kit-codemod v12 [path]
```

Be sure to provide specific directories that need to be updated via the `[path]` argument. This
decreases the amount of AST the codemod needs to traverse and reduces the chances of the script
having an error. For example, if your source code lives in `src/`, use `src/` as your `[path]`. Or,
if you have a monorepo with three packages using Canvas Kit, provide those specific packages as your
`[path]`.

Alternatively, if you're unable to run the codemod successfully using `npx`, you can install the
codemod package as a dev dependency, run it with `yarn`, and then remove the package after you're
finished.

```sh
yarn add @workday/canvas-kit-codemod --dev
yarn canvas-kit-codemod v12 [path]
yarn remove @workday/canvas-kit-codemod
```

> **Note**: The codemod only works on `.js`, `.jsx`, `.ts`, and `.tsx` files. You'll need to
> manually edit other file types (`.json`, `.mdx`, `.md`, etc.). You may need to run your linter
> after executing the codemod, as its resulting formatting (spacing, quotes, etc.) may not match
> your project conventions.

## Styling Updates

### Compatibility Mode

In v12, we have addressed a style merge issue with removing forced compatibility mode. For more
information on this change, please read our
[discussion](https://github.com/Workday/canvas-kit/discussions/2893).

## Deprecations

We add the [@deprecated](https://jsdoc.app/tags-deprecated.html) JSDoc tag to code we plan to remove
in a future major release. This signals consumers to migrate to a more stable alternative before the
deprecated code is removed.

### Form Field Container

**PR:** [#2865](https://github.com/Workday/canvas-kit/pull/2865)

We've deprecated `FormField.Container` in v12. Please use `FormField.Field` or
`FormFieldGroup.Field` for grouped inputs as this ensures proper label alignment and spacing of
inputs and hint text, regardless of the orientation.

```tsx
// v11
<FormField>
  <FormField.Label>Email</FormField.Label>
  <FormField.Container>
    <FormField.Input as={TextInput} />
    <FormField.Hint>You must provide an email</FormField.Hint>
  </FormField.Container>
</FormField>

// v12
<FormField>
  <FormField.Label>Email</FormField.Label>
  <FormField.Field>
    <FormField.Input as={TextInput} />
    <FormField.Hint>You must provide an email</FormField.Hint>
  </FormField.Field>
</FormField>
```

## Removals

Removals are deletions from our codebase and you can no longer consume this component. We've either
promoted or replaced a component or utility.

### Input Icon Container

**PR:** [#2838](https://github.com/Workday/canvas-kit/pull/2838)

We've removed `InputIconContainer` from Main. Please use
[InputGroup](https://workday.github.io/canvas-kit/?path=/docs/components-inputs-text-input--icons)
from Main instead.

---

## Infrastructure

### TypeScript

**PR:** [#2908](https://github.com/Workday/canvas-kit/pull/2908)

We've upgraded to TypeScript 5.0 to make use of
[const Type Parameters](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-0.html#const-type-parameters).
You will need to upgrade to TypeScript 5.0+ to avoid any TypeScript syntax errors. TypeScript does
not follow semver, so 5.0 doesn't mean a large breaking change from 4.9. TypeScript doesn't have a
`x.10` release, they bump the `x.9` to `{x+1}.0`.

## Component Updates

### Styling API and CSS Tokens

**PRs:** [#2793](https://github.com/Workday/canvas-kit/pull/2793),
[#2865](https://github.com/Workday/canvas-kit/pull/2865),
[#2881](https://github.com/Workday/canvas-kit/pull/2881),
[#2825](https://github.com/Workday/canvas-kit/pull/2825),
[#2795](https://github.com/Workday/canvas-kit/pull/2795),

Several components have been refactored to use our new
[Canvas Tokens](https://workday.github.io/canvas-tokens/?path=/docs/docs-getting-started--docs) and
[styling API](https://workday.github.io/canvas-kit/?path=/docs/styling-basics--create-modifiers#createstyles-api).
The React interface **has not changed**, but CSS variables are now used for dynamic properties.

> **Note:** These components also support our new `cs` prop for styling. Learn more about styling
> with `cs` in our
> [documentation](https://workday.github.io/canvas-kit/?path=/docs/styling-basics--cs-prop).

The following components are affected:

- `Avatar`
- `Dialog`
- `Modal`
- `Popup`
- `TextArea`
- `TextInput`
- `Toast`

### Avatar

**PR** [#2793](https://github.com/Workday/canvas-kit/pull/2793)

Avatar has been updated to use our new
[styling utilities](https://workday.github.io/canvas-kit/?path=/docs/styling-basics--create-stencil).
The following changes have been made to the API:

- `Avatar.Size` has been deprecated. The `size` prop still accepts `Avatar.Size` in addition to the
  following values:
  `"extraExtraLarge" | "extraLarge" | "large" | "medium" | "small" | "extraSmall" | (string{})`
- `Avatar.Variant` has been deprecated. The `variant` prop still accepts `Avatar.Variant` in
  addition to the following values: `"dark" | "light"`
- The `as` prop now accepts any element, not just a `div`.

> **Note:** Both `Avatar.Size` and `Avatar.Variant` have been deprecated in favor of the new string
> union types. You will see a console warn message while in development if you're still using this.
> Please update your types and usage before v13.

### Combobox

**PR** [#2983](https://github.com/Workday/canvas-kit/pull/2983)

The `useComboboxInput` hook, and the `Combobox.Input` component used to automatically update the
input when an option was selected. This functionality has been split between
`useComboboxInputArbitrary` and `useComboboxInputConstrained` depending on the combobox's value
type. The `useComboboxInput` had the arbitrary functionality built in. This has been separated out.
The `<Select>` component has been updated to use `useComboboxInputConstrained` hook and the
`Autocomplete` example uses the `useComboboxInputArbitrary` hook. This is a breaking change if you
use the `Combobox.Input` component directly. You'll have to either pass the
`useComboboxInputArbitrary` elemProps hook directly to the `<Combbox.Input>` or create a new
component composing them.

```tsx
// v11
<Combobox>
  <Combobox.Input />
  // ...
</Combobox>

// v12
<Combobox>
  <Combobox.Input elemPropsHook={useComboboxInputArbitrary} />
  // ...
</Combobox>

// Better - create a specialized component
const useMyComboboxInput = composeHooks(
  // or your own model that extends `useComboboxModel`
  createElemPropsHook(useComboboxModel)(model => {
    return {
      // anything you need your input to do
    }
  }),
  useComboboxInputArbitrary,
  useComboboxInput
)

const MyComboboxInput = createSubcomponent(TextInput)({
  // or your own model that extends `useComboboxModel`
  modelHook: useComboboxModel,
  elemPropsHook: useMyComboboxInput,
})((elemProps, Element) => {
  // return a TextInput
  return <Element {...elemProps} />

  // return an InputGroupgs
  return (
    <InputGroup>
      <InputGroup.InnerStart>{/* Icon or something */}</InputGroup.InnerStart>
      <InputGroup.Input as={Element} {...elemProps} />
      <InputGroup.InnerEnd><InputGroup.ClearButton /></InputGroup.InnerEnd>
    </InputGroup>
  )
})
```

### Form Field

<div style={{display: 'inline-flex', gap: '.5rem'}}>
  <StatusIndicator variant="red" emphasis="low">
    <StatusIndicator.Label>Breaking Change</StatusIndicator.Label>
  </StatusIndicator>
  <StatusIndicator variant="green" emphasis="low">
    <StatusIndicator.Label>🤖 Codemod Available</StatusIndicator.Label>
  </StatusIndicator>
</div>

**PRs:** [#2865](https://github.com/Workday/canvas-kit/pull/2865),
[#2881](https://github.com/Workday/canvas-kit/pull/2881),
[#2934](https://github.com/Workday/canvas-kit/pull/2934),
[#2973](https://github.com/Workday/canvas-kit/pull/2973)

We've promoted FormField from [Preview](#preview) to [Main](#main). The following changes has been
made to provide more flexibility and better explicit components when using inputs.

- The orientation prop on the `FormField` component will be updated to accept the following values:
  `"vertical"`, `"horizontalStart"`, and `"horizontalEnd"`. `"horizontal"` will still be accepted as
  a value in v12, but it will be deprecated and slated for removal in a future major release. These
  changes are intended to provide more flexibility with label alignments on `FormField` elements.

> **Note**: The horizontal alignment of start and end are relative to its container, meaning start
> and end match the flex property of `flex-start` and `flex-end`. This is especially applicable for
> moving between RTL (right-to-left) and LTR (left-to-right) languages.

> **Note:** Orientation `"horizontal"` has been deprecated. You will see a console warn message
> suggesting to update your types and usage to `"horizontalStart"`, `"horizontalEnd"` or
> `"vertical"`.

- `useFormFieldModel`: `orientation` has been added back into `useFormFieldModel`. While we still
  support compat mode due to
  [style merging issues](https://github.com/Workday/canvas-kit/discussions/2893), having orientation
  on the model allows for proper styling of sub components.

- Styles clean up: `FormField.Hint` and `FormField.Label` where using `margin` for spacing. We've
  updated styles so that the containing element uses `gap` for proper spacing.

- We've added a new
  [example](https://workday.github.io/canvas-kit/?path=/docs/examples-forms-density-and-alignment--docs)
  to our docs to showcase how our inputs can be styled in different environments like density and
  container alignment.

> **Note:** If spacing seems off between the input and hint text, ensure you're using
> `FormField.Field` wrapping your input and hint text.

##### Breaking API Change

The newly promoted `FormField` is a
[compound component](https://workday.github.io/canvas-kit/?path=/docs/guides-compound-components--docs).
Due to the different APIs of the component, this change is **not codemodable**. The following shows
an example of how to **update** your code to match the new compound component API.

```tsx
// v11 FormField in Main
<FormField
  error={FormField.ErrorType.Alert}
  labelPosition={FormField.LabelPosition.Left}
  useFieldSet={true}
  required={true}
	inputId='input-id'
  hintId="hint-alert"
  hintText="Please enter a valid email."
  label="Email"
>
  <TextInput onChange={handleChange} value={value} />
</FormField>

// v12 Newly promoted FormField from Preview to Main
<FormField
  error="alert"
  orientation="horizontalStart"
  isRequired={true}
	id='input-id'
>
	<FormField.Label>Email</FormField.Label>
	<FormField.Field>
		<FormField.Input as={TextInput} onChange={handleChange} value={value} />
		<FormField.Hint>Please enter a valid email.</FormField.Hint>
	</FormField.Field>
</FormField>
```

- `FormField.LabelPosition.Hidden` is no longer valid. If you still want to hide the label, use the
  prop `isHidden`.

```tsx
// v11 FormField in Main
<FormField
  error={FormField.ErrorType.Alert}
  labelPosition={FormField.LabelPosition.Hidden}
  useFieldSet={true}
  required={true}
  inputId="input-id"
  label="Search"
>
  <TextInput onChange={handleChange} value={value} />
</FormField>;

// v12 Newly promoted FormField from Preview to Main

//...

<FormField error="alert" orientation="horizontalStart" isRequired={true} id="input-id">
  <FormField.Label isHidden>Search</FormField.Label>
  <FormField.Field>
    <FormField.Input as={TextInput} onChange={handleChange} value={value} />
  </FormField.Field>
</FormField>;
```

**Noticeable changes:**

- `error` prop takes in the following values: `"error" | "alert"`.
- `labelPosition` becomes `orientation` with the following values:
  `"horizontal" | "horizontalStart" | "horizontalEnd" | "vertical"`.
- `useFieldSet` is no longer valid. If you want to group inputs, use
  [`FormFieldGroup`](#form-field-group) component.
- `required` becomes `isRequired`.
- `hintId` is no longer needed. The component handles associating the hint text, label and input
  automatically. If you wish to have a unique `id`, you can add one onto the `FormField` element.
- `hintText` is no longer a valid prop. Use `FormField.Hint` sub-component.
- `errorLabel` and `alertLabel` are no longer valid props. Customize your hint text inside of
  `FormField.Hint`.
- `label` is no longer a valid prop. Use `FormField.Label` sub component to render your label text.
- Instead of rendering an input, ensure you use `FormField.Input` with the `as` prop. This ensures
  proper error handling and aria attributes for accessibility.
- `inputId` is no longer a valid prop. Use `id` if you want a custom `id`, otherwise, the component
  will handle generating a unique id to associate each element for accessibility.
- `isHidden` has been added as a prop to `FormField.Label` in cases where you want to hide the label
  while still meeting accessibility standards.

🤖 The codemod will handle the change of `orientation="horizontal"` to
`orientation="horizontalStart"` if you're using the string literal values. It will also handle
updating your imports from `@workday/canvas-kit-preview-react/form-field` to
`@workday/canvas-kit-react/form-field`.

#### Form Field Group

We've added a new component to the `FormField` package to allow users to group inputs without
worrying about setting the `as` prop on the `FormField` component.

Use `FormFieldGroup` when you have a group of inputs that need to be associated to one another, like
`RadioGroup` or a group of `Checkbox`'s.

`FormFieldGroup` supports the same props of `FormField`:

- `error`: `"alert" | "error"` Defines the error around the whole group of inputs.
- `orientation`: `"horizontalStart" | "horizontalEnd" | "vertical" | "horizontal" `. Defines the
  label placement.
- `isRequired`: `true` Defines if a group like `RadioGroup` is required.

#### Form Field Field

We've added a new sub-component to `FormField` and `FormFieldGroup`, `FormField.Field` and
`FormFieldGroup.Field`. This sub-component is meant to ensure that the label is always aligned with
the input regardless of the `orientation`prop's value on`FormField` or `FormFieldGroup`. This
component should replace `FormField.Container` and always be used to ensure proper alignment of the
label and hint text. Our examples have been updated to reflect this.

Although there is no codemod for this change and it's non-breaking, we suggest moving towards adding
this sub-component when using `FormField`. This component also exists on `FormFieldGroup`.

```tsx
<FormField orientation="horizontal">
  <FormField.Label>Email</FormField.Label>
  <FormField.Field>
    <FormField.Input as={TextInput} />
    <FormField.Hint>You must provide an email</FormField.Hint>
  </FormField.Field>
</FormField>
```

### Menu Item

**PR:** [2969](https://github.com/Workday/canvas-kit/pull/2969)

`Menu.Item` was converted to use Stencils for styling and uses `SystemIcon` stencil variables to
change icon color instead of deeply nested selectors. We also added `Menu.Option` component for
menus that have a selected visual state. `Menu.Option` will need more accessibility affordances that
depend on the nature of your use of the `Menu` component. For example, `<Combobox>` and `<Select>`
use `Menu.Option` and add keyboard events and `aria-*` attributes to function according to w3c
specifications.

We've deprecated the `isDisabled` prop. It didn't do anything in v10 or v11. It was part of the
preview Menu deprecation, but was never hooked up. We mapped it to `aria-disabled` and added a
deprecation comment to use `aria-disabled` instead.

We've removed the `MenuItemProps` export from `@workday/canvas-kit-react/menu`. Use
`ExtractProps<typeof Menu.Item, never>` instead. We don't mean to export prop interfaces of
polymorphic components. The `never` means "don't add element props". The second parameter is used to
pass the interface that the `as` prop is pointing to.

`Menu.Item` no longer sets `aria-selected` since that attribute is not valid on a `role=menuitem`.
The `Menu.Option` was added to support the role of a `role=option` for going inside a
`role=listbox`. The `Combobox` family of components uses a `role=listbox` for menu options. The
`Menu.Option` renders a checkmark for a visual indication of selected options.

### MultiSelect

**PR:** [2911](https://github.com/Workday/canvas-kit/pull/2911)

Added the `MultiSelect` component to select more than one option from a list of options. The
`MultiSelect` is similar in API to the `Select` component, except the values are comma delimited
with a space. If the ids represented are `['1', '2']`, then the string value of the form field is
`'1, 2'`.

### Search Form (Labs)

**PRs:** [#2934](https://github.com/Workday/canvas-kit/pull/2934),

`SearchForm` is now using the newly promoted `FormField` component. `SearchForm` now uses `labelId`
to set the appropiate aria attributes and `id` on the underlying input element.

### Select

**PRs:** [#2865](https://github.com/Workday/canvas-kit/pull/2865),
[#2983](https://github.com/Workday/canvas-kit/pull/2983)

As we transition to use our CSS tokens to provide better theming capabilities and our new styling
methods, we're moving away from components extending `Themeable`. `Themeable` has been removed from
`SelectProps.`

If you wish to theme `Select` we suggest using the `CanvasProvider` to do so.

```tsx
const theme: PartialEmotionCanvasTheme = {
  canvas: {
    palette: {
      common: {
        focusOutline: 'pink',
      },
      primary: {
        main: 'green',
        light: 'lightgreen',
      },
    },
  },
};

//...

<CanvasProvider theme={theme}>
  <Flex cs={parentContainerStyles}>
    <Select items={options}>
      <FormField>
        <FormField.Label>Contact</FormField.Label>
        <FormField.Input as={Select.Input} onChange={handleChange} />
        <Select.Popper>
          <Select.Card>
            <Select.List>
              {item => {
                return <Select.Item>{item}</Select.Item>;
              }}
            </Select.List>
          </Select.Card>
        </Select.Popper>
      </FormField>
    </Select>
    Selected Value: {value}
  </Flex>
</CanvasProvider>;
```

`Select` has been refactored to use `useComboboxInputConstrained` to sync the model and the `input`
element regardless of the source. This makes the `Select` a controllable component.

### Text Area

**PR:** [#2825](https://github.com/Workday/canvas-kit/pull/2825)

`TextAreaResizeDirection` is no longer a TypeScript enum, but a JavaScript object. This change does
not effect runtime at all, but may cause TypeScript errors if you use `TextAreaResizeDirection` as a
type.

```tsx
// v11
interface MyProps {
  resize?: TextAreaResizeDirection;
}

// v12
type ValueOf<T> = T[keyof T];
interface MyProps {
  resize?: ValueOf<typeof TextAreaResizeDirection>;
}
```

`Themeable` has been removed from `TextAreaProps`. If you wish to theme `TextArea`, use our
`CanvasProvider` with the `theme` object.

```tsx
const theme: PartialEmotionCanvasTheme = {
  canvas: {
    palette: {
      common: {
        focusOutline: 'pink',
      },
      primary: {
        main: 'green',
        light: 'lightgreen',
      },
    },
  },
};

//...

<CanvasProvider theme={theme}>
  <FormField>
    <FormField.Label>Contact</FormField.Label>
    <FormField.Input as={TextArea} onChange={handleChange} />
  </FormField>
</CanvasProvider>;
```

### Text Input

**PR:** [#2825](https://github.com/Workday/canvas-kit/pull/2825)

`Themeable` has been removed from `TextInputProps`. If you wish to theme `TextInput`, use our
`CanvasProvider` with the `theme` object.

```tsx
const theme: PartialEmotionCanvasTheme = {
  canvas: {
    palette: {
      common: {
        focusOutline: 'pink',
      },
      primary: {
        main: 'green',
        light: 'lightgreen',
      },
    },
  },
};

//...

<CanvasProvider theme={theme}>
  <FormField>
    <FormField.Label>Contact</FormField.Label>
    <FormField.Input as={TextInput} onChange={handleChange} />
  </FormField>
</CanvasProvider>;
```

### Collections

**PR:** [#2982](https://github.com/Workday/canvas-kit/pull/2982)

The `navigation.getItem()` function can now return `undefined` instead of throwing an error when an
item is not found. Throwing an error caused lots of problems when it came to dynamic data. This is a
breaking change if your application uses `getItem`. It will now have to deal with the possibility of
an `undefined`.

## Utility Updates

**PR:** [#2908](https://github.com/Workday/canvas-kit/pull/2908)

### `mergeProps`

`mergeProps` had a bug where sometimes the returned props would be `never`. Also `mergeProps` would
not narrow types which would require you to add `as const`. We fixed the type signature to more
accurately reflect how `mergeProps` works. This may catch new type errors not caught before. There
is no way to codemod this. Let us know if you need help fixing new type errors introduced by this
change.

More information: https://github.com/Workday/canvas-kit/discussions/2979

### `createElemPropsHook`

`createElemPropsHook` now uses
[const Type Parameters](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-0.html#const-type-parameters)
to narrow types in the object. This prevents requiring `as const` in some situations. This alone
should fix bugs instead of introduce them.

More information: https://github.com/Workday/canvas-kit/discussions/2979

### `composeHooks`

`composeHooks` uses `mergeProps` and suffered the same bugs. If any hook in the `composeHooks` chain
used a `null` prop, the entire prop object returned was typed as `never`. This caused a bug where if
the Component required a prop, it wasn't being provided by the composed hook. Some of our components
manually added to the component's prop interface so the component's render function wouldn't
complain. This has been fixed. This may be a breaking change where before the spread `elemProps` was
`never`, so no type conflicts could exist with component props. Now all props are properly
represented which may mean TypeScript is now catching bugs it didn't before.

More information: https://github.com/Workday/canvas-kit/discussions/2979

## Troubleshooting

### My Styles Seem Broken?

Our components are reliant on our new Canvas Tokens Web package. Be sure to install
`@workday/canvas-tokens-web`. For more information, reference our
[Getting Started docs](https://workday.github.io/canvas-tokens/?path=/docs/docs-getting-started--docs)
for this package.

### Did You Upgrade All Canvas Kit Related Packages?

In order for all the packages to work in harmony, you must upgrade all Canvas Kit packages to the
same version that you're using, including:

- `@workday/canvas-kit-react`
- `@workday/canvas-kit-preview-react`
- `@workday/canvas-kit-labs-react`
- `@workday/canvas-kit-styling`
- `@workday/canvas-kit-react-fonts`
- `@workday/canvas-kit-docs`

## Glossary

### Main

Our Main package of Canvas Kit tokens, components, and utilities at `@workday/canvas-kit-react` has
undergone a full design and a11y review and is approved for use in product.

Breaking changes to code in Main will only occur during major version updates and will always be
communicated in advance and accompanied by migration strategies.

---

### Preview

Our Preview package of Canvas Kit tokens, components, and utilities at
`@workday/canvas-kit-preview-react` has undergone a full design and a11y review and is approved for
use in product, but may not be up to the high code standards upheld in the [Main](#main) package.
Preview is analagous to code in beta.

Breaking changes are unlikely, but possible, and can be deployed to Preview at any time without
triggering a major version update, though such changes will be communicated in advance and
accompanied by migration strategies.

Generally speaking, our goal is to eventually promote code from Preview to [Main](#main).
Occasionally, a component with the same name will exist in both [Main](#main) and Preview (for
example, see Segmented Control in [Preview](/components/buttons/segmented-control/) and
[Main](https://d2krrudi3mmzzw.cloudfront.net/v8/?path=/docs/components-buttons-segmented-control--basic)).
In these cases, Preview serves as a staging ground for an improved version of the component with a
different API. The component in [Main](#main) will eventually be replaced with the one in Preview.

---

### Labs

Our Labs package of Canvas Kit tokens, components, and utilities at `@workday/canvas-kit-labs-react`
has **not** undergone a full design and a11y review. Labs serves as an incubator space for new and
experimental code and is analagous to code in alpha.

Breaking changes can be deployed to Labs at any time without triggering a major version update and
may not be subject to the same rigor in communcation and migration strategies reserved for breaking
changes in [Preview](#preview) and [Main](#main).
`import { opacity } from "@workday/canvas-tokens-web/dist/es6/system"`

---

## Codemod Reference

# What is a Codemod?

A codemod is a script that makes programmatic transformations on your codebase by traversing the
[AST](https://www.codeshiftcommunity.com/docs/understanding-asts), identifying patterns, and making
prescribed changes. This greatly decreases opportunities for error and reduces the number of manual
updates, which allows you to focus on changes that need your attention. **We highly recommend you
use the codemod for these reasons.**

If you're new to running codemods or if it's been a minute since you've used one, there are a few
things you'll want to keep in mind.

- Our codemods are meant to be run sequentially. For example, if you're using v8 of Canvas Kit,
  you'll need to run the v9 codemod before you run v10 and so on.
- The codemod will update your code to be compatible with the specified version, but it will **not**
  remove outdated dependencies or upgrade dependencies to the latest version. You'll need to upgrade
  dependencies on your own.
  - We recommend upgrading dependencies before running the codemod.
  - Always review your `package.json` files to make sure your dependency versions look correct.
- The codemod will not handle every breaking change in this upgrade. You will likely need to make
  some manual changes to be compatible. Use our Upgrade Guide as a checklist.
- Codemods are not bulletproof.
  - Conduct a thorough PR and QA review of all changes to ensure no regressions were introduced.
  - As a safety precaution, we recommend committing the changes from the codemod as a single
    isolated commit (separate from other changes) so you can roll back more easily if necessary.

We're here to help! Automatic changes to your codebase can feel scary. You can always reach out to
our team. We'd be very happy to walk you through the process to set you up for success.

## Running a Codemod

### Instructions

The easiest way to run our codemod is to use `npx` in your terminal.

```sh npx
@workday/canvas-kit-codemod v${canvasKitMajorVersionNumber} [path]

```

Be sure to provide specific directories that need to be updated via the `[path]` argument. This
decreases the amount of AST the codemod needs to traverse and reduces the chances of the script
having an error. For example, if your source code lives in `src/`, use `src/` as your `[path]`. Or,
if you have a monorepo with three packages using Canvas Kit, provide those specific packages as your
`[path]`.

Alternatively, if you're unable to run the codemod successfully using `npx`, you can install the
codemod package as a dev dependency, run it with `yarn`, and then remove the package after you're
finished.

```sh
yarn add @workday/canvas-kit-codemod --dev
yarn canvas-kit-codemod v${canvasKitMajorVersionNumber} [path]
yarn remove @workday/canvas-kit-codemod
```

> **Note**: The codemod only works on `.js`, `.jsx`, `.ts`, and `.tsx` files. You'll need to
> manually edit other file types (`.json`, `.mdx`, `.md`, etc.). You may need to run your linter
> after executing the codemod, as its resulting formatting (spacing, quotes, etc.) may not match
> your project conventions.

## Codemod Transformations for v12

The following automated transformations are available for upgrading to v12:

- **Promote Form Field**: promoteFormField
- **Rename Form Field Horizontal**: renameFormFieldHorizontal

Run the codemod with: `npx @workday/canvas-kit-codemod v12 [path]`
