Ionic Samples

Ionic hybrid mobile application framework examples including components, navigation, state management, and native integration

Key Facts

Category
Mobile Development
Items
1
Format Families
sample

Sample Overview

Ionic hybrid mobile application framework examples including components, navigation, state management, and native integration This sample set belongs to Mobile Development and can be used to test related workflows inside Elysia Tools.

💻 Ionic Hello World typescript

🟢 simple

Basic Ionic app examples with components, pages, routing, and fundamental concepts for Angular, React, and Vue

// Ionic Hello World Examples

// ============ IONIC ANGULAR EXAMPLES ============

// 1. Basic Ionic Angular App Structure
// src/app/app.component.ts
import { Component } from '@angular/core';
import { Platform } from '@ionic/angular';

@Component({
  selector: 'app-root',
  templateUrl: 'app.component.html',
  styleUrls: ['app.component.scss'],
})
export class AppComponent {
  constructor(private platform: Platform) {
    this.initializeApp();
  }

  initializeApp() {
    this.platform.ready().then(() => {
      console.log('Platform ready');
    });
  }
}

// src/app/app.component.html
<ion-app>
  <ion-router-outlet></ion-router-outlet>
</ion-app>

// 2. Basic Hello World Page
// src/app/pages/hello-world/hello-world.page.ts
import { Component } from '@angular/core';

@Component({
  selector: 'app-hello-world',
  templateUrl: './hello-world.page.html',
  styleUrls: ['./hello-world.page.scss'],
})
export class HelloWorldPage {
  title = 'Hello Ionic!';
  subtitle = 'Welcome to the hybrid mobile development framework';

  constructor() {}

  showMessage() {
    console.log('Hello from Ionic!');
  }
}

// src/app/pages/hello-world/hello-world.page.html
<ion-header [translucent]="true">
  <ion-toolbar>
    <ion-title>Hello World</ion-title>
  </ion-toolbar>
</ion-header>

<ion-content [fullscreen]="true">
  <ion-header collapse="condense">
    <ion-toolbar>
      <ion-title size="large">{{ title }}</ion-title>
    </ion-toolbar>
  </ion-header>

  <div class="ion-padding">
    <h1>{{ title }}</h1>
    <p>{{ subtitle }}</p>

    <ion-button expand="block" (click)="showMessage()">
      <ion-icon slot="start" name="hand-left-outline"></ion-icon>
      Say Hello
    </ion-button>
  </div>
</ion-content>

// src/app/pages/hello-world/hello-world.page.scss
ion-content {
  --background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
}

h1 {
  color: #fff;
  text-align: center;
  margin-bottom: 20px;
}

p {
  color: rgba(255, 255, 255, 0.8);
  text-align: center;
  margin-bottom: 30px;
}

ion-button {
  margin-top: 20px;
}

// 3. Ionic Angular Counter Component
// src/app/components/counter/counter.component.ts
import { Component, Input } from '@angular/core';

@Component({
  selector: 'app-counter',
  templateUrl: './counter.component.html',
  styleUrls: ['./counter.component.scss'],
})
export class CounterComponent {
  @Input() initialValue: number = 0;
  count: number = 0;

  constructor() {
    this.count = this.initialValue;
  }

  increment() {
    this.count++;
  }

  decrement() {
    this.count--;
  }

  reset() {
    this.count = this.initialValue;
  }
}

// src/app/components/counter/counter.component.html
<div class="counter-container">
  <h2>Counter: {{ count }}</h2>

  <div class="button-group">
    <ion-button color="danger" (click)="decrement()">
      <ion-icon name="remove"></ion-icon>
    </ion-button>

    <ion-button color="warning" (click)="reset()">
      <ion-icon name="refresh"></ion-icon>
    </ion-button>

    <ion-button color="success" (click)="increment()">
      <ion-icon name="add"></ion-icon>
    </ion-button>
  </div>
</div>

// src/app/components/counter/counter.component.scss
.counter-container {
  text-align: center;
  padding: 20px;

  h2 {
    color: #fff;
    margin-bottom: 20px;
  }

  .button-group {
    display: flex;
    justify-content: center;
    gap: 10px;
  }
}

// 4. Interactive User Profile
// src/app/pages/profile/profile.page.ts
import { Component } from '@angular/core';

@Component({
  selector: 'app-profile',
  templateUrl: './profile.page.html',
  styleUrls: ['./profile.page.scss'],
})
export class ProfilePage {
  user = {
    name: 'John Doe',
    email: '[email protected]',
    age: 28,
    bio: 'Mobile app developer passionate about hybrid apps',
    avatar: 'https://via.placeholder.com/150'
  };

  isEditing = false;
  editUser = { ...this.user };

  constructor() {}

  toggleEdit() {
    this.isEditing = !this.isEditing;
    if (!this.isEditing) {
      this.editUser = { ...this.user };
    }
  }

  saveProfile() {
    this.user = { ...this.editUser };
    this.isEditing = false;
  }

  cancelEdit() {
    this.editUser = { ...this.user };
    this.isEditing = false;
  }
}

// src/app/pages/profile/profile.page.html
<ion-header [translucent]="true">
  <ion-toolbar>
    <ion-buttons slot="end">
      <ion-button (click)="toggleEdit()">
        <ion-icon [name]="isEditing ? 'save' : 'create'"></ion-icon>
      </ion-button>
    </ion-buttons>
    <ion-title>User Profile</ion-title>
  </ion-toolbar>
</ion-header>

<ion-content [fullscreen]="true">
  <div class="ion-padding">
    <!-- Avatar Section -->
    <div class="avatar-section">
      <ion-avatar>
        <img [src]="user.avatar" [alt]="user.name">
      </ion-avatar>

      <ion-chip color="primary">
        <ion-icon name="star"></ion-icon>
        <ion-label>Pro User</ion-label>
      </ion-chip>
    </div>

    <!-- User Information -->
    <ion-card>
      <ion-card-header>
        <ion-card-title>User Information</ion-card-title>
      </ion-card-header>

      <ion-card-content>
        <ion-list>
          <ion-item>
            <ion-label position="stacked">Name</ion-label>
            <ion-input
              *ngIf="isEditing"
              [(ngModel)]="editUser.name"
              type="text">
            </ion-input>
            <h3 *ngIf="!isEditing">{{ user.name }}</h3>
          </ion-item>

          <ion-item>
            <ion-label position="stacked">Email</ion-label>
            <ion-input
              *ngIf="isEditing"
              [(ngModel)]="editUser.email"
              type="email">
            </ion-input>
            <p *ngIf="!isEditing">{{ user.email }}</p>
          </ion-item>

          <ion-item>
            <ion-label position="stacked">Age</ion-label>
            <ion-input
              *ngIf="isEditing"
              [(ngModel)]="editUser.age"
              type="number">
            </ion-input>
            <p *ngIf="!isEditing">{{ user.age }} years old</p>
          </ion-item>
        </ion-list>
      </ion-card-content>
    </ion-card>

    <!-- Bio Section -->
    <ion-card>
      <ion-card-header>
        <ion-card-title>About</ion-card-title>
      </ion-card-header>

      <ion-card-content>
        <ion-textarea
          *ngIf="isEditing"
          [(ngModel)]="editUser.bio"
          placeholder="Tell us about yourself..."
          rows="4">
        </ion-textarea>
        <p *ngIf="!isEditing">{{ user.bio }}</p>
      </ion-card-content>
    </ion-card>

    <!-- Action Buttons -->
    <div class="action-buttons" *ngIf="isEditing">
      <ion-button expand="block" color="success" (click)="saveProfile()">
        <ion-icon name="checkmark" slot="start"></ion-icon>
        Save Changes
      </ion-button>

      <ion-button expand="block" fill="outline" (click)="cancelEdit()">
        <ion-icon name="close" slot="start"></ion-icon>
        Cancel
      </ion-button>
    </div>
  </div>
</ion-content>

// ============ IONIC REACT EXAMPLES ============

// 1. Basic Ionic React App
// src/App.tsx
import React from 'react';
import { IonApp, IonRouterOutlet } from '@ionic/react';
import { IonReactRouter } from '@ionic/react-router';
import { Route, Redirect } from 'react-router-dom';

/* 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 that can be commented out */
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';

import HelloPage from './pages/HelloPage';
import CounterPage from './pages/CounterPage';
import ProfilePage from './pages/ProfilePage';

const App: React.FC = () => (
  <IonApp>
    <IonReactRouter>
      <IonRouterOutlet>
        <Route exact path="/hello" component={HelloPage} />
        <Route exact path="/counter" component={CounterPage} />
        <Route exact path="/profile" component={ProfilePage} />
        <Route exact path="/">
          <Redirect to="/hello" />
        </Route>
      </IonRouterOutlet>
    </IonReactRouter>
  </IonApp>
);

export default App;

// 2. Hello World Page with React
// src/pages/HelloPage.tsx
import React, { useState } from 'react';
import {
  IonContent,
  IonHeader,
  IonPage,
  IonTitle,
  IonToolbar,
  IonButton,
  IonIcon,
  IonCard,
  IonCardContent,
  IonCardHeader,
  IonCardTitle,
  IonItem,
  IonLabel,
  IonBadge,
  IonChip,
} from '@ionic/react';
import { heart, star, thumbsUp } from 'ionicons/icons';

const HelloPage: React.FC = () => {
  const [likeCount, setLikeCount] = useState(0);
  const [isLiked, setIsLiked] = useState(false);

  const handleLike = () => {
    setLikeCount(prev => prev + (isLiked ? -1 : 1));
    setIsLiked(!isLiked);
  };

  return (
    <IonPage>
      <IonHeader>
        <IonToolbar>
          <IonTitle>Hello Ionic React</IonTitle>
        </IonToolbar>
      </IonHeader>

      <IonContent fullscreen>
        <IonHeader collapse="condense">
          <IonToolbar>
            <IonTitle size="large">Welcome</IonTitle>
          </IonToolbar>
        </IonHeader>

        <div className="ion-padding">
          <div className="welcome-section">
            <h1>Hello, Ionic!</h1>
            <p>Welcome to the hybrid mobile framework with React</p>

            <IonChip color="primary">
              <IonIcon icon={star} />
              <IonLabel>React</IonLabel>
            </IonChip>

            <IonChip color="secondary">
              <IonIcon icon={heart} />
              <IonLabel>TypeScript</IonLabel>
            </IonChip>
          </div>

          <IonCard>
            <IonCardHeader>
              <IonCardTitle>Interactive Demo</IonCardTitle>
            </IonCardHeader>

            <IonCardContent>
              <IonItem>
                <IonLabel>
                  <h3>Like this page!</h3>
                  <p>Click the button to show your appreciation</p>
                </IonLabel>
                <IonBadge color="primary">{likeCount}</IonBadge>
              </IonItem>

              <div className="button-container">
                <IonButton
                  expand="block"
                  fill={isLiked ? "solid" : "outline"}
                  color={isLiked ? "danger" : "primary"}
                  onClick={handleLike}
                >
                  <IonIcon icon={thumbsUp} slot="start" />
                  {isLiked ? 'Liked!' : 'Like'}
                </IonButton>
              </div>
            </IonCardContent>
          </IonCard>

          <IonCard>
            <IonCardHeader>
              <IonCardTitle>Features</IonCardTitle>
            </IonCardHeader>

            <IonCardContent>
              <IonItem>
                <IonIcon icon={heart} color="danger" slot="start" />
                <IonLabel>Cross-platform development</IonLabel>
              </IonItem>

              <IonItem>
                <IonIcon icon={star} color="warning" slot="start" />
                <IonLabel>Beautiful UI components</IonLabel>
              </IonItem>

              <IonItem>
                <IonIcon icon={thumbsUp} color="success" slot="start" />
                <IonLabel>Native app performance</IonLabel>
              </IonItem>
            </IonCardContent>
          </IonCard>
        </div>
      </IonContent>
    </IonPage>
  );
};

export default HelloPage;

// 3. Counter Component with React Hooks
// src/pages/CounterPage.tsx
import React, { useState, useEffect } from 'react';
import {
  IonContent,
  IonHeader,
  IonPage,
  IonTitle,
  IonToolbar,
  IonButton,
  IonIcon,
  IonCard,
  IonCardContent,
  IonCardHeader,
  IonCardTitle,
  IonItem,
  IonLabel,
  IonGrid,
  IonRow,
  IonCol,
  IonRange,
  IonProgressBar,
  IonChip,
} from '@ionic/react';
import { add, remove, refresh, stats } from 'ionicons/icons';

interface CounterHistory {
  id: number;
  action: string;
  value: number;
  timestamp: Date;
}

const CounterPage: React.FC = () => {
  const [count, setCount] = useState(0);
  const [step, setStep] = useState(1);
  const [history, setHistory] = useState<CounterHistory[]>([]);
  const [maxValue, setMaxValue] = useState(100);

  useEffect(() => {
    // Calculate progress
    const progress = (Math.abs(count) / maxValue) * 100;
    console.log(`Progress: ${progress}%`);
  }, [count, maxValue]);

  const addToHistory = (action: string, value: number) => {
    const newEntry: CounterHistory = {
      id: Date.now(),
      action,
      value,
      timestamp: new Date(),
    };
    setHistory(prev => [newEntry, ...prev].slice(0, 10));
  };

  const increment = () => {
    const newValue = count + step;
    setCount(newValue);
    addToHistory('increment', newValue);
  };

  const decrement = () => {
    const newValue = count - step;
    setCount(newValue);
    addToHistory('decrement', newValue);
  };

  const reset = () => {
    setCount(0);
    addToHistory('reset', 0);
  };

  const getCountColor = () => {
    if (count > 0) return 'success';
    if (count < 0) return 'danger';
    return 'primary';
  };

  const getProgress = () => {
    const progress = (Math.abs(count) / maxValue) * 100;
    return Math.min(progress, 100);
  };

  return (
    <IonPage>
      <IonHeader>
        <IonToolbar>
          <IonTitle>Counter</IonTitle>
        </IonToolbar>
      </IonHeader>

      <IonContent fullscreen>
        <IonHeader collapse="condense">
          <IonToolbar>
            <IonTitle size="large">Interactive Counter</IonTitle>
          </IonToolbar>
        </IonHeader>

        <div className="ion-padding">
          <IonCard>
            <IonCardHeader>
              <IonCardTitle>Counter Value</IonCardTitle>
            </IonCardHeader>

            <IonCardContent>
              <div className="counter-display">
                <IonChip color={getCountColor()}>
                  <IonIcon icon={stats} />
                  <IonLabel>{count}</IonLabel>
                </IonChip>
              </div>

              <IonProgressBar
                value={getProgress() / 100}
                color={getCountColor()}
                className="ion-margin-top"
              />

              <p className="ion-text-center">
                Progress: {getProgress().toFixed(1)}%
              </p>
            </IonCardContent>
          </IonCard>

          <IonCard>
            <IonCardHeader>
              <IonCardTitle>Controls</IonCardTitle>
            </IonCardHeader>

            <IonCardContent>
              <IonItem>
                <IonLabel position="stacked">Step Size</IonLabel>
                <IonRange
                  min={1}
                  max={10}
                  value={step}
                  onIonChange={e => setStep(parseInt(e.detail.value as string))}
                  snaps
                  ticks
                >
                  <IonLabel slot="start">{step}</IonLabel>
                  <IonLabel slot="end">{step}</IonLabel>
                </IonRange>
              </IonItem>

              <IonItem>
                <IonLabel position="stacked">Max Value</IonLabel>
                <IonRange
                  min={50}
                  max={200}
                  step={10}
                  value={maxValue}
                  onIonChange={e => setMaxValue(parseInt(e.detail.value as string))}
                  snaps
                >
                  <IonLabel slot="start">{maxValue}</IonLabel>
                  <IonLabel slot="end">{maxValue}</IonLabel>
                </IonRange>
              </IonItem>

              <IonGrid>
                <IonRow>
                  <IonCol>
                    <IonButton
                      expand="block"
                      color="danger"
                      onClick={decrement}
                      disabled={count <= -maxValue}
                    >
                      <IonIcon icon={remove} slot="start" />
                      Decrease
                    </IonButton>
                  </IonCol>

                  <IonCol>
                    <IonButton
                      expand="block"
                      color="warning"
                      onClick={reset}
                    >
                      <IonIcon icon={refresh} slot="start" />
                      Reset
                    </IonButton>
                  </IonCol>

                  <IonCol>
                    <IonButton
                      expand="block"
                      color="success"
                      onClick={increment}
                      disabled={count >= maxValue}
                    >
                      <IonIcon icon={add} slot="start" />
                      Increase
                    </IonButton>
                  </IonCol>
                </IonRow>
              </IonGrid>
            </IonCardContent>
          </IonCard>

          <IonCard>
            <IonCardHeader>
              <IonCardTitle>History</IonCardTitle>
            </IonCardHeader>

            <IonCardContent>
              {history.length > 0 ? (
                history.map(item => (
                  <IonItem key={item.id}>
                    <IonLabel>
                      <h3>{item.action}</h3>
                      <p>New value: {item.value}</p>
                    </IonLabel>
                    <IonLabel slot="end">
                      {item.timestamp.toLocaleTimeString()}
                    </IonLabel>
                  </IonItem>
                ))
              ) : (
                <p className="ion-text-center ion-color-medium">
                  No actions yet. Start counting!
                </p>
              )}
            </IonCardContent>
          </IonCard>
        </div>
      </IonContent>
    </IonPage>
  );
};

export default CounterPage;

// ============ IONIC VUE EXAMPLES ============

// 1. Basic Ionic Vue App
// src/main.ts
import { createApp } from 'vue';
import { IonicVue } from '@ionic/vue';
import router from './router';

import App from './App.vue';

import '@ionic/vue/css/core.css';
import '@ionic/vue/css/normalize.css';
import '@ionic/vue/css/structure.css';
import '@ionic/vue/css/typography.css';
import '@ionic/vue/css/padding.css';
import '@ionic/vue/css/float-elements.css';
import '@ionic/vue/css/text-alignment.css';
import '@ionic/vue/css/text-transformation.css';
import '@ionic/vue/css/flex-utils.css';
import '@ionic/vue/css/display.css';

const app = createApp(App).use(IonicVue).use(router);
app.mount('#app');

// 2. Hello World Page with Vue 3 Composition API
// src/views/HelloWorld.vue
<template>
  <ion-page>
    <ion-header :translucent="true">
      <ion-toolbar>
        <ion-title>Hello Ionic Vue</ion-title>
      </ion-toolbar>
    </ion-header>

    <ion-content :fullscreen="true">
      <ion-header collapse="condense">
        <ion-toolbar>
          <ion-title size="large">{{ title }}</ion-title>
        </ion-toolbar>
      </ion-header>

      <div class="ion-padding">
        <div class="welcome-container">
          <h1>{{ title }}</h1>
          <p>{{ subtitle }}</p>

          <ion-chip color="primary">
            <ion-icon :icon="starOutline" />
            <ion-label>Vue 3</ion-label>
          </ion-chip>

          <ion-chip color="secondary">
            <ion-icon :icon="codeSlash" />
            <ion-label>TypeScript</ion-label>
          </ion-chip>

          <ion-chip color="tertiary">
            <ion-icon :icon="phonePortrait" />
            <ion-label>Mobile</ion-label>
          </ion-chip>
        </div>

        <ion-card>
          <ion-card-header>
            <ion-card-title>Interactive Features</ion-card-title>
          </ion-card-header>

          <ion-card-content>
            <ion-list>
              <ion-item>
                <ion-thumbnail slot="start">
                  <img src="https://via.placeholder.com/50" alt="Feature 1" />
                </ion-thumbnail>
                <ion-label>
                  <h3>Cross-platform</h3>
                  <p>Build once, deploy everywhere</p>
                </ion-label>
              </ion-item>

              <ion-item>
                <ion-thumbnail slot="start">
                  <img src="https://via.placeholder.com/50" alt="Feature 2" />
                </ion-thumbnail>
                <ion-label>
                  <h3>Native Performance</h3>
                  <p>Fast, smooth user experience</p>
                </ion-label>
              </ion-item>
            </ion-list>

            <div class="button-group">
              <ion-button
                expand="block"
                color="primary"
                @click="showAlert"
              >
                <ion-icon :icon="heart" slot="start" />
                Show Alert
              </ion-button>

              <ion-button
                expand="block"
                fill="outline"
                color="secondary"
                @click="navigateToCounter"
              >
                <ion-icon :icon="trendingUp" slot="start" />
                Try Counter
              </ion-button>
            </div>
          </ion-card-content>
        </ion-card>
      </div>
    </ion-content>
  </ion-page>
</template>

<script setup lang="ts">
import { ref } from 'vue';
import {
  alertController,
  IonContent,
  IonHeader,
  IonPage,
  IonTitle,
  IonToolbar,
  IonChip,
  IonLabel,
  IonIcon,
  IonCard,
  IonCardHeader,
  IonCardTitle,
  IonCardContent,
  IonList,
  IonItem,
  IonThumbnail,
  IonButton
} from '@ionic/vue';
import { useRouter } from 'vue-router';
import {
  starOutline,
  codeSlash,
  phonePortrait,
  heart,
  trendingUp
} from 'ionicons/icons';

const router = useRouter();
const title = ref('Hello, Ionic!');
const subtitle = ref('Welcome to the hybrid mobile development framework with Vue 3');

const showAlert = async () => {
  const alert = await alertController.create({
    header: 'Welcome!',
    message: 'This is an Ionic alert dialog in Vue 3!',
    buttons: ['OK'],
  });

  await alert.present();
};

const navigateToCounter = () => {
  router.push('/counter');
};
</script>

<style scoped>
.welcome-container {
  text-align: center;
  margin-bottom: 30px;
}

.welcome-container h1 {
  color: #fff;
  margin-bottom: 10px;
}

.welcome-container p {
  color: rgba(255, 255, 255, 0.8);
  margin-bottom: 20px;
}

.button-group {
  margin-top: 20px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

ion-content {
  --background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
}
</style>

// 3. Reactive Counter with Vue Composition API
// src/views/Counter.vue
<template>
  <ion-page>
    <ion-header :translucent="true">
      <ion-toolbar>
        <ion-title>Counter</ion-title>
      </ion-toolbar>
    </ion-header>

    <ion-content :fullscreen="true">
      <div class="ion-padding">
        <ion-card>
          <ion-card-header>
            <ion-card-title>Reactive Counter</ion-card-title>
          </ion-card-header>

          <ion-card-content>
            <div class="counter-display">
              <ion-chip :color="counterColor">
                <ion-icon :icon="stats" />
                <ion-label>{{ count }}</ion-label>
              </ion-chip>
            </div>

            <ion-progress-bar
              :value="progress"
              :color="counterColor"
              class="ion-margin-top"
            />

            <p class="ion-text-center">
              {{ progressText }}
            </p>
          </ion-card-content>
        </ion-card>

        <ion-card>
          <ion-card-header>
            <ion-card-title>Statistics</ion-cardTitle>
          </ion-card-header>

          <ion-card-content>
            <ion-grid>
              <ion-row>
                <ion-col>
                  <div class="stat-item">
                    <h2>{{ incrementCount }}</h2>
                    <p>Increments</p>
                  </div>
                </ion-col>

                <ion-col>
                  <div class="stat-item">
                    <h2>{{ decrementCount }}</h2>
                    <p>Decrements</p>
                  </div>
                </ion-col>

                <ion-col>
                  <div class="stat-item">
                    <h2>{{ resetCount }}</h2>
                    <p>Resets</p>
                  </div>
                </ion-col>
              </ion-row>
            </ion-grid>
          </ion-card-content>
        </ion-card>

        <ion-card>
          <ion-card-header>
            <ion-cardTitle>Controls</ion-cardTitle>
          </ion-cardHeader>

          <ion-cardContent>
            <ion-range
              v-model="stepSize"
              :min="1"
              :max="10"
              :step="1"
              :snaps="true"
              :ticks="true"
            >
              <ion-label slot="start">Step: {{ stepSize }}</ion-label>
              <ion-label slot="end">{{ stepSize }}</ion-label>
            </ion-range>

            <ion-grid class="ion-margin-top">
              <ion-row>
                <ion-col>
                  <ion-button
                    expand="block"
                    color="danger"
                    @click="decrement"
                    :disabled="count <= -maxValue"
                  >
                    <ion-icon :icon="remove" slot="start" />
                    Decrease
                  </ion-button>
                </ion-col>

                <ion-col>
                  <ion-button
                    expand="block"
                    color="warning"
                    @click="reset"
                  >
                    <ion-icon :icon="refresh" slot="start" />
                    Reset
                  </ion-button>
                </ion-col>

                <ion-col>
                  <ion-button
                    expand="block"
                    color="success"
                    @click="increment"
                    :disabled="count >= maxValue"
                  >
                    <ion-icon :icon="add" slot="start" />
                    Increase
                  </ion-button>
                </ion-col>
              </ion-row>
            </ion-grid>
          </ion-card-content>
        </ion-card>
      </div>
    </ion-content>
  </ion-page>
</template>

<script setup lang="ts">
import { ref, computed } from 'vue';
import {
  IonContent,
  IonHeader,
  IonPage,
  IonTitle,
  IonToolbar,
  IonCard,
  IonCardHeader,
  IonCardTitle,
  IonCardContent,
  IonChip,
  IonLabel,
  IonIcon,
  IonProgressBar,
  IonGrid,
  IonRow,
  IonCol,
  IonRange,
  IonButton
} from '@ionic/vue';
import {
  stats,
  add,
  remove,
  refresh
} from 'ionicons/icons';

// Reactive state
const count = ref(0);
const stepSize = ref(1);
const maxValue = ref(100);

// Statistics
const incrementCount = ref(0);
const decrementCount = ref(0);
const resetCount = ref(0);

// Computed properties
const counterColor = computed(() => {
  if (count.value > 0) return 'success';
  if (count.value < 0) return 'danger';
  return 'primary';
});

const progress = computed(() => {
  const progressValue = (Math.abs(count.value) / maxValue.value) * 100;
  return Math.min(progressValue / 100, 1);
});

const progressText = computed(() => {
  const progressValue = (Math.abs(count.value) / maxValue.value) * 100;
  return `Progress: ${progressValue.toFixed(1)}%`;
});

// Methods
const increment = () => {
  if (count.value < maxValue.value) {
    count.value += stepSize.value;
    incrementCount.value++;
  }
};

const decrement = () => {
  if (count.value > -maxValue.value) {
    count.value -= stepSize.value;
    decrementCount.value++;
  }
};

const reset = () => {
  count.value = 0;
  resetCount.value++;
};
</script>

<style scoped>
.counter-display {
  text-align: center;
  margin: 20px 0;
}

.stat-item {
  text-align: center;
}

.stat-item h2 {
  margin: 0;
  font-size: 24px;
  font-weight: bold;
}

.stat-item p {
  margin: 4px 0 0 0;
  color: var(--ion-color-medium);
}
</style>

// ============ SHARED TYPES AND INTERFACES ============

// types/interfaces.ts
export interface User {
  id: string;
  name: string;
  email: string;
  age: number;
  bio: string;
  avatar?: string;
}

export interface TodoItem {
  id: string;
  title: string;
  description: string;
  completed: boolean;
  createdAt: Date;
  dueDate?: Date;
  priority: 'low' | 'medium' | 'high';
}

export interface CounterState {
  count: number;
  step: number;
  maxValue: number;
  history: HistoryEntry[];
}

export interface HistoryEntry {
  id: string;
  action: 'increment' | 'decrement' | 'reset';
  value: number;
  timestamp: Date;
}

// ============ ROUTING CONFIGURATION ============

// Angular Routing - app-routing.module.ts
import { NgModule } from '@angular/core';
import { PreloadAllModules, RouterModule, Routes } from '@angular/router';

const routes: Routes = [
  {
    path: 'home',
    loadChildren: () => import('./home/home.module').then( m => m.HomePageModule)
  },
  {
    path: '',
    redirectTo: 'home',
    pathMatch: 'full'
  },
];

@NgModule({
  imports: [
    RouterModule.forRoot(routes, { preloadingStrategy: PreloadAllModules })
  ],
  exports: [RouterModule]
})
export class AppRoutingModule { }

// React Routing - App.tsx (shown above)
// Vue Router - router/index.ts (shown above)

// ============ MAIN ENTRIES ============

// Use these main functions to run different framework examples:

// For Angular:
// npm run start (in Ionic Angular project)

// For React:
// npm run start (in Ionic React project)

// For Vue:
// npm run dev (in Ionic Vue project)