Quick Start
There are two ways in. Both need GSAP (core; Flip for the lists that reorder, Draggable and InertiaPlugin for the sheet, the swipe rows, the wheel picker and the page stack).
Everything, two files. In <head>:
Code snippet omitted: it ships with the download.
At the top of <body>, paste the contents of assets/icons.svg once (it is an SVG sprite; the icons reference it with <use href="#i-name">). Before </body>:
Code snippet omitted: it ships with the download.
Then copy any component's fragment from components/<name>/specimen.html into your page.
One component. Link assets/tokens.css, assets/base.css and the component's components/<name>/style.css; load GSAP, assets/base.js and the component's components/<name>/script.js; paste its specimen.html. tokens.css, base.css and base.js are required by everything; a component's own files are all it adds.
The scripts find every instance of their component by its data-kit attribute and initialise each once, so the same fragment can appear as many times as you need. If you render the markup from a framework, call the init after mount (each script is an IIFE that runs on DOMContentLoaded or immediately if the DOM is already parsed; reloading it, or dispatching a synthetic DOMContentLoaded, initialises anything new).
A phone app in a web page
The kit lays everything out in a 390px column. A handset component is built on the .screen scaffold from base.css: the root is the column, .screen__status reserves the status region, .screen__bar holds the navigation bar, .screen__scroll is the only thing that scrolls, .screen__dock holds a tab bar or toolbar and .screen__home the home-indicator inset. Overlays that belong to a screen (a sheet, a menu, an alert) are .layer children of that column and lock the column's scroll region rather than the document.
On a real phone, make the app's root a .screen that fills the viewport (height: 100svh) and the components take the width. In the shipped screen pages the same root sits inside a phone-sized frame above 520px wide and fills the viewport below it; that frame is a few lines of CSS in each page's <head>, and you can delete it.
What's Included
index.html: the catalogue, every component assembled. Generated fromcomponents/andkit.json; the rail and search are demo furniturehome.html,recipe.html,cook.html,shopping.html,settings.html,onboarding.html: the six screens as pagescomponents/<name>/: one folder per component:specimen.html(the fragment),style.css,script.jsassets/tokens.css: the design system: every surface, ink, line, accent, status and series colour, the type ramp, spacing, radii, control and bar heights, safe areas, durations and eases, in two themesassets/base.css: reset, type ramp, the shared primitives (.btn,.input,.badge,.avatar,.icon,.group,.menu,.screen,.layer,.hscroll) and layout utilitiesassets/base.js:window.Kit, the shared runtime: the overlay layer stack, positioning, focus helpers, motion tokens, the theme switch, long press, a live regionassets/icons.svg: the icon spriteassets/img/: twenty recipe photographs as baked WebP derivatives, at 640x480 and 240x240assets/style.cssandassets/script.js: the two bundles, generated from the files aboveassets/catalogue.cssandassets/catalogue.js: the catalogue page chrome only; not needed in a product
The six screens
Each screen has two lives. In the catalogue it is a specimen in the phone stage, so you can see the parts compose. As a page it is the app: the tab bar and the back buttons navigate between the screens, and a cross-document view transition holds the bars still while the content changes.
- Home is the entry: tonight's plan, the weeknight shelf, recently cooked, a large title that collapses into the bar as you scroll, the tab bar.
- Recipe is the worked example: the photo header, nutrition rings that draw on enter, a servings stepper that rescales every ingredient, the method with inline timers, and a Start cooking toolbar that leads to cook mode.
- Cook mode shows one step at a time with the timer, progress along the top, next and back by button or swipe, and the finished alert.
- Shopping is the list by aisle: check an item and it strikes through and moves down, swipe to delete with undo, an add field, pull to refresh.
- Settings carries the profile header, grouped settings with toggles and value rows, the plan picker and the sign-out alert.
- Onboarding is the pager, a diet chips step, the notifications prompt, and into the app.
Components
Foundations
The tokens every screen reads: two themes, one type ramp, the handset column and its safe areas.
| Component | Folder | Root | Keyboard |
|---|---|---|---|
| Colour roles | components/colors/ |
||
| Type ramp | components/typography/ |
||
| Icons | components/icons/ |
||
| Layout | components/layout/ |
Controls
Buttons and the small things a thumb rests on, every one 44px to hit.
| Component | Folder | Root | Keyboard |
|---|---|---|---|
| Button | components/button/ |
[data-kit="button"] .btn |
Enter, Space |
| Icon button | components/icon-button/ |
[data-kit="icon-button"] .btn--icon |
Enter, Space |
| Switch | components/switch/ |
.k-switch |
Space |
| Checkbox and radio | components/checkbox-radio/ |
.k-checkbox-radio__row |
Space; arrows in a radio group |
| Segmented control | components/segmented-control/ |
.k-segmented-control |
Arrows, Home, End |
| Stepper | components/stepper/ |
.k-stepper |
Arrows, Home, End |
| Slider | components/slider/ |
.k-slider |
Arrows, Home, End, PgUp, PgDn |
| Chips | components/chip/ |
.k-chip |
Enter, Space; arrows move along the row |
| Rating | components/rating/ |
.k-rating |
Arrows, Home, End |
Inputs
Grouped form fields, search, a wheel picker and a calendar, in the shapes a phone keyboard expects.
| Component | Folder | Root | Keyboard |
|---|---|---|---|
| Text field | components/text-field/ |
.k-text-field |
Native; Escape clears |
| Search bar | components/search-bar/ |
.k-search-bar |
Escape cancels; arrows through recents |
| Wheel picker | components/picker/ |
.k-picker |
Arrows, PgUp, PgDn, Home, End |
| Date picker | components/date-picker/ |
.k-date-picker |
Arrows move days, PgUp and PgDn months, Enter picks, Escape |
| Form layout | components/form-layout/ |
.k-form-layout |
Native; Enter adds an ingredient row |
| Photo picker | components/photo-picker/ |
.k-photo-picker |
Enter opens the picker; Delete removes the focused tile |
Navigation
The shell a phone app lives in: bars, tabs, a page stack with swipe back, and the menus that hang off them.
| Component | Folder | Root | Keyboard |
|---|---|---|---|
| App shell | components/app-shell/ |
.k-app-shell |
Tab order: nav bar, content, tab bar |
| Navigation bar | components/nav-bar/ |
.k-nav-bar |
Native |
| Tab bar | components/tab-bar/ |
.k-tab-bar |
Arrows between tabs, Enter or Space selects |
| Page stack | components/page-stack/ |
.k-page-stack |
Escape pops; Backspace on the back button |
| Tabs | components/tabs/ |
.k-tabs |
Arrows, Home, End |
| Page indicator | components/page-indicator/ |
.k-page-indicator |
Arrows page |
| Context menu | components/context-menu/ |
.k-context-menu |
Shift+F10 or the menu key opens; arrows; Escape |
| Toolbar | components/toolbar/ |
.k-toolbar |
Native |
Data display
Recipes as cards and rows, the numbers a cook watches, and the lists a cook works through.
| Component | Folder | Root | Keyboard |
|---|---|---|---|
| Recipe card | components/recipe-card/ |
.k-recipe-card |
Enter opens; the save button is its own control |
| List | components/list/ |
.k-list |
Arrows move focus; the actions also appear on focus |
| Carousel | components/carousel/ |
.k-carousel |
Arrows page |
| Nutrition rings | components/nutrition-ring/ |
.k-nutrition-ring |
None |
| Timer | components/timer/ |
.k-timer |
Space starts and pauses; Escape resets |
| Step list | components/step-list/ |
.k-step-list |
Arrows move; Space completes; Enter starts a timer |
| Ingredient list | components/ingredient-list/ |
.k-ingredient-list |
Space checks; the stepper is a control |
| Avatar | components/avatar/ |
.avatar |
None |
| Badges | components/badge/ |
.badge |
None |
| Progress | components/progress/ |
.k-progress |
None |
| Bar chart | components/bar-chart/ |
.k-bar-chart |
Arrows move between bars |
Feedback and overlays
Everything that rises over a screen shares one layer: Escape, focus, scroll lock and stacking are one implementation.
| Component | Folder | Root | Keyboard |
|---|---|---|---|
| Toast | components/toast/ |
.k-toast |
Escape dismisses the newest |
| Alert | components/alert/ |
.k-alert |
Escape, focus trap, return |
| Action sheet | components/action-sheet/ |
.k-action-sheet |
Escape, arrows, focus trap, return |
| Bottom sheet | components/bottom-sheet/ |
.k-bottom-sheet |
Escape; the grabber is a button that cycles detents |
| Menu | components/menu/ |
.k-menu |
Arrows, Enter, Escape, type-ahead |
| Empty state | components/empty-state/ |
.k-empty-state |
Native |
| Skeleton | components/skeleton/ |
.k-skeleton |
None |
| Pull to refresh | components/pull-to-refresh/ |
.k-pull-to-refresh |
A Refresh button for the keyboard |
| Banner | components/banner/ |
.k-banner |
Native |
Sections
The assembled parts of a recipe app, ready to place: heroes, shelves, the shopping list, the week, settings.
| Component | Folder | Root | Keyboard |
|---|---|---|---|
| Recipe header | components/recipe-header/ |
.k-recipe-header |
Native |
| Collection shelf | components/collection-shelf/ |
.k-collection-shelf |
Native |
| Shopping list | components/shopping-list/ |
.k-shopping-list |
Space checks; Enter adds |
| Meal plan | components/meal-plan/ |
.k-meal-plan |
Arrows across days |
| Settings group | components/settings-group/ |
.k-settings-group |
Native |
| Profile header | components/profile-header/ |
.k-profile-header |
Native |
| Onboarding pager | components/onboarding-pager/ |
.k-onboarding-pager |
Arrows page; Enter continues |
| Plan picker | components/plan-picker/ |
.k-plan-picker |
Arrows between plans |
| Permission prompt | components/permission-prompt/ |
.k-permission-prompt |
Native |
Screens
Six pages composed from the parts above, verbatim. Each opens full screen and navigates to the others.
| Component | Folder | Root | Keyboard |
|---|---|---|---|
| Home | components/home-screen/ and home.html |
.k-home-screen |
|
| Recipe | components/recipe-screen/ and recipe.html |
.k-recipe-screen |
|
| Cook mode | components/cook-screen/ and cook.html |
.k-cook-screen |
|
| Shopping | components/shopping-screen/ and shopping.html |
.k-shopping-screen |
|
| Settings | components/settings-screen/ and settings.html |
.k-settings-screen |
|
| Onboarding | components/onboarding-screen/ and onboarding.html |
.k-onboarding-screen |
Themes
<html data-theme="light"> or dark. The toggle in the catalogue rail calls Kit.theme.set(name), remembers the choice in localStorage, and dispatches kit:theme so a chart or a ring can re-read a colour. Light is the default; every foreground and background pair in both themes clears 4.5:1.
Motion and reduced motion
Durations and eases are tokens (--dur-fast 150ms, --dur-base 260ms, --dur-slow 400ms; a soft ease-out for lands, a short overshoot for a tab pop or a toggle knob) read by Kit.dur() and Kit.ease(). Under prefers-reduced-motion every duration reads as zero and continuous motion (shimmer, an indeterminate bar, the timer's ring) shows its end state. Nothing runs while it is off screen: rings draw and counters count when they enter, and stop when they leave.
Gestures and the keyboard
Every gesture has a keyboard route, listed per component in the table above. The rules the touch pieces follow, in case you extend them: a vertical sheet takes the drag; a horizontal swipe row hands the vertical axis back to the list; swipe back starts only from the left edge; a long press is 500ms and cancels on 8px of movement; pull to refresh only begins with the list at the top. Every hit target is 44px in both directions.
Photographs
The twenty recipe photographs are Pexels photographs, cropped and re-encoded as WebP and shipped inside assets/img/. The Pexels licence permits use, modification and redistribution without attribution; the originals are credited below anyway. Replace them by dropping your own files over the same names, or edit assets/img-manifest.json and re-run the bake script in the repository this kit was built from.
Sources (Pexels photo ids): ramen 7490494, shakshuka 29177374, chicken 10821330, aubergine 34492423, burrata 22882531, babka 6150700, carbonara 29039082, tacos 33614224, pancakes 4790406, curry 27287005, soup 17402671, pizza 18437684, smoothie 7937002, salmon 8862746, banana 9928323, risotto 14537701, toast 8335331, cake 19791251, dumplings 7364113, granola 6823360.
What is demo-only
assets/catalogue.css, assets/catalogue.js, kit.json and the rail, search and stage markup in index.html. The phone frame CSS in each screen page's <head>. Everything else is product.
Requirements
GSAP 3.12+ with Flip, Draggable and InertiaPlugin. No other dependency. Built against GSAP 3.15.0.
Worked examples, the events and programmatic API, and the class reference ship with the download, alongside the full source.