
Ionic Design
- 513 installs
- 57 repo stars
- Updated July 13, 2026
- cap-go/capgo-skills
ionic-design is a mobile UI skill that applies Ionic component patterns, layouts, and accessibility guidance when building Capacitor hybrid app screens and navigation for developers who need consistent cross-platform int
About
ionic-design is a Capgo agent skill for Ionic and Capacitor hybrid app development. It steers engineers toward proven Ionic component patterns, mobile-first layouts, accessible screen structure, and navigation flows when implementing app screens in TypeScript, HTML, and Ionic markup. The skill fits projects that ship one codebase to iOS and Android through Capacitor while keeping native-feeling UI conventions. Developers reach for ionic-design when scaffolding tabs, modals, lists, forms, or routing in an Ionic app and want agent suggestions aligned with Ionic design idioms instead of generic web layouts. It complements Capacitor plugin work by focusing on presentation layer decisions that affect usability on phones and tablets.
- Ionic component conventions
- Mobile-first hybrid layouts
- Capacitor-friendly theming
- Accessible touch UI patterns
Ionic Design by the numbers
- 513 all-time installs (skills.sh)
- Ranked #586 of 1,880 Design & UI/UX skills by installs in the Skillselion catalog
- Data as of Aug 1, 2026 (Skillselion catalog sync)
npx skills add https://github.com/cap-go/capgo-skills --skill ionic-designAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 513 |
|---|---|
| repo stars | ★ 57 |
| Last updated | July 13, 2026 |
| Repository | cap-go/capgo-skills ↗ |
How do you structure Ionic Capacitor screens and navigation?
Apply Ionic component patterns, mobile layouts, and accessible hybrid UI when building Capacitor app screens and navigation.
Who is it for?
Developers building Capacitor hybrid apps who want Ionic-consistent UI and navigation guidance during screen implementation.
Skip if: Developers building fully native Swift/Kotlin apps or React Native projects without Ionic components should skip ionic-design.
When should I use this skill?
A developer asks to design or implement Ionic screens, mobile layouts, tabs, modals, or navigation inside a Capacitor app.
What you get
Ionic screen layouts, navigation flows, and accessible component selections aligned with Capacitor hybrid apps.
- Ionic screen layouts
- Navigation structure recommendations
Files
Ionic Framework Design Guide
Build beautiful, native-looking mobile apps with Ionic Framework and Capacitor.
When to Use This Skill
- User is using Ionic components
- User wants native-looking UI
- User asks about Ionic theming
- User needs mobile UI patterns
- User wants platform-specific styling
What is Ionic Framework?
Ionic provides:
- 100+ mobile-optimized UI components
- Automatic iOS/Android platform styling
- Built-in dark mode support
- Accessibility out of the box
- Works with React, Vue, Angular, or vanilla JS
Getting Started
Installation
# For React
npx create-vite@latest my-app --template react-ts
cd my-app
npm install @ionic/react @ionic/react-router
# For Vue
npx create-vite@latest my-app --template vue-ts
cd my-app
npm install @ionic/vue @ionic/vue-router
# Add Capacitor
npm install @capacitor/core @capacitor/cli
npx cap initSetup (React)
// main.tsx
import React from 'react';
import { createRoot } from 'react-dom/client';
import { IonApp, setupIonicReact } from '@ionic/react';
import App from './App';
/* Core CSS required for Ionic components to work properly */
import '@ionic/react/css/core.css';
/* Basic CSS for apps built with Ionic */
import '@ionic/react/css/normalize.css';
import '@ionic/react/css/structure.css';
import '@ionic/react/css/typography.css';
/* Optional CSS utils */
import '@ionic/react/css/padding.css';
import '@ionic/react/css/float-elements.css';
import '@ionic/react/css/text-alignment.css';
import '@ionic/react/css/text-transformation.css';
import '@ionic/react/css/flex-utils.css';
import '@ionic/react/css/display.css';
/* Theme */
import './theme/variables.css';
setupIonicReact();
const root = createRoot(document.getElementById('root')!);
root.render(
<IonApp>
<App />
</IonApp>
);Core Components
Page Structure
import {
IonPage,
IonHeader,
IonToolbar,
IonTitle,
IonContent,
IonButtons,
IonBackButton,
} from '@ionic/react';
function MyPage() {
return (
<IonPage>
<IonHeader>
<IonToolbar>
<IonButtons slot="start">
<IonBackButton defaultHref="/home" />
</IonButtons>
<IonTitle>Page Title</IonTitle>
</IonToolbar>
</IonHeader>
<IonContent fullscreen>
{/* Large title for iOS */}
<IonHeader collapse="condense">
<IonToolbar>
<IonTitle size="large">Page Title</IonTitle>
</IonToolbar>
</IonHeader>
{/* Page content */}
<div className="ion-padding">
Your content here
</div>
</IonContent>
</IonPage>
);
}Lists
import {
IonList,
IonItem,
IonLabel,
IonNote,
IonAvatar,
IonIcon,
IonItemSliding,
IonItemOptions,
IonItemOption,
} from '@ionic/react';
import { chevronForward, trash, archive } from 'ionicons/icons';
function ContactList() {
return (
<IonList>
{/* Simple item */}
<IonItem>
<IonLabel>Simple Item</IonLabel>
</IonItem>
{/* Item with detail */}
<IonItem detail button>
<IonLabel>
<h2>Item Title</h2>
<p>Item description text</p>
</IonLabel>
<IonNote slot="end">Note</IonNote>
</IonItem>
{/* Item with avatar */}
<IonItem>
<IonAvatar slot="start">
<img src="/avatar.jpg" alt="" />
</IonAvatar>
<IonLabel>
<h2>John Doe</h2>
<p>john@example.com</p>
</IonLabel>
</IonItem>
{/* Sliding item */}
<IonItemSliding>
<IonItem>
<IonLabel>Swipe me</IonLabel>
</IonItem>
<IonItemOptions side="end">
<IonItemOption color="danger">
<IonIcon slot="icon-only" icon={trash} />
</IonItemOption>
<IonItemOption>
<IonIcon slot="icon-only" icon={archive} />
</IonItemOption>
</IonItemOptions>
</IonItemSliding>
</IonList>
);
}Forms
import {
IonInput,
IonTextarea,
IonSelect,
IonSelectOption,
IonToggle,
IonCheckbox,
IonRadioGroup,
IonRadio,
IonItem,
IonLabel,
IonButton,
} from '@ionic/react';
function MyForm() {
return (
<form>
{/* Text input */}
<IonItem>
<IonInput
label="Email"
labelPlacement="floating"
type="email"
placeholder="Enter email"
/>
</IonItem>
{/* Password */}
<IonItem>
<IonInput
label="Password"
labelPlacement="floating"
type="password"
/>
</IonItem>
{/* Textarea */}
<IonItem>
<IonTextarea
label="Bio"
labelPlacement="floating"
rows={4}
placeholder="Tell us about yourself"
/>
</IonItem>
{/* Select */}
<IonItem>
<IonSelect label="Country" placeholder="Select">
<IonSelectOption value="us">United States</IonSelectOption>
<IonSelectOption value="uk">United Kingdom</IonSelectOption>
<IonSelectOption value="de">Germany</IonSelectOption>
</IonSelect>
</IonItem>
{/* Toggle */}
<IonItem>
<IonToggle>Enable notifications</IonToggle>
</IonItem>
{/* Checkbox */}
<IonItem>
<IonCheckbox slot="start" />
<IonLabel>I agree to terms</IonLabel>
</IonItem>
{/* Radio group */}
<IonRadioGroup>
<IonItem>
<IonRadio value="small">Small</IonRadio>
</IonItem>
<IonItem>
<IonRadio value="medium">Medium</IonRadio>
</IonItem>
<IonItem>
<IonRadio value="large">Large</IonRadio>
</IonItem>
</IonRadioGroup>
<IonButton expand="block" type="submit">
Submit
</IonButton>
</form>
);
}Buttons
import { IonButton, IonIcon } from '@ionic/react';
import { heart, share, download } from 'ionicons/icons';
function Buttons() {
return (
<>
{/* Fill variants */}
<IonButton>Solid</IonButton>
<IonButton fill="outline">Outline</IonButton>
<IonButton fill="clear">Clear</IonButton>
{/* Colors */}
<IonButton color="primary">Primary</IonButton>
<IonButton color="secondary">Secondary</IonButton>
<IonButton color="danger">Danger</IonButton>
<IonButton color="success">Success</IonButton>
{/* Sizes */}
<IonButton size="small">Small</IonButton>
<IonButton size="default">Default</IonButton>
<IonButton size="large">Large</IonButton>
{/* With icons */}
<IonButton>
<IonIcon slot="start" icon={heart} />
Like
</IonButton>
{/* Icon only */}
<IonButton>
<IonIcon slot="icon-only" icon={share} />
</IonButton>
{/* Full width */}
<IonButton expand="block">Block Button</IonButton>
<IonButton expand="full">Full Width</IonButton>
</>
);
}Cards
import {
IonCard,
IonCardHeader,
IonCardTitle,
IonCardSubtitle,
IonCardContent,
IonImg,
IonButton,
} from '@ionic/react';
function Cards() {
return (
<IonCard>
<IonImg src="/card-image.jpg" alt="" />
<IonCardHeader>
<IonCardSubtitle>Card Subtitle</IonCardSubtitle>
<IonCardTitle>Card Title</IonCardTitle>
</IonCardHeader>
<IonCardContent>
Card content goes here. This is a standard card with
an image, title, subtitle, and content.
</IonCardContent>
<div className="ion-padding-horizontal ion-padding-bottom">
<IonButton fill="clear">Action 1</IonButton>
<IonButton fill="clear">Action 2</IonButton>
</div>
</IonCard>
);
}Modals and Sheets
import { IonModal, IonButton, IonContent, IonHeader, IonToolbar, IonTitle } from '@ionic/react';
import { useState, useRef } from 'react';
function ModalExample() {
const [isOpen, setIsOpen] = useState(false);
const modal = useRef<HTMLIonModalElement>(null);
return (
<>
<IonButton onClick={() => setIsOpen(true)}>Open Modal</IonButton>
{/* Full page modal */}
<IonModal isOpen={isOpen} onDidDismiss={() => setIsOpen(false)}>
<IonHeader>
<IonToolbar>
<IonTitle>Modal Title</IonTitle>
<IonButton slot="end" onClick={() => setIsOpen(false)}>
Close
</IonButton>
</IonToolbar>
</IonHeader>
<IonContent>
<p>Modal content</p>
</IonContent>
</IonModal>
{/* Bottom sheet */}
<IonModal
ref={modal}
trigger="open-sheet"
initialBreakpoint={0.5}
breakpoints={[0, 0.25, 0.5, 0.75, 1]}
>
<IonContent>
<div className="ion-padding">
<h2>Sheet Content</h2>
<p>Drag to resize</p>
</div>
</IonContent>
</IonModal>
<IonButton id="open-sheet">Open Sheet</IonButton>
</>
);
}Navigation
Tab Navigation
import {
IonTabs,
IonTabBar,
IonTabButton,
IonIcon,
IonLabel,
IonRouterOutlet,
} from '@ionic/react';
import { Route, Redirect } from 'react-router-dom';
import { home, search, person } from 'ionicons/icons';
function TabsLayout() {
return (
<IonTabs>
<IonRouterOutlet>
<Route exact path="/tabs/home" component={HomePage} />
<Route exact path="/tabs/search" component={SearchPage} />
<Route exact path="/tabs/profile" component={ProfilePage} />
<Route exact path="/tabs">
<Redirect to="/tabs/home" />
</Route>
</IonRouterOutlet>
<IonTabBar slot="bottom">
<IonTabButton tab="home" href="/tabs/home">
<IonIcon icon={home} />
<IonLabel>Home</IonLabel>
</IonTabButton>
<IonTabButton tab="search" href="/tabs/search">
<IonIcon icon={search} />
<IonLabel>Search</IonLabel>
</IonTabButton>
<IonTabButton tab="profile" href="/tabs/profile">
<IonIcon icon={person} />
<IonLabel>Profile</IonLabel>
</IonTabButton>
</IonTabBar>
</IonTabs>
);
}Stack Navigation
import { IonReactRouter } from '@ionic/react-router';
import { IonRouterOutlet } from '@ionic/react';
import { Route } from 'react-router-dom';
function App() {
return (
<IonReactRouter>
<IonRouterOutlet>
<Route exact path="/" component={Home} />
<Route exact path="/detail/:id" component={Detail} />
</IonRouterOutlet>
</IonReactRouter>
);
}Theming
Theme Variables
/* theme/variables.css */
:root {
/* Primary */
--ion-color-primary: #3880ff;
--ion-color-primary-rgb: 56, 128, 255;
--ion-color-primary-contrast: #ffffff;
--ion-color-primary-shade: #3171e0;
--ion-color-primary-tint: #4c8dff;
/* Secondary */
--ion-color-secondary: #3dc2ff;
/* Custom colors */
--ion-color-brand: #ff6b35;
--ion-color-brand-rgb: 255, 107, 53;
--ion-color-brand-contrast: #ffffff;
--ion-color-brand-shade: #e05e2f;
--ion-color-brand-tint: #ff7a49;
}
/* Dark mode */
@media (prefers-color-scheme: dark) {
:root {
--ion-background-color: #121212;
--ion-text-color: #ffffff;
--ion-color-step-50: #1e1e1e;
--ion-color-step-100: #2a2a2a;
}
}
/* iOS specific */
.ios {
--ion-toolbar-background: #f8f8f8;
}
/* Android specific */
.md {
--ion-toolbar-background: #ffffff;
}Custom Component Styling
/* Global styles */
ion-content {
--background: var(--ion-background-color);
}
ion-card {
--background: #ffffff;
border-radius: 16px;
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1);
}
/* Platform-specific */
.ios ion-toolbar {
--border-width: 0;
}
.md ion-toolbar {
--border-width: 0 0 1px 0;
}Platform-Specific Code
Detect Platform
import { isPlatform } from '@ionic/react';
// Check platform
if (isPlatform('ios')) {
// iOS-specific code
}
if (isPlatform('android')) {
// Android-specific code
}
if (isPlatform('hybrid')) {
// Running in native app
}
if (isPlatform('mobileweb')) {
// Running in mobile browser
}Conditional Rendering
import { isPlatform, IonIcon } from '@ionic/react';
import { chevronBack, arrowBack } from 'ionicons/icons';
function BackButton() {
return (
<IonIcon
icon={isPlatform('ios') ? chevronBack : arrowBack}
/>
);
}Best Practices
Performance
// Use IonVirtualScroll for long lists
import { IonVirtualScroll } from '@ionic/react';
<IonVirtualScroll
items={items}
renderItem={(item) => (
<IonItem key={item.id}>
<IonLabel>{item.name}</IonLabel>
</IonItem>
)}
/>
// Lazy load images
<IonImg src={url} /> // Automatically lazy loadsAccessibility
// Always provide labels
<IonButton aria-label="Delete item">
<IonIcon slot="icon-only" icon={trash} />
</IonButton>
// Use semantic elements
<IonItem button role="link">
<IonLabel>Clickable item</IonLabel>
</IonItem>Safe Area
// Content respects safe areas by default
<IonContent>
{/* Auto padding for notch/home indicator */}
</IonContent>
// Custom safe area handling
<div style={{ paddingTop: 'env(safe-area-inset-top)' }}>
Custom header
</div>Resources
- Ionic Documentation: https://ionicframework.com/docs
- Ionic Components: https://ionicframework.com/docs/components
- Ionicons: https://ionic.io/ionicons
- Color Generator: https://ionicframework.com/docs/theming/color-generator
{
"version": "1.0.0",
"organization": "Capgo",
"date": "January 2026",
"abstract": "Comprehensive guide to using Ionic Framework for building native-looking Capacitor apps. Covers components, navigation patterns, theming, platform-specific styling, and mobile UI best practices.",
"triggers": [
"ionic component",
"ionic ui",
"mobile ui",
"native look",
"ionic theming",
"ion-button",
"ion-list"
],
"references": [
"https://ionicframework.com/docs",
"https://ionicframework.com/docs/components",
"https://ionic.io/ionicons"
]
}
Related skills
How it compares
Pick ionic-design when the stack is Ionic plus Capacitor and you need UI and navigation patterns, not native-only or React Native screen guidance.
FAQ
What does ionic-design help with?
ionic-design helps developers apply Ionic component patterns, mobile layouts, and accessible hybrid UI when building Capacitor app screens and navigation, keeping cross-platform interfaces consistent across iOS and Android.
When should I use ionic-design in a Capacitor project?
Use ionic-design when implementing Ionic screens, tabs, modals, lists, or routing in a Capacitor hybrid app and you want agent guidance aligned with Ionic UI conventions rather than generic web layouts.