we return can accept motion props.
## Component Sizing
How to let your code components use Framer’s auto-sizing, give them default dimensions, and choose which sizing options users can select in the Properties Panel.
### Sizing options in Framer's canvas
Framer’s properties panel, you’ll see 4 size options:
Fixed:
Fixed — You define the height/width in px.
Relative — A % of the parent width/height.
Fill — This option is available inside a Stack (a div with flex). Define layer width in fr (like flex-grow)
Auto-sizing:
Fit Content — The component itself decides how big it should be. When you place it in a Stack, Framer will also give it the space it needs.
Canvas components vs. code component
In addition to selected fixed or auto-sizing options, a component can have its own preference. We use
### Making a code component resizable
Avoid defining height/width without spreading props inside style after any defined width/height so Framer can overwrite them by passing a props.style.width and/or props.style.height of "100%".
style={{
width: 150,
height: 80,
...props.style,
borderRadius: 20,
…
}}
It's often tidier to unpack style from props i.e. const { text, style } = props
Now this supports Framer’s default ‘any’ option: can use both auto and fixed sizing.
### Auto-sizing component
This one’s easy. You just remove the predefined width and/or height.
style={{
...style,
borderRadius: 20,
…
}}
Don’t use 100%.
You might be tempted to make the width and/or height a hundred percent, like this:
style={{
width: "100%",
height: "100%",
borderRadius: 20,
…
}}
This will cause problems if we ever import this component into another code component as it'll always try to fill the parent.
### Annotations / special comments
These special comments control component sizing and default behaviour. Place directly above the component.
#### Intrinsic size
Always define intrinsic width and size:
* @framerIntrinsicWidth 290
* @framerIntrinsicHeight 100
This only works when sizing in that direction is fixed (not spread in props.).
Use 'any' by default and set width and height inside the component:
/**
* @framerSupportedLayoutWidth any
* @framerSupportedLayoutHeight any
*/
All options:
any — The default, which lets you select both the auto and fixed sizing options.
auto — Only Fit Content can be selected.
fixed — Only the fixed options can be selected: Fixed, Relative, and Fill.
Example: Width always Auto
/**
* @framerSupportedLayoutWidth auto
* @framerSupportedLayoutHeight any
*/
...
style={{
height: 80,
...style,
borderRadius: 20,
backgroundColor: "Yellow",
…
}}
When you want to limit only width (or height) to fixed, you can use it to provide a default width (or height).
Example: Width always Fixed
This component will have the default width of 290 when you place it on the canvas, and will return to that width when you click ‘Default Size’.
/**
* @framerIntrinsicWidth 290
*
* @framerSupportedLayoutWidth fixed
* @framerSupportedLayoutHeight any
*/
...
style={{
// width: 290, // Will not work in this case
height: 100,
...style,
borderRadius: 20,
…
## Structure / syntax
’Frame’ has been deprecated in favour of regular divs.
Ensure you leave nothing undefined. Always use React useRef for DOM references in functional components instead of 'this'. Ensure the refs are properly defined and used within the component to track and manipulate DOM elements.
Structure the export and return statement like this:
export default function Component(props) {
return (
)
}
Avoid this type of statement without the return nested inside: "export default Squircle;"
## Style + spreading props
- To pass all props to child components, the props are spread using {...props}. This allows passing down any props defined by the parent.
- To extract specific props while also passing the remaining props, destructuring is used. For example: const {style, ...rest} = props
- Always give code components a height and width.
### Motion / Animation
For both code components and overrides, always default to Framer Motion for animation.
Remember we cannot access external stylesheets. This means that if we want to use keyframes, we have to use them like so:
const variants = {
slide: {
x: [0, 200, 0]
}
}
export default function Loader() {
return (
)
}
Use motion.div for animation instead of manually handling the animation logic with motion.animate.
The animate object allows motion components to automatically animate to new states when values change.
Use transition to configure animation types and keyframe spacing.
#### Keyframes
Define keyframes as an array to animate through values.
Configure timing and easing with transition.
Example:
export const MyComponent = () => (
)
#### Variants
Define visual states with variants.
Orchestrate child animations and dynamic functions with transition props and custom props.
#### Drag
Enable drag with the drag prop.
Constrain movement with dragConstraints.
Control elasticity and drag behavior with dragElastic.
#### MotionValues
Track state and velocity with MotionValues.
Create chains of values with useMotionValue and useTransform.
Example:
export const MyComponent = () => {
const x = useMotionValue(0)
const background = useTransform(x, [-100, 0, 100], ["#ff008c", "#7700ff", "rgb(230, 255, 0)"])
return (
)
}
#### Scroll Animations
whileInView triggers animations when a component enters the viewport.
Use useScroll for scroll-linked animations, like progress indicators or parallax effects.
Example:
#### Exit Animations
Use AnimatePresence for exit animations.
Define exit properties or variant names to animate before removal from the DOM.
#### Layout Animations
Apply layout prop to animate layout changes.
Use layoutId for shared layout animations between components.
#### Advanced Gestures and Transitions
motion components support advanced gestures like hover, tap, drag, and focus.
Use variants for complex animations and orchestration with transition props like delayChildren and staggerChildren.
Transition settings can be customized for each animating value.
### Property Controls
Property controls allow users to configure the components props in Framer's UI.
import { addPropertyControls, ControlType } from "framer"
With the addPropertyControls() function, you’ll add a set of controls, and the ControlType TypeScript object contains the possible settings for each type of control.
Implement this regularly, whenever there are obvious opportunities for the user to tweak values.
#### Default props
You can set default values for the properties in a defaultProps object that you add to the component:
BetterButton.defaultProps = {
buttonText: "Create",
buttonColor: "#09f",
}
addPropertyControls(Counter, {
From: {
type: ControlType.Number,
defaultValue: 0,
min: 0,
max: 99,
step: 1,
displayStepper: true,
},
})
Here's a more detailed example:
import {
addPropertyControls,
ControlType,
} from "framer"
export function MyComponent(props) {
return {props.text}
}
MyComponent.defaultProps = {
text: "Hello World!",
}
addPropertyControls(MyComponent, {
text: { type: ControlType.String, title: "Hello World" },
})
####
When creating components with text, always include controls for fontFamily, weight, size, color, lineHeight and spacing. Default to Inter, 400, 16px, #000. You can hide and show controls inside the font type using "displayTextAlignment: false,". Color cannot be included within this control.
font: {
type: ControlType.Font,
controls: "extended",
displayFontSize: true,
displayTextAlignment: false,
defaultFontType: "monospace",
defaultValue: {
fontSize: 14,
lineHeight: "1.5em"
#### Hiding Controls
Controls can be hidden by adding the hidden prop 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 {props.text}
}
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
Optional description prop adds documentation about the control in the Framer UI. Supports emphasis and links via Markdown. For line breaks, use “\n”.
description: "*On* by default",
## Control types
#### Array controlType.Array
allows multiple values per ControlType, provided as an array. 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
})
return {frames}
}
// 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 (
{props.showText ? "Hello World" : null}
)
}
addPropertyControls(MyComponent, {
showText: {
type: ControlType.Boolean,
title: "Show Text",
defaultValue: true,
enabledTitle: "On",
disabledTitle: "Off",
},
})
#### Color controlType.Color
A color value included in the component props as a string.
function MyComponent(props) {
return
}
addPropertyControls(MyComponent, {
background: {
type: ControlType.Color,
defaultValue: "#fff",
},
})
#### ComponentInstance controlType.ComponentInstance
References another component on the canvas, included in the component props as a React node with an outlet to allow linking to other Frames. The component reference will be provided as a prop. The name for the property is usually 'children'.
Multiple components can be linked by combining the ComponentInstance type with the ControlType.Array.
export function MyComponent(props) {
return {props.children}
}
addPropertyControls(MyComponent, {
children: {
type: ControlType.ComponentInstance,
},
})
#### Date controlType.Date
Passed as an ISO 8601 formatted string.
#### Enum controlType.Enum
A list of options. Contains primitive values where each value is unique. The selected option will be provided as a property. Default control is dropdown, displaySegmentedControl can 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 (
{value}
)
}
addPropertyControls(MyComponent, {
value: {
type: ControlType.Enum,
defaultValue: "a",
displaySegmentedControl: true,
segmentedControlDirection: "vertical",
options: ["a", "b", "c"],
optionTitles: ["Option A", "Option B", "Option C"]
},
})
#### File controlType.File
Allows the user to pick a file. Included in 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 (
)
}
addPropertyControls(MyComponent, {
filepath: {
type: ControlType.File,
allowedFileTypes: ["mov"],
},
})
#### FusedNumber controlType.FusedNumber
Takes either 1 or 4 distinct numeric input fields. Typically for visual props like border / padding.
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
}
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
An image included in the component props as an URL string.
function MyComponent(props) {
return
}
addPropertyControls(MyComponent, {
image: {
type: ControlType.Image,
}
})
#### Number controlType.Number
Accepts any numeric value, is provided directly as a property. Range slider by default, displayStepper can be enabled to include a stepper.
export function MyComponent(props) {
return (
{props.rotation}
)
}
addPropertyControls(MyComponent, {
rotation: {
type: ControlType.Number,
defaultValue: 0,
min: 0,
max: 360,
unit: "deg",
step: 0.1,
displayStepper: true,
},
})
#### Object controlType.Object
Allows for grouping multiple properties as an object.
export function MyComponent(props) {
return (
)
}
addPropertyControls(MyComponent, {
myObject: {
type: ControlType.Object,
controls: {
opacity: { type: ControlType.Number },
tint: { type: ControlType.Color },
}
}
})
#### String controlType.String
Accepts plain text values, is provided directly as a property. 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.
export function MyComponent(props) {
return {props.title} — {props.body}
}
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
Allows for editing Framer Motion transition options within the Framer UI.
export function MyComponent(props) {
return (
)
}
addPropertyControls(MyComponent, {
transition: {
type: ControlType.Transition,
},
})
#### Property control icons
Use these icons where relevant:
horizontal: {
type: ControlType.Enum,
defaultValue: "center",
options: ["left", "center", "right"],
optionTitles: ["Left", "Center", "Right"],
displaySegmentedControl: true,
},
vertical: {
type: ControlType.Enum,
defaultValue: "center",
options: ["top", "center", "bottom"],
optionTitles: ["Top", "Center", "Bottom"],
displaySegmentedControl: true,
},
direction: {
type: ControlType.Enum,
defaultValue: "horizontal",
options: ["horizontal", "vertical"],
displaySegmentedControl: true,
},
anyDirection: {
type: ControlType.Enum,
defaultValue: "horizontal",
options: ["vertical", "horizontal", "both"],
displaySegmentedControl: true,
},
directions: {
type: ControlType.Enum,
defaultValue: "Left",
options: ["left", "right", "top", "bottom"],
optionTitles: ["Left", "Right", "Top", "Bottom"],
optionIcons: [
"direction-left",
"direction-right",
"direction-up",
"direction-down",
],
displaySegmentedControl: true,
},
alignment: {
type: ControlType.Enum,
options: ["flex-start", "center", "flex-end"],
optionIcons: {
directions: {
right: ["align-top", "align-middle", "align-bottom"],
left: ["align-top", "align-middle", "align-bottom"],
top: ["align-left", "align-center", "align-right"],
bottom: ["align-left", "align-center", "align-right"],
},
},
defaultValue: "center",
displaySegmentedControl: true,
},
orientation: {
type: ControlType.Enum,
options: ["portrait", "landscape"],
optionTitles: ["Portrait", "Landscape"],
optionIcons: ["orientation-portrait", "orientation-landscape"],
displaySegmentedControl: true,
},
```