---
image: /generated/articles-docs-studio-make-component-interactive.png
title: Make a component interactive
crumb: 'Remotion Studio'
---

# Make a component interactive<AvailableFrom v="4.0.530" />

Remotion's default components are already interactive, meaning they can be selected and edited in the Studio.

To make your component interactive too, wrap it with [`Interactive.withSchema()`](/docs/interactive-with-schema).

## Create the component

Create any component. Make sure it accepts `style` and passes it on to its visual root.<br />
Styles for transforming, premounting, and cropping will be injected.

```tsx twoslash title="Badge.tsx"
import type React from 'react';

type BadgeProps = {
  readonly children?: React.ReactNode;
  readonly color?: string;
  readonly padding?: number;
  readonly style?: React.CSSProperties;
};

export const BadgeInner: React.FC<BadgeProps> = ({children, color = '#0b84ff', padding = 16, style}) => {
  return (
    <div
      style={{
        ...style,
        display: 'inline-flex',
        borderRadius: 999,
        backgroundColor: color,
        color: 'white',
        fontWeight: 700,
        padding,
      }}
    >
      {children}
    </div>
  );
};
```

## Create a schema

Define an [`InteractivitySchema`](/docs/interactivity-schema) to declare the props that may be interactively edited.

```tsx twoslash title="Badge.tsx"
import type {InteractivitySchema} from 'remotion';

const badgeSchema = {
  color: {
    type: 'color',
    default: '#0b84ff',
    description: 'Color',
  },
  padding: {
    type: 'number',
    min: 0,
    step: 1,
    default: 16,
    description: 'Padding',
    hiddenFromList: false,
  },
} as const satisfies InteractivitySchema;
```

`Interactive.withSchema()` includes these schemas:

- [`Interactive.baseSchema`](/docs/interactive#interactivebaseschema): [`durationInFrames`](/docs/sequence#durationinframes), [`from`](/docs/sequence#from), [`trimBefore`](/docs/sequence#trimbefore), [`playbackRate`](/docs/sequence#playbackrate), [`freeze`](/docs/sequence#freeze), [`hidden`](/docs/sequence#hidden), [`name`](/docs/sequence#name) and [`showInTimeline`](/docs/sequence#showintimeline).
- [`Interactive.premountSchema`](/docs/interactive#interactivepremountschema): [`premountFor`](/docs/sequence#premountfor) and [`postmountFor`](/docs/sequence#postmountfor).
- [`Interactive.cropSchema`](/docs/interactive#interactivecropschema): [`cropLeft`](/docs/sequence#cropleft), [`cropRight`](/docs/sequence#cropright), [`cropTop`](/docs/sequence#croptop) and [`cropBottom`](/docs/sequence#cropbottom).
- [`Interactive.transformSchema`](/docs/interactive#interactivetransformschema): [`style.transformOrigin`](https://developer.mozilla.org/en-US/docs/Web/CSS/transform-origin), [`style.translate`](/docs/transforms#translate), [`style.scale`](/docs/transforms#scale), [`style.rotate`](/docs/transforms#rotate) and [`style.opacity`](/docs/transforms#opacity).

### Caption fields<AvailableFrom v="4.0.500" />

Include [`Interactive.captionsSchema`](/docs/interactivity-schema#interactivecaptionsschema) when the component accepts [`captions: Caption[]`](/docs/captions/caption) data:

```ts twoslash title="Captions.tsx"
import {Interactive, type InteractivitySchema} from 'remotion';

const captionsSchema = {
  ...Interactive.captionsSchema,
} as const satisfies InteractivitySchema;
```

Captions will become editable in the Studio.

## Turn on interactivity

Call `Interactive.withSchema()` to link the schema to the component.

```tsx twoslash title="Badge.tsx"
import type React from 'react';
import {Interactive, type InteractivitySchema} from 'remotion';

type BadgeProps = {
  readonly children?: React.ReactNode;
  readonly color?: string;
  readonly padding?: number;
  readonly style?: React.CSSProperties;
};

const BadgeInner: React.FC<BadgeProps> = ({children, color = '#0b84ff', padding = 16, style}) => {
  return (
    <div
      style={{
        ...style,
        display: 'inline-flex',
        borderRadius: 999,
        backgroundColor: color,
        color: 'white',
        fontWeight: 700,
        padding,
      }}
    >
      {children}
    </div>
  );
};

const badgeSchema = {
  color: {
    type: 'color',
    default: '#0b84ff',
    description: 'Color',
  },
  padding: {
    type: 'number',
    min: 0,
    step: 1,
    default: 16,
    description: 'Padding',
    hiddenFromList: false,
  },
} as const satisfies InteractivitySchema;

export const Badge = Interactive.withSchema({
  Component: BadgeInner,
  componentName: '<Badge>',
  schema: badgeSchema,
  wrapInSequence: true,
});
```

## Use the component

You can now use the component regularly.

In the Studio, it will render an outline and its props become editable.

```tsx title="MyComp.tsx"
import {Badge} from './Badge';

export const MyComp = () => {
  return (
    <Badge from={30} durationInFrames={90} premountFor={30} color="#ff5c7a" cropLeft={0.2} style={{translate: '120px 80px'}}>
      Sale
    </Badge>
  );
};
```

## See also

- [Interactivity best practices](/docs/studio/interactivity-best-practices)
- [`Interactive.withSchema()`](/docs/interactive-with-schema)
- [`InteractivitySchema`](/docs/interactivity-schema)
- [`Interactive`](/docs/interactive)
- [Studio interactivity](/docs/studio/interactivity)
