Framer Cheat Sheet: Classes & Modules
Classes and modules help you reuse the same element over and over again without duplicating code. And if you put it in a module, you can use it in different prototypes too! This is recommend for users with more experience.
Shit guys. Things just got real. We are building classes and modules. Hot damn. But calm down, it’s not as difficult as it sounds. Even for me, a professional copy-and-paster, can figure it out (well, sort of).
In this cheat sheet we will cover:
- What is a class? And a module?
- Setting up a class
- Creating defaults
- Add more layers in a class
- Adding new properties
- Functions and events
- Setting properties outside of initialization (Getters and Setters)
- Making a module
- Examples
- Resources that really helped me
1. What is a class? And a module?
You know PageComponent
, ScrollComponent
, SliderComponent
? Well, they are all just classes built into Framer.
Great. So what does that mean for you? Basically, by building your own class, you can reuse the same code over and over again in different contexts.
This helps keep consistency through a prototype (or across multiple prototypes), as well as saving you from re writing whole chunks of code for functionality.
A module is a file that we use to keep and organise our classes. Imagine you you had 10 classes in the same Framer file — it would be nuts! So by putting our classes in a module, we keep everything neater, and it also allows us to move the same class to future projects easier.
2. Setting up a class
To set up the basic of most basic classes, you need to do three things;
- Define a class
- Create a constructor
- Create a super
And then call your class.
For the most part you will be able to copy and paste this slab of code before you start creating your own. (But you will need to change the name of MyNewAndImprovedLayer)
class MyNewAndImprovedLayer extends Layer
constructor: (@options={}) ->
super @optionsthing = new MyNewAndImprovedLayer
Pro Tip: See how it says, extends Layer
? You can extend other components by just saying extends ScrollComponent
or whatever. I use extends TextLayer
when I want to create a universal label, for example.
A note on etiquette when creating classes, always have your class’ name in CamelCase. For example, don’t name your class
button
, name itButton
.Textfield
isn’t any good either, ratherTextField
. That way it doesn’t get confused with other layers.
3. Creating defaults for the parent layer of the class
So, before we begin — there are two types of defaults. Those you can change outside of the class and those you can’t.
And it all comes down to the ?=
and =
.
In the below example I have used an =
to say that the background colour is black. And you CAN’T change it later. Notice how in the example below that thing’s background colour isn’t blue.
class MyNewAndImprovedLayer extends Layer
constructor: (@options={}) ->
@options.backgroundColor = "#000"
super @optionsthing = new MyNewAndImprovedLayer
backgroundColor: "blue"
thing.center()
In this example below, I have used the ?=
which means that you will be able to change the backgroundColor
outside of the class. See how the code is almost exactly the same.
class MyNewAndImprovedLayer extends Layer
constructor: (@options={}) ->
@options.backgroundColor ?= "#000"
super @optionsthing = new MyNewAndImprovedLayer
backgroundColor: "#blue"
thing.center()
Pro Tip: To do a whole lot of defaults in one go, see below. Note: you will be able change these properties outside of the class.
class MyNewAndImprovedLayer extends Layer
constructor: (@options={}) -> _.defaults @options,
backgroundColor : "#000"
height: 48
borderRadius : 2 super @optionsthing = new MyNewAndImprovedLayer
backgroundColor: "#00aeff"
4. Add more layers in a class
You know how in a slider component you refer to the slider’s knob as slider.knob.
? What you are doing here is referring to a layer within the slider component.
To create a layer that can be accessed outside of the class, add an @
symbol before the layer name. In this example below we are creating a new text layer for a button.
NOTE: You only define the parent for the added layer AFTER the super, along with it’s position.
class Button extends Layer
constructor: (@options={}) ->
@options.backgroundColor ?= "#000"
@options.height = 44
@label = new TextLayer
fontSize: 16
super @options
@label.parent = @
@label.center()button = new Button
button.center()button.label.text = "Hello there"
5. Adding new properties
You ever notice how sliderComponent
s have a min
and max
property, while most other components don’t? This is a property that has been added.
In this example, we are going to make a very VERY crude version of the TextLayer
. The property mySuperSexyFont doesn’t mean anything in code (in fact, in this example you could replace it with HotPants and it wouldn’t change anything).
class SimpleTextLayer extends Layer
constructor: (@options={}) -> @options.backgroundColor = "000"
@options.mySuperSexyFont ?= "'Source Sans', sans serif"
@options.html = @options.text
@options.style =
fontFamily : @options.mySuperSexyFont
textAlign: "center"
lineHeight: "200px"
super @options
myText = new SimpleTextLayer
text: "hello"
mySuperSexyFont: "'Roboto', sans serif"
myText.center()
6. Functions and events
While you can build events within the constructor of the class, it is neater and more useful to build them outside. Unlike a normal function, use : =>
as opposed to = ->
.
class Button extends Layer
constructor: (@options={}) -> @options.backgroundColor = "#F14676" super @options #event
@.onMouseOver @Hover
@.onMouseOut @HoverOff #function
Hover: =>
@.brightness = 70
HoverOff: =>
@.brightness = 100button = new Button
button.center()
7. Setting properties outside of initialization (Getters and Setters)
So you can add new properties in a class — but how do you change them later? Enter Getters and Setters.
In this example below, we are setting the default for the class to be enabled. Later in the prototype we might want to change it’s class to be disabled — in this case it is onClick
.
class Button extends Layer
constructor: (@options={}) ->
@options.disabled ?= false
@options.backgroundColor = "000"
if @options.disabled is true
@options.opacity = 0.5 super @options @define 'disabled',
get: ->
@options.disabled
set: (value) ->
@options.disabled = value
if @options.disabled is true
@opacity = 0.5
else
@opacity = 1
Button = new ButtondeactiveButton = new TextLayer
text: "deactive"deactiveButton.onClick ->
Button.disabled = true
8. Making a module
Making a module would be easy — if it wasn’t for all the moving parts. There are two ways to set up a module, and it depends on the amount of classes you have. If you only have one class, choose method 1, if you have more choose method 2.
But, first download Sublime.
1. If you only have one class in the module
In this example we will be making a “button” module. Please for the Love of all things chocolate and holy, change it to your own module’s name.
- Once you have downloaded Sublime, copy and paste your class from Framer into a blank Sublime document.
- Where you have
class Button extends Layer
or whatever, change it toclass exports.Button extends Layer
- Save your Sublime file as the SAME (exact same) name as your class. e.g. if you class’ name is
Button
save your module’s name as Button. - Next, create a new framer file and drop the module in the module’s folder.
- Now make sure your module’s format is in coffee script. You do this by right clicking on the file and renaming it to e.g. Button.coffee
- Now switch over to your Framer file and add
{Button} = require "Button"
at the top of your file. - Then call your class by just saying
button = new Button
2. If you have two or more classes in your module
In this example we will be making a module with a few different form field components. Like something that would help keep consistency across different prototypes through out a company.
- Once you have downloaded Sublime, copy and paste your classES into a Sublime blank page.
- For each instance where you have
class textField extends Layer
or whatever, change it toclass exports.textField extends Layer
. Do this for EVERY class that you want to import. - Save your Sublime file as something that doesn’t relate to any of the classes in your file. For this example we will use MaterialComponents.
- Next create a new framer file and drop the module in the module’s folder.
- Now make sure your module’s format is in coffee script. You do this by right clicking on the file and renaming it to e.g. MaterialComponents.coffee
- Now switch over to your Framer file and add
MaterialComponents = require ‘MaterialComponents'
at the top of your file. Notice how it is different than if you were just importing one class - Now to call on a class go,
button = new MaterialComponents.Button
orformField = new MaterialComponents.TextField
. Notice how you have to call the module AND the class.
9. Examples
Button Class
This is just a class for a button. The class is within the Framer code — not tucked away in a module.
Button Module
Seeing double? Yes, this does look exactly like the above example — because it kinda is. Except it has the class tucked away in a module.
MaterialComponents Module
This is a massive module I made with more bugs than an anthill — especially around the form fields. But it is a good example of how you can put loads of classes in one module. Read more about it here.
10. Resources that really helped me
Figuring things out for yourself isn’t easy. These two stories really helped me along the way, and hopefully they will help you too.
Developing a Framer Module
This article written by John Marstall really helped me when I was trying to figure things out. Go over and give him 50 claps for me won’t you?
Classes, Loops and Arrays in Framer
Øyvind Nordbø’s article had some great examples of classes and how they can work practically. Go give him some love.