Overriding Code Components
With an override, you can dynamically change a code component’s properties, and by overriding its events, you can have it talk to other elements on the canvas.
- Public packages
- Which properties can you override?
- Components with a connector
- Components without a connector
- Testing which values an event returns
- Examples
- Even more properties
Public packages
These examples use components from different public packages (of the legacy kind ) that are not available in newly created Framer Sites projects. (If you don’t see public packages in the Insert Menu, check Preferences > Show Packages.) The new version of this page, for Framer Sites projects, is here.
Which properties can you override?
Code components (almost always) have property controls for their custom properties, but these don’t necessarily show each property’s actual name. A property control might say ‘Text color’ while the prop’s name is defaultTextColor
. But there’s a simple way to know the correct prop names: The ‘Code’ section in the right-hand panel will list a component’s properties, also the props whose controls might be temporarily hidden.
One thing might be missing, though: events. Components that don’t have a connector on the canvas will not list their events under Code.

For example, Framer’s default button has a connector, but the button from the (older) Framer Base Kit package hasn’t.
Components with a connector
Framer’s Default Components all have connectors, and components from recently updated public packages might have them as well. The technical reason? They have event handler property controls that tell Framer to which events they’ll react.
Here’s Framer’s default button again:

and its properties in Handoff 👉

Event names almost always start with ‘on
’, so this button has onClick()
, onMouseEnter()
, and onMouseLeave()
.
As you know, you can drag the connector to create a Transition ( archived version) to a different screen, one of the possible Interactions . That’s why you’ll also see these same three events as interaction triggers in the component’s Interactions panel (top of the Properties Panel).
A component’s events (triggers) will often be user gestures, e.g., onClick()
, onMouseEnter()
, etc. But a video player component might have onPlay()
and onEnd()
triggers (that let you know when the video started and stopped), and Framer’s Loading Indicator has an onTimeout()
trigger.

The components in Carbon Design System, an implementation of IBM’s design system by Framer’s Iain Kettles, also have connectors.

So with components like these, it’s easy to know which events you can use in an override. But if you also want to know which values an event returns, you’ll need to test for it with an override.
Button example
As an example of using overrides with a code component, we’ll make Framer’s default button toggle-able.

Here the button’s onClick()
event flips the value of toggled
in the data store:
const useStore = createStore({ toggled: false })
export function FramerDefaultButton(Component): ComponentType {
return (props) => {
const [store, setStore] = useStore()
return (
<Component
{...props}
text={store.toggled ? "Great tap 🤟!" : "Tap me !"}
defaultBackground={
store.toggled
? "Coral"
: props.children.props.defaultBackground
}
hoverBackground={
store.toggled
? "Coral"
: props.children.props.hoverBackground
}
pressedBackground={
store.toggled
? "Coral"
: props.children.props.pressedBackground
}
onClick={() => setStore({ toggled: !store.toggled })}
/>
)
}
}
The current state of toggled
(true
or false
) defines the button’s text
and its background color:
const useStore = createStore({ toggled: false })
export function FramerDefaultButton(Component): ComponentType {
return (props) => {
const [store, setStore] = useStore()
return (
<Component
{...props}
text={store.toggled ? "Great tap 🤟!" : "Tap me !"}
defaultBackground={
store.toggled
? "Coral"
: props.children.props.defaultBackground
}
hoverBackground={
store.toggled
? "Coral"
: props.children.props.hoverBackground
}
pressedBackground={
store.toggled
? "Coral"
: props.children.props.pressedBackground
}
onClick={() => setStore({ toggled: !store.toggled })}
/>
)
}
}
This button has a prop for its defaultBackground
color and separate ones for the color when hovered over or pressed. The override changes all three to “Coral” when toggled
is true
.
When toggled
is false
, the colors all default to the values picked with their property controls, just like would happen without this override. The values set by the property controls are in the props.children.props
object (same as with smart components).
Unpacking properties
Pro tip: You can use JavaScript’s destructuring assignment to unpack the properties you need from props
. This way, you don’t have to write props.children.props…
everywhere.
export function FramerDefaultButton_UnpackProps(Component): ComponentType {
return (props) => {
const { defaultBackground, hoverBackground, pressedBackground } = props
const [store, setStore] = useStore()
return (
<Component
{...props}
text={store.toggled ? "Great tap 🤟!" : "Tap me !"}
defaultBackground={store.toggled ? "Coral" : defaultBackground}
hoverBackground={store.toggled ? "Coral" : hoverBackground}
pressedBackground={store.toggled ? "Coral" : pressedBackground}
onClick={() => setStore({ toggled: !store.toggled })}
/>
)
}
}
Components without a connector
Like this button from the Framer Base Kit package, many older components don’t list their events in the Handoff panel. When a component doesn’t have event handler property controls, Framer has no way of telling to which events it might respond.

and its properties in Handoff 👉


Events hunt
So, how do you figure out which events to use with these components?
onWhoKnows()
?
1. Check the docs
I would first peruse the package’s description in the Insert Menu. The component’s creator might have listed all its props, including event callback properties.
When the component is part of an existing UI kit, wrapped for use in Framer, you can check the original documentation. For example, that’s how I learned that the Material-UI slider (docs) not only has an onChange()
, but also an onChangeCommitted()
event, called when you release its knob.
2. Test for common events
The second option: Use an override to listen for popular events.
This override checks for four common events, onClick()
, onTap()
, onChange()
, and onValueChange()
by logging a message to the Console.
export function CheckCallback(Component): ComponentType {
return (props) => {
return (
<Component
{...props}
onClick={() => console.log(`${props.name} : onClick() works`)}
onTap={() => console.log(`${props.name} : onTap() works`)}
onChange={() => console.log(`${props.name} : onChange() works`)}
onValueChange={() =>
console.log(`${props.name} : onValueChange() works`)
}
/>
)
}
}
We don’t know which events a component might react to, but these make sense for the following reasons:
onClick()
is the standard click event used on the web (actually a ‘mouse event’, but it also works on touch devices);onTap()
is a common Framer event;onChange()
is the event emitted by form elements on the web, like text fields, radio buttons, checkboxes, etc.;onValueChange()
is just an often used event name for input elements.
Still, the component’s creator could have used completely different event names. I’ve seen, for instance: onCheck()
and onUnCheck()
on a checkbox, onToggle()
for switches, and onChangeDate()
for a date picker.
Pro tip: How to open the console is a bit hidden. Check the preview’s hamburger menu in the top left corner, or type ⌘I (Windows: Ctrl+I).
Example: Framer Base Kit
I did this override test with a few elements from Framer Base Kit. You could consider the components in this package the predecessors of Framer’s current default components.

- The ‘Button’ and ‘Icon’ emit an
onClick()
; - the ‘Toggle’ (💙), ‘Input’, ‘Switch’, and ‘Slider’ have both
onChange()
andonValueChange()
events; - the ‘RadioGroup’ emits an
onClick()
when you tap the already selected option, plus addsonChange()
andonValueChange()
when you change its selection.
3. Dive in the code
When nothing was documented, you can look at the component’s code. That’s how I found out that Fernando Hurtado’s Data Stack has an onItemTapped()
callback event that is triggered when you tap a row.
…
export type Props = {
component: any;
width?: number;
height?: number;
direction: "horizontal" | "vertical";
expandChildren: boolean;
onItemTapped: (index: number, record: any) => void;
limit: number;
debug: boolean;
scrollable: boolean;
} & SourceProps &
StackProperties;
…
You might find event names in the component’s TypeScript Props
object (as above), its defaultProps
, or in the list of unpacked properties at the beginning of its code.
Button example
In this example, we’ll make it possible to flip the state of the Framer Base Kit button, making it act like a toggle.

Here’s another look at this button’s Handoff props:


No events are listed, but we now know that tapping it triggers an onClick()
, which we’ll use to change store.toggled
to its opposite value.
const useStore = createStore({ toggled: false })
export function FramerBaseKitButton(Component): ComponentType {
return (props) => {
const [store, setStore] = useStore()
return (
<Component
{...props}
text={store.toggled ? "Great tap 🤟!" : "Tap me !"}
intent={
store.toggled ? "success" : props.children.props.intent
}
onClick={() => setStore({ toggled: !store.toggled })}
/>
)
}
}
When toggled
is true
, the button will have "Great tap 🤟!"
as its text
and "success"
as its intent
.
const useStore = createStore({ toggled: false })
export function FramerBaseKitButton(Component): ComponentType {
return (props) => {
const [store, setStore] = useStore()
return (
<Component
{...props}
text={store.toggled ? "Great tap 🤟!" : "Tap me !"}
intent={
store.toggled ? "success" : props.children.props.intent
}
onClick={() => setStore({ toggled: !store.toggled })}
/>
)
}
}
Initially, or whenever toggled
is false
, the button will say "Tap me !"
and have the intent
you gave it on the canvas.
Pro tip: The Intent property control doesn’t show which string it uses behind the scenes ("success"
), but you can select an option with the property control and then check the resulting value under Code in the right-hand panel.
Testing which values an event returns
Sometimes you’ll want more information than just when the component was tapped or clicked. You might want to know what the component’s current state is.
- With a checkbox or switch: Was it flipped on or off?
- When it’s a slider: What’s its current value?
Sometimes there’s only one way to get this information from the component: through an event that returns a value.
Components with a connector
When a component has a connector, it will list its events in the Handoff panel. To figure out which information they return, you can log these events’ arguments to the console.
I first noted down the event names of four default components: Input, Toggle, Radio Buttons, and the Slider:
- Input:
onFocus()
,onChange()
,onSubmit()
, andonBlur()
- Toggle:
onToggle()
,onToggleOn()
, andonToggleOff()
- Radio Buttons:
onChange()
,onOption1Tap()
,onOption2Tap()
, etc. up toonOption10Tap()
- Slider:
onChange()
,onMax()
, andonMin()
…and then gave each component a special override that prints out the returned values:

Here’s the override for the Toggle, with onToggle()
, onToggleOn()
, and onToggleOff()
:
export function CheckToggle(Component): ComponentType {
return (props) => {
return (
<Component
{...props}
onToggle={(...args) => {
console.log(`${props.name} : onToggle()`)
args.map((arg, index) => {
console.log(" " + index + `: ${arg}`)
})
}}
onToggleOn={(...args) => {
console.log(`${props.name} : onToggleOn()`)
args.map((arg, index) => {
console.log(" " + index + `: ${arg}`)
})
}}
onToggleOff={(...args) => {
console.log(`${props.name} : onToggleOff()`)
args.map((arg, index) => {
console.log(" " + index + `: ${arg}`)
})
}}
/>
)
}
}
There’s no way to know how many arguments each event will return, so I map()
through all of them (after putting them in an args
array with the ...
rest parameter).
export function CheckToggle(Component): ComponentType {
return (props) => {
return (
<Component
{...props}
onToggle={(...args) => {
console.log(`${props.name} : onToggle()`)
args.map((arg, index) => {
console.log(" " + index + `: ${arg}`)
})
}}
…
The onToggle()
will log something like this to the Console:

It returns two objects, plus a Boolean telling whether you toggled it on or off.
To know what those objects contain, use console.log()
to only print out the object, like this:
export function CheckToggle(Component): ComponentType {
return (props) => {
return (
<Component
{...props}
onToggle={(...args) => {
console.log(`${props.name} : onToggle()`)
args.map((arg, index) => {
console.log(arg)
})
}}
…
You’ll see them appear with a little ▶ signaling you can open them to view their contents:

Components without a connector
With other components, we’ll again have to guess, check their docs, or take a look at their code. However, UI controls (input, toggle, switch, slider,…) will often use onValueChange()
or onChange()
to return their values. Here’s another investigative override with these two events:
export function CheckReturnedValues(Component): ComponentType {
return (props) => {
return (
<Component
{...props}
onChange={(...args) => {
console.log(`${props.name} : onChange()`)
if (typeof args[0] === "object" && args[0] !== null) {
console.log(
" event.target.value: " + args[0].target.value
)
console.log(
" event.target.checked: " + args[0].target.checked
)
} else {
console.log(" 0: " + event)
}
if (args[1]) {
console.log(" 1: " + args[1])
}
}}
onValueChange={(...args) => {
console.log(`${props.name} : onValueChange()`)
args.map((arg, index) => {
console.log(" " + index + `: ${arg}`)
})
}}
/>
)
}
}
The onChange()
event
An HTML <input>
element (like a textfield, checkbox, radiobutton,…) will emit an onChange()
event.
This event returns an event
object that contains a target
(a reference to the HTML element itself). And this target
object will contain (among other things) the current value
(string or number), or, in the case of a checkbox or radio button, a checked
value (Boolean).
The above override prints out both event.target.value
and event.target.checked
. And when the first argument isn’t an event
object, it’ll print whatever else was returned. Plus: it also looks for a potential second argument (args[1]
).
The onValueChange()
event
The onValueChange()
event is not part of any official API, not even Framer’s, but it’s a name often used by component creators.
The event might return anything, even an entire list of values. That’s why I map()
through all the arguments. (I’ve put them into an args
array with the ...
rest parameter.)
Let’s test!
Example: Framer Base Kit
Here again, a few controls from Framer Base Kit.

onChange()
and onValueChange()
These input elements seem to follow web standards because they all have an onChange()
that returns either an event.target.value
or event.target.checked
, depending on the type of input. But their creator(s) also equipped them with an onValueChange()
that returns just the value.
Examples
Slider + Arconic
Let’s grab the default Slider and use it to control the arc of Benjamin den Boer’s Arconic component.
These components’ properties, as listed by Handoff:
<Slider
overdrag={false}
{/* Using default values */}
background={"#DDD"}
color={"#FFF"}
fillColor={"#09F"}
knobSize={25}
max={100}
min={0}
onChange={undefined}
onMax={undefined}
onMin={undefined}
shadow={"rgba(0,0,0,0.1)"}
track={4}
value={50}
/>
<Arconic
strokeWidth={50}
{/* Using default values */}
color={"#0EF"}
colorEnd={"#60F"}
length={360}
/>
I made two overrides:
Input()
gets the slider’s currentvalue
through itsonChange()
callback event,- and
Output()
sets thelength
of the arc.
const useStore = createStore({ sliderValue: 180 })
export function Input(Component): ComponentType {
return (props) => {
const [store, setStore] = useStore()
return (
<Component
{...props}
onChange={(value) => setStore({ sliderValue: value * 3.6 })}
/>
)
}
}
export function Output(Component): ComponentType {
return (props) => {
const [store, setStore] = useStore()
return <Component {...props} length={store.sliderValue} />
}
}
The first override, Input()
, saves the returned value
in store.sliderValue
. (Multiplied by 3.6
because I want to convert the slider’s 0–100 range to the 0–360 degrees of the arc.)
And by binding the Arconic’s length
property to store.sliderValue
, the arc will always follow the slider.
Radio Buttons + Charts
Here we use Framer’s Radio Buttons to change the properties of one of the Charts in Kirill Morozov’s package.
The Radio Buttons’ onChange()
event changes the chart’s data and color, and the color of the radio button itself.
Chart data
But let me first show you the data:
const barChart = {
names: ["Hotel", "Mini", "Dive", "Sports", "Music", "Karaoke"],
values: [1830, 2420, 204, 3010, 3360, 274],
color: "Crimson",
}
const pieChart = {
names: ["Apple", "Cherry", "Pumpkin", "Pecan", "Rhubarb", "Peach"],
values: [772, 189, 179, 55, 16, 97],
color: "Brown",
}
const bubbleChart = {
names: ["Bath", "Tea", "Gum", "Stock market", "Sort"],
values: [181, 335, 169, 402, 263],
color: "ForestGreen",
}
const useStore = createStore({ selectedChart: 0 })
The data used for each chart never changes, so I made a separate const
object for each chart with its names
and values
arrays, and its color
.
The currently selectedChart
does change, so I made this one a variable in the data store.
Override for the radio buttons
Here’s the RadioButtons()
override. The onChange()
event returns the selected option as an index number (the first button being 0
), which I save in store.selectedChart
.
export function RadioButtons(Component): ComponentType {
return (props) => {
const { activeColor, textActiveColor } = props
const [store, setStore] = useStore()
return (
<Component
{...props}
onChange={(value) => setStore({ selectedChart: value })}
activeColor={
store.selectedChart === 1
? barChart.color
: store.selectedChart === 2
? pieChart.color
: store.selectedChart === 3
? bubbleChart.color
: activeColor
}
textActiveColor={
store.selectedChart === 1
? barChart.color
: store.selectedChart === 2
? pieChart.color
: store.selectedChart === 3
? bubbleChart.color
: textActiveColor
}
/>
)
}
}
Override for the chart
The override for the Chart()
changes a bunch of properties:
- the chart’s
barsNames
andbarsValues
arrays, - the color of the bars:
barColor
, - the color of the lighter background after each bar:
bgColor
, - and the color of the horizontal and vertical text labels:
xAxisColor
andyAxisColor
.
export function Chart(Component): ComponentType {
return (props) => {
const [store, setStore] = useStore()
return (
<Component
{...props}
barsNames={
store.selectedChart === 1
? barChart.names
: store.selectedChart === 2
? pieChart.names
: store.selectedChart === 3
? bubbleChart.names
: props.children.props.barsNames
}
barsValues={
store.selectedChart === 1
? barChart.values
: store.selectedChart === 2
? pieChart.values
: store.selectedChart === 3
? bubbleChart.values
: props.children.props.barsValues
}
barColor={
store.selectedChart === 1
? barChart.color
: store.selectedChart === 2
? pieChart.color
: store.selectedChart === 3
? bubbleChart.color
: props.children.props.barColor
}
bgColor={Color.toString(
Color.alpha(
Color(
store.selectedChart === 1
? barChart.color
: store.selectedChart === 2
? pieChart.color
: store.selectedChart === 3
? bubbleChart.color
: props.children.props.barColor
),
0.25
)
)}
xAxisColor={
store.selectedChart === 1
? barChart.color
: store.selectedChart === 2
? pieChart.color
: store.selectedChart === 3
? bubbleChart.color
: props.children.props.xAxisColor
}
yAxisColor={
store.selectedChart === 1
? barChart.color
: store.selectedChart === 2
? pieChart.color
: store.selectedChart === 3
? bubbleChart.color
: props.children.props.yAxisColor
}
/>
)
}
}
(The bgColor
prop needs a lighter version of the color, which I get by creating a Framer Color()
object and changing its alpha()
to 0.25
, after which I use toString()
to get a CSS rgb()
string.)
When selectedChart
is equal to 1
, 2
, or 3
, I use the corresponding value inside barChart
, pieChart
, or bubbleChart
. In the ‘else’ case, when selectedChart
is 0
, I use the value set by the property control inside props.children.props
.
As you probably noticed: I’m also changing the Radio Buttons’ activeColor
(color of the selected 🔘) and its textActiveColor
.
export function RadioButtons(Component): ComponentType {
return (props) => {
const { activeColor, textActiveColor } = props
const [store, setStore] = useStore()
return (
<Component
{...props}
onChange={(value) => setStore({ selectedChart: value })}
activeColor={
store.selectedChart === 1
? barChart.color
: store.selectedChart === 2
? pieChart.color
: store.selectedChart === 3
? bubbleChart.color
: activeColor
}
textActiveColor={
store.selectedChart === 1
? barChart.color
: store.selectedChart === 2
? pieChart.color
: store.selectedChart === 3
? bubbleChart.color
: textActiveColor
}
/>
)
}
}
(That color change doesn’t happen instantly, probably because the button and text label were animated to the current color.)
By the way, these charts don’t display random values. This is hard-core data 📊. They show how many millions of Google search results there are for each search term.
More examples
The Smart Components section has a few more examples that use the values returned by my iOS segmented control component.
Even more properties
When a component was made with <Frame>
s or Motion elements, you might be able to pass it Framer properties, including animation props and events.
Take this FABButton and PrimaryButton from the Elements UI Kit by Todd Reynolds:

These are the buttons’ ‘official’ properties:
<FABButton
{/* Using default values */}
name={"Add"}
onTap={undefined}
tint={"#4af196"}
/>
<PrimaryButton
{/* Using default values */}
buttonType={"a"}
label={"Hello Framer!"}
onTap={undefined}
tint={"#0099ff"}
/>
What’s particular about the components in this package, and what I recommend every component should do, is that they accept incoming properties and pass them to the container frame (or Motion element).
Here’s a snippet from FABButton’s code. It unpacks the component’s custom props (text
, tint
, onTap
) and passes the rest
to the <Frame>
.
export function FABButton(props) {
const { text, tint, onTap, ...rest } = props
return (
<Frame
{...rest}
borderRadius={28}
top={0}
left={0}
style={{
WebkitBackdropFilter: "blur(6px)",
backdropFilter: "blur(6px)",
backgroundColor: "rgba(0,0,0,0)",
}}
>
…
This means that any other property you pass it will be passed on to the frame, just like happens when you override a frame drawn on the canvas.
The component doesn’t have a property control for its background color, but it contains a <Frame>
, so I can set its backgroundColor
directly. And I can give it some ‘while’ animations.
export function Buttons(Component): ComponentType {
return (props) => {
return (
<Component
{...props}
tint="White"
backgroundColor="Tomato"
whileHover={{ backgroundColor: "Red" }}
whileTap={{ backgroundColor: "DarkRed" }}
/>
)
}
}

It’s hard to tell if a component was constructed like this without looking at the code. So an easy way to figure this out is by doing a small test, like trying to make it draggable:
export function Draggable(Component): ComponentType {
return (props) => {
return <Component {...props} drag />
}
}
My iOS Segmented Control is another one that does this.

This component also accepts other Framer properties, like here onHoverStart()
and onHoverEnd()
.
export function SegmentedControl(Component): ComponentType {
return (props) => {
const [hover, setHover] = useState(false)
return (
<Component
{...props}
onHoverStart={() => setHover(true)}
onHoverEnd={() => setHover(false)}
options={
hover
? ["🍒", "🥝", "🍌", "🥭", "🍋"]
: props.children["props"].options
}
/>
)
}
}
Which options the segmented control now shows depends on its hover
state. When hovered over, it will show the emojis; and when not, the options
set by the property control.
Just wrap it
When a component doesn’t support a prop or event you’d like to use, you can often just wrap it in a frame and apply an override to that frame.
Here’s how to do a similar ‘change options on hover’ trick with Framer’s Segmented Control.

This control’s ‘Track Color’ was set to 0% opacity. Thus, the gray (or orange) background you see is that of the frame wrapping it.
The parent frame has the below Wrapper()
override applied. A whileHover
animates the frame’s backgroundColor
to “Coral”, and the onHoverStart()
and onHoverEnd()
events flip the hover
variable in the data store.
const useStore = createStore({ hover: false })
export function Wrapper(Component): ComponentType {
return (props) => {
const [store, setStore] = useStore()
return (
<Component
{...props}
onHoverStart={() => setStore({ hover: true })}
onHoverEnd={() => setStore({ hover: false })}
whileHover={{ backgroundColor: "Coral" }}
/>
)
}
}
This store.hover
is then used to toggle the segments
and fontSize
of the segmented control:
export function SegmentedControl(Component): ComponentType {
return (props) => {
const [store, setStore] = useStore()
return (
<Component
{...props}
segments={
store.hover
? ["🍒", "🥝", "🍌", "🥭", "🍋"]
: props.children.props.segments
}
fontSize={store.hover ? 22 : props.children.props.fontSize}
/>
)
}
}
14 comments on “Overriding Code Components”
Leave a Reply
You must be logged in to post a comment.
Hi! I can’t figure out how to listen for value changes for the components in this design system: https://github.com/EMCECS/clarity-react which I’m trying to integrate within Framer X.
I tried your approach, but to no avail with neither the Toggle component or the checkbox and others, I only got the Input to work. I can see that e.g. the original Checkbox component has an onChange prop, but somehow I can’t get its value.
Could you have a look and see what I’m missing? Thanks! Here’s my Framer file: https://send.firefox.com/download/4d594eb17bc02d5a/#TRG8S2ukXrVd1PxZzL6cYQ
I took a look at that design system’s checkbox and noticed that it doesn’t share its state.
It does have an internal
value
state, which gets toggled by thishandleChange()
function (triggered by itsonChange()
):… but the current
value
is not sent back upstream. It’s not shared through theonChange()
callback event.When you pass it an
onChange()
, it will call it (whenonChange !== undefined
see below), but then its internalhandleChange()
isn’t called anymore (so the checkbox stays unchecked).This means that this component is meant to be used as a controlled component. Its parent has to keep track of its state.
So in your wrapper component I added a
checked
state:… which gets passed to the component:
Together with a
handleToggle()
function that updates that state and also shares it throughonValueChange()
:(I used
onValueChange()
because anonChange()
normally also returns the event object.)See the attachment for this updated Checkbox wrapper. (For Framer Beta, because your project was also updated for beta.)
Say I have an override that (successfully) changes a certain property to a design component, like changing its position from the top of the viewport dynamically.
I’ve now replaced that design component with a code component. Using the same override as above, my prototype works just fine (i.e. my code components are overridable).
But I don’t want to use overrides. I want to include all the behavior inside my code component. My thought has been to move my override function inside the code component and use an event (onLoad?) to fire it, just like I did before with the override function. This doesn’t seem to be working (the property doesn’t change). Any idea what event should I look for to instantly change the property of a code component if I wanted to avoid using overrides?
What did the override do? Did it change the component’s position all the time (and with which kind of event?), or just once, when the prototype loads?
Whatever you did in the override when the prototype loads, you should be able to do it inside the component as well, if you place that code before the component’s
return()
statement.When animating upon load, it’s even simpler, the component then doesn’t need any logic (or state), just an
animate
, like this:About properties: A component cannot change its own props. Props are always send down to it by a parent component or an override. (More about this and the difference between ‘props’ and ‘state’.)
To get rid of overrides or parent components that control a component (by sending it props), you often just need to make the component, sort of… bigger. Take the 25. Colors: Switching between states project as an example.
The version with overrides has two overrides. One for the white box and another one for the background. So the overrides have the ‘state’ (in that Data object) and send down the
animate
properties to those frames (and also those hover events).But the code component version is just one big component that contains everything. It has the state (now a
useState()
), contains both frames, and controls them by sending them the correct properties. (A frame is actually also a component, but a dumb one, like a design component.)Alright – this is all beginning to make sense – but I have a problem with the opacity not working here. Can you see anything wrong with this?
—
My code component…
import * as React from “react”
import { Frame, addPropertyControls, ControlType } from “framer”
export function Controls(props) {
return (
)
}
Controls.defaultProps = {
radius: 25,
opacity: 1,
scale: 1,
x: 0,
rotate: 50,
}
addPropertyControls(Controls, {
radius: { type: ControlType.Number, title: “Radius” },
})
—–
My override…
import * as React from “react”
import { Override, Data, Color, motionValue, useTransform } from “framer”
const scrollY = motionValue(0)
export function Scroll(): Override {
return {
contentOffsetY: scrollY,
}
}
export function PageHeader(props): Override {
const newOpacity = useTransform(scrollY, [0, -50], [1, 0.5])
const newScale = useTransform(scrollY, [0, -50], [2, 0.6])
const x = useTransform(scrollY, [0, -50], [300, -200])
const newRotate = useTransform(scrollY, [0, -50], [0, 360])
return {
opacity: newOpacity,
scale: newScale,
x,
rotate: newRotate,
}
}
—-
??
I’m guessing you’re attaching the
PageHeader()
override to thatControls()
component?Unfortunately, some code (every
<
) gets stripped by this comment form… so I can’t see the most important part of your code component: the stuff that’s inside thereturn()
.My first guess would be that the opacity property doesn’t get passed to the
<Frame>
inside the code component, as mentioned as a possible problem at the beginning of this page, or more in detail here.Here is a screen grab of the code. Everything works except the opacity.
That’s odd. That looks like it should work.
Maybe you need to animate it. I would try putting opacity in an animate. Like this:
animate={{ opacity: props.opacity }}
.If that doesn’t work I would try to unpack some properties, because currently you’re passing
opacity
(and the others) twice to the Frame: once insideprops
and once separately.Hej – Thanks for your help. Still no joy. If you have a second. Take a look at this.
https://framer.com/projects/ScollAnimate–5G96rmeNMqj0qi7mB0TZ-gCSuR
Okay, I found something!
Apparently the
opacity
property doesn’t get passed to a code component by its ‘component container’ (a thingy that wraps every code component on the canvas).A workaround is to not explicitly use
opacity
but pick some other name (I usedsomethingElse
😃). This way it doesn’t get removed.Here’s an example:
https://framer.com/projects/ScollAnimate-copy–e1N83vKUlU3uBDuxO4kb-idLJv
Legend! Thanks for all your assistance on this. Top man : )
Really am enjoying, working through the Book, .. much appreciated Tes…
I have been using charts in my prototypes so was more than happy to see an example of the bar chart that was using overrides to dynamically push the data … For the life of me, I cannot figure out how to override the ‘Scatter’ chart using overrides … // Is there something different I should be doing different here with multiple sets and multiple values to override this particular chart?
Any direction, much appreciated!
Hi!
It seems to work more or less the same… only with different properties. I made a simple example.
One thing tripped me up: I noticed you can enter the data for not one but three scatter charts (you pick which data set you want to enter with the last property control: ‘Current set’).
So I thought you could switch between three displayable sets (maybe with a better animation)… but it’s different: you can display only the first set, or both the first and second set, or all three sets. (You make this selection with the first property control: ‘Sets’)
Hope this helps!
This is absolutely awesome my friend. I was so close :/ the current set is where I was tripping up. Although the Framer community is growing, there is limited knowledge available when it comes to great examples using code… Happy I found this gem of site.