npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

ui5.touch.controls

v1.2.0

Published

UI5 Library: ui5.touch.controls — touch-friendly OpenUI5 controls with configurable sizes

Downloads

552

Readme

Standard OpenUI5 controls, rebuilt for touch — plus the ones sap.m is missing.

sap.m controls are made for mouse and keyboard. On a tablet, a shop floor terminal or a device operated with gloves they are simply too small — and the cozy content density only gets you one step further.

The library does two things about that:

  1. It rebuilds the most important sap.m controls on their original structure and opens them up for sizing through one central size property (S6XL) that works the same way on every control. You do not have to rebuild your app: the controls keep the familiar properties, aggregations and events of their originals for the common cases, so you can use them as a drop-in replacement — add the namespace, put tc: in front of the control, set a size. Everything else stays the way it is.

  2. It adds controls that sap.m does not have at all, for situations that only come up on touch devices. The prime example is tc:VirtualKeyboard — a terminal without a hardware keyboard needs an on-screen keyboard, and OpenUI5 does not ship one.

Screenshot of the ui5.touch.controls library

Link of full documentation: https://mariokernich.github.io/ui5-touch-controls/test-resources/ui5/touch/controls/index.html

Drop-in replacement — before and after

A sap.m.Page with an OverflowToolbar as footer. This is the standard version:

<mvc:View
	xmlns:mvc="sap.ui.core.mvc"
	xmlns="sap.m">
	<Page title="Order">
		<footer>
			<OverflowToolbar>
				<Button text="Save" type="Emphasized" icon="sap-icon://save" press=".onSave" />
				<Button text="Cancel" icon="sap-icon://decline" press=".onCancel" />
				<ToolbarSpacer />
				<Button text="Approve" type="Accept" icon="sap-icon://accept" press=".onApprove" />
				<Button text="Reject" type="Reject" icon="sap-icon://decline" press=".onReject" />
				<Button text="History" icon="sap-icon://history" press=".onHistory" />
			</OverflowToolbar>
		</footer>
	</Page>
</mvc:View>

And the touch version — the namespace tc, a tc: in front of the controls and a size:

<mvc:View
	xmlns:mvc="sap.ui.core.mvc"
	xmlns="sap.m"
	xmlns:tc="ui5.touch.controls">
	<Page title="Order">
		<footer>
			<tc:OverflowToolbar size="XL">
				<tc:Button text="Save" type="Emphasized" icon="sap-icon://save" size="XL" press=".onSave" />
				<tc:Button text="Cancel" icon="sap-icon://decline" size="XL" press=".onCancel" />
				<ToolbarSpacer />
				<tc:Button text="Approve" type="Accept" icon="sap-icon://accept" size="XL" press=".onApprove" />
				<tc:Button text="Reject" type="Reject" icon="sap-icon://decline" size="XL" press=".onReject" />
				<tc:Button text="History" icon="sap-icon://history" size="XL" press=".onHistory" />
			</tc:OverflowToolbar>
		</footer>
	</Page>
</mvc:View>

Same aggregations, same properties, same event handlers — press=".onSave" still calls the same method in your controller. sap.m controls such as ToolbarSpacer can stay exactly where they are.

The result: buttons big enough to hit with a finger, and a toolbar that moves everything that does not fit behind a button with three dots.

Screenshot of the OverflowToolbar with the overflow popover

Bind size to a model to switch the size of the whole app at runtime:

<tc:Button text="Save" size="{settings>/touchSize}" press=".onSave" />

New controls for touch

Not everything a touch app needs exists in sap.m. Where that is the case, the library adds a control of its own — built from the same sized building blocks, themed through the same theme parameters, so it fits in with the rest.

tc:VirtualKeyboard

On a shop floor terminal, a kiosk or a device operated with gloves there is often no hardware keyboard, and the on-screen keyboard of the operating system is either unavailable or covers half the screen. OpenUI5 has no control for this. tc:VirtualKeyboard is an on-screen keyboard rendered from the library's own buttons — no third-party dependency, and sized through the same size property as everything else.

The VirtualKeyboard with a QWERTY layout

Which keys it shows is one property: mode picks one of the ready-made layouts — QWERTY, Numeric, Phone or Calculator.

<tc:VirtualKeyboard
	value="{/quantity}"
	size="XL"
	width="700px"
	mode="Numeric"
	change=".onChange"
	enter=".onEnter" />

For a key set of your own there is mode="Custom", and only then the layout property is read. A layout is a list of rows, keys separated by spaces:

<tc:VirtualKeyboard
	value="{/article}"
	size="XL"
	mode="Custom"
	layout="A B C D, E F G H, {bksp} {space} {enter}" />

{shift}, {space}, {bksp} and {enter} are the special keys; every other key inserts its own label into the value. With hardwareKeys="true" the control additionally accepts input from a real keyboard, which helps when the same screen runs both on a terminal and on a desktop.

On a field

The keyboard does not have to sit on the page. Put it into the virtualKeyboard aggregation of a tc:Input and switch showVirtualKeyboard on, and it opens in a popover below the field while the field has the focus:

<tc:Input
	value="{/quantity}"
	size="XL"
	showVirtualKeyboard="true">
	<tc:virtualKeyboard>
		<tc:VirtualKeyboard mode="Numeric" size="XL" />
	</tc:virtualKeyboard>
</tc:Input>

The keyboard types into the field: it is filled with the value of the field whenever the popover opens, every key fires liveChange, and its Enter key fires change and submit — the popover stays open, since the field still has the focus. tc:TextArea takes the same aggregation, where Enter adds a line break instead.

tc:BarcodeInput

On a shop floor or in a warehouse most input does not come from a keyboard but from a barcode scanner in keyboard wedge mode: it types the code into the focused field within a few milliseconds and closes it with Enter. A plain input cannot tell that apart from a person, so an application ends up reacting either to every Enter or to none.

tc:BarcodeInput measures the time between the keystrokes. A run of at least minLength characters whose gaps all stay below scanTimeout and that is closed by Enter fires scan; everything else is manual input and fires change:

<tc:BarcodeInput
	value="{/code}"
	placeholder="Scan a pallet..."
	size="XL"
	clearOnScan="true"
	scan=".onScan"
	change=".onManualEntry" />

So a scanned code can go straight to the backend while a typed one gets a confirmation first. prefix and suffix cut off the characters scanners put around the code.

tc:SignaturePad

Handing over goods, confirming a repair or acknowledging a safety briefing all end with a signature, and on a tablet the natural place for it is the screen. tc:SignaturePad draws on a canvas and hands the result over as a PNG data URL in value, so it can be bound to a model and sent to the backend like any other value:

<tc:SignaturePad
	value="{/signature}"
	placeholder="Sign here"
	height="12rem"
	size="XL"
	change=".onSigned" />

Stroke width, placeholder and clear button follow the size property, and the pad keeps its strokes when it is resized.

Requirements

  • UI5 version 1.116 or higher (OpenUI5 or SAPUI5)

1.116 is the oldest release the library runs on, and the test page is checked against it. What sets the limit is sap/base/i18n/Localization, which the DatePicker reads the language from and which does not exist before 1.116.

Installation

The library is published on npm as ui5.touch.controls and can be consumed in any UI5 application that is built with the UI5 Tooling (v3 or higher).

1. Install the package

Install the library as a regular dependency (not a devDependency) so the UI5 Tooling picks it up as a project dependency:

npm install ui5.touch.controls
{
	"dependencies": {
		"ui5.touch.controls": "^1.2.0"
	}
}

The package ships a ui5.yaml, so the UI5 Tooling automatically resolves it as a library dependency.

With UI5 middleware (alternative setup)

Instead of consuming the library as a UI5 Tooling project dependency, you can serve it statically with ui5-middleware-servestatic:

npm i ui5.touch.controls && npm i -D ui5-middleware-servestatic

Add the following configuration to your ui5.yaml:

server:
  customMiddleware:
    - name: ui5-middleware-servestatic
      afterMiddleware: compression
      mountPath: /resources/ui5/touch/controls/
      configuration:
        npmPackagePath: 'ui5.touch.controls/dist/resources/ui5/touch/controls'

2. Declare the library in manifest.json

Add the library to the dependencies of your app:

{
	"sap.ui5": {
		"dependencies": {
			"libs": {
				"ui5.touch.controls": {}
			}
		}
	}
}

3. Add the namespace to your views

<mvc:View
	xmlns:mvc="sap.ui.core.mvc"
	xmlns="sap.m"
	xmlns:tc="ui5.touch.controls">
	<tc:Button text="Hello" size="XL" />
</mvc:View>

TypeScript support

For TypeScript projects, add the package to the types entry in your tsconfig.json — otherwise the UI5 Tooling will not load the library automatically:

{
	"compilerOptions": {
		"types": [
			"@sapui5/types",
			"ui5.touch.controls"
		]
	}
}

The package includes TypeScript type definitions (dist/index.d.ts), so you get full typing out of the box:

import Button from "ui5/touch/controls/Button";
import { SizeMode } from "ui5/touch/controls/library";

const button = new Button({ text: "Confirm", size: SizeMode.XL });

Controls

Touch versions of sap.m controls

These are rebuilds of standard controls. They keep the properties, aggregations and events of their originals for the common cases, so they can be used as a drop-in replacement — the Replaces column names the control each one steps in for.

| Control | Replaces | Description | | --- | --- | --- | | tc:Button | sap.m.Button | Button with configurable size, icon, icon position, type (all sap.m.ButtonType values), side padding and width. Fires press. | | tc:SegmentedButton | sap.m.SegmentedButton | A row of joined buttons of which exactly one is selected, filled through tc:SegmentedButtonItem (key, text, icon, enabled). Supports selectedKey, width for evenly spread segments and fires selectionChange. | | tc:CheckBox | sap.m.CheckBox | Check box whose box, check mark, label and hit area scale together. Supports selected, partiallySelected, text, editable, wrapping, value states and width. Fires select. | | tc:RadioButton / tc:RadioButtonGroup | sap.m.RadioButton / sap.m.RadioButtonGroup | Circle, dot, label and hit area scale together. Buttons sharing a groupName are mutually exclusive; the group arranges them in columns and hands its size, enabled, editable and value state down to them. Fires select. | | tc:Switch | sap.m.Switch | Track, handle and label scale together, where sap.m.Switch is fixed at 4rem x 2rem. Supports state, customTextOn, customTextOff and the AcceptReject type. Fires change. | | tc:Select | sap.m.Select | Drop-down filled with plain sap.ui.core.Item elements. The list opens in a popover whose rows are as big as the field, so they can be hit with a finger — the native list of sap.m.Select keeps its standard row height however large the field is. Supports selectedKey, editable, forceSelection, value states and width. Fires change. | | tc:ComboBox | sap.m.ComboBox | A tc:Select the user can type into: free text is allowed and what is typed filters the list, whose rows are as big as the field. Works together with tc:VirtualKeyboard on a device without a keyboard. Supports value, selectedKey, placeholder, editable, value states, width and showSecondaryValues, which puts the additionalText of a sap.ui.core.ListItem at the end of a row. Fires change and selectionChange. | | tc:DatePicker | sap.m.DatePicker | Field with a calendar built from the library's own buttons, so a day is a square that grows with size instead of the fixed grid of sap.ui.unified.Calendar. Days and months view, minDate / maxDate, valueFormat and displayFormat. Fires change. | | tc:TimePicker | sap.m.TimePicker | Field with two columns of buttons — hours and minutes — so a time is picked with one tap on a target that grows with size, where sap.m.TimePicker uses a slider that has to be dragged. Supports minutesStep, valueFormat and displayFormat. Fires change. | | tc:Input | sap.m.Input | Single-line input with configurable size. A tc:VirtualKeyboard can be put into its virtualKeyboard aggregation; with showVirtualKeyboard it then opens in a popover below the field while the field has the focus and types into it. | | tc:TextArea | sap.m.TextArea | Multi-line input with configurable size, rows, max length and value states. Takes a tc:VirtualKeyboard in its virtualKeyboard aggregation just like tc:Input does; there the Enter key adds a line break. Fires change / liveChange. | | tc:Text | sap.m.Text | Text with configurable size and color. Fires press. | | tc:Link | sap.m.Link | Anchor with configurable size, so the area that can be hit with a finger grows with the label. Supports href, target, wrapping, subtle, emphasized and width; a target="_blank" link automatically gets rel="noopener noreferrer". Fires press. | | tc:Toolbar | sap.m.Toolbar | Toolbar container with a content aggregation. Usable in standard aggregations such as the footer of a Page or Dialog. | | tc:OverflowToolbar | sap.m.OverflowToolbar | Like tc:Toolbar, but content that does not fit into the available width is moved behind a button with three dots which opens a popover with the remaining content. Understands the priorities of sap.m.OverflowToolbarLayoutData. | | tc:StepInput | sap.m.StepInput | Minus button, input and plus button, sized together. Supports min, max, step. Fires change. | | QuickDialog | sap.m.MessageBox | Helper class for touch-ready dialogs, used from the controller instead of a view: show, confirm, information, error, input, select, details. Every method returns a Promise. |

Controls without a sap.m equivalent

These exist only in this library, for situations that only come up on a touch device — see New controls for touch above for what they are good for.

| Control | Description | | --- | --- | | tc:BarcodeInput | Input field that tells a barcode scanner from a person typing: a run of at least minLength characters whose gaps stay below scanTimeout and that is closed by Enter fires scan, everything else fires change. prefix and suffix are cut off the code, clearOnScan empties the field for the next one. | | tc:VirtualKeyboard | On-screen keyboard built from the library's own buttons. mode picks one of the ready-made layouts (QWERTY, Numeric, Phone, Calculator); mode="Custom" reads a layout of your own from layout (incl. {shift}, {space}, {bksp}, {enter}). Optional hardware key input, value binding and change / keyPress / enter events. | | tc:SignaturePad | A field to sign in with a finger or a stylus. Draws on a canvas and hands the signature over as a PNG data URL in value. Stroke width, placeholder and clear button follow size; the strokes survive a resize. Fires change. |

Sizes

Every control has the same size property. Available values:

S · M (default) · L · XL · 2XL · 3XL · 4XL · 5XL · 6XL

The size scales font size, icon size, padding and height together, so the controls stay proportional at every step.

ISized

All controls with a size property implement the marker interface ui5.touch.controls.ISized. This allows generic size handling, e.g. to apply a user setting to a whole view:

if (control.isA<ISized>("ui5.touch.controls.ISized")) {
	control.setSize(SizeMode.XL);
}

Theme compatibility

The library ships its own theme library for the following themes, so the controls take their colours, borders and shadows from the theme parameters of the active theme and blend in with the surrounding sap.m controls. Set the theme as usual through data-sap-ui-theme in the bootstrap or at runtime through Theming.setTheme().

| Theme | Theme ID | Supported | Remark | | --- | --- | --- | --- | | Horizon | sap_horizon | ✅ | Default theme of the demo | | Horizon Dark | sap_horizon_dark | ✅ | Dark variant of Horizon | | Horizon High Contrast Black | sap_horizon_hcb | ✅ | High contrast, dark background | | Horizon High Contrast White | sap_horizon_hcw | ✅ | High contrast, light background | | Fiori 3 (Quartz Light) | sap_fiori_3 | ✅ | Previous default theme of SAPUI5 / OpenUI5 | | Fiori 3 Dark (Quartz Dark) | sap_fiori_3_dark | ✅ | Dark variant of Fiori 3 |

Themes that are not listed here are not shipped with the library. UI5 then falls back to the base theme for ui5.touch.controls, so the controls stay usable, but they will not match the colours of the rest of the application.

More examples

The controls integrate seamlessly with existing standard controls and aggregations — for example tc:Button and tc:Text inside a sap.m.Table:

sap.m.Table using ui5.touch.controls Button and Text controls

Use tc:Toolbar or tc:OverflowToolbar as a replacement for the toolbar in a Page or Dialog:

Screenshot of Toolbar in Dialog

⚠️ Aggregations that only accept sap.m.Button

Some standard aggregations are typed to sap.m.Button and therefore cannot take a tc:Button at all — the most common ones are buttons, beginButton and endButton of sap.m.Dialog:

<!-- does NOT work — these aggregations only accept sap.m.Button -->
<Dialog title="Delete order">
	<buttons>
		<tc:Button text="Delete" type="Reject" size="XL" press=".onDelete" />
		<tc:Button text="Cancel" size="XL" press=".onCancel" />
	</buttons>
</Dialog>

UI5 rejects the control at runtime:

"Element ui5.touch.controls.Button#__button0" is not valid
for aggregation "buttons" of Element sap.m.Dialog#__dialog0

And these button slots are not meant to be resized either — they are laid out for the standard button height.

The way around it is the footer aggregation. It is typed to sap.m.Toolbar (available since UI5 1.110), and because tc:Toolbar and tc:OverflowToolbar extend sap.m.Toolbar, they fit straight in. The dialog then sizes its footer to the toolbar, so touch-sized buttons are rendered properly:

<!-- works — the footer takes any sap.m.Toolbar, so also the touch ones -->
<Dialog title="Delete order">
	<footer>
		<tc:OverflowToolbar size="XL">
			<tc:Button text="Delete" type="Reject" icon="sap-icon://delete" size="XL" press=".onDelete" />
			<ToolbarSpacer />
			<tc:Button text="Cancel" icon="sap-icon://decline" size="XL" press=".onCancel" />
		</tc:OverflowToolbar>
	</footer>
</Dialog>

Use tc:OverflowToolbar rather than tc:Toolbar whenever the dialog can get narrow — actions that no longer fit then move into the overflow popover instead of being cut off.

The same applies in a controller:

import Button from "ui5/touch/controls/Button";
import OverflowToolbar from "ui5/touch/controls/OverflowToolbar";
import { SizeMode } from "ui5/touch/controls/library";

dialog.setFooter(
	new OverflowToolbar({
		size: SizeMode.XL,
		content: [
			new Button({ text: "Delete", type: ButtonType.Reject, size: SizeMode.XL, press: onDelete }),
			new ToolbarSpacer(),
			new Button({ text: "Cancel", size: SizeMode.XL, press: onCancel }),
		],
	}),
);

For plain message-box style dialogs you do not have to build this yourself — QuickDialog already creates its footer this way, sized through its size option.

Development

Prerequisites

Getting started

pnpm install
npm run start

This starts the dev server (ui5 serve with ui5-docs.yaml) and opens the demo application. The demo is a standalone UI5 app in docs/: Component.ts and manifest.json wire the router, view/ holds one XML view per page and controller/ the matching controllers. The shell (side navigation, theme switcher, previous/next) lives in view/App.view.xml, the page list in model/pages.ts. It always runs against the latest UI5.

Test pages

test/ holds a single plain page that shows every control — no descriptions, no navigation, no models, nothing but the controls, so a broken render is the library's doing and not the demo's. It exists to see the controls on the older UI5 versions the library supports:

npm run start:test          # latest
npm run start:test:1.116    # the oldest supported release
npm run start:test:1.120    # and 1.124, 1.130, 1.140

#Button in the hash — or ?control=Button — narrows the page to a single control; without either, every control is shown, one section after the other. Switching by hash rebuilds the page without reloading it. The cases are built in test/cases.ts.

UI tests

The same page is what the UI tests run against. They are written with wdi5 (WebdriverIO plus the UI5 service), so the controls are addressed through the UI5 control tree and read back through their own getters:

npm run test:ui                        # the version pinned in ui5-test.yaml
UI5_VERSION=1.116.0 npm run test:ui    # any other release

wdio.conf.js starts the dev server itself, so there is nothing to have running beforehand. The suite checks that every control of test/cases.ts is on the page, that a CheckBox, a Switch, an Input and a Select still react, that a Button grows with its size, and that the page reports no error along the way.

The GitHub workflow ci.yml runs the suite on every supported UI5 release in parallel. The matrix is not a second list: scripts/ui5-versions.mjs reads it from the start:test* scripts in package.json, so a release is added to CI by adding the script for it.

Scripts

| Script | Description | | --- | --- | | npm run start | Start the local dev server with livereload and open the demo application | | npm run start:test | Open the plain test page on the latest UI5 | | npm run start:test:1.116 | Same page on UI5 1.116, the oldest supported release | | npm run start:test:1.120 | Same page on UI5 1.120 (:1.124, :1.130 and :1.140 for the other supported versions) | | npm run build | Build the library into dist/ | | npm run build:self-contained | Self-contained build (used for the GitHub Pages deployment) | | npm run build:ts-interfaces | Generate the *.gen.d.ts TypeScript interfaces for the controls | | npm run test:ui | Run the wdi5 UI tests against the test page (UI5_VERSION picks the release) | | npm run check:ts | TypeScript type check (tsc --noEmit) | | npm run check:lint | ESLint check for src, docs, test, e2e, scripts and wdio.conf.js | | npm run build:icon-font | Generate the library's icon font (TTF/WOFF/WOFF2 + metadata) from the SVGs in src/icons (runs automatically before start/build) | | npm run clean | Remove dist and coverage |

Project structure

src/                  Library sources (controls, library.ts, themes)
src/themes/           Base + theme-specific LESS files
docs/                 Demo application (Component, manifest, views, controllers)
test/                 Plain test page (one section per control)
e2e/                  wdi5 UI tests that run against the test page
scripts/              Build helper scripts
ui5.yaml              UI5 tooling config (library build)
ui5-docs.yaml         UI5 tooling config (dev server / demo application)
ui5-test.yaml         UI5 tooling config (test page, any UI5 version)
ui5-self-contained.yaml  UI5 tooling config (self-contained build)

Deployment

Pushes to main trigger the GitHub Actions workflow (.github/workflows/deploy-pages.yml), which runs the self-contained build and deploys the demo application to GitHub Pages.

License

Licensed under the Apache License 2.0.