ui-040

Relay App UI Kit

£25 or the whole Vault, £79.20

A browsable component library for building a product: fifty-seven components on one token file, from buttons and fields to tables, kanban, charts and overlays, plus four screens that open as working pages, dark and light.

FlipDraggableInertiaPlugin advanced
16 more details
token-themingtheme-switchflip-layoutdragcommand-palettekeyboard-navigationfocus-managementdialog-animationdata-vizcount-upsvg-drawstaggerstate-transitionmicro-interactiontabsfilter

The kit's assembled screens, full window and fully interactive:

Updated

About this kit

Relay is a component library rather than a demo of one screen. The page you see is the library itself: an index down the left, a search that filters it, and fifty-seven components shown live at product density, grouped into foundations, controls, inputs, navigation, data display, feedback and overlays, sections, and four screens composed from the parts above.

Read the full effect overview

Every component reads one token file, so tables, menus, dialogs and charts agree about surface, ink, line, radius, spacing and motion, and the dark and light themes are the same design at two sets of values. The register is a modern issue tracker: a near-black neutral ground, hairline borders, one indigo accent that means primary or selected, colour otherwise reserved for status, and one typeface carrying hierarchy through weight and ink rather than size.

Each component ships in its own folder with its markup, its stylesheet and its script, so you can take one part or link the two bundled files and take everything. Overlays share one Escape, one focus trap and one scroll lock; motion is short, layered product motion with GSAP, and every animated part has a reduced-motion state.

The four screens are not screenshots. Issues, settings, billing and onboarding each open as a full page (issues.html and its three siblings) that you can click around: the sidebar navigates between them, the command menu's commands act, filters filter, the drawer edits write back to the row, and the onboarding walk-through validates each step. Every one of them is composed from the components with include directives and a short glue script, so a screen is also the worked example of how the parts fit together.

Relay App UI Kit - UI component kit preview

What's included

13 items
  • Fifty-seven components in eight families, each in its own folder with markup, styles and script
  • A searchable catalogue page with an index rail, family groups and a theme toggle
  • One token file driving dark and light themes; no component holds a colour of its own
  • Data table with sorting, selection, a bulk bar, sticky header and density toggle
  • Kanban board with drag between columns and a keyboard route for the same moves
  • Line and bar charts that draw on enter, with crosshair, legend toggles and a range control
  • Command menu, context menu, dropdown, select, combobox and date picker on one shared menu style
  • Dialog, drawer, bottom sheet, popover, tooltip and toast queue sharing one overlay layer
  • Sections ready to drop in: page header, settings groups, pricing table, billing and usage, onboarding steps, activity feed, team members
  • Keyboard and ARIA contracts on every control, with live announcements for state changes
  • Reduced-motion end states throughout; nothing animates while off screen
  • Four screens that open as working pages: an issues view with 31 issues, filters, a board switch, a drawer, a composer and a right-click menu; settings, billing and a five-step onboarding
  • Screens composed from the components with include directives, never redrawn, so each is a worked example of how the parts fit together

Perfect for

4 use cases
  • A SaaS product that needs a complete component set on one design system
  • An admin panel or internal tool that should feel like a modern product rather than a framework default
  • A project management, CRM, support desk or analytics app that starts from finished tables, boards and forms
  • A design system starting point where the tokens are the deliverable and the components prove them

How it works

3 sections

The library is the page

The catalogue is generated from the component folders, so what you browse is exactly what you download. The rail lists every component by family, the search filters both the rail and the specimens, and each specimen is the component in every state a buyer would check, with product copy rather than placeholder text.

One token file, two themes

Surfaces, ink, lines, accent, status colours, chart series, radii, spacing, control heights, durations and eases are role-named custom properties in one file. The light theme re-values the same names, so a component never branches on the theme and a rebrand is one edit.

One overlay contract

Everything that opens over the page goes through a shared layer stack in the base script, which owns Escape, the focus trap, focus return, scroll lock and stacking order. A component only supplies its enter and exit motion, so a dialog inside a drawer inside a command menu behaves like one system.

Plugins Flip, Draggable, InertiaPlugin
Difficulty Advanced
Includes Every component in its own folder of markup, styles and script, the assembled screens, the two bundles, documentation, AI setup prompt, lifetime updates

Lighthouse, as measured

Google Lighthouse on this component kit's demo (5 pages, lowest score shown), from the latest scan. A measurement of the demo as shipped, not a promise for your page.

Accessibility
100
Best practices
100

No performance score, on purpose. That figure depends on how you deploy: your server's compression and caching, your CDN, the connection and the device doing the test, none of which the code controls. The same page can score very differently on two consecutive runs, so measure it where it will live.

Questions about this component kit

Can I take one component without the rest?

Yes. Each component lives in its own folder with its markup, its stylesheet and, where it needs one, its script. To use one part you link tokens.css, base.css and base.js, then that folder's files, and paste the fragment. To use everything you link the two bundled files instead. The catalogue page and its rail are demo furniture; nothing in a product needs them.

What kind of app does this suit, and how do I rebrand it?

Anything with lists, tables, forms and settings: a project tool, a CRM, a support desk, an analytics dashboard, an admin panel. The worked example is a work tracker, but no layout says so except the words. Rebranding is editing tokens.css: change the accent, the ground, the ink ramp or the face and every component follows, in both themes, with no component-level overrides.

Is there a backend, and do the components hold state?

No backend. Every issue, member, invoice and event is sample content in the markup, and the interactions change the page rather than a database: sorting reorders rows, dragging moves a card, the invite form appends a pending row. Wiring it to your data means rendering the same markup from whatever you already have; the scripts initialise any instance they find.

Which framework is it for?

None. It is HTML, CSS custom properties and plain JavaScript with GSAP, so it drops into a static page, a server-rendered app or a React, Vue, Svelte or Astro component as markup and classes. The scripts find their components by a data attribute and initialise every instance once, so rendering the markup from a framework and calling the init after mount is enough.

What happens on a phone?

The app shell's sidebar becomes a bottom tab bar, tables and wide boards scroll sideways inside their frame, dialogs sit at the bottom of the screen, the bottom sheet is built for touch with drag to dismiss, and hover-only affordances such as row actions also appear on focus and on tap. The catalogue's rail becomes an Index button opening a sheet.

Does the kanban really drag, and what about the keyboard?

Yes, cards drag between and within columns with GSAP Draggable, and the siblings settle into place. The same moves exist on the keyboard: Space picks up a card, the arrow keys move it, Space drops it and Escape cancels. Every menu, select, tab set, table and picker in the kit has its keyboard route listed in the README.

Paid component kit

Purchase to unlock the code.

Buying Relay App UI Kit opens every component as its own folder of markup, styles and script, the assembled screens and both bundles, the full documentation, an AI setup prompt for your editor, and every update we ship to it. Standard license: unlimited personal and commercial projects. Every paid product is tested for desktop and mobile layouts, reduced-motion handling, animation cleanup and keyboard controls wherever there is something to operate.

£25 Standard license, unlimited projects

Browse UI elements

Or the whole library: the Vault, £79.20, one payment.

Documentation

Quick Start

There are two ways in. Both need GSAP (core; Flip, Draggable and InertiaPlugin for the board, the table sort and the bottom sheet).

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).

What's Included

  • index.html: the catalogue, every component assembled. Generated from components/ and kit.json; the rail and search are demo furniture
  • kit.json: the manifest: families, components, their root selectors and keyboard contracts
  • components/<name>/: one folder per component: specimen.html (the fragment), style.css, script.js
  • assets/tokens.css: the design system: every surface, ink, line, accent, status and series colour, the type scale, spacing, radii, control heights, durations and eases, in two themes
  • assets/base.css: reset, type ramp, the shared primitives (.btn, .input, .kbd, .badge, .avatar, .icon, .card, .menu, .layer) and layout utilities
  • assets/base.js: window.Kit, the shared runtime: the overlay layer stack, positioning, focus helpers, motion tokens, the theme switch, a live region
  • assets/icons.svg: the icon sprite
  • assets/style.css and assets/script.js: the two bundles, generated from the files above
  • assets/catalogue.css and assets/catalogue.js: the catalogue page chrome only; not needed in a product

The four screens

Each screen has two lives. In the catalogue it is a specimen in a fixed frame, so you can see the parts compose. As a page (issues.html, settings.html, billing.html, onboarding.html) it fills the viewport and behaves like the product: the shell's sidebar and the account menu navigate between the three app screens and back to the library, Cmd/Ctrl+K opens the command menu everywhere and its commands act, and the account menu's Keyboard shortcuts lists the keys each screen answers to.

  • Issues is the worked example. Thirty-one issues grouped by status, filter chips that add and remove and actually filter, an Add filter popover with the real fields, a list/board switch that crossfades to the kanban, rows that open the drawer with that issue's data, drawer controls that write the change back to the row with a toast, a New issue dialog that adds a row to the top of its group, and a right-click menu whose Move to, Assign, Set priority and Delete (with undo) act on the row under the pointer. J/K move, Enter opens, C creates, S sets status, ? shows the shortcuts.
  • Settings switches between its groups, keeps a dirty state until Save, and invites a member into the team list.
  • Billing changes plan through a confirm dialog, sorts and downloads invoices, and updates the payment method.
  • Onboarding is a five-step walk-through with per-step validation, a slug that derives from the workspace name, and progress kept in sessionStorage.

Using one as a starting point. A screen owns no markup of its own: its components/<screen>/specimen.html is a handful of @include directives naming the components it composes, and its script.js is glue plus the data it renders from. So the way to start from a screen is to copy that folder's script.js, replace the data at the top with yours, and keep the wiring: the selectors it uses ([data-kit="issue-list"], [data-shell-nav], [data-drawer-field], root.kitDrawer.open(), root.kitCommandMenu.handle()) are the components' documented API, not private plumbing. Delete a component from the include list and its glue block, and the rest still runs.

Components

Foundations

The tokens every component reads, so a rebrand is one file.

Component Folder Root Keyboard
Colour roles components/colors/ assets/tokens.css
Type ramp components/typography/ assets/tokens.css
Icons components/icons/ assets/icons.svg
Layout components/layout/ assets/base.css

Controls

The things a hand rests on. Every one has a keyboard route and a disabled state.

Component Folder Root Keyboard
Button components/button/ .btn Enter, Space
Icon button components/icon-button/ .btn--icon Enter, Space
Switch components/switch/ [data-kit="switch"] Space
Checkbox and radio components/checkbox-radio/ [data-kit="checkbox-radio"] Space; arrows in a radio group
Segmented control components/segmented-control/ [data-kit="segmented-control"] Left, Right, Home, End
Select components/select/ [data-kit="select"] Up, Down, type-ahead, Enter, Escape
Combobox components/combobox/ [data-kit="combobox"] Up, Down, Enter, Escape
Slider components/slider/ [data-kit="slider"] Arrows, Home, End, Page Up, Page Down

Inputs and forms

Fields with their hints and errors, and the form that puts them in rows.

Component Folder Root Keyboard
Text field components/text-field/ [data-kit="text-field"] Native
Search field components/search-field/ [data-kit="search-field"] / focuses, Escape clears
Date picker components/date-picker/ [data-kit="date-picker"] Arrows move days, Page Up/Down months, Enter picks, Escape
File drop components/file-drop/ [data-kit="file-drop"] Enter opens the picker
Tag input components/tag-input/ [data-kit="tag-input"] Enter adds, Backspace removes, arrows in suggestions
Form layout components/form-layout/ [data-kit="form-layout"] Native

Navigation

The frame around the work and the ways through it.

Component Folder Root Keyboard
App shell components/app-shell/ [data-kit="app-shell"] Cmd/Ctrl+B collapses the rail
Sidebar navigation components/sidebar-nav/ [data-kit="sidebar-nav"] Up, Down, Enter
Top bar components/top-bar/ [data-kit="top-bar"] Native
Tabs components/tabs/ [data-kit="tabs"] Left, Right, Home, End
Breadcrumbs components/breadcrumbs/ [data-kit="breadcrumbs"] Native
Pagination components/pagination/ [data-kit="pagination"] Native
Command menu components/command-menu/ [data-kit="command-menu"] Cmd/Ctrl+K, Up, Down, Enter, Escape
Context menu components/context-menu/ [data-kit="context-menu"] Shift+F10, arrows, Right opens a submenu, Escape

Data display

Tables, lists, boards and charts at the density a product needs.

Component Folder Root Keyboard
Data table components/data-table/ [data-kit="data-table"] Space selects, Enter sorts a focused header
Stat tiles components/stat-tiles/ [data-kit="stat-tiles"]
Line chart components/line-chart/ [data-kit="line-chart"] Left, Right move the crosshair
Bar chart components/bar-chart/ [data-kit="bar-chart"]
Progress components/progress/ [data-kit="progress"]
Issue list components/issue-list/ [data-kit="issue-list"] Up, Down, J, K, Enter opens, S sets status
Kanban board components/kanban/ [data-kit="kanban"] Space picks up, arrows move, Space drops
Timeline components/timeline/ [data-kit="timeline"]
Avatar group components/avatar-group/ [data-kit="avatar-group"]
Status and priority components/status-badge/ [data-kit="status-badge"]

Feedback and overlays

Everything that opens over the page shares one Escape, one focus trap and one scroll lock.

Component Folder Root Keyboard
Toast components/toast/ [data-kit="toast"] Escape dismisses the newest
Dialog components/dialog/ [data-kit="dialog"] Escape, Cmd/Ctrl+Enter confirms; focus trapped and returned
Drawer components/drawer/ [data-kit="drawer"] Escape; focus trapped and returned
Bottom sheet components/bottom-sheet/ [data-kit="bottom-sheet"] Escape
Popover components/popover/ [data-kit="popover"] Escape, outside press, arrows and Enter in the filter list
Dropdown menu components/dropdown-menu/ [data-kit="dropdown-menu"] Arrows, Enter, Escape, type-ahead
Tooltip components/tooltip/ [data-kit="tooltip"] Focus shows
Banner components/banner/ [data-kit="banner"] Native
Empty state components/empty-state/ [data-kit="empty-state"]
Skeleton components/skeleton/ [data-kit="skeleton"]

Sections

Whole blocks of a page, ready to drop in.

Component Folder Root Keyboard
Page header components/page-header/ [data-kit="page-header"]
Settings group components/settings-group/ [data-kit="settings-group"] Up, Down, Home, End on the section nav
Pricing table components/pricing-table/ [data-kit="pricing-table"] Space on the switch, Escape closes the confirm
Onboarding steps components/onboarding-steps/ [data-kit="onboarding-steps"] Enter advances, Back never validates
Activity feed components/activity-feed/ [data-kit="activity-feed"]
Billing and usage components/billing-plan/ [data-kit="billing-plan"]
Team members components/team-members/ [data-kit="team-members"]

Screens

Four pages composed from the components above, markup reused verbatim.

Component Folder Root Keyboard
Issues components/issues-screen/ and issues.html [data-kit="issues-screen"]
Settings components/settings-screen/ and settings.html [data-kit="settings-screen"]
Billing components/billing-screen/ and billing.html [data-kit="billing-screen"]
Onboarding components/onboarding-screen/ and onboarding.html [data-kit="onboarding-screen"]

Themes

Dark is the default. The light theme is one attribute on the root:

Code snippet omitted: it ships with the download.

Kit.theme.set('light') does the same at runtime, remembers the choice in localStorage, and dispatches kit:theme on document so anything reading a colour (the charts do) can re-read it. Both themes are the same design at two sets of values; no component has a theme branch, so a third theme is a copied block in tokens.css.

Rebranding

Edit assets/tokens.css. The accent (--accent and its hover, active, ink and wash values) is the one colour with a job; the ground and panel surfaces, the four-step ink ramp, the hairlines and the status colours are each a handful of values per theme. The face is --font-ui; sizes and weights are the --text-* and --weight-* steps. Nothing else in the kit holds a colour, a radius or a duration, so there is nowhere else to look.

Motion and reduced motion

Durations and eases are tokens (--dur-fast, --dur-base, --dur-slow, --ease-out, --ease-inout, --ease-spring) read by both CSS and, through Kit.dur() and Kit.ease(), by the scripts. Under prefers-reduced-motion, Kit.dur() returns 0 so every tween lands in its end state, decorative loops (shimmer, indeterminate progress) stop, and nothing on the page animates continuously. Anything that animates on enter is gated so it only runs while on screen.

Overlays and the keyboard

Everything that opens over the page (dialog, drawer, bottom sheet, popover, dropdown, context menu, select, combobox, date picker, command menu, tooltip) opens through Kit.layer.open(). The layer stack owns Escape (closes the topmost), the focus trap for modal layers, focus return to the trigger, the scroll lock, and outside-press dismissal for non-modal layers. A component supplies only its enter and exit motion. The per-component keyboard contract is in the Components table above.

Requirements

  • GSAP 3.13+ (built against 3.15.0); Flip, Draggable and InertiaPlugin are loaded from the same CDN
  • Modern browsers with CSS custom properties, position: sticky, IntersectionObserver and :focus-visible
  • No build step and no framework

Demo-only files

assets/catalogue.css, assets/catalogue.js, the rail, the search and the specimen frames in index.html exist so the catalogue can be browsed. Nothing in a product needs them.

Worked examples, the events and programmatic API, and the class reference ship with the download, alongside the full source.