Setting Props in Framer X

In Framer X, you can set a component’s props right from the UI. Here’s how to do it and why it’s awesome.

Steve Ruiz
Sep 10, 2018 · 8 min read
Photo by Hermes Riversa, courtesy of Unsplash.

One of the most interesting aspects of Framer X is the relationship between the components that you create in code and the design environment used to place and manipulate those components. While this relationship is still developing, the beta already includes what may well be its killer feature: the ability to engineer a component in such a way that a user can set the component’s props through Framer X’s user interface.

On the left, a regular Framer X frame. On the right, a Code Component with custom prop controls.

In the screenshots above, you can see a number of extra property controls on the photo at right. All of these are custom: the author of the component wrote them into the component itself.

This article will cover everything there (currently) is to know about property controls. It comes in four small parts:

  • Part 1: Props in React is a quick refresher on what props are, where they come from, and what they’re used for
  • Part 2: Props in Framer X covers how Framer X handles props
  • Part 3: Setting up Property Controls will demonstrate how to add property controls to a code component
  • Part 4: Property Control Types describes each of the different property controls available in Framer X and the exact code required to create them

Part 1: Props in React

In Framer X, code components are React components. I won’t go into too much detail about how React works, but it’s important to know that components in React accept data from the outside world in the form of properties, or props.

Technically, these props are the second argument of theReact.createElement method. More often, you’ll more often see props in JSX, where they resemble properties of an HTML element.

For example, if we had a component like the one above:

const UserCard = props => (
<div>
<h2>{props.username}</h2>
<h4>{props.motto}</h4>
{props.children}
</div>
)

We could create an instance of this component with props like this:

React.createElement(
UserCard,
{ username: "ClodMorden420", motto: "sry im sry" },
"hell is full"
)

We could also (and would probably) do the same with with JSX instead:

<UserCard username="ClodMorden420" motto="sry im sry">
hell is full
</UserCard>

Either way, we’re feeding our UserCard instance two props, username and motto, both of which will be available inside the component under the argument props.

There’s also a third prop, children, which is defined either by the third argument in React.createElement or by whatever comes between the JSX tags.

If you look again at the UserCard component, you’ll see that we’ve set it up to display these values as props.username, props.motto and props.children. And, given those props, the resulting instance would render something like this:

Props enable re-use… and re-act

If we were to create a second instance with different values for those props, then that second instance would display those other values instead. Even better — and here’s part of where React earns its name — if sometime later we decided to pass different prop values into our UserCard instance, it would immediately re-render (with its new props value) and show the new values.

<UserCard username="DeadTired666" motto="dead strong">
run with wild skellies
</UserCard>

Part 2: Setting Props in Framer X

Ok, back to Framer X, where unlike a regular React environment, we create instances of our components using the user interface: we drag our components out of the tray or copy them from around our designs.

However, even though we’re not creating our instances in code, we still need some way of passing props— and that’s where Framer X’s property controls come in, allowing us to set props through the user interface.

A code component with many property controls.

But there’s a problem: every component will have different props, each of which might require different interface controls depending on the type of data the prop expects. How can we ensure that users are shown the right controls for the component?

Framer X solves this by checking a code component’s propertyControls property, where it expects to find an object describing which controls to show, how to show them, and the props that they control.

Follow the lingo: the values of the UI controls are passed to the component as props.

When a code component is selected, Framer X will use this propertyControls object to create the controls that the author has set up. As a user changes any of the control values, the values will be passed back to the component as props and the component will re-render.


Part 3: Setting up Property Controls

To give Framer X the instructions for your property controls, we need to start with the propertyControls object to our code component’s class. When you create a new code component, one property control comes by default:

It might be more useful to think of the propertyControls object starting as an empty object:

static propertyControls: PropertyControls = {}

…to which we add controls like this:

static propertyControls: PropertyControls = {    
username: {
type: ControlType.String,
title: "Username"
},
motto: {
type: ControlType.String,
title: "Motto"
}
}

Default Props

Before we get into the different types of property controls, it’s worth mentioning defaultProps. When you first create an instance, Framer X will use the values you provide in defaultProps as the component’s initial props.

static defaultProps = {
username: "admin guy",
motto: "im the ADMIN"
}
static propertyControls: PropertyControls = {
username: {
type: ControlType.String,
title: "Username"
},
motto: {
type: ControlType.String,
title: "Motto"
}
}

Part 4: Property Control Types

Shared options: title and hidden

There are a few types of property controls. Each has a set of required properties, as well as a few that aren’t required. While most of these properties are unique to the type, they all share the two: title and hidden.

The title property is straightforward: it’s a string that gets displayed to the left of the control.

The hidden property is more interesting: it’s a function that takes the component’s props as an argument and returns either true or false. You can use hidden to hide or show controls depending on other controls. For example, we might want to show an errorText control only if our component’s status is "error".

static propertyControls: PropertyControls = {    
status: {
type: ControlType.Enum,
options: ["idle", "fetching", "success", "error"],
optionTitles: ["Idle", "Fetching", "Success", "Error"],
title: "Status"
},
errorText: {
type: ControlType.String,
title: "Error Text",
hidden: (props) => props.status !== "error"
}
}
The hidden property controls whether or not to show a control.

These two properties, title and hidden, are available on all of the following control types.

ControlType.Boolean

A boolean value may be either true or false. Framer X uses a switch for this control. In addition to the shared properties described above, a the control may take two optional properties, disabledTitle and enabledTitle , that set the switch’s text.

ControlType.Boolean controls a prop that may be either true or false
. You can change the labels with disabledTitle and enabledTitle properties.
tired: {
type: ControlType.Boolean,
title: "Strong",
disabledTitle: "Nope",
enabledTitle: "Yep"
}

ControlType.String

String is used for text inputs. In addition to the shared options mentioned above, it has one optional property, placeholder, that sets the placeholder text for the control’s text field.

ControlType.String captures text values.
email: {
type: ControlType.String,
title: "Email",
placeholder: "you@example.com"
}

ControlType.Number

Number is used to capture number inputs. Framer X uses a slider for this control, and . This type has many optional properties: you can specify the step taken between values, provide a unit to display next to the number and set the slider’s min and max values.

ControlType.Number lets you capture a constrained number.
teeth: {
type: ControlType.Number,
title: "Teeth",
min: 0,
max: 32,
unit: "t",
step: 1
}

ControlType.Enum

Don’t let the computer-sciencey name throw you: the Enum control type is just used to select between a set of mutually exclusive options — or, if you’re feeling precise, an enumerated set of options.

Framer X uses a dropdown menu for this control. It requires one property, options: an array of values. It also has one optional property, optionTitles, that provides an array of strings to display for each of those options.

status: {
type: ControlType.Enum,
options: ["idle", "fetching", "success", "error"],
optionTitles: ["Idle", "Fetching", "Success", "Error"],
title: "Status"
},

ControlType.Color and ControlType.Image

Both of these control types take no properties apart from the defaults, title and hidden.

bonesColor: {
type: ControlType.Color,
title: "Color"
},
userPhoto: {
type: ControlType.Image,
title: "User Photo"
}

ControlType.SegmentedEnum

A segmented enum is the same as an ControlType.Enum, only it is presented as a segment control.

align: {
type: ControlType.SegmentedEnum,
options: ["left", "center", "right", "justify"],
optionTitles: ["L", "C", "R", "J"],
title: "Align"
}

ControlType.FusedNumber

By far more unusual strangest control type is ControlType.FusedNumber. This control allows you to set a four separate properties, or else a fifth property that determines all four. Consider padding as a use case: in CSS, you can specify a single padding value, like padding: 4px; — or four different values, like padding: 4px 8px 12px 8px;, that will set the top, right, bottom and left paddings. A fused number control would allow you to easily set these types of values.

padding: {
type: ControlType.FusedNumber,
title: "Padding",
toggleKey: "pSide",
toggleTitles: ["Padding", "Padding per Side"],
valueKeys: ["pt", "pr", "pb", "pl"],
valueLabels: ["T", "R", "B", "L"],
min: 0
}

ControlType.File

With ControlType.File, you can allow users to add files to your Framer X project. You must include an array of file extensions as strings (e.g. "jpeg") in order to tell the control which file types to allow.

file: {
type: ControlType.File,
title: "Document",
allowedFileTypes: ["txt", "pdf", "docx"]
}

Conclusion

Framer X is still in beta, so some of these interfaces may change faster than I can update this article. If something isn’t working, jump on the slack and find some help.

If you enjoyed this article, smash that precious clap button and let me know.

Updates:

  • 15 September 2018: added ControlType.File, updated ControlType.Color

Steve Ruiz

Written by

Design Educator at Framer.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade