- Notifications
You must be signed in to change notification settings - Fork35
License
k-vyn/framer-ios-kit
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
iOS Kit was created to make prototyping for iOS fast and easy without compromising the quality or customization.
There are three core pieces that make up iOS Kit. There is thefoundational elements that help iOS Kit mold to devices. There is thecomponent library that’ll save you time by providing native iOS offerings, and then there’s thesupporting functions that help power the foundation & components.
##UpdatesAugust 3rd, 2016 – Sketch integration & major code cleanup:
- AddedSketch convert &Sketch components.
- AddedView layer, which is like a Framer Layer but accepts constraints.
- Major field component update.
- Better cursor handling.
- Allows for keyboard to move between fields.
- Keyboard overhaul.
- Added iPad Pro support.
- Added dark style.
- Banner is updated to iOS 10 styling.
- Tab & Tab Bars work with only layers.
- The module is now broken into subcoffee files, and it's stitched together with the
ios-kit.coffee
. - Layout functions have been changed from
ios.layout()
toios.layout.set()
andios.animateLayout()
toios.layout.animate()
. - All supporting functions were moved to
ios-utils
and all assets were moved toios-library
. - Added Contribution section toREADME.
- Empty component added as
iso-temp
.
- Empty component added as
- Alerts now dismiss automatically.
- Bunch of bug fixes.
- Setup
Foundational Elements - Sketch convert
- Sketch components
- Dynamic Layout
- Real device override
- Device details library
System Components - Action String Shortcuts
- Alert
- Banner
- Button
- Field
- Keyboard
- Navigation Bar
- Sheet
- Status Bar
- Tab
- Tab Bar
- Text
Supporting Functions
How to Contribute
ios-kit.coffeeios-kit-alert.coffeeios-kit-banner.coffeeios-kit-button.coffeeios-kit-field.coffeeios-kit-keyboard.coffeeios-kit-layout.coffeeios-kit-library.coffeeios-kit-nav-bar.coffeeios-kit-sheet.coffeeios-kit-status-bar.coffeeios-kit-tab-bar.coffeeios-kit-text.coffeeios-kit-utils.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 –ios = require 'ios-kit'
You can write any variable name you'd like, but for the purposes of this guide we'll be usingios
.
To use Sketch convert, just wrap your sketch file inside ofios.convert()
ios = require "ios-kit"sketch = Framer.Importer.load("imported/iOS Kit Demo@1x")sketch = ios.convert(sketch)
That’s it! You’re done.
Pro-Tip – Framer imports layers that not in groups as combined layers, so the more you separate your layers into groups the more accurate Sketch convert can be.
To convert Sketch layers into iOS Kit components, you write the same convert statement as above.
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.
1pt = 1px * scale
Side note: you can also use the built-in functions.ios.pt(6) #returns 3 points on iPhone 6 and 2 points on iPhone 6 plus
ios.px(1) #returns 2 pixels on iPhone 6 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 Layerlayer.constraints = top:10 leading:10ios.layout.set()
This will position the layer at x:20, y:20 on iPhone 6, and x:30, y:30 on iPhone 6 plus.
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 ios.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 toleading: 0
andtrailing: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:boxAios.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]ios.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:boxAios.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:boxAios.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, colorModelString
Each of these properties will work the same as native animations - timeNum
This will be the time of each layer's animation, not the entire animation of all the layers. - staggerNum
This will put an incremental delay across all layers being animated. - fadeOutBoolean 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. - fadeInBoolean 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 thetopLayer
's constraint to 50, and all the layers with a relationship with topLayer will also move up.
topLayer.constraints.top = 50 ##Set a new constraintios.animateLayoutstagger:.05curve:"spring"
Note: When updating a constraint on a layer, please be careful on your syntax. Writinglayer.constraints =
will wipe out your previous object.
This will wipe out your top constraint.
topLayer.constraints = top:50leading:10topLayer.constraints = leading:20
Where as, this will keep your top constraint.
topLayer.constraints = top:50leading:10topLayer.constraints.leading = 20
boxB.constraints = top:[boxA, 10]trailingEdges:boxAheight:100width:100ios.layout.set()
#####When to call itYou'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 ios.layout.set before that positioning is stored otherwise it'll be wrong or 0. Once you call ios.layout.set(), it'll set the position to the accurate position.
#####Mixing up the queueios.layout.set will accept layers in the parathesis. This will layoutonly 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.
ios.layout.set(boxB)
This will only layout boxB and not boxA.
You may also want to play with the creation order if you're having issues with relationships.
For this to work properly, you'll need a full-screen browser. I use & recommend Frameless.
ios.scale # returns 1,2,3ios.height # returns the height of the device in pixelsios.width # returns the width of the device in pixelsios.device # returns one of the device names belowipad # for any iPad other than the proipad-pro # for the iPad Proiphone-5 # for iPhone 5, iPhone 5s, iPhone 5c, and iPhone SEiphone-6s # for iPhone 6 & 6siphone-6s-plus # for iPhone 6 plus & 6s plus
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.
-b
- bold string-g
- make string green-r
- make string red-rb
- make string blue-lb
- make string light blue-o
- make string orange-p
- make string pink-y
- make string yellow-#000000
- change color to any 6 digit hex code.
Alerts are blocking notifications that will force the users to address the alert before continuing.
- titleString
Embolded text at the top. - messageString
Body text before actions. - actionsArray of Strings
Series of actions that can be taken on the alert.
alert = new ios.Alerttitle:"Warning"message:"Don't do this"actions:["OK", "Cancel"]
alert : {alert.modal alert.titlealert.messagealert.actions : { OK, Cancel }alert.overlay}
To listen to different actions, you can use dot notation if it's a single word or brackets for any case
- Dot notation
alert.actions.OK.on Events...
- Square bracket notation
alert.actions["OK"].on Events...
The banner is a non-blocking notification. Typically, the banner will send you to a specific screen in an app.
####Properties
- titleString
Embolded top text - messageString
Body text - timeString
time string that appears next to title. - iconLayer
This will put the layer inside the banner and size it accordingly. By default, it's a green box. - durationInteger
This will override the time before the banner animates-out. By default, this is set to 7. - animatedBoolean
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 ios.Banner title:"Time to do something"message:"Don't miss out"icon:iconLayeranimated:true
banner : {banner.iconbanner.titlebanner.message}
To make the banner clickable, you can write -
banner.on Events...
Button is a small versatile component that handles press states automatically.
####Properties
- textString
Sets button text - buttonTypeString
Can betext
,big
,small
- styleString
Can belight
,dark
, orcustom
- backgroundColorHex Color
Will set the background on big buttons. - colorHex Color
Setssmall
andtext
colors. - fontSizeInteger
When custom, sets the fontSize style property. - fontWeightInteger
When custom, sets the fontWeight style property. - blurBoolean
On big buttons, this will turn it slightly opaque and add background blur. - superLayerLayer
set the passed layer as the super layer. - constraintsConstraints Object
will set constraints usingDynamic Layout.
button = new ios.Buttontext:"Download"buttonType:"small"color:"red"
####Schema
button: {button.label }
Listening to buttons is no different than normal framer.button.on Events...
The field is a versatile input for the keyboard. Please note, this is not a HTML field.
####Properties
- textString
Adds text by default to the field. - placeholderTextString
Sets the placeholder text. - placeholderColorColor String
Sets the placeholder text color. - borderRadiusInteger
Sets border radius of field. - borderWidthInteger
Sets border width. - borderColorColor String
Sets border color. - colorColor String
Sets text color. - backgroundColorColor String
Sets field background color. - widthInteger
Sets width in points. - heightInteger
Sets height in points. - constraintsConstraints Object
Will set the field's constraints and run layout usingDynamic Layout - textConstraintsConstraints Object
Will set the text's constraints and run layout usingDynamic Layout
####Example
field = new ios.FieldplaceholderText:"Enter a name or email address"constraints:{align:"center"}
####Schema
field: {field.placeholderfield.text# after touchEnd eventfield.keyboard { ... Keyboard Schema}}
####Listening to keys inside of a fieldIn order to listen for the return key or any other key, you'll need to wrap it up in a touch event since the keyboard only exists after the field is being touched.
field.on Events.TouchEnd, ->field.keyboard.keys.return.on Events...
The keyboard is a fully rendered component that mimics the native iOS keyboard. It'll adapt to all devices.
####Properties
- returnTextString
Overrides the text on the return button. - returnColorHexcode String
Will set the return button color - animatedBoolean
Will determine if the keyboard is animated in. By default, this is set to false.
board = new ios.KeyboardreturnText = "Done"
board: {board.keysArray #contains all keys A-Z in array objectboard.keys {board.keys.a - board.keys.zboard.keys.shiftboards.keys.returnboards.keys.numboards.keys.spaceboards.keys.emoji# if on iPadboards.keys.shift2boards.keys.num2boards.keys.dismiss}
}
You can listen to keys using dot notation or square bracket notation.
- Dot notation
board.keys.return.on Events...
- Square bracket notation
board.keys["return"].on Events...
##Sheet
The sheet is quick action list. The sheet component is super simple to create.
####Properties
- actionsArray of strings
Series of actions that can be taken on the sheet. - animatedBoolean
When set totrue
sheet will animate-in. - descriptionString
When declared, a small grey text will appear at the top of the sheet. By default, this will not appear. - cancelString
This will override the label on the dismiss button.
**NOTE - ** The cancel button will always animate-out. You don't have to add any additional code to handle/animate that.
sheet = new ios.sheet actions:[“-r Delete, Edit, Share”]animated:truedescription:"Do something"
####Schema
sheet : {sheet.cancel sheet.overlaysheet.descriptionsheet.actions : {"-r Delete", Edit, Share}}
To listen to different actions, you can use dot notation if it's a single word or brackets for any case
- Dot notation
sheet.actions.Share.on Events...
- Square bracket notation
sheet.actions["-r Delete"].on Events...
The status bar allows users to see the connection, current time, and battery.
####Properties
- carrierString
Carrier name ex. Verizon/Orange/FramerJS - networkString
network strength ex. 3G/LTE. Only will be showed when a carrier is set. By default, this is set to the wifi icon. Upon setting carrier, this will be set to LTE. - batteryInteger
Battery percentage - this will change the battery icon - signalInteger(0 - 5)
Changes number of filled/unfilled dots. Zero will set the singal to "No Network" - styleString
Dark is black text. Light is white text. - clock24Boolean
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 ios.StatusBarcarrier:"Verizon"network:"3G"battery:70style:"light"
####Schema
statusBar : { statusBar.battery.percent statusBar.battery.icon statusBar.bluetooth statusBar.time statusBar.network statusBar.carrier statusBar.signal}
The navigation bar is made up of 3 elements, two actions and a title.
####Properties
- rightLayer or String or Bool
A layer or string will appear on the right side of the navigation bar. If you do not want a right action, set this tofalse
. - leftLayer or String
A layer or string will appear on the left side of the navigation bar. You can add a < to show a back arrow. - titleString or Tab
You can either pass a string that'll appear as the title on the Nav. You can also pass a tab object. If you pass a tab, the navigation bar's title will be the label of the tab. - blurBoolean
If set to true, the bar will be slightly opaque and have a background blur applied. By default, this is set to true. If false, the bar will be solid white without a blur.
nav = new ios.NavBar right:"Share"left:"< Back"title:"Document"blur:false
####Schema
bar: {bar.rightbar.leftbar.title}
To listen to different actions, you can use dot notation if it's a single word or brackets for any case
- Dot notation
bar.right
- Square bracket notation
bar["right"]
Tabs are light-weight objects that fit into the tab bar component.
####Properties
- labelString
name of tab - iconSVG String
only accepts an SVG string
home = new ios.Tablabel:"home"icon:"< svg>...< /svg>"
####Schema
home: {home.labelhome.iconhome.view}
####Adding contents to a tabCreating a tab will give you access totab.view. In this case, you'll havehome.view
. When the home tab is active only those layers inside ofhome.view
will be shown.
discovery = new Layer superLayer:home.view
The discovery layer will only be shown when the home tab is active in the tab bar.
The tab bar is comprised of multiple tabs. It'll handle switching of tabs and views.
####Properties
- tabsArray of tabs
Add the tabs you made to this array - activeColorString
This is the color that will be shown on the active tabs and label. - inactiveColorString
the color that will be shown on inactive tabs and labels.
tabBar = new ios.TabBar tabs:[home, discovery, profile], activeColor:"#blue", inactiveColor:"grey"
Tab switching is automatically given, so there shouldn't necessarily be anything you need to do. If you'd like to do something additional when a user clicks a tab, you can reference your tab object.
A dynamic text object that'll automatically size for you.
####Properties
- textString
Adds text by default to the field. - fontSizeInteger
Sets font size in points. - fontWeightInteger
Sets font weight. - fontFamilyString
Sets font family. - lineHeightInteger
Sets line height in points. It's automatically done if left unset. - textTransformString
Sets text-transform style property. - opacityInteger
Sets opacity. - widthInteger
Sets width in points. - heightInteger
Sets height in points. - constraintsConstraints Object
Will set the text's constraints and run layout usingDynamic Layout
####Example
text = new ios.Texttext:"Try iOS Kit for Framer JS"fontSize:21fontWeight:100width:320constraints:{align:"center"}
A generic layer that you can set constraints at initiization. These constraints will be rendered immediately.
view = new ios.Viewconstraints:top:0leading:25width:200backgroundColor:'red'
This was specifically intended for text objects. If the html or style of a text object is altered, the width/height of the object would be incorrect. With ios.update, you'll be able to pass your changes in while also resizing the text layer.
ios.update(headerOne, [text:"Done!"]
These functions will automatically convert pixels -> points and points -> pixels.
ios.pt(6) # will return 3 points on an iPhone 6ios.px(6) # will return 12 pixels on an iPhone 6
####ios.utils.clean(string)This will remove any space or bracket HTML syntax from a string.ios.clean("Hi, how are you?<br>
") returns "Hi, how are you?"
####ios.utils.svg(svg path)This does a series of things: it'll rewrite the SVG path into points, and it'll provide variables to set the layer's height and width.
svgObj = ios.svg(svgPath)svgObj.svg = # is the new SVG path in pointssvgObj.height = # is the value for the height of the layersvgObj.width = # is the value for the width of the layer
####ios.utils.changeFill(layer, color)This only works with layers with a SVG path. This will change the SVG fill to whatever color is passed.
####ios.utils.capitalize(string)This will capitalize only the first letter of the entire string.
print ios.capitalize("welcome to the party") #returns "Welcome to the party"
####ios.utils.getTime()Fetches the current time and returns a neatly organized time object with some humanization.
time = ios.getTime()print time.month # prints "April"print time.date # prints "12"print time.day # prints "Tuesday"print time.hours # prints "10"print time.mins # prints "33"print time.secs # prints "1"
####ios.utis.timeDelegate(layer, clock24)This sets up a reoccuring task at the top of every minute to update whatever layer passed to the current time. If clock24 is set to true, it'll return 24-hour clock values. If set to false or omitted, it'll return 12-hour clock values.
####ios.utils.timeFormatter(timeObj, clock24)This will create a time string for screen display. It'll return a hours-minutes string based on the clock24 object.
This changes the color words to be set to iOS default colors in place of web color defaults. If it's a hexcode, it'll set the hexcode. If invalid, it'll return a grey hexcode.
Supports -red, blue, pink, grey/gray, black, white, orange, green, light blue/light-blue, yellow
ios.utils.color("light-blue) # returns "#54C7FC"
This will decide whether to return black or white based on the contrast of the color passed through the color object. So an easy example would be: if you pass white it'll return black. If you pass black, it'll return white. It'll work with any color.
ios.utils.autoColor(ios.utils.color("yellow")) # returns "#000"ios.utils.autoColor(ios.utils.color("blue")) # returns "#FFF"
Add background blur to any layer using -webkit-backdrop-filter. Make sure that whatever layer you use is using rgba with an alpha set below 1.
If you'd like to add a component, please start a new coffee file, unless it's a directly related to another component similar to Tab & TabBar. Please use this boilerplate to help make the components consistent.
## Allows you to use all the ios kit components & logicios = require 'ios-kit'exports.defaults = {## Add any thing a user can set in here. For example:backgroundColor: "blue"}## Creates a property list exports.defaults.props = Object.keys(exports.defaults)exports.create = (array) ->## Creates a setup object that has defaults + any custom props.setup = ios.utils.setupComponent(array, exports.defaults)print setup.backgroundColor ## prints blue
Please add any layout logic to the layout file. Otherwise, please add the logic toios-kit-utils.coffee
.
Please add any referencable data object toios-kit-library.coffee
. You can either reference it withios.library["object"]
or withios.assets["object"]
. Whatever works best for you.
Feel free to hit me up onTwitter.