Render ios keyboard
Skill gooseworks-ai/goose-skills/skills/ads/packs/video-ad-formats/render-ios-keyboard
Render a static iOS QWERTY keyboard as inline HTML+CSS sized for the 750-wide 9:16 stage. Includes the 3-suggestion bar, alpha keys, shift/backspace, 123/emoji/space/return row, and the bottom globe+mic strip. No animation logic — slide up/down is the molecule's job (CSS transform on the .keyboard root).From its SKILL.md
npx -y skills add gooseworks-ai/goose-skills --skill render-ios-keyboardAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
SKILL.md
7.2 KB, ~1.8k tokens by cl100k_base, as published. Nobody here has run it
render-ios-keyboard
Purpose
Provide a drop-in iOS QWERTY keyboard fragment that pairs with messaging atoms (create-chatgpt-mockup, create-imessage-mockup) when a video needs to show someone typing. Static only: the keyboard sits at the bottom of the screen, the molecule's recorder slides it up/down with transform: translateY(...).
Inputs
const { renderKeyboardHTML, renderKeyboardCSS } = require('./generate');
const html = renderKeyboardHTML({
suggestions: ['"He"', 'Hey', 'Heating'], // optional, default ['I', 'The', "I'm"]
layout: 'qwerty-lower', // 'qwerty-lower' | 'qwerty-upper' | 'numbers'
});
The atom returns an HTML fragment (one <div class="ios-keyboard">…</div>) plus the matching CSS. The CSS uses scoped class names so it won't collide with the rest of the page.
Workflow
- Require the module.
const { renderKeyboardHTML, renderKeyboardCSS } = require('./generate');— no build step, no dependencies beyond Node'sfs/path. - Pick a layout.
renderKeyboardHTMLreadsopts.layoutand looks it up inROWS:qwerty-lower(default),qwerty-upper, ornumbers. An unknown layout silently falls back toqwerty-lower. The molecule decides which state to show; this atom never switches on its own. - Pass suggestions.
opts.suggestionsis an array of up to three strings rendered into the suggestion bar; each value is run throughescapeHTMLso quotes/angle brackets are safe. Omit it to get the default['I', 'The', "I'm"]. - Receive the fragment. The function returns a single root
<div class="ios-keyboard" data-layout="…">containing, in order: the.kb-suggestionsbar, three letter rows (row-110 keys,row-29 keys padded with two 18px spacers,row-3= shift/#+=modifier + 7 keys + backspace), therow-bottom(123/ABCswitch, emoji, widespace, return), and the.kb-system-rowglobe + mic strip. - Inject the CSS once. Call
renderKeyboardCSS()(which readstemplates/keyboard.cssfrom disk) and place it in a<style>block on the page. The molecule mounts the fragment at the bottom of the stage next to.composer-wrap. - Animate externally. The atom emits no JS and never sets a
transform. The owning molecule slides the keyboard in/out viatransform: translateY(...)on the.ios-keyboardroot (the CSS setswill-change: transformfor this). - (Optional) Preview standalone.
render.jswraps the fragment + CSS in a 750×1334 white.stageHTML page and writes it to--outfor eyeballing padding/colors.
CLI (for local visual testing)
node render.js --out /tmp/kb.html --suggestions 'I,The,I'\''m'
Produces a standalone HTML page with just the keyboard, useful for tweaking padding/colors.
Output
| Output | Shape |
|---|---|
renderKeyboardHTML(opts) | HTML string (one root <div class="ios-keyboard">) |
renderKeyboardCSS() | CSS string (scoped to .ios-keyboard *) |
The molecule injects these into the chatgpt-mockup page next to .composer-wrap.
Files
| File | Purpose |
|---|---|
generate.js | Returns {renderKeyboardHTML, renderKeyboardCSS} |
render.js | Standalone CLI for visual review |
templates/keyboard.css | All keyboard styling |
Quality checks
- Keyboard fits in 518px vertical space on the 750-wide stage (matches iOS QWERTY on a Pro-class iPhone)
- Three suggestion pills are visible above the keys with vertical dividers between them
- Shift, backspace are sized correctly (~10% wider than letter keys)
- Space bar reads as a single wide white pill
- Globe and mic at the very bottom edge of the keyboard, in the system tray strip
- No JS — pure HTML/CSS so the recorder can slide it without re-render
Known limitations
- No key-pop animation. When a key is pressed in the real keyboard, the letter renders larger above the row briefly. v1 skips this.
- Lowercase QWERTY default. Uppercase/numbers variants supported via
layoutbut are visual-only — the molecule decides which to show. - No emoji panel. The emoji button is rendered but doesn't expand.
Quality Checks
renderKeyboardHTML()returns a single root element starting with<div class="ios-keyboard"and carrying the matchingdata-layoutattribute (qwerty-lower|qwerty-upper|numbers).- The fragment contains exactly one
.kb-suggestionsbar, three letter rows (.row-1,.row-2,.row-3), one.row-bottom, and one.kb-system-row— in that DOM order. - Suggestion count and text match the
suggestionsarray (default['I', 'The', "I'm"]); the bar renders one.kb-suggestionspan per entry with vertical dividers between adjacent pills. qwerty-lowerrenders lowercase letters and a shift glyph;qwerty-upperrenders uppercase letters;numbersrenders the digit/symbol rows with the#+=modifier and anABCswitch key instead of123.- User-supplied strings are HTML-escaped — passing
'<b>'or'"He"'yields<b>/"He", never raw markup. renderKeyboardCSS()returns the full contents oftemplates/keyboard.css, scoped under.ios-keyboard, and the fragment carries no inlinestyleexcept the two 18pxrow-2spacer divs.- Rendered at 750px stage width, the keyboard occupies roughly 518px of vertical space; shift/backspace/
123/emoji/return modifier keys are visibly wider than letter keys;spaceis one wide white pill; the globe sits bottom-left and mic bottom-right in the system strip. - The output is pure HTML/CSS — no
<script>and no JS event handlers — so a recorder can slide it with a CSS transform without re-rendering.
Failure Modes
- Unknown
layoutvalue →ROWS[layout]isundefined, so the renderer silently falls back toqwerty-lower. Symptom: you asked for uppercase or numbers and got lowercase letters. Fix: pass exactly'qwerty-lower','qwerty-upper', or'numbers'. - More than three suggestions → every entry still renders as a
.kb-suggestion(theyflex: 1 1 0), so a long array squashes the pills and breaks the iOS-accurate 3-up layout. Keepsuggestionsto three or fewer; long strings are clipped withtext-overflow: ellipsis. - CSS not injected → calling
renderKeyboardHTML()without also emittingrenderKeyboardCSS()produces an unstyled stack of divs (no rounded keys, no gray tray). Always include both on the page. templates/keyboard.cssmissing or unreadable →renderKeyboardCSS()callsfs.readFileSyncand will throwENOENT. Run from a checkout wheretemplates/keyboard.csssits next togenerate.js.render.jsrun without--out→ the CLI prints the usage line and exits with code1; nothing is written. Always pass--out <path>.- Expecting animation or interactivity → there is none. No key-pop, no emoji panel, no caps-lock toggle. The molecule owns slide-up/down and which layout to show; this atom is static by design.
What ships with it: 9 files
18.5 KB alongside SKILL.md, 2 of them executable
templates/
- keyboard.css2.7 KB
tests/
- expected-output.md2.9 KB
- human-test.md1.7 KB
- sample-input.md1.6 KB
- smoke-test.md2.1 KB
- verifier.md1.4 KB
- generate.jsruns4.3 KB
- render.jsruns1.5 KB
- skill.meta.json270 B