Basics

There are a few things where code comes into play in Framer. Important things to know before you start working with code in Framer:

Animation

The open source Framer Motion powers the production quality animation and can be used in Framer or any React based project.

Editor

The canvas is rendered using the DOM and React. It can render any custom React component and it handles the measuring of sizes and layout for you.

Canvas Interface

Framer code components can optionally expose UI on the canvas to let anyone configure properties.

SSR

Published projects automatically get pre-rendered for performance and SEO, including custom components.

Because the Framer canvas is based on the DOM and rendered with React, you can create your own React components and allow users to configure your props visually. Alternatively, you can modify props for any element on the canvas using overrides. Typical use cases are:

  • Create a navigation login button that knows your current login state.

  • Create a custom form with logic and validation.

  • Show a text field with live custom data from an API.

  • Add a WebGL animation to a canvas element.

Custom Page Code

You can insert custom code at the start or end of the <head> and <body> tag of your site. Custom code and scripts will be added to every page across the published site. These changes will not be visible in your preview, only in the published site.

In order to insert custom code, click on the name of the project to access the Site Settings and scroll down to the Custom Code section.

HTML, CSS, and Javascript are supported. The following tags are allowed: <link>, <script>, <meta>, and <style>. You will not be able to integrate any server-side languages, such as Perl, PHP, Python, or Ruby. Learn more about custom page code on our learn page.

Code Overrides

Code overrides are small functions that you can modify properties for any element. You can apply them to any element on the canvas, but the effects are only visible in the preview.

You can create overrides directly inside Framer. Go to the properties panel and create a new file under the Code Overrides section.

Example

The code is essentially the same as a React Higher Order Component. The example below modifies the opacity property of the element it is applied to. Framer uses TypeScript types to detect your overrides, hence the ComponentType.

import type { ComponentType } from "react";

export const withLowerOpacity = (Component): ComponentType => {
  // This part of the code is only run once when creating the component
  return (props) => {
    // This part runs every time the component is rendered.
    return <Component {...props} opacity={0.5} />;
  };
};
import type { ComponentType } from "react";

export const withLowerOpacity = (Component): ComponentType => {
  // This part of the code is only run once when creating the component
  return (props) => {
    // This part runs every time the component is rendered.
    return <Component {...props} opacity={0.5} />;
  };
};

Now that you have your new override, you can apply it to any element on the canvas from the same section in the property panel. If you now preview or publish the site, the element will have an opacity of 0.5.

Text Content

A popular use case is to replace text contents for any text element. You can use the text property to pass in any text content. The preview or published site will now show “Hello World”.

import type { ComponentType } from "react";

export function withText(Component): ComponentType {
    return (props) => {
        return <Component {...props} text="Hello World" />
    }
}
import type { ComponentType } from "react";

export function withText(Component): ComponentType {
    return (props) => {
        return <Component {...props} text="Hello World" />
    }
}

Tags

You can also use overrides to add custom tags to elements. For example if you want to add a class or id tag to elements, you can do something like:

import type { ComponentType } from "react";

export function withTags(Component): ComponentType {
    return (props) => {
        return <Component {...props} id="SomeID" />
    }
}
import type { ComponentType } from "react";

export function withTags(Component): ComponentType {
    return (props) => {
        return <Component {...props} id="SomeID" />
    }
}

We don’t recommend to override core attributes like class or className as Framer relies on those and it will result in breaking styling.

Code Components

Code Components can extend Framers capabilities by rendering any React Component directly on the canvas. Framer has a built in code editor to write them directly in Framer.

Framer components are just plain React components, but they have a few optional extras:

Basics

To create a new code component, go to the assets panel and select Code. Then, click Create Code File. You'll be presented with a new code file that exports a single React component.

To preview your component in real time while editing, click the top right preview button to get a split preview of your work.

If you switch back to Components, you'll see the component (named after your choice) which you can now drag onto the canvas as often as you like.

Example

Let's look at the very simplest component we could make. That would really just be a vanilla React button component. There really is no magic here, but it already works.

export default function Button(props) {
    return <div>Hello</div>
}
export default function Button(props) {
    return <div>Hello</div>
}

Let’s go a step deeper and add some styling. We can do this the standard React way too with style.

export default function Button(props) {
    const style = {
        display: "inline-block",
        backgroundColor: "orange",
        padding: 8,
    }

    return <div style={style}>Hello</div>
}
export default function Button(props) {
    const style = {
        display: "inline-block",
        backgroundColor: "orange",
        padding: 8,
    }

    return <div style={style}>Hello</div>
}

Now, let’s make a title prop that is configurable from the interface (we will explain more about property controls later).

import { addPropertyControls, ControlType } from "framer"

export default function Button(props) {
    const style = {
        display: "inline-block",
        backgroundColor: "orange",
        padding: 8,
    }

    return <div style={style}>{props.text}</div>
}

Button.defaultProps = {
    text: "My Title",
}

addPropertyControls(Button, {
    text: {
        title: "Text",
        type: ControlType.String,
    },
})
import { addPropertyControls, ControlType } from "framer"

export default function Button(props) {
    const style = {
        display: "inline-block",
        backgroundColor: "orange",
        padding: 8,
    }

    return <div style={style}>{props.text}</div>
}

Button.defaultProps = {
    text: "My Title",
}

addPropertyControls(Button, {
    text: {
        title: "Text",
        type: ControlType.String,
    },
})

And there your have a simple configurable React component, right on the canvas. But I hope you can see how you can use the same concepts to build any React component you like. title prop that is configurable from the interface (we will explain more about property controls later).

Auto-Sizing

Framer has the ability to accurately measure any content on the canvas. When building code components this means you can write styles as you are used to on the web and Framer will figure out the rest.

Defining Component Size

There are four settings for code component layout in Framer: auto, fixed, any, and any-prefer-fixed. These can be set for width or height axis individually, using @framerSupportedLayoutWidth and @framerSupportedLayoutHeightannotations.

  • auto — The component will dictate its own size.

  • fixed — The component is in a fixed size container and can fill 100% of its width & height.

  • any — The user can switch between auto and fixed sizing by using the controls in the properties panel. It will insert with its sizing set to auto by default.

  • any-prefer-fixed — The same as the any option however it will insert with its sizing set to fixed by default.

Specifying Options

The default layout setting for all components in Framer is any. To select different layout options for your component you'll need to add an annotation. This annotation is a special comment that Framer reads and uses to accordingly set options for your component. Make sure this comment is on the lines directly above where you declare your component.

The following code will make your component have auto-sizing for width, but not height. You can make these two properties any combination of sizing options as long as you have both width & height specified at all times.

/**
* @framerSupportedLayoutWidth auto
* @framerSupportedLayoutHeight fixed
*/
export function Toggle(props) { ...
/**
* @framerSupportedLayoutWidth auto
* @framerSupportedLayoutHeight fixed
*/
export function Toggle(props) { ...

Intrinsic Size

These annotations let Framer know what size your component should be inserted into the canvas when fixed sizing is enabled. In this case, it will insert with a width of 200px and a height of 200px.

/**
* @framerIntrinsicHeight 200
* @framerIntrinsicWidth 200
*/
export function Box(props) { ...
/**
* @framerIntrinsicHeight 200
* @framerIntrinsicWidth 200
*/
export function Box(props) { ...

Using Auto-Sizing

Now, let’s make a title prop that is configurable from the interface (we will explain more about property controls later).

Supporting the default any

By spreading the style prop into your parent container style properties with {...style}, Framer will override the width and height when auto-sizing is turned off (fixed sizing) by passing down { width: "100%", height: "100%" } via the style prop. While doing this, Framer wraps your component in a fixed-sized container set to the user-defined size on the canvas.

export function Toggle(props) {
    return <div style={{ width: 50, height: 50 }} />
}
export function Toggle(props) {
    return <div style={{ width: 50, height: 50 }} />
}

Auto-Sizing Dynamically

If you want to auto-size your component based on logic or state changes, using a useLayoutEffect will work best with our measuring system. Generally you'll want to use this approach when controlling internal state from outside the component.

import { addPropertyControls, ControlType } from "framer"
import { useState, useEffect, useLayoutEffect } from "react"

/*
 * @framerSupportedLayoutWidth auto
 * @framerSupportedLayoutHeight auto
 */
export default function Test(props) {
    const start = 0
    const [count, setCount] = useState(0)
    
    useLayoutEffect(() => {
        if (start !== count) setCount(start)
    }, [start])
    
    return (
        <div
            style={{ ...containerStyle }}
            onClick={() => {
                setCount(count + 1)
            }}
        >
            {new Array(count).fill(1, 0, count).map((_, index) => {
                return <div style={squareStyle}>{index}</div>
            })}
        </div>
    )
}

const containerStyle = {
    display: "flex",
    justifyContent: "center",
    alignItems: "center",
    overflow: "hidden",
}

const squareStyle = {
    margin: 10,
    padding: 50,
    color: "white",
    fontWeight: 600,
    borderRadius: 25,
    backgroundColor: "#09F",
    width: "max-content",
    whiteSpace: "pre-wrap",
    flexShrink: 0,
}
import { addPropertyControls, ControlType } from "framer"
import { useState, useEffect, useLayoutEffect } from "react"

/*
 * @framerSupportedLayoutWidth auto
 * @framerSupportedLayoutHeight auto
 */
export default function Test(props) {
    const start = 0
    const [count, setCount] = useState(0)
    
    useLayoutEffect(() => {
        if (start !== count) setCount(start)
    }, [start])
    
    return (
        <div
            style={{ ...containerStyle }}
            onClick={() => {
                setCount(count + 1)
            }}
        >
            {new Array(count).fill(1, 0, count).map((_, index) => {
                return <div style={squareStyle}>{index}</div>
            })}
        </div>
    )
}

const containerStyle = {
    display: "flex",
    justifyContent: "center",
    alignItems: "center",
    overflow: "hidden",
}

const squareStyle = {
    margin: 10,
    padding: 50,
    color: "white",
    fontWeight: 600,
    borderRadius: 25,
    backgroundColor: "#09F",
    width: "max-content",
    whiteSpace: "pre-wrap",
    flexShrink: 0,
}

Measuring Absolute Height Width Values

Sometimes when writing components you may want to know the size of the component in pixels. To do this you will need to measure the component with a resizeObserver. Be careful, as this will reduce the performance of your site, as well as your canvas.

Property Controls

Property Controls allow users to pass properties (or props) to a code component through the Framer interface. When a user selects a code component on the canvas, its Property Controls are visible on the properties panel. As a component author, it’s up to you to decide which Property Controls to add and what options they should present to the user.

Adding Controls

To give your component Property Controls, import both the addPropertyControls function and the ControlType type from the framer library.

Below your component, call the addPropertyControls function with two arguments: first, the name of your component; and second, an object that defines controls for different properties. You have several types of controls to choose from, each of which are documented on this page.

Property Controls only affect components on the canvas. For this reason, you'll still want to use defaultProps for your component’s props, both to prevent errors as you code the component and when a designer creates an instance of your component from code.

In this example, we’re adding a Property Control for our component’s text prop. On the canvas, selecting the component will now display a control that allows us to set this property.

import {
  addPropertyControls,
  ControlType,
} from "framer"

export function MyComponent(props) {
  return <div>{props.text}</div>
}

MyComponent.defaultProps = {
  text: "Hello World!",
}

addPropertyControls(MyComponent, {
  text: { type: ControlType.String, title: "Hello World" },
})
import {
  addPropertyControls,
  ControlType,
} from "framer"

export function MyComponent(props) {
  return <div>{props.text}</div>
}

MyComponent.defaultProps = {
  text: "Hello World!",
}

addPropertyControls(MyComponent, {
  text: { type: ControlType.String, title: "Hello World" },
})

Hiding Controls

Controls can be hidden by adding the hidden function to the property description. The function receives an object containing the set properties and returns a boolean. In this example, we hide the text property entirely when the connected property (the toggle) is false.

Now you can toggle the visibility of the text property control by changing the toggle boolean from within the property panel in Framer.

export function MyComponent(props) {
  return <div>{props.text}</div>
}

MyComponent.defaultProps = {
  text: "Hello World!",
  toggle: true,
}

addPropertyControls(MyComponent, {
  toggle: {
    type: ControlType.Boolean,
    title: "Toggle",
    enabledTitle: "Show",
    disabledTitle: "Hide",
  },
  text: {
    type: ControlType.String,
    title: "Text",
    hidden(props) {
      return props.toggle === false
    },
  },
})
export function MyComponent(props) {
  return <div>{props.text}</div>
}

MyComponent.defaultProps = {
  text: "Hello World!",
  toggle: true,
}

addPropertyControls(MyComponent, {
  toggle: {
    type: ControlType.Boolean,
    title: "Toggle",
    enabledTitle: "Show",
    disabledTitle: "Hide",
  },
  text: {
    type: ControlType.String,
    title: "Text",
    hidden(props) {
      return props.toggle === false
    },
  },
})

Adding Descriptions

Controls can have a description property to add documentation about the control in the Framer UI—it appears in the Properties panel just above the control. It also supports adding emphasis and links using Markdown syntax. To add line breaks, use the newline character “\n”.

export function MyComponent(props) {
  return <div>{props.text}</div>
}

MyComponent.defaultProps = {
  text: "Hello World!",
  toggle: true,
}

addPropertyControls(MyComponent, {
  toggle: {
    type: ControlType.Boolean,
    title: "Toggle",
    description: "*On* by default",
  },
  text: {
    type: ControlType.String,
    title: "Text",
    description: "[Need inspiration?](https://www.lipsum.com)",
  },
})
export function MyComponent(props) {
  return <div>{props.text}</div>
}

MyComponent.defaultProps = {
  text: "Hello World!",
  toggle: true,
}

addPropertyControls(MyComponent, {
  toggle: {
    type: ControlType.Boolean,
    title: "Toggle",
    description: "*On* by default",
  },
  text: {
    type: ControlType.String,
    title: "Text",
    description: "[Need inspiration?](https://www.lipsum.com)",
  },
})

Controls

Array controlType.Array

A control that allows multiple values per ControlType, provided as an array via properties. For most control types this will be displayed as an additional section in the properties panel allowing as many fields to be provided as required.

For a ControlType.ComponentInstance the component will also gain an additional outlet control on the Canvas that allows links to be created between frames.

Group properties together by using an object control.

For multiple ControlType.FusedNumber values, you can pass in an array of single values as the React default prop.

export function MyComponent(props) {
  const frames = props.images.map(image => {
    return <img src={image} style={{ width: 50, height: 50 }} />
  })
  
  return <div style={{ display: "flex", gap: 10 }}>{frames}</div>
}

// Add a repeatable image property control
addPropertyControls(MyComponent, {
  images: {
    type: ControlType.Array,
    control: {
      type: ControlType.Image
    }
  },
  // Allow up to five items
  maxCount: 5,
})

// Add a multi-connector to your component to connect components on the canvas
addPropertyControls(MyComponent, {
  children: {
    type: ControlType.Array,
    control: {
      type: ControlType.ComponentInstance
    },
    maxCount: 5,
  },
})

// Add a list of objects
addPropertyControls(MyComponent, {
  myArray: {
    type: ControlType.Array,
    control: {
      type: ControlType.Object,
      controls: {
        title: { type: ControlType.String, defaultValue: "Employee" },
        avatar: { type: ControlType.Image },
      },
    },
    defaultValue: [
      { title: "Jorn" },
      { title: "Koen" },
    ],
  },
})

// For multiple values, you can pass in an array of single values as the React default prop.
MyComponent.defaultProps = {
   paddings: [5, 10, 15],
}
export function MyComponent(props) {
  const frames = props.images.map(image => {
    return <img src={image} style={{ width: 50, height: 50 }} />
  })
  
  return <div style={{ display: "flex", gap: 10 }}>{frames}</div>
}

// Add a repeatable image property control
addPropertyControls(MyComponent, {
  images: {
    type: ControlType.Array,
    control: {
      type: ControlType.Image
    }
  },
  // Allow up to five items
  maxCount: 5,
})

// Add a multi-connector to your component to connect components on the canvas
addPropertyControls(MyComponent, {
  children: {
    type: ControlType.Array,
    control: {
      type: ControlType.ComponentInstance
    },
    maxCount: 5,
  },
})

// Add a list of objects
addPropertyControls(MyComponent, {
  myArray: {
    type: ControlType.Array,
    control: {
      type: ControlType.Object,
      controls: {
        title: { type: ControlType.String, defaultValue: "Employee" },
        avatar: { type: ControlType.Image },
      },
    },
    defaultValue: [
      { title: "Jorn" },
      { title: "Koen" },
    ],
  },
})

// For multiple values, you can pass in an array of single values as the React default prop.
MyComponent.defaultProps = {
   paddings: [5, 10, 15],
}

Boolean controlType.Boolean

A control that displays an on / off checkbox. The associated property will be true or false, depending on the state of the checkbox. Includes an optional defaultValue, which is set to true by default. You can also customize the labels displayed in the property panel with the enabledTitle and disabledTitle properties.

export function MyComponent(props) {
    return (
        <div style={{ minHeight: 50, minWidth: 50 }}>
            {props.showText ? "Hello World" : null}
        </div>
    )
}

addPropertyControls(MyComponent, {
  showText: {
    type: ControlType.Boolean,
    title: "Show Text",
    defaultValue: true,
    enabledTitle: "On",
    disabledTitle: "Off",
  },
})
export function MyComponent(props) {
    return (
        <div style={{ minHeight: 50, minWidth: 50 }}>
            {props.showText ? "Hello World" : null}
        </div>
    )
}

addPropertyControls(MyComponent, {
  showText: {
    type: ControlType.Boolean,
    title: "Show Text",
    defaultValue: true,
    enabledTitle: "On",
    disabledTitle: "Off",
  },
})

Color controlType.Color

A control that represents a color value. It will be included in the component props as a string. This control is displayed as a color field and will provide the selected color in either RGB (rgb(255, 255, 255)) or RGBA (rgba(255, 255, 255, 0.5) notation, depending on whether there is an alpha channel.

function MyComponent(props) {
  return <div style={{ backgroundColor: props.background, width: 50, height: 50 }} />
}

addPropertyControls(MyComponent, {
  background: {
    type: ControlType.Color,
    defaultValue: "#fff",
  },
})
function MyComponent(props) {
  return <div style={{ backgroundColor: props.background, width: 50, height: 50 }} />
}

addPropertyControls(MyComponent, {
  background: {
    type: ControlType.Color,
    defaultValue: "#fff",
  },
})

ComponentInstance controlType.ComponentInstance

A control that references to another component on the canvas, included in the component props as a React node. The component will have an outlet to allow linking to other Frames. Available Frames will also be displayed in a dropdown menu in the properties panel. The component reference will be provided as a property. As a convention, the name for the property is usually just children.

Multiple components can be linked by combining the ComponentInstance type with the ControlType.Array.

export function MyComponent(props) {
  return <div>{props.children}</div>
}

addPropertyControls(MyComponent, {
  children: {
    type: ControlType.ComponentInstance,
  },
})
export function MyComponent(props) {
  return <div>{props.children}</div>
}

addPropertyControls(MyComponent, {
  children: {
    type: ControlType.ComponentInstance,
  },
})

Date controlType.Date

A property control that represents a date. The date will be passed in as an ISO 8601 formatted string.

export function Date(props) {
  return <div>{props.date}</div>
}

addPropertyControls(Date, {
    date: {
        type: ControlType.Date,
        title: "Date"
    },
})
export function Date(props) {
  return <div>{props.date}</div>
}

addPropertyControls(Date, {
    date: {
        type: ControlType.Date,
        title: "Date"
    },
})

Enum controlType.Enum

A property control that represents a list of options. The list contains primitive values and each value has to be unique. The selected option will be provided as a property. This control is displayed as a dropdown menu in which a user can select one of the items. displaySegmentedControl can be enabled to display a segmented control instead.

Note: ControlType.SegmentedEnum is deprecated, please use ControlType.Enum and enable displaySegmentedControl.

export function MyComponent(props) {
  const value = props.value || "a"
  const colors = { a: "red", b: "green", c: "blue" }
  return (
    <div 
      style={{ 
        backgroundColor: colors[value], 
        width: 50, 
        height: 50 
      }}
    >
      {value}
    </div>
  )
}

addPropertyControls(MyComponent, {
  value: {
    type: ControlType.Enum,
    defaultValue: "a",
    displaySegmentedControl: true,
    segmentedControlDirection: "vertical",
    options: ["a", "b", "c"],
    optionTitles: ["Option A", "Option B", "Option C"]
  },
})
export function MyComponent(props) {
  const value = props.value || "a"
  const colors = { a: "red", b: "green", c: "blue" }
  return (
    <div 
      style={{ 
        backgroundColor: colors[value], 
        width: 50, 
        height: 50 
      }}
    >
      {value}
    </div>
  )
}

addPropertyControls(MyComponent, {
  value: {
    type: ControlType.Enum,
    defaultValue: "a",
    displaySegmentedControl: true,
    segmentedControlDirection: "vertical",
    options: ["a", "b", "c"],
    optionTitles: ["Option A", "Option B", "Option C"]
  },
})

EventHandler controlType.EventHandler

A control that exposes events in the prototyping panel within the Framer UI. When choosing an event from the prototyping panel, you can select from a list of actions to trigger.

export function MyComponent(props) {
  return <motion.div onTap={props.onTap} style={{ width: 50, height: 50 }} />
}

addPropertyControls(MyComponent, {
  onTap: {
    type: ControlType.EventHandler,
  },
})
export function MyComponent(props) {
  return <motion.div onTap={props.onTap} style={{ width: 50, height: 50 }} />
}

addPropertyControls(MyComponent, {
  onTap: {
    type: ControlType.EventHandler,
  },
})

File controlType.File

A control that allows the user to pick a file resource. It will be included in the component props as a URL string. Displayed as a file picker that will open a native file browser. The selected file will be provided as a fully qualified URL. The allowedFileTypes property must be provided to specify acceptable file types.

export function MyComponent(props) {
  return (
      <video
        style={{ objectFit: "contain", ...props.style }}
        src={props.filepath}
        controls
      />
  )
}

addPropertyControls(MyComponent, {
  filepath: {
    type: ControlType.File,
    allowedFileTypes: ["mov"],
  },
})
export function MyComponent(props) {
  return (
      <video
        style={{ objectFit: "contain", ...props.style }}
        src={props.filepath}
        controls
      />
  )
}

addPropertyControls(MyComponent, {
  filepath: {
    type: ControlType.File,
    allowedFileTypes: ["mov"],
  },
})

FusedNumber controlType.FusedNumber

A control that can be used to take a single number or four distinct numeric input fields. The typical use case for this control is for visual properties like border, padding or margin. It will display an input field to accept a single value, alongside a segmented control allowing four distinct values to be provided.

You can also set the default value for each valueKey as well as the toggleKey by setting their values on defaultProps.

export function MyComponent({
  radius = 50,
  topLeft,
  topRight,
  bottomRight,
  bottomLeft,
  isMixed = false,
}) {
  const borderRadius = isMixed
    ? `${topLeft}px ${topRight}px ${bottomRight}px ${bottomLeft}px`
    : `${radius}px`
  return <div style={{ backgroundColor: "#09F", width: 50, height: 50, borderRadius }} />
}

addPropertyControls(MyComponent, {
  radius: {
    type: ControlType.FusedNumber,
    title: "Radius",
    defaultValue: 50,
    toggleKey: "isMixed",
    toggleTitles: ["All", "Individual"],
    valueKeys: ["topLeft", "topRight", "bottomRight", "bottomLeft"],
    valueLabels: ["NW", "NE", "SE", "SW"],
    min: 0,
  },
})

// Set the default value for each valueKey as well as the toggleKey by setting their values on `defaultProps`:
MyComponent.defaultProps = {
    radius: 10,
    isMixed: true,
    topLeft: 5,
    topRight: 15,
    bottomRight: 5,
    bottomLeft: 15,
}
export function MyComponent({
  radius = 50,
  topLeft,
  topRight,
  bottomRight,
  bottomLeft,
  isMixed = false,
}) {
  const borderRadius = isMixed
    ? `${topLeft}px ${topRight}px ${bottomRight}px ${bottomLeft}px`
    : `${radius}px`
  return <div style={{ backgroundColor: "#09F", width: 50, height: 50, borderRadius }} />
}

addPropertyControls(MyComponent, {
  radius: {
    type: ControlType.FusedNumber,
    title: "Radius",
    defaultValue: 50,
    toggleKey: "isMixed",
    toggleTitles: ["All", "Individual"],
    valueKeys: ["topLeft", "topRight", "bottomRight", "bottomLeft"],
    valueLabels: ["NW", "NE", "SE", "SW"],
    min: 0,
  },
})

// Set the default value for each valueKey as well as the toggleKey by setting their values on `defaultProps`:
MyComponent.defaultProps = {
    radius: 10,
    isMixed: true,
    topLeft: 5,
    topRight: 15,
    bottomRight: 5,
    bottomLeft: 15,
}

Image controlType.Image

A control that allows the user to pick an image resource. It will be included in the component props as an URL string. Displayed as an image picker with associated file picker. The chosen asset will be provided as a fully qualified URL.

function MyComponent(props) {
  return <img src={props.image} style={{ width: 200, height: 200 }} />
}

addPropertyControls(MyComponent, {
  image: {
    type: ControlType.Image,
  }
})
function MyComponent(props) {
  return <img src={props.image} style={{ width: 200, height: 200 }} />
}

addPropertyControls(MyComponent, {
  image: {
    type: ControlType.Image,
  }
})

Number controlType.Number

A control that accepts any numeric value. This will be provided directly as a property. Will display an input field with a range slider by default. The displayStepper option can be enabled to include a stepper control instead.

import { motion } from "framer-motion"

export function MyComponent(props) {
    return (
        <motion.div rotateZ={props.rotation} style={{ width: 50, height: 50 }}>
            {props.rotation}
        </motion.div>
    )
}

addPropertyControls(MyComponent, {
  rotation: {
    type: ControlType.Number,
    defaultValue: 0,
    min: 0,
    max: 360,
    unit: "deg",
    step: 0.1,
    displayStepper: true,
  },
})
import { motion } from "framer-motion"

export function MyComponent(props) {
    return (
        <motion.div rotateZ={props.rotation} style={{ width: 50, height: 50 }}>
            {props.rotation}
        </motion.div>
    )
}

addPropertyControls(MyComponent, {
  rotation: {
    type: ControlType.Number,
    defaultValue: 0,
    min: 0,
    max: 360,
    unit: "deg",
    step: 0.1,
    displayStepper: true,
  },
})

Object controlType.Object

A control that allows for grouping multiple properties as an object.

export function MyComponent(props) {
  return (
    <div 
      style={{ 
        opacity: props.myObject.opacity,
        backgroundColor: props.myObject.tint
      }} 
    />
  )
}

addPropertyControls(MyComponent, {
  myObject: {
    type: ControlType.Object,
    controls: {
      opacity: { type: ControlType.Number },
      tint: { type: ControlType.Color },
    }
  }
})
export function MyComponent(props) {
  return (
    <div 
      style={{ 
        opacity: props.myObject.opacity,
        backgroundColor: props.myObject.tint
      }} 
    />
  )
}

addPropertyControls(MyComponent, {
  myObject: {
    type: ControlType.Object,
    controls: {
      opacity: { type: ControlType.Number },
      tint: { type: ControlType.Color },
    }
  }
})

String controlType.String

A control that accepts plain text values. This will be provided directly as a property. Will display an input field with an optional placeholder value. If obscured attribute is set to true a password input field will be used instead of a regular text input so that the value in the input will be visually obscured, yet still be available as plain text inside the component. displayTextArea can be enabled to display a multi-line input area instead.

export function MyComponent(props) {
  return <div>{props.title} — {props.body}</div>
}

addPropertyControls(MyComponent, {
  title: {
    type: ControlType.String,
    defaultValue: "Framer",
    placeholder: "Type something…",
  },
  body: {
    type: ControlType.String,
    defaultValue: "Lorem ipsum dolor sit amet.",
    placeholder: "Type something…",
    displayTextArea: true,
  },
})
export function MyComponent(props) {
  return <div>{props.title} — {props.body}</div>
}

addPropertyControls(MyComponent, {
  title: {
    type: ControlType.String,
    defaultValue: "Framer",
    placeholder: "Type something…",
  },
  body: {
    type: ControlType.String,
    defaultValue: "Lorem ipsum dolor sit amet.",
    placeholder: "Type something…",
    displayTextArea: true,
  },
})

Transition controlType.Transition

A control that allows for editing Framer Motion transition options within the Framer UI.

export function MyComponent(props) {
  return (
      <motion.div
         animate={{ scale: 2 }}
         transition={props.transition}
      />
  )
}

addPropertyControls(MyComponent, {
  transition: {
      type: ControlType.Transition,
  },
})
export function MyComponent(props) {
  return (
      <motion.div
         animate={{ scale: 2 }}
         transition={props.transition}
      />
  )
}

addPropertyControls(MyComponent, {
  transition: {
      type: ControlType.Transition,
  },
})

Code Component Sharing

Code components are built on ES Modules. That means that every code component has a unique url that can be shared. If Framer detects a paste with a code component url, it automatically adds the component to your project and places an instance on the canvas. Find your code component under Assets → Code Component and right click to “Copy URL…”. Now your clipboard will contain a url like:

https://framer.com/m/Button-5TDo.js@rXSyWUm5fMakCtp8K3gM
https://framer.com/m/Button-5TDo.js@rXSyWUm5fMakCtp8K3gM

You can paste this url into any Framer project.

FAQ

Should I use code in Framer?

Framer is a site builder that doesn't require code. Code in Framer is a way to extend the application beyond that standard (very extensive) functionality.

You should use code in Framer if you are comfortable with React and JavaScript and need to add something dynamic to your website that Framer cannot provide out of the box, like a menu login button, a custom form, or a metric integration.

Is Framer a full blown developer platform? Can it help me write code?

No. Framer uses code as an escape hatch to extend capabilities to for example add small dynamic parts to a site. If your project needs a lot of logic and components we advice to create a normal React application instead.

What happens if I make a bug in my custom code?

Code in Framer shares the runtime and dom with everything else. That means that you can do anything, but also that subtle bugs can break your entire site. In short, with great powers comes great responsibility and we advice to only use it for production projects if you’re comfortable writing production quality code.

My custom code isn’t working as expected, can you help me debug?

Unfortunately we don’t have the resources to support your custom code for obvious reasons, but our #developers community channel channel is very popular and a great place to ask questions.

Can  share my code components across projects?

Yes. You can simply copy and paste code components across projects and it will work. If you have a set of components that you would like to share with your team, you can organize them in a central project or even publish them as a mini website. If you write the component url to the clipboard, Framer can paste it and will load your component.

Can I import Framer components into my React application directly?

Framer components are React Components based on ES Modules. That means that you can technically import them into other projects, but in reality there are quite a few hurdles to overcome, so we only recommend this for testing or if you really know what you are doing.

We have been experimenting making the experience easier for this with a beta feature called Handshake. But as this relies on the Next.js compiler which is currently being rewritten and browser features that aren't broadly supported yet, you should consider this very experimental for some time.

Can I import npm packages?

Importing npm packages is currently an experimental feature. Most packages typically don’t work unless unless they were built specifically for Framer. Some projects with multiple npm imports may run into errors with adding multiple npm dependencies, as sub-dependency conflicts can occur.

Should I use external code libraries with Framer?

Framer can import any ES Module based code. But the code itself generally is only useful in Framer if it’s made for Framer. So importing large libraries that did not have Framer as the main use case in mind will likely not yield the expected results.

Should I add state management to let different components communicate to each other?

This may be alright in some cases, but if you need to do advanced logic, you are often better off with a real React application. Both Framer and your state management will try and control components, and conflicts can cause subtle bugs.

Should I use code to integrate tokens or build design systems for my team?

No. While many designers dream about a deeper design and production integration with code, Framer is not currently setup to get great results for that use case.

Basics

There are a few things where code comes into play in Framer. Important things to know before you start working with code in Framer:

Animation

The open source Framer Motion powers the production quality animation and can be used in Framer or any React based project.

Editor

The canvas is rendered using the DOM and React. It can render any custom React component and it handles the measuring of sizes and layout for you.

Canvas Interface

Framer code components can optionally expose UI on the canvas to let anyone configure properties.

SSR

Published projects automatically get pre-rendered for performance and SEO, including custom components.

Because the Framer canvas is based on the DOM and rendered with React, you can create your own React components and allow users to configure your props visually. Alternatively, you can modify props for any element on the canvas using overrides. Typical use cases are:

  • Create a navigation login button that knows your current login state.

  • Create a custom form with logic and validation.

  • Show a text field with live custom data from an API.

  • Add a WebGL animation to a canvas element.

Custom Page Code

You can insert custom code at the start or end of the <head> and <body> tag of your site. Custom code and scripts will be added to every page across the published site. These changes will not be visible in your preview, only in the published site.

In order to insert custom code, click on the name of the project to access the Site Settings and scroll down to the Custom Code section.

HTML, CSS, and Javascript are supported. The following tags are allowed: <link>, <script>, <meta>, and <style>. You will not be able to integrate any server-side languages, such as Perl, PHP, Python, or Ruby. Learn more about custom page code on our learn page.

Code Overrides

Code overrides are small functions that you can modify properties for any element. You can apply them to any element on the canvas, but the effects are only visible in the preview.

You can create overrides directly inside Framer. Go to the properties panel and create a new file under the Code Overrides section.

Example

The code is essentially the same as a React Higher Order Component. The example below modifies the opacity property of the element it is applied to. Framer uses TypeScript types to detect your overrides, hence the ComponentType.

import type { ComponentType } from "react";

export const withLowerOpacity = (Component): ComponentType => {
  // This part of the code is only run once when creating the component
  return (props) => {
    // This part runs every time the component is rendered.
    return <Component {...props} opacity={0.5} />;
  };
};

Now that you have your new override, you can apply it to any element on the canvas from the same section in the property panel. If you now preview or publish the site, the element will have an opacity of 0.5.

Text Content

A popular use case is to replace text contents for any text element. You can use the text property to pass in any text content. The preview or published site will now show “Hello World”.

import type { ComponentType } from "react";

export function withText(Component): ComponentType {
    return (props) => {
        return <Component {...props} text="Hello World" />
    }
}

Tags

You can also use overrides to add custom tags to elements. For example if you want to add a class or id tag to elements, you can do something like:

import type { ComponentType } from "react";

export function withTags(Component): ComponentType {
    return (props) => {
        return <Component {...props} id="SomeID" />
    }
}

We don’t recommend to override core attributes like class or className as Framer relies on those and it will result in breaking styling.

Code Components

Code Components can extend Framers capabilities by rendering any React Component directly on the canvas. Framer has a built in code editor to write them directly in Framer.

Framer components are just plain React components, but they have a few optional extras:

Basics

To create a new code component, go to the assets panel and select Code. Then, click Create Code File. You'll be presented with a new code file that exports a single React component.

To preview your component in real time while editing, click the top right preview button to get a split preview of your work.

If you switch back to Components, you'll see the component (named after your choice) which you can now drag onto the canvas as often as you like.

Example

Let's look at the very simplest component we could make. That would really just be a vanilla React button component. There really is no magic here, but it already works.

export default function Button(props) {
    return <div>Hello</div>
}

Let’s go a step deeper and add some styling. We can do this the standard React way too with style.

export default function Button(props) {
    const style = {
        display: "inline-block",
        backgroundColor: "orange",
        padding: 8,
    }

    return <div style={style}>Hello</div>
}

Now, let’s make a title prop that is configurable from the interface (we will explain more about property controls later).

import { addPropertyControls, ControlType } from "framer"

export default function Button(props) {
    const style = {
        display: "inline-block",
        backgroundColor: "orange",
        padding: 8,
    }

    return <div style={style}>{props.text}</div>
}

Button.defaultProps = {
    text: "My Title",
}

addPropertyControls(Button, {
    text: {
        title: "Text",
        type: ControlType.String,
    },
})

And there your have a simple configurable React component, right on the canvas. But I hope you can see how you can use the same concepts to build any React component you like. title prop that is configurable from the interface (we will explain more about property controls later).

Auto-Sizing

Framer has the ability to accurately measure any content on the canvas. When building code components this means you can write styles as you are used to on the web and Framer will figure out the rest.

Defining Component Size

There are four settings for code component layout in Framer: auto, fixed, any, and any-prefer-fixed. These can be set for width or height axis individually, using @framerSupportedLayoutWidth and @framerSupportedLayoutHeightannotations.

  • auto — The component will dictate its own size.

  • fixed — The component is in a fixed size container and can fill 100% of its width & height.

  • any — The user can switch between auto and fixed sizing by using the controls in the properties panel. It will insert with its sizing set to auto by default.

  • any-prefer-fixed — The same as the any option however it will insert with its sizing set to fixed by default.

Specifying Options

The default layout setting for all components in Framer is any. To select different layout options for your component you'll need to add an annotation. This annotation is a special comment that Framer reads and uses to accordingly set options for your component. Make sure this comment is on the lines directly above where you declare your component.

The following code will make your component have auto-sizing for width, but not height. You can make these two properties any combination of sizing options as long as you have both width & height specified at all times.

/**
* @framerSupportedLayoutWidth auto
* @framerSupportedLayoutHeight fixed
*/
export function Toggle(props) { ...

Intrinsic Size

These annotations let Framer know what size your component should be inserted into the canvas when fixed sizing is enabled. In this case, it will insert with a width of 200px and a height of 200px.

/**
* @framerIntrinsicHeight 200
* @framerIntrinsicWidth 200
*/
export function Box(props) { ...

Using Auto-Sizing

Now, let’s make a title prop that is configurable from the interface (we will explain more about property controls later).

Supporting the default any

By spreading the style prop into your parent container style properties with {...style}, Framer will override the width and height when auto-sizing is turned off (fixed sizing) by passing down { width: "100%", height: "100%" } via the style prop. While doing this, Framer wraps your component in a fixed-sized container set to the user-defined size on the canvas.

export function Toggle(props) {
    return <div style={{ width: 50, height: 50 }} />
}

Auto-Sizing Dynamically

If you want to auto-size your component based on logic or state changes, using a useLayoutEffect will work best with our measuring system. Generally you'll want to use this approach when controlling internal state from outside the component.

import { addPropertyControls, ControlType } from "framer"
import { useState, useEffect, useLayoutEffect } from "react"

/*
 * @framerSupportedLayoutWidth auto
 * @framerSupportedLayoutHeight auto
 */
export default function Test(props) {
    const start = 0
    const [count, setCount] = useState(0)
    
    useLayoutEffect(() => {
        if (start !== count) setCount(start)
    }, [start])
    
    return (
        <div
            style={{ ...containerStyle }}
            onClick={() => {
                setCount(count + 1)
            }}
        >
            {new Array(count).fill(1, 0, count).map((_, index) => {
                return <div style={squareStyle}>{index}</div>
            })}
        </div>
    )
}

const containerStyle = {
    display: "flex",
    justifyContent: "center",
    alignItems: "center",
    overflow: "hidden",
}

const squareStyle = {
    margin: 10,
    padding: 50,
    color: "white",
    fontWeight: 600,
    borderRadius: 25,
    backgroundColor: "#09F",
    width: "max-content",
    whiteSpace: "pre-wrap",
    flexShrink: 0,
}

Measuring Absolute Height Width Values

Sometimes when writing components you may want to know the size of the component in pixels. To do this you will need to measure the component with a resizeObserver. Be careful, as this will reduce the performance of your site, as well as your canvas.

Property Controls

Property Controls allow users to pass properties (or props) to a code component through the Framer interface. When a user selects a code component on the canvas, its Property Controls are visible on the properties panel. As a component author, it’s up to you to decide which Property Controls to add and what options they should present to the user.

Adding Controls

To give your component Property Controls, import both the addPropertyControls function and the ControlType type from the framer library.

Below your component, call the addPropertyControls function with two arguments: first, the name of your component; and second, an object that defines controls for different properties. You have several types of controls to choose from, each of which are documented on this page.

Property Controls only affect components on the canvas. For this reason, you'll still want to use defaultProps for your component’s props, both to prevent errors as you code the component and when a designer creates an instance of your component from code.

In this example, we’re adding a Property Control for our component’s text prop. On the canvas, selecting the component will now display a control that allows us to set this property.

import {
  addPropertyControls,
  ControlType,
} from "framer"

export function MyComponent(props) {
  return <div>{props.text}</div>
}

MyComponent.defaultProps = {
  text: "Hello World!",
}

addPropertyControls(MyComponent, {
  text: { type: ControlType.String, title: "Hello World" },
})

Hiding Controls

Controls can be hidden by adding the hidden function to the property description. The function receives an object containing the set properties and returns a boolean. In this example, we hide the text property entirely when the connected property (the toggle) is false.

Now you can toggle the visibility of the text property control by changing the toggle boolean from within the property panel in Framer.

export function MyComponent(props) {
  return <div>{props.text}</div>
}

MyComponent.defaultProps = {
  text: "Hello World!",
  toggle: true,
}

addPropertyControls(MyComponent, {
  toggle: {
    type: ControlType.Boolean,
    title: "Toggle",
    enabledTitle: "Show",
    disabledTitle: "Hide",
  },
  text: {
    type: ControlType.String,
    title: "Text",
    hidden(props) {
      return props.toggle === false
    },
  },
})

Adding Descriptions

Controls can have a description property to add documentation about the control in the Framer UI—it appears in the Properties panel just above the control. It also supports adding emphasis and links using Markdown syntax. To add line breaks, use the newline character “\n”.

export function MyComponent(props) {
  return <div>{props.text}</div>
}

MyComponent.defaultProps = {
  text: "Hello World!",
  toggle: true,
}

addPropertyControls(MyComponent, {
  toggle: {
    type: ControlType.Boolean,
    title: "Toggle",
    description: "*On* by default",
  },
  text: {
    type: ControlType.String,
    title: "Text",
    description: "[Need inspiration?](https://www.lipsum.com)",
  },
})

Controls

Array controlType.Array

A control that allows multiple values per ControlType, provided as an array via properties. For most control types this will be displayed as an additional section in the properties panel allowing as many fields to be provided as required.

For a ControlType.ComponentInstance the component will also gain an additional outlet control on the Canvas that allows links to be created between frames.

Group properties together by using an object control.

For multiple ControlType.FusedNumber values, you can pass in an array of single values as the React default prop.

export function MyComponent(props) {
  const frames = props.images.map(image => {
    return <img src={image} style={{ width: 50, height: 50 }} />
  })
  
  return <div style={{ display: "flex", gap: 10 }}>{frames}</div>
}

// Add a repeatable image property control
addPropertyControls(MyComponent, {
  images: {
    type: ControlType.Array,
    control: {
      type: ControlType.Image
    }
  },
  // Allow up to five items
  maxCount: 5,
})

// Add a multi-connector to your component to connect components on the canvas
addPropertyControls(MyComponent, {
  children: {
    type: ControlType.Array,
    control: {
      type: ControlType.ComponentInstance
    },
    maxCount: 5,
  },
})

// Add a list of objects
addPropertyControls(MyComponent, {
  myArray: {
    type: ControlType.Array,
    control: {
      type: ControlType.Object,
      controls: {
        title: { type: ControlType.String, defaultValue: "Employee" },
        avatar: { type: ControlType.Image },
      },
    },
    defaultValue: [
      { title: "Jorn" },
      { title: "Koen" },
    ],
  },
})

// For multiple values, you can pass in an array of single values as the React default prop.
MyComponent.defaultProps = {
   paddings: [5, 10, 15],
}

Boolean controlType.Boolean

A control that displays an on / off checkbox. The associated property will be true or false, depending on the state of the checkbox. Includes an optional defaultValue, which is set to true by default. You can also customize the labels displayed in the property panel with the enabledTitle and disabledTitle properties.

export function MyComponent(props) {
    return (
        <div style={{ minHeight: 50, minWidth: 50 }}>
            {props.showText ? "Hello World" : null}
        </div>
    )
}

addPropertyControls(MyComponent, {
  showText: {
    type: ControlType.Boolean,
    title: "Show Text",
    defaultValue: true,
    enabledTitle: "On",
    disabledTitle: "Off",
  },
})

Color controlType.Color

A control that represents a color value. It will be included in the component props as a string. This control is displayed as a color field and will provide the selected color in either RGB (rgb(255, 255, 255)) or RGBA (rgba(255, 255, 255, 0.5) notation, depending on whether there is an alpha channel.

function MyComponent(props) {
  return <div style={{ backgroundColor: props.background, width: 50, height: 50 }} />
}

addPropertyControls(MyComponent, {
  background: {
    type: ControlType.Color,
    defaultValue: "#fff",
  },
})

ComponentInstance controlType.ComponentInstance

A control that references to another component on the canvas, included in the component props as a React node. The component will have an outlet to allow linking to other Frames. Available Frames will also be displayed in a dropdown menu in the properties panel. The component reference will be provided as a property. As a convention, the name for the property is usually just children.

Multiple components can be linked by combining the ComponentInstance type with the ControlType.Array.

export function MyComponent(props) {
  return <div>{props.children}</div>
}

addPropertyControls(MyComponent, {
  children: {
    type: ControlType.ComponentInstance,
  },
})

Date controlType.Date

A property control that represents a date. The date will be passed in as an ISO 8601 formatted string.

export function Date(props) {
  return <div>{props.date}</div>
}

addPropertyControls(Date, {
    date: {
        type: ControlType.Date,
        title: "Date"
    },
})

Enum controlType.Enum

A property control that represents a list of options. The list contains primitive values and each value has to be unique. The selected option will be provided as a property. This control is displayed as a dropdown menu in which a user can select one of the items. displaySegmentedControl can be enabled to display a segmented control instead.

Note: ControlType.SegmentedEnum is deprecated, please use ControlType.Enum and enable displaySegmentedControl.

export function MyComponent(props) {
  const value = props.value || "a"
  const colors = { a: "red", b: "green", c: "blue" }
  return (
    <div 
      style={{ 
        backgroundColor: colors[value], 
        width: 50, 
        height: 50 
      }}
    >
      {value}
    </div>
  )
}

addPropertyControls(MyComponent, {
  value: {
    type: ControlType.Enum,
    defaultValue: "a",
    displaySegmentedControl: true,
    segmentedControlDirection: "vertical",
    options: ["a", "b", "c"],
    optionTitles: ["Option A", "Option B", "Option C"]
  },
})

EventHandler controlType.EventHandler

A control that exposes events in the prototyping panel within the Framer UI. When choosing an event from the prototyping panel, you can select from a list of actions to trigger.

export function MyComponent(props) {
  return <motion.div onTap={props.onTap} style={{ width: 50, height: 50 }} />
}

addPropertyControls(MyComponent, {
  onTap: {
    type: ControlType.EventHandler,
  },
})

File controlType.File

A control that allows the user to pick a file resource. It will be included in the component props as a URL string. Displayed as a file picker that will open a native file browser. The selected file will be provided as a fully qualified URL. The allowedFileTypes property must be provided to specify acceptable file types.

export function MyComponent(props) {
  return (
      <video
        style={{ objectFit: "contain", ...props.style }}
        src={props.filepath}
        controls
      />
  )
}

addPropertyControls(MyComponent, {
  filepath: {
    type: ControlType.File,
    allowedFileTypes: ["mov"],
  },
})

FusedNumber controlType.FusedNumber

A control that can be used to take a single number or four distinct numeric input fields. The typical use case for this control is for visual properties like border, padding or margin. It will display an input field to accept a single value, alongside a segmented control allowing four distinct values to be provided.

You can also set the default value for each valueKey as well as the toggleKey by setting their values on defaultProps.

export function MyComponent({
  radius = 50,
  topLeft,
  topRight,
  bottomRight,
  bottomLeft,
  isMixed = false,
}) {
  const borderRadius = isMixed
    ? `${topLeft}px ${topRight}px ${bottomRight}px ${bottomLeft}px`
    : `${radius}px`
  return <div style={{ backgroundColor: "#09F", width: 50, height: 50, borderRadius }} />
}

addPropertyControls(MyComponent, {
  radius: {
    type: ControlType.FusedNumber,
    title: "Radius",
    defaultValue: 50,
    toggleKey: "isMixed",
    toggleTitles: ["All", "Individual"],
    valueKeys: ["topLeft", "topRight", "bottomRight", "bottomLeft"],
    valueLabels: ["NW", "NE", "SE", "SW"],
    min: 0,
  },
})

// Set the default value for each valueKey as well as the toggleKey by setting their values on `defaultProps`:
MyComponent.defaultProps = {
    radius: 10,
    isMixed: true,
    topLeft: 5,
    topRight: 15,
    bottomRight: 5,
    bottomLeft: 15,
}

Image controlType.Image

A control that allows the user to pick an image resource. It will be included in the component props as an URL string. Displayed as an image picker with associated file picker. The chosen asset will be provided as a fully qualified URL.

function MyComponent(props) {
  return <img src={props.image} style={{ width: 200, height: 200 }} />
}

addPropertyControls(MyComponent, {
  image: {
    type: ControlType.Image,
  }
})

Number controlType.Number

A control that accepts any numeric value. This will be provided directly as a property. Will display an input field with a range slider by default. The displayStepper option can be enabled to include a stepper control instead.

import { motion } from "framer-motion"

export function MyComponent(props) {
    return (
        <motion.div rotateZ={props.rotation} style={{ width: 50, height: 50 }}>
            {props.rotation}
        </motion.div>
    )
}

addPropertyControls(MyComponent, {
  rotation: {
    type: ControlType.Number,
    defaultValue: 0,
    min: 0,
    max: 360,
    unit: "deg",
    step: 0.1,
    displayStepper: true,
  },
})

Object controlType.Object

A control that allows for grouping multiple properties as an object.

export function MyComponent(props) {
  return (
    <div 
      style={{ 
        opacity: props.myObject.opacity,
        backgroundColor: props.myObject.tint
      }} 
    />
  )
}

addPropertyControls(MyComponent, {
  myObject: {
    type: ControlType.Object,
    controls: {
      opacity: { type: ControlType.Number },
      tint: { type: ControlType.Color },
    }
  }
})

String controlType.String

A control that accepts plain text values. This will be provided directly as a property. Will display an input field with an optional placeholder value. If obscured attribute is set to true a password input field will be used instead of a regular text input so that the value in the input will be visually obscured, yet still be available as plain text inside the component. displayTextArea can be enabled to display a multi-line input area instead.

export function MyComponent(props) {
  return <div>{props.title} — {props.body}</div>
}

addPropertyControls(MyComponent, {
  title: {
    type: ControlType.String,
    defaultValue: "Framer",
    placeholder: "Type something…",
  },
  body: {
    type: ControlType.String,
    defaultValue: "Lorem ipsum dolor sit amet.",
    placeholder: "Type something…",
    displayTextArea: true,
  },
})

Transition controlType.Transition

A control that allows for editing Framer Motion transition options within the Framer UI.

export function MyComponent(props) {
  return (
      <motion.div
         animate={{ scale: 2 }}
         transition={props.transition}
      />
  )
}

addPropertyControls(MyComponent, {
  transition: {
      type: ControlType.Transition,
  },
})

Code Component Sharing

Code components are built on ES Modules. That means that every code component has a unique url that can be shared. If Framer detects a paste with a code component url, it automatically adds the component to your project and places an instance on the canvas. Find your code component under Assets → Code Component and right click to “Copy URL…”. Now your clipboard will contain a url like:

https://framer.com/m/Button-5TDo.js@rXSyWUm5fMakCtp8K3gM

You can paste this url into any Framer project.

FAQ

Should I use code in Framer?

Framer is a site builder that doesn't require code. Code in Framer is a way to extend the application beyond that standard (very extensive) functionality.

You should use code in Framer if you are comfortable with React and JavaScript and need to add something dynamic to your website that Framer cannot provide out of the box, like a menu login button, a custom form, or a metric integration.

Is Framer a full blown developer platform? Can it help me write code?

No. Framer uses code as an escape hatch to extend capabilities to for example add small dynamic parts to a site. If your project needs a lot of logic and components we advice to create a normal React application instead.

What happens if I make a bug in my custom code?

Code in Framer shares the runtime and dom with everything else. That means that you can do anything, but also that subtle bugs can break your entire site. In short, with great powers comes great responsibility and we advice to only use it for production projects if you’re comfortable writing production quality code.

My custom code isn’t working as expected, can you help me debug?

Unfortunately we don’t have the resources to support your custom code for obvious reasons, but our #developers community channel channel is very popular and a great place to ask questions.

Can  share my code components across projects?

Yes. You can simply copy and paste code components across projects and it will work. If you have a set of components that you would like to share with your team, you can organize them in a central project or even publish them as a mini website. If you write the component url to the clipboard, Framer can paste it and will load your component.

Can I import Framer components into my React application directly?

Framer components are React Components based on ES Modules. That means that you can technically import them into other projects, but in reality there are quite a few hurdles to overcome, so we only recommend this for testing or if you really know what you are doing.

We have been experimenting making the experience easier for this with a beta feature called Handshake. But as this relies on the Next.js compiler which is currently being rewritten and browser features that aren't broadly supported yet, you should consider this very experimental for some time.

Can I import npm packages?

Importing npm packages is currently an experimental feature. Most packages typically don’t work unless unless they were built specifically for Framer. Some projects with multiple npm imports may run into errors with adding multiple npm dependencies, as sub-dependency conflicts can occur.

Should I use external code libraries with Framer?

Framer can import any ES Module based code. But the code itself generally is only useful in Framer if it’s made for Framer. So importing large libraries that did not have Framer as the main use case in mind will likely not yield the expected results.

Should I add state management to let different components communicate to each other?

This may be alright in some cases, but if you need to do advanced logic, you are often better off with a real React application. Both Framer and your state management will try and control components, and conflicts can cause subtle bugs.

Should I use code to integrate tokens or build design systems for my team?

No. While many designers dream about a deeper design and production integration with code, Framer is not currently setup to get great results for that use case.