Install
openclaw skills install ionic-expertA comprehensive starting point for AI agents to work with the Ionic Framework. Covers core concepts, components, CLI, theming, layout, lifecycle, navigation, and framework-specific patterns for Angular, React, and Vue. Pair with the other Ionic skills in this collection for deeper topic-specific guidance like app creation, framework integration, and upgrades.
openclaw skills install ionic-expertComprehensive reference for Ionic Framework development — core concepts, components, theming, lifecycle, navigation, framework-specific patterns (Angular, React, Vue), upgrading, and Capawesome Cloud integration.
Ionic Framework is a UI toolkit for building cross-platform apps with web technologies. It provides 80+ pre-built UI components as Web Components prefixed with ion- (e.g., <ion-button>, <ion-content>).
ios mode; Android and all other platforms use md (Material Design). The <html> element receives a class (ios or md).capacitor-app-development skill for Capacitor guidance.@ionic/angular), React (@ionic/react), and Vue (@ionic/vue).npm install -g @ionic/cli
ionic start <name> <template> --type=<framework> --capacitor --package-id=<id>
--type value | Framework |
|---|---|
angular | Angular (NgModules) |
angular-standalone | Angular (Standalone Components) |
react | React |
vue | Vue |
| Template | Description |
|---|---|
blank | Empty project, single page |
tabs | Tab-based layout |
sidemenu | Side menu layout |
For details, see ionic-app-creation.
Run ionic --help for the full and always up-to-date command list.
| Command | Description |
|---|---|
ionic start | Scaffold a new Ionic project. |
ionic serve | Start a local dev server with live reload (port 8100). |
ionic build | Build the web app for production. |
ionic generate | Generate pages, components, services (framework-dependent). |
ionic info | Print system/environment info. |
ionic repair | Remove and recreate dependencies and platform files. |
Useful ionic serve flags: --external (all network interfaces), --port=<port>, --prod, --no-open.
Ionic provides 80+ UI components organized by category. For full API reference (properties, events, methods, slots, CSS custom properties), see the linked reference files.
ion-app (root container), ion-content (scrollable area), ion-header, ion-footer, ion-toolbar, ion-title, ion-buttons, ion-back-button, ion-grid/ion-row/ion-col, ion-split-pane.
Key usage:
<ion-header>
<ion-toolbar>
<ion-buttons slot="start">
<ion-back-button defaultHref="/home"></ion-back-button>
</ion-buttons>
<ion-title>Page Title</ion-title>
</ion-toolbar>
</ion-header>
<ion-content>
<!-- Scrollable content -->
</ion-content>
For details, see components-layout.md.
ion-tabs, ion-tab-bar, ion-tab-button, ion-menu, ion-menu-button, ion-menu-toggle, ion-router-outlet, ion-nav, ion-breadcrumbs.
For details, see components-navigation.md.
ion-input, ion-textarea, ion-select/ion-select-option, ion-checkbox, ion-toggle, ion-radio/ion-radio-group, ion-range, ion-datetime/ion-datetime-button, ion-searchbar, ion-segment/ion-segment-button, ion-input-otp.
Key properties shared by most form components: label, labelPlacement (floating, stacked, fixed, start), fill (outline, solid), errorText, helperText, disabled, value, placeholder.
Key events:
ionInput — fires on each keystroke (use for ion-input/ion-textarea).ionChange — fires when value is committed (use for ion-select, ion-toggle, ion-checkbox, ion-range).<ion-input label="Email" labelPlacement="floating" fill="outline"
type="email" placeholder="you@example.com"
errorText="Invalid email" helperText="Enter your email">
</ion-input>
<ion-select label="Country" labelPlacement="floating" fill="outline" interface="popover">
<ion-select-option value="us">United States</ion-select-option>
<ion-select-option value="de">Germany</ion-select-option>
</ion-select>
For details, see components-form.md.
ion-modal, ion-alert, ion-toast, ion-action-sheet, ion-loading, ion-popover.
All overlays share: isOpen prop for declarative control, trigger prop to open from a button ID, backdropDismiss, animated, and lifecycle events (didPresent, didDismiss, willPresent, willDismiss).
Sheet modal (bottom sheet):
<ion-modal [isOpen]="isOpen" [breakpoints]="[0, 0.5, 1]" [initialBreakpoint]="0.5" [handle]="true">
<ion-content>Sheet content</ion-content>
</ion-modal>
For details, see components-overlay.md.
ion-list, ion-item, ion-item-sliding/ion-item-options/ion-item-option, ion-card/ion-card-header/ion-card-content, ion-accordion/ion-accordion-group, ion-chip, ion-badge, ion-label, ion-note.
For details, see components-data-display.md.
ion-refresher/ion-refresher-content (pull-to-refresh), ion-infinite-scroll/ion-infinite-scroll-content, ion-reorder-group/ion-reorder.
For details, see components-scroll.md.
ion-button, ion-fab/ion-fab-button, ion-icon, ion-avatar, ion-thumbnail, ion-spinner, ion-skeleton-text, ion-progress-bar.
For details, see components-action.md and components-media.md.
Nine default colors: primary, secondary, tertiary, success, warning, danger, light, medium, dark. Apply via the color attribute:
<ion-button color="primary">Save</ion-button>
<ion-button color="danger">Delete</ion-button>
Customize a color by overriding all six CSS variables in :root:
:root {
--ion-color-primary: #3880ff;
--ion-color-primary-rgb: 56, 128, 255;
--ion-color-primary-contrast: #ffffff;
--ion-color-primary-contrast-rgb: 255, 255, 255;
--ion-color-primary-shade: #3171e0;
--ion-color-primary-tint: #4c8dff;
}
Key variables: --ion-background-color, --ion-text-color, --ion-font-family, --ion-safe-area-top/right/bottom/left, --ion-margin, --ion-padding.
Three approaches (import from @ionic/angular/css/, @ionic/react/css/, or @ionic/vue/css/):
@import '@ionic/<framework>/css/palettes/dark.system.css';@import '@ionic/<framework>/css/palettes/dark.always.css';@import '@ionic/<framework>/css/palettes/dark.class.css'; then add .ion-palette-dark to <html>.Target platform-specific styles in CSS using the mode class on <html>:
.ios ion-toolbar { --background: #f8f8f8; }
.md ion-toolbar { --background: #ffffff; }
Preview a specific mode in the browser: http://localhost:8100/?ionic:mode=ios
12-column flexbox grid: ion-grid, ion-row, ion-col. Columns expand evenly unless size (1-12) is specified.
| Breakpoint | Min Width | Property Suffix |
|---|---|---|
xs | 0 | Xs |
sm | 576px | Sm |
md | 768px | Md |
lg | 992px | Lg |
xl | 1200px | Xl |
.ion-padding, .ion-padding-top/bottom/start/end, .ion-no-padding.ion-margin, .ion-margin-top/bottom/start/end, .ion-no-margin.ion-text-center, .ion-text-start, .ion-text-end, .ion-text-wrap, .ion-text-nowrap.ion-display-none, .ion-display-block, .ion-display-flex.ion-justify-content-center, .ion-align-items-center, .ion-flex-row, .ion-flex-columnAll utility classes support responsive suffixes: .ion-text-md-center (applies at 768px+).
Ionic provides four lifecycle hooks that fire during page transitions. These exist because ion-router-outlet caches pages in the DOM — framework-native lifecycle hooks (ngOnInit, useEffect, onMounted) only fire once on first creation, not on every page visit.
| Hook | Fires When | Use For |
|---|---|---|
ionViewWillEnter | Page about to enter (pre-animation) | Refresh data on every visit |
ionViewDidEnter | Page fully entered (post-animation) | Start animations, focus inputs |
ionViewWillLeave | Page about to leave (pre-animation) | Save state, pause subscriptions |
ionViewDidLeave | Page fully left (post-animation) | Clean up off-screen resources |
Critical rules:
ion-router-outlet.For full details, see ionic-angular.
Detect architecture: Check src/main.ts for bootstrapApplication (standalone) vs platformBrowserDynamic().bootstrapModule (NgModule).
| Aspect | Standalone | NgModule |
|---|---|---|
| Ionic setup | provideIonicAngular({}) in app.config.ts | IonicModule.forRoot() in app.module.ts |
| Component imports | Each from @ionic/angular/standalone | IonicModule provides all globally |
| Lazy loading | loadComponent in routes | loadChildren in routes |
| Icons | addIcons() from ionicons required | Automatic |
Navigation: Use NavController from @ionic/angular for animated navigation (navigateForward, navigateBack, navigateRoot, back). Use routerLink with routerDirection in templates.
Lifecycle: Implement interfaces ViewWillEnter, ViewDidEnter, ViewWillLeave, ViewDidLeave from @ionic/angular:
import { ViewWillEnter } from '@ionic/angular';
@Component({ /* ... */ })
export class HomePage implements ViewWillEnter {
ionViewWillEnter() {
this.loadData(); // Runs on every page visit
}
}
For navigation details, see angular/navigation.md. For lifecycle details, see angular/lifecycle.md.
For full details, see ionic-react.
Key setup differences:
setupIonicReact() before rendering in src/main.tsx.IonReactRouter (from @ionic/react-router) instead of BrowserRouter.IonRouterOutlet to contain routes with the component prop (not render or children).IonPage as root — required for transitions and lifecycle hooks.Navigation: Use useIonRouter hook for programmatic navigation:
import { useIonRouter } from '@ionic/react';
const router = useIonRouter();
router.push('/detail/123', 'forward', 'push');
router.goBack();
Lifecycle hooks (from @ionic/react):
import { useIonViewWillEnter } from '@ionic/react';
useIonViewWillEnter(() => {
fetchData(); // Runs on every page visit
});
Overlay hooks: useIonAlert, useIonToast, useIonActionSheet, useIonLoading, useIonModal, useIonPopover, useIonPicker.
Form events: Use onIonInput for IonInput/IonTextarea, onIonChange for IonSelect/IonToggle/IonCheckbox/IonRange. Access values via e.detail.value.
For routing details, see react/routing.md. For hooks, see react/hooks.md.
For full details, see ionic-vue.
Key setup differences:
IonicVue plugin in src/main.ts: createApp(App).use(IonicVue).use(router).createRouter from @ionic/vue-router (not from vue-router).IonPage as root template element — without it, transitions and lifecycle hooks silently fail.@ionic/vue.@ion-change, @ion-input).ionicons/icons — never as strings.Navigation: Use useIonRouter composable:
<script setup lang="ts">
import { useIonRouter } from '@ionic/vue';
const ionRouter = useIonRouter();
ionRouter.push('/detail/123');
ionRouter.back();
</script>
Declarative: <ion-button router-link="/detail" router-direction="forward">Go</ion-button>
Lifecycle hooks (from @ionic/vue):
<script setup lang="ts">
import { onIonViewWillEnter } from '@ionic/vue';
onIonViewWillEnter(() => {
fetchData(); // Runs on every page visit
});
</script>
Composables: useIonRouter(), useBackButton(priority, handler), useKeyboard(), isPlatform(name), getPlatforms().
Access Web Component methods via $el: contentRef.value.$el.scrollToBottom(300).
For navigation details, see vue/navigation.md. For composables, see vue/composables.md.
Each framework uses ion-tabs with ion-tab-bar and child routes per tab. Each tab maintains its own navigation stack.
Rules:
tab attribute on ion-tab-button must match the child route path.ion-modal instead of cross-tab routing.Use ion-menu with contentId matching the id on ion-router-outlet. Wrap menu items in ion-menu-toggle to auto-close after selection. Use routerDirection="root" for top-level menu navigation.
Use non-linear routing for tabs or split-pane layouts. Use linear routing for simple page flows.
Ionic supports upgrades from version 4 through 8. Each major version jump must be applied sequentially — do not skip intermediate versions.
For full upgrade guides, see ionic-app-upgrades.
Ionic apps use Capacitor for native device features (camera, filesystem, push notifications, etc.). The standard workflow:
npm run build
npx cap sync
npx cap run android
npx cap run ios
For live reload on a device:
ionic cap run android --livereload --external
ionic cap run ios --livereload --external
For Capacitor guidance, see the capacitor-app-development skill.
Capawesome Cloud provides CI/CD services for Ionic/Capacitor apps:
Visit capawesome.io for the full Capawesome ecosystem. For setup, see the capawesome-cloud skill.
ionic: command not found: Run npm install -g @ionic/cli.@ionic/angular/standalone.ionViewWillEnter not firing: The component must be directly routed via ion-router-outlet. Child components do not receive lifecycle events. For React/Vue, verify IonPage is the root element.ionViewWillEnter) instead of framework-native lifecycle hooks (ngOnInit, useEffect, onMounted). Ionic caches pages in the DOM.NavController for Angular, IonReactRouter for React, createRouter from @ionic/vue-router for Vue). Standard framework routers do not trigger Ionic animations.--background, --color) instead of targeting internal elements.addIcons() from ionicons with the required icons and import IonIcon from @ionic/angular/standalone.Failed to resolve component: ion-* (Vue): The Ionic component is not imported. Add the import from @ionic/vue.IonRouterOutlet within IonTabs.onIonInput for IonInput/IonTextarea, not onChange. Access values via e.detail.value.'vue/no-deprecated-slot-attribute': 'off'.ionic-app-creation — Create a new Ionic app from scratch.ionic-app-development — General Ionic development, full component API reference.ionic-angular — Angular-specific patterns (standalone vs NgModule, navigation, forms, testing).ionic-react — React-specific patterns (IonReactRouter, hooks, state management).ionic-vue — Vue-specific patterns (composables, navigation, IonPage requirement).ionic-app-upgrades — Upgrade Ionic to a newer major version.capacitor-app-development — General Capacitor development.capawesome-cloud — Live updates, native builds, and app store publishing.