---
# System prepended metadata

title: Migration of components using IButtonProps

---

# Migration of components using IButtonProps

**See https://hackmd.io/836e7v9oReGWP6I_Y7CVXg for original discussion.**

Using SpinButton as an example here. It's relatively clean, but in other cases if the actual use of button is inside a sub-component (like in ContextualMenu) it will be messier.

The basic idea is:
- **Leave SpinButton in `@fluentui/react` to avoid circular dependencies**
- Update the prop types to accept new ButtonProps by default
- Add compat prop types which use the old IButtonProps
- In SpinButtonBase, use the new button by default, but add essentially an internal slot prop for overriding which button to use
- Add a compat SpinButton file which uses the compat props and passes through the old IconButton to the button slot

## Details

In `SpinButton.types.ts`, update to use the new `ButtonProps`:
```ts
import { ButtonProps } from '@fluentui/react-button';

export interface ISpinButtonProps /*...*/ {
  iconButtonProps?: IButtonProps;
}

// This is mainly a hack to ensure links work on the doc site
/**
 * {@docCategory SpinButton}
 */
export type INewSpinButtonProps = ISpinButtonProps;
```

In new `CompatSpinButton.types.ts` (may not use that exact filename), export props which switch back to the old `IButtonProps`:
```ts
import { IButtonProps } from '../../compat/Button';
import { INewSpinButtonProps } from './SpinButton.types';

export interface ISpinButtonProps extends Omit<INewSpinButtonProps, 'iconButtonProps'> {
  iconButtonProps?: IButtonProps; // switch type back to old version
}
```

In `SpinButton.base.tsx`, use the new button by default but add (essentially) a slot for passing the compat one through. (Do NOT directly reference the old Button to avoid bundle size issues!)
```tsx
import { Button } from '@fluentui/react-button';

export interface ISpinButtonInternalProps extends ISpinButtonProps {
  buttonComponent?: React.ComponentType;
}

export const SpinButtonBase: React.FunctionComponent<ISpinButtonInternalProps> = props => {
  // Update references to button as follows:
  const { buttonComponent: ButtonComponent = Button, iconButtonProps } = props;
  <ButtonComponent {...(iconButtonProps as any)}>
}
```

In new `CompatSpinButton.tsx` (may not use that exact filename), use the slot to pass in the old button:
```tsx
import { ISpinButtonInternalProps, SpinButtonBase } from './SpinButton.base';
import { ISpinButtonProps } from './CompatSpinButton.types';
import { IconButton } from '../../compat/Button';

export const SpinButton: React.FunctionComponent<ISpinButtonProps> = styled<ISpinButtonProps, {}, ISpinButtonStyles>(
  SpinButtonBase,
  getStyles,
  () => {
    const internalProps: Partial<ISpinButtonInternalProps> = { buttonComponent: IconButton };
    // Use a cast so we don't expose the internal props in the public typings
    return internalProps as any;
  },
  {
    scope: 'SpinButton',
  },
);
```