@sosweetham/tauri-plugin-system-components-api
v0.1.3
Published
Native system UI components for Tauri 2 — native iOS tab bar over the webview, native controls, and glass window backgrounds on macOS/iOS.
Maintainers
Readme
tauri-plugin-system-components
Native system UI components for Tauri 2 apps — real UIKit/AppKit controls over the webview, including Apple's Liquid Glass material on iOS 26 / macOS 26:
iOS — native bottom tab bar. A real UIKit
UITabBarfloated over the webview. Built with Xcode 26 against the iOS 26 SDK, it adopts Liquid Glass automatically and refracts the live web content rendered behind it — something CSS cannot reproduce, because glass samples the native layers beneath the view (the same mechanism Safari's own iOS 26 toolbars use over aWKWebView). Tab taps are delivered to JS astabSelectedevents so the web app drives its own page switching. On pre-26 devices the same bar renders the classic translucent look.macOS — native floating tab bar. The same
configureTabBarAPI mounts anNSSegmentedControl(the controlNSTabViewControlleruses for toolbar-style tabs, with SF Symbol icons) inside a floatingNSGlassEffectViewcapsule pinned to the bottom center of the window — blur capsule fallback pre-26. Selection reaches JS through the sameonTabSelectedhelper.macOS — glass window background. An
NSGlassEffectView(macOS 26) inserted behind a transparent webview, with anNSVisualEffectViewblur fallback on older systems. The class is resolved dynamically at runtime, so the plugin builds and runs against older SDKs/systems.Native overlay components on both platforms via one generic API:
createComponent({ id, kind, props, anchor, dx, dy })with kindsswitch(UISwitch/NSSwitch),button(glassUIButton.Configurationon iOS 26 / NSButton),slider,progress, andimage. Components float over the webview anchored to a corner/center, optionally inside a glass capsule (props.glass: true). Interaction arrives viaonComponentEvent(({ id, event, on, value }) => …); state updates go back withupdateComponent(id, props).Image data everywhere. Tab items and components accept bitmaps as base64 /
data:URLs (image), decoded natively toUIImage/NSImage, withcircular: truefor the avatar treatment — e.g. a user avatar as the profile tab icon, rendered by the real native bar.
Windows, Linux, and Android are graceful stubs: the commands reject with
unsupported on this platform, which is the documented signal to fall back
to an HTML UI (see the example app). Tab badges (setBadge) are iOS-only —
NSSegmentedControl has no badge concept.
Install
# src-tauri/Cargo.toml
[dependencies]
tauri-plugin-system-components = { path = "..." }// src-tauri/src/lib.rs
tauri::Builder::default()
.plugin(tauri_plugin_system_components::init())// src-tauri/capabilities/default.json
{ "permissions": ["system-components:default"] }pnpm add @sosweetham/tauri-plugin-system-components-apiUsage
import {
configureTabBar,
onTabSelected,
getTabBarInsets,
isGlassSupported,
setWindowGlass,
} from '@sosweetham/tauri-plugin-system-components-api';
try {
// Native Liquid Glass tab bar (iOS UITabBar / macOS glass capsule).
await configureTabBar({
items: [
{ id: 'home', title: 'Home', sfSymbol: 'house.fill' },
// A bitmap icon — e.g. the user's avatar — clipped to a circle:
{ id: 'profile', title: 'Profile', image: avatarDataUrl, circular: true },
{ id: 'settings', title: 'Settings', sfSymbol: 'gearshape.fill' },
],
selectedId: 'home',
});
// Pad the page bottom so content scrolls clear of the floating bar.
const { bottom } = await getTabBarInsets();
await onTabSelected(({ id }) => router.goto(id));
} catch {
// Not iOS. On macOS, put glass behind the (transparent) webview instead:
const { supported, fallback } = await isGlassSupported();
await setWindowGlass({}).catch(() => {/* Windows/Linux */});
}Native overlay components:
import {
createComponent, updateComponent, removeComponent, onComponentEvent,
} from '@sosweetham/tauri-plugin-system-components-api';
await createComponent({
id: 'wifi', kind: 'switch', anchor: 'topTrailing',
props: { glass: true, on: true },
});
await createComponent({
id: 'volume', kind: 'slider', anchor: 'bottomTrailing', dy: 96,
props: { glass: true, min: 0, max: 100, value: 40 },
});
await createComponent({
id: 'me', kind: 'image', anchor: 'topLeading',
props: { image: avatarDataUrl, circular: true, width: 48, height: 48 },
});
await onComponentEvent(({ id, event, on, value }) => {
if (id === 'volume' && event === 'change') setVolume(value);
});
await updateComponent('wifi', { on: false });
await removeComponent('me');Other commands: removeTabBar, showTabBar, hideTabBar,
selectTab(id) (no event, mirrors AppKit/UIKit), setBadge(id, value?)
(iOS-only), clearWindowGlass.
onTabSelected subscribes to both transports under the hood — the mobile
plugin event channel on iOS and the system-components://tab-selected Tauri event
on macOS — so app code is identical everywhere.
Requirements & caveats
- Seeing glass on iOS requires building with Xcode 26 (iOS 26 SDK) and an iOS 26 device/simulator. The bar itself works from iOS 14.
- macOS window glass requires
"transparent": trueon the window and"app": { "macOSPrivateApi": true }intauri.conf.json(plus themacos-private-apitauri feature) so the webview lets the glass show through — note the private-API flag has App Store implications. Real glass needs macOS 26; older systems get a behind-window blur. - The web page must leave regions transparent (no opaque full-bleed background) wherever macOS glass should be visible.
tabBarMinimizeBehavior(bar collapses on scroll) is not exposed yet — it lives onUITabBarController, not the bareUITabBar; planned for a later iteration along with more glass components (switches, etc.).- Keyboard does not auto-hide the bar (standard for floating bars).
Example app
examples/tauri-app is a Svelte 5 + Vite app with an animated gradient
background (so the refraction is obvious), four pages switched by in-app
state, the native bar on iOS, and an HTML fallback bar + window glass on
desktop.
cd examples/tauri-app
pnpm install
pnpm tauri dev # macOS: HTML bar + window glass
pnpm tauri ios dev "iPhone 17 Pro" # iOS 26 simulator: Liquid Glass bar