Material Kit was created to make prototyping with Material Design fast and easy without compromising the quality or customization.
There are three core pieces that make up Material Kit. There is the foundational elements that help Material Kit mold to devices. There is the component library that’ll save you time by providing material offerings, and then there’s the supporting functions that help power the foundation & components.
If you're interested in prototyping with iOS, check out the iOS Kit for FramerJS
- Setup
Foundational Elements - Dynamic Layout
- Real device override
- Device details library
System Components - Material Color
- Material Icon
- Status Bar
- App Bar
- Banner
- Video
- Dialog
- Text
- Buttons
- Snack Bar
- Navigation Bar
Supporting Functions
How to Contribute
material-kit.coffee material-kit-dialog.coffee material-kit-appbar.coffee material-kit-banner.coffee material-kit-button.coffee material-kit-layout.coffee material-kit-library.coffee material-kit-nav-bar.coffee material-kit-status-bar.coffee material-kit-snack-bar.coffee material-kit-stack.coffee material-kit-icon.coffee material-kit-text.coffee material-kit-utils.coffee material-kit-video.coffee
Please note: that Framer Studio currently doesn't support subfolders in the modules folder, so they'll need to be added to the root.
In Framer Studio, write –
m = require 'material-kit'
You can write any variable name you'd like, but for the purposes of this guide we'll be using m
.
The most fundamental piece of this module is Dynamic Layout. Dynamic Layout is a robust layout engine that’ll not only help make positioning layers easier and smarter, it'll will make positioning layers across devices possible.
1dp = 1px * scale
Side note: you can also use the built-in functions.
m.dp(6) #returns 3 points on HTC One and 2 points on Nexus 4
m.px(1) #returns 4 pixels on Nexus 6p and 3 pixels on iPhone 6 plus
As we get away from using pixel positioning, we won't be using x & y based positioning. Instead, we'll be setting things called constraints. When you set a constraint, it's like saying that a layer can't go beyond a certain position. There are four constraints for positioning: leading, trailing, top, and bottom.
To set a leading & top constraint on a box, write this –
layer = new Layer layer.constraints = top:10 leading:10 m.layout.set()
This will position the layer at x:30, y:30 on Samsung S5, and x:40, y:40 on Samsung S7
Side note: you can also do this on one line if you'd prefer using this syntax. Just replace the layer.constraints line from above with this line. You'll still need to run the m.layout.set function.
layer.constraints = {top:10, leading:10}
If you set a leading & trailing or a top & bottom, Dynamic Layout will do its best to honor the constraints, which will mean the height/width will need to be adjusted. For example, if you set the constraints of a layer to leading: 0
and trailing:0
, the layer's width will be adjusted to the device's width.
WARNING - If you set too many opposing constraints, I'm not sure what'll happen. Best of luck. ¯\_(ツ)_/¯
Try to just set no more than one of each constraint.
One of the most powerful things of Dynamic Layout is relationships. Relationships allows you to link a layer onto another layer in a variety of ways.
When you declare a constraint, you can set a constraint as a layer instead of an integer. For example, if you have two layers (boxA & boxB) you can set boxB's top as boxA.
boxB.constraints = top:boxA m.layout.set()
This will stack the boxes so that boxB's top edge is constrained to below boxA, but what if you want a little buffer? That's really easy. We'll use a little different syntax with wrapping the layer and buffer in brackets.
boxB.constraints = top:[boxA, 10] m.layout.set()
This will set boxB's top edge to 10 points below boxA.
There are a couple other types of constraints that'll help make positioning layers even easier. There are two centering constraints: verticalCenter, horizontalCenter. These constraints will only accept just a layer as a constraint.
For example, if you'd like boxB to be horizontally centered on boxA, write this:
boxB.constraints = top:[boxA, 10] horizontalCenter:boxA m.layout.set()
This will set boxB 10 points below boxA, and it'll center it within boxA on the x-axis. The other centering constraint verticalCenter will work simliarly center boxB within boxA on the y-axis. If you've set a top/bottom constraint, it'll ignore those constraints.
If you'd like to align boxB's trailing edge onto boxA's trailing edge, write this:
boxB.constraints = top:[boxA, 10] trailingEdges:boxA m.layout.set()
- target (optional) Layer or Array of layers
When set, this will only animate the target layers with updated constraints. When this is not set, it'll animate all layers with their updated constraints. - curve, curveOptions, delay, repeat, colorModel String
Each of these properties will work the same as native animations - time Num
This will be the time of each layer's animation, not the entire animation of all the layers. - stagger Num
This will put an incremental delay across all layers being animated. - fadeOut Boolean or Layer
When set to true, this will animate all layers' opacity to 0. When set to a layer, that layer's opacity will be set to 0. - fadeIn Boolean or Layer
When set to true, this will animate all layers' opacity to 1. When set to a layer, that layer's opacity will be set to 1.
If we have a bunch of layers in a column and we want them to all move up, we can set the topLayer
's constraint to 50, and all the layers with a relationship with topLayer will also move up.
topLayer.constraints.top = 50 ##Set a new constraint m.animateLayout stagger:.05 curve:"spring"
Note: When updating a constraint on a layer, please be careful on your syntax. Writing layer.constraints =
will wipe out your previous object.
This will wipe out your top constraint.
topLayer.constraints = top:50 leading:10 topLayer.constraints = leading:20
Where as, this will keep your top constraint.
topLayer.constraints = top:50 leading:10 topLayer.constraints.leading = 20
boxB.constraints = top:[boxA, 10] trailingEdges:boxA height:100 width:100 m.layout.set()
#####When to call it
You'll need to call it before any x/y positions are referenced. If you have a function that's based off another layer, you'll need to call m.layout.set before that positioning is stored otherwise it'll be wrong or 0. Once you call m.layout.set(), it'll set the position to the accurate position.
#####Mixing up the queue
m.layout.set will accept layers in the parathesis. This will layout only that layer and ignore all other constraints. This is to be used if a layer created after others needs to be laid out before others.
m.layout.set(boxB)
This will only layout boxB and not boxA.
If you need a completely different order, you can use the target property and pass an array in the order you wish for them to be laid out.
m.layout.set target:[boxB, boxD, boxA]
For this to work properly, you'll need a full-screen browser. I use & recommend Framer on Android and Frameless on iOS.
m.device.scale # returns 1,2,3 m.device.height # returns the height of the device in pixels m.device.width # returns the width of the device in pixels m.device.name # returns many different options
Every component in this module was written to feel native to Framer, so the way you create components should feel as familar as creating a new layer. The difference is that in addition to Framer properties there's added customization parameters, which will be accepted, and any component that can accept constraints from Dynamic Layout is able to.
After creation, components will operate as native layers under the variable name you declared. The only difference is the sublayers of the component are accessible via dot notation, so it's easier for you to turn on event listeners etc.
One of the core parts of material design is color. To make it convenient, there's a color function that has all of material design's color palette included. Also, all the objects below will by default use them, so when you pass a backgroundColor or color property feel free to use the following codes.
Color codes in material design are setup as name + code like blue400 or red100. The color name is lower camel-case like "deepPurple" and any code that includes an "A" is uppercase.
# Non-material design layers layer = new Layer color:m.color("lime700") ## sets color to #AFB42B # Material design layers text = new m.Text color:"yellowA400" ## sets color to #FFEA00
You can easly access all the icons in the Material Design library with a simple & easy object.
- name String
String that grabs the icon from the library - scale Int
Scales the icon's height & width. - color Color String
Sets the color of the icon. - superLayer String
Same as Framer's superLayer property. - constraints Constraints Object
Sets the icon's constraints. - clip Boolean
Same as Framer's clip property.
Please note: Whenever an icon has more than one words, use an _ between the words. So flight land would be "flight_land"
icon = new m.Icon name:"exit_to_app" color:"white"
The status bar allows users to see the connection, current time, and battery.
####Properties
- style String
Dark is black white on black. Light is grey on white text. - opacity Int
Sets the opacity of the layers in the status bar. - color Color String
Sets the color of the layers in the status bar. - backgroundColor Color String
Sets the background color in the status bar. - clock24 Boolean
By default, it's set to false, so it's a 12 hour clock with AM/PM. When set to true, the clock will cycle through 0-23 hours and removes AM/PM.
statusBar = new material-kit.StatusBar style:"light"
####Schema
statusBar : { statusBar.batteryIcon statusBar.time statusBar.cellular statusBar.wifi }
The app bar in android is the most versatile component. It can handle tabbing & key actions.
####Properties
- title String
Sets intial title of app bar. - menu Layer or Icon String
If set, it will appear to the left of the title. - superLayer String or Tab
Same as Framer's superLayer. - backgroundColor Boolean
Sets the background color of the app bar. - titleColor Layer or String or Bool
Sets the color of the title. - actionColor Layer or String
Sets the color of the actions. - actions Array of Layers or Strings
Sets the actions to the right of the Title. - tabs Array of String
If set, the app bar will show tabs. - tabIcons Array of Layers or Icon strings
If set, will replace tab names with icons. - tabsInk Ink Object
Sets the ink effect on the tabs. - tabsAlt {Color and/or Opacity}
Sets the non-active tabs color and/or opacity. - tabsBarColor Color String
Sets color of the bar that appears under the active tab.
bar = new m.AppBar backgroundColor:"red600" title:"YouTube" tabs:["YouTube Red", "trending", "subscriptions", "account"] tabIcons:["home", "whatshot", "subscriptions", "person"] tabsInk:{color:"red800", scale:3} tabsBarColor:"white" tabsColor:"white" tabsAlt:{color:"black", opacity:.7} actions:["more_vert", "search"]
The banner is a non-blocking notification. Typically, the banner will send you to a specific screen in an app.
####Properties
- app String
Sets app text. - title String
Sets title text. - message String
Sets message text. - time String
time string that appears next to title. - icon Layer
This will put the layer inside the banner and size it accordingly. By default, it's a green box. - duration Integer
This will override the time before the banner animates-out. By default, this is set to 7. - animated Boolean
When set totrue
sheet will animate-in.
**NOTE - ** The banner will be, by default, draggable. If you drag down, it'll reset, and if you drag up it'll dismiss & destroy the banner.
banner = new material-kit.Banner title:"Time to do something" message:"Don't miss out" icon:iconLayer animated:true
banner : { banner.app banner.icon banner.title banner.message }
To make the banner clickable, you can write -
banner.on Events...
##Video This is a video object that comes with UI controls.
####Properties
- video URL
Sets the video being played. - image URL
Sets image loaded before playing. - width Int
Sets width of the video. - height Int
Sets the height of the video. - max Boolean
Sets the width & height to max for the video on the device. - progressColor Color String
Sets color of the seeker & progress bar. - backgroundColor Color String
Sets background color of the video. - superLayer Layer
Sets superLayer of the video. - autoplay Boolean
If true, the video will start on load. - loop Boolean
If true, the video will repeat when finished. - muted Boolean
If true, the video will be muted on computers. - idleLimit Int
Sets the duration before the controls hide. - showPlayStop Boolean
If true, the circle behind the play/hide will be shown. - constraints Constraints Object
Sets constraints for the video.
video = new m.Video video: "myDog.mp4"
video : { video.controls video.progressBar video.seeker video.seekerDot video.timebar video.endTime video.currentTime video.fullscreen video.fullscreenExit }
Dialogs are blocking notifications that will force the users to address the dialog before continuing.
- title String
Embolded text at the top. - message String
Body text before actions. - actions Array of Strings
Series of actions that can be taken on the dialog.
dialog = new m.Dialog title:"Warning" message:"Don't do this" actions:["OK", "Cancel"]
dialog : { dialog.modal dialog.title dialog.message dialog.actions : { OK, Cancel } dialog.overlay }
To listen to different actions, you can use dot notation if it's a single word or brackets for any case
- Dot notation
dialog.actions.OK.on Events...
- Square bracket notation
dialog.actions["OK"].on Events...
A dynamic text object that'll automatically size for you.
####Properties
- text String
Adds text by default to the field. - fontSize Integer
Sets font size in points. - fontWeight Integer
Sets font weight. - fontFamily String
Sets font family. - lineHeight Integer
Sets line height in points. It's automatically done if left unset. - textTransform String
Sets text-transform style property. - opacity Integer
Sets opacity. - width Integer
Sets width in points. - height Integer
Sets height in points. - constraints Constraints Object
Will set the text's constraints and run layout using Dynamic Layout
####Example
text = new m.Text text:"Try Material Kit for Framer JS" fontSize:21 fontWeight:100 width:320 constraints:{align:"center"}
Button is a small versatile component that handles press states automatically.
####Properties
- text String
Sets button text. - type String
Can befloating
,raised
,flat
. - backgroundColor Hex Color
Will set the background on big buttons. - icon Icon String
If floating, this will set the icon. - color Hex Color
Setssmall
andtext
colors. - superLayer Layer
set the passed layer as the super layer. - constraints Constraints Object
will set constraints using Dynamic Layout. - ink Ink Object
Sets parameters of ink. - clip Boolean
Sets whether the ink should be cut off when extending beyond the button object.
button = new m.Button text:"Download" type:"raised"
####Schema
button: { button.label }
Listening to buttons is no different than normal framer.
button.on Events...
####Properties
- text String
Sets the text of the snackbar. - action String
Sets the action button of the snackbar. - actionColor Color String
Will set color of the action. - animated Boolean
Animates the snackbar in. - duration Int
Sets the time before animating out in seconds.
snack = new m.SnackBar text:"I'm afraid you can't do that." action:"Retry"
####Schema
snack: { snack.text snack.action snack.bg }