This Framer X component gives you the functional keyboard which can be fully customized: from the appearance of the different keys to the layout and behavior.
This package contains the single code component (the keyboard itself) and multiple design components for the keys. Just connect them to the keyboard and you're locked and loaded. Download example file for the reference.
If you like the component and want to contribute or leave feedback hit me via FACEBOOK, SPECTRUM or GITHUB
Sometimes you'd like to use the native mobile keyboard in your prototypes, but soon you find that native keyboard behavior is unpredictable in browsers (especially on iOS) and hard to control. Solution: use the keyboard from this package and control it with overrides.
- Drag the keyboard to the canvas.
- Drag the design components to the canvas and connect to the
Keys templates
section of the keyboard. - Use a simple override to obtain typed value.
- Customize keyboard if needed (for nerds) 🤓
- Profit x999 😱
To use built in functionality you should give your keys special names. You can use custom keys as well. See the Customization section for the details.
Special name | Description |
---|---|
$value |
This one will be used to render the regural key values like numbers and letters. Also this one should be converted to the design component with a text override turned on and named value . |
$space |
Adds a space on tap. Equalt to . |
$return |
Breaks the line by default. Equals to /n . |
$backspace |
Removes the last sybol from the string. |
$m1 , $m2 |
Functional keys to toggle between mods. |
$m1a , $m1b , $m2a , $m2b |
Functional keys to toggle between sub-modes of a current mode. |
Property | Description |
---|---|
template |
Template is the main configuration of the keyboard. It defines each key's value, size and position on a keyboard. When set to custom will use the custom layout from .json file or overrides. |
customTemplate |
You can create your own layouts by overriding this prop or uploading a .json file with a template. See the Customization section for more details about templating. |
widthType |
Toggles between the auto and custom width of the keys. If auto is selected the width of the key is calculated as a fraction of the keyboard width, else keyWidth is used. |
keyWidth |
Explicitly sets the width of the single key. Visible only if widthType is set to custom . |
keyHeight |
Explicitly sets the height of the single key. |
gap |
Sets gap between the keys. |
background |
Defines the background color of the keyboard. |
initialValue |
Sets the initial value of the keyboard. |
onValueChange() |
Callback that returns a modified value. |
setMod |
Switches the active keyboard layout to the desired mode: m1 or m2 |
setSub |
Switches the active keyboard layout to the desired sub-mode: a or b |
The keyboard is a stateful component. Stateful means it has it's own inner state where it stores the value typed by the user. The most common override you'll need is to obtain the value from the keyboard. Use onValueChange()
callback:
const data = Data({
text: "",
})
export function HandleKeyboard(props): Override {
return {
// This callback returns a value
// while the user is typing
onValueChange(value) {
data.text = value
},
}
}
While normally you wouldn't set the keyboard value explicitly, sometimes it's useful to override it. Like when you want to reset its value between the different appears. Use the following snippet for that:
const data = Data({
reset: false,
})
export function HandleKeyboard(props): Override {
return {
// This callback returns a value
initialValue: data.reset && "",
}
}
Sometimes you want to control mode switch of the keyboard. The most common case for that is when you start typing you often start from the capital letter. Just override the setMod
property:
const data = Data({
text: "",
})
export function HandleKeyboard(props): Override {
return {
// Switch layout to letters
setMod: "m1",
// Start from the capital letter
setSub: data.text ? "a" : "b",
onValueChange(value) {
data.text = value
},
}
}
Last but not least: add your keyboard a tint of feedback. Just assign the following override to the inner frame of the key's design component:
export function KeyTapResponse(props): Override {
return {
// Light theme
whileTap: { background: "#CCC" },
// Dark theme 😈
whileTap: { background: "#666" },
}
}
The keyboard is fully customizable, so you're able to create your own layouts! But how?! There are two ways basically:
- Pass your custom template to the
customTemplate
through overrides - From UI select
Template > Custom
and below upload the.json
file with your template.
The first option allows you to preview the result in realtime, however, it's not rendered on the canvas. The second option is rendered on the canvas but doesn't allow you to change template on the go.
Recommended flow: use overrides when creating the custom layout, and once you're happy with the result — copy that into separate .json
file and upload through UI.
In general, template is a set of single/couple keyboard layouts (mods) defined within keys
and inRow
property. Here is a template for the Text iOS
keyboard:
{
keys: {
m1a: `q w e r t y u i o p --.5 a s d f g h j k l --.5 $m1a--1.25 --.25 z x c v b n m --.25 $backspace--1.25 $m1--2.5 $space--5 $return--2.5`,
m1b: `Q W E R T Y U I O P --.5 A S D F G H J K L --.5 $m1b--1.25 --.25 Z X C V B N M --.25 $backspace--1.25 $m1--2.5 $space--5 $return--2.5`,
m2a: `1 2 3 4 5 6 7 8 9 0 - / : ; ( ) $ & @ " $m2a--1.25 --.25 .--1.4 ,--1.4 ?--1.4 !--1.4 '--1.4 --.25 $backspace--1.25 $m2--2.5 $space--5 $return--2.5`,
m2b: `[ ] { } # % ^ * + = _ / | ~ < > € $ £ ∙ $m2b--1.25 --.25 .--1.4 ,--1.4 ?--1.4 !--1.4 '--1.4 --.25 $backspace--1.25 $m2--2.5 $space--5 $return--2.5`
},
inRow: 10
}
// Note: this is written in .js format
// For the .json you should wrap each property with a "" so the keys becomes "keys" etc
It might look complex at a glance, but it's not! Let's break it apart:
{
keys: {}, // Holds all the keys information like the key-value and its ratio
inRow: 10 // Defines the maximum number of keys in a row
}
Now get it? But what are those m1a
, m1b
, m2a
, m2b
? Those are what I call keyboard modes. Basically they hold different keyboard layouts which could be toggled. Mods could be nested. Eg top-level mod m1
holds the layout with letters only. It has the 2 sub-modes — a
and b
, for the lowercase and uppercase accordingly. The combination of the 1st level mode m1
and 2nd level mode a
gives the layout template of m1a
.
{
keys: {
m1: { // Mod1: Letters
m1a: 'abc', // lowercase
m1b: 'ABC', // UPPERCASE
},
m2: { // Mod2: Numbers & Symbols
m2a: '123', // numbers
m2b: '#+=', // symbols
},
},
}
// Note: m1 and m2 are omitted in the final template, so we write only m1a, m1b, m2a, m2b
Now once we're good with the template structure in general, let's take a look at a single layout:
`q w e r t y u i o p --.5 a s d f g h j k l --.5 $m1a--1.25 --.25 z x c v b n m --.25 $backspace--1.25 $m1--2.5 $space--5 $return--2.5`
It's written as a set of symbols separated with spaces. Mostly symbols represent key values like q w e
, except the specials. They start with a $
prefix; those are the keys with the special functionality, eg $backspace
(for the full list see the top section).
You have probably noticed the --
symbol and a number after it. This notation defines a ratio of a key relative to the other keys in a row. So If you see the $space--5
it means to render a space key 5 times wider than a single key. If the number is omitted – ratio 1 will be applied for that key. Think of it as of flex-grow if you're familiar with CSS Flexbox. You can also skip the value but specify a ratio like this --2
. In that case an empty spacer element will be rendered with a width set to 2.
You can use just any number of custom keys beside the default one. Just name custom keys properly, starting with a $
prefix, and include those names into the layout template as described above.
The keyboard component doesn't work with the included key component. The issue is under investigation.
As a temporary solution you can creat your own design key component, turn on text override and name it value
as well.
- Added support for the
custom keys
- Removed the need to plug each key to the separate keyboard node. Just use the
Keys templates
section of the component to plug all the keys you want to use. Just don't forget to name your keys properly first!