FRAMER FORGE
← All posts
componentstutorialhow-toframer-basics

How to use a Framer code component (step-by-step)

From file creation to prop controls to canvas drop. The 4-step install flow, the addPropertyControls system designers usually don't see explained, and common gotchas.

May 24, 2026·By Kaiborg

Code components in Framer are drag-and-drop UI elements you build in code — different from overrides (which modify existing frames). Installing one is a 4-step process: create the file, define the component, drag it to the canvas, configure props.

Here's the walk-through, including the prop controls system that designers usually don't see explained well.

Step 1: Open the Code Components panel

In Framer's left sidebar, find the Assets section. Inside Assets there's a Code Components sub-section. If you don't see it, click the + icon next to Assets and select Code Component to start a new one.

Framer creates a new .tsx file and opens the code editor. The starter template shows roughly what a component looks like — feel free to delete it and paste in your own code.

Step 2: Define the component (and prop controls)

A code component needs two things to be useful in Framer:

  1. A React component function that renders the UI
  2. An addPropertyControls call that tells Framer how to expose the component's props as editable fields in the design panel

Here's a minimal example — a callout box with a title, body, and tone:

import { addPropertyControls, ControlType } from "framer"
import type { ReactNode } from "react"

export function Callout({ title, body, tone }: {
  title: string
  body: ReactNode
  tone: "info" | "warning"
}) {
  const color = tone === "warning" ? "#ff8a3d" : "#1a4fa0"
  return (
    <div style={{ border: `1px solid ${color}`, padding: 16, borderRadius: 4 }}>
      <h4 style={{ color, margin: 0 }}>{title}</h4>
      <p style={{ margin: "8px 0 0" }}>{body}</p>
    </div>
  )
}

addPropertyControls(Callout, {
  title: { type: ControlType.String, defaultValue: "Heads up", title: "Title" },
  body: { type: ControlType.String, defaultValue: "Hello world", title: "Body" },
  tone: {
    type: ControlType.Enum,
    options: ["info", "warning"],
    optionTitles: ["Info", "Warning"],
    defaultValue: "info",
    title: "Tone",
  },
})

Without the addPropertyControls call, the component still renders — but the designer can't tweak title, body, or tone from Framer's UI. They'd have to edit the code. With the controls, those props become editable fields in Framer's right sidebar.

Save the file (Cmd+S / Ctrl+S).

Step 3: Drag the component to the canvas

In the Code Components panel, your component now appears as a draggable thumbnail. Drag it onto the canvas wherever you want it.

If the component has no fixed size, it'll render at its intrinsic size (whatever the inner content takes up). To make it resizable from Framer's UI, add a defaultProps block to control the height/width — but for most components, the intrinsic size works fine.

Step 4: Configure via the prop controls

With the component selected on the canvas, the right sidebar now shows your prop controls. Each addPropertyControls entry becomes a field:

  • ControlType.String → text input
  • ControlType.Number → number input (optionally with min/max/step)
  • ControlType.Enum → dropdown
  • ControlType.Boolean → toggle
  • ControlType.Color → color picker
  • ControlType.Image → image picker
  • ControlType.ComponentInstance → lets the designer pass any Framer frame as a child

Tweaking these updates the component live on the canvas. Designers never have to touch the code again — props become their interface.

Common gotchas

"My component shows up in the panel but won't render"

  • Check the export. Code components need to use export function ComponentName(...). Default exports don't surface.
  • Check the prop types. If you typed tone: "info" but addPropertyControls says ControlType.Number, Framer hands you a number and your switch breaks.

"The prop controls don't update the canvas"

  • Check the browser console for errors.
  • Make sure the component is reading props by destructuring, not by accessing a wrong key (props.title if you named it titleText in the controls won't work).

"I want defaults for size, padding, etc. when the component is dropped"

Add a defaultProps block:

Callout.defaultProps = {
  width: 320,
  height: 120,
}

These set the component's default canvas size when first dropped. The designer can resize from there.

Try one now

The cleanest way to learn the install flow is to drop a real component on a canvas. Grab the marquee component from our marketplace and walk through steps 3 + 4 with it:

CMPMarquee Row$12

Once you've dropped it on the canvas + tweaked the prop controls, you've done every step of the workflow except writing the component yourself.

Override or component?

If you're not sure which one your use case calls for, read the side-by-side comparison. Picking right the first time saves a rebuild.

Writing custom components

If you're new to the concept of a code component (vs just the install flow), the What is a Framer code component? explainer covers the why before the how.

The steps above cover the install side. Writing the component itself is the deeper work — designing the prop controls, picking the right ControlType for each field, handling edge cases.

Component Forge is on its way — AI-generated code components are a separate workflow we're shipping next. Until it lands, the Override Forge handles the override side of the house, and the marketplace ships production-ready components for the most common patterns (marquee row, code block, command palette, etc.).

Need a custom version? The Forge writes it.

Try the Forge