Animation
These gesture and animation helpers are production-ready and optional. The theme works without them.
Sheet of Glass with ion-tab-button / ion-segment-button
Register an ion-tab-bar or ion-segment element to add a moving selection effect to its buttons.
registerTabBarEffect respects prefers-reduced-motion, including changes while the page is open. Reduced motion removes the moving lens and tab scaling while preserving standard Ionic selection. Turning it off restores the optional effect until the registration is destroyed.
registerSegmentEffect adds only a visual layer; Ionic still owns selection, dragging, keyboard handling, and events. An unselected segment starts its lens movement on release, while a selected segment expands in place, including on short taps. The motion follows iOS 27 presentation-layer measurements. Reduced motion skips this optional effect; native glass refraction is approximated with CSS.
import { registerTabBarEffect, registerSegmentEffect } from '@rdlabo/ionic-theme-ios27';
/**
* Register initialized Ionic DOM elements.
*/
const tabBar = document.querySelector<HTMLElement>('ion-tab-bar');
const segment = document.querySelector<HTMLElement>('ion-segment');
const registeredTabBarEffect = tabBar ? registerTabBarEffect(tabBar) : undefined;
const registeredSegmentEffect = segment ? registerSegmentEffect(segment) : undefined;
const destroy = () => {
/**
* If the registered DOM element is removed (e.g., due to page navigation),
* make sure to destroy the gesture and animation. This will also remove the event listeners.
* You can re-register them if needed.
*/
registeredTabBarEffect?.destroy();
registeredSegmentEffect?.destroy();
};
Searchbar cancel icon
Ionic 8 and 9 render cancelButtonIcon only in Material Design mode. Register a searchbar to use that same property in iOS mode. Without this optional helper, the theme keeps Ionic's cancel text button.
This is a temporary rendering shim, scheduled for removal once the supported Ionic versions render cancelButtonIcon in the iOS DOM. It skips insertion when an icon is already present. It does not change keyboard handling, focus, accessibility attributes on the button, or cancel/clear behavior; these remain Ionic's responsibility. The CSS design and animations are independent of the helper and also apply to an icon rendered by Ionic itself.
import { supportSeachbarCancelButtonIcon } from '@rdlabo/ionic-theme-ios27';
import { closeOutline } from 'ionicons/icons';
const searchbar = document.querySelector<HTMLIonSearchbarElement>('ion-searchbar')!;
searchbar.animated = true;
searchbar.showCancelButton = 'focus'; // 'always' and 'never' also work
searchbar.cancelButtonIcon = closeOutline;
searchbar.clearIcon = closeOutline;
searchbar.cancelButtonText = 'Close search'; // accessible name of the icon button
const effect = supportSeachbarCancelButtonIcon(searchbar);
// After changing cancelButtonIcon as a JavaScript property, call effect.refresh().
// When the component/page is destroyed:
// effect.destroy();
Registration and exclusions
Register after the Ionic element has initialized (for example, Angular's ngAfterViewInit).
| Condition | Behavior |
|---|---|
| Supported iOS-mode searchbar | Preserves Ionic's button and event handlers; destroy() restores text content. |
MD mode, searchbar-classic, ios-theme-disabled or ios26-disabled |
Helper does not apply. |
animated / prefers-reduced-motion |
Respected by the CSS animation. |
| CSS customization | --background, --box-shadow, --border-radius and --cancel-button-color remain available. |
Clear and cancel buttons
| Button | Ionic appearance settings | Action |
|---|---|---|
| Clear | clearIcon, showClearButton, --clear-button-color |
Clears while retaining input focus. |
| Cancel | cancelButtonIcon, --cancel-button-color |
Ends the search. |
Both can appear together beside the input. Set clearIcon and cancelButtonIcon to the same icon for matching appearance.
Both external glass buttons use a 44px resting size and expand while pressed. Reduced motion disables scaling. The clear button appears outside the text field; Ionic supplies the icons.
While held, the glass background becomes opaque and the icon opacity is 0.55, preserving its configured color. Use --background-activated to customize the pressed background independently of --background.
TabBarSearchable: Searchable with ion-tab-bar and ion-fab-button
Use the following structure inside ion-tabs to animate a search button into a search toolbar.
<ion-content>...</ion-content>
<ion-fab vertical="bottom" horizontal="end" slot="fixed">
<ion-fab-button aria-label="Search" (click)="present($event)">
<ion-icon name="search"></ion-icon>
</ion-fab-button>
</ion-fab>
<ion-footer [translucent]="true">
<ion-toolbar>
<ion-buttons slot="start">
<!-- ion-icon name is set dynamically by the animation -->
<ion-button fill="default"><ion-icon slot="icon-only"></ion-icon> </ion-button>
</ion-buttons>
<!-- User set `ionChange` or other events. -->
<ion-searchbar aria-label="Search" (ionChange)="example($event)"></ion-searchbar>
</ion-toolbar>
</ion-footer>
import { attachTabBarSearchable, TabBarSearchableType } from '@rdlabo/ionic-theme-ios27';
import type { TabBarSearchableFunction } from '@rdlabo/ionic-theme-ios27';
let searchableFun: TabBarSearchableFunction | undefined;
const initialize = () => {
// attachTabBarSearchable has state. You should initialize per page.
const tabBar = document.querySelector<HTMLElement>('ion-tab-bar');
const fabButton = document.querySelector<HTMLElement>('ion-fab-button');
const footer = document.querySelector<HTMLElement>('ion-footer');
if (!tabBar || !fabButton || !footer) {
return;
}
searchableFun = attachTabBarSearchable(tabBar, fabButton, footer);
};
const present = (event: Event) => {
searchableFun!(event, TabBarSearchableType.Enter);
};
const dismiss = (event: Event) => {
searchableFun!(event, TabBarSearchableType.Leave);
};

