update,
This commit is contained in:
@@ -0,0 +1,52 @@
|
||||
import {
|
||||
IonButton,
|
||||
IonButtons,
|
||||
IonCol,
|
||||
IonContent,
|
||||
IonHeader,
|
||||
IonIcon,
|
||||
IonPage,
|
||||
IonRow,
|
||||
IonTitle,
|
||||
IonToolbar,
|
||||
useIonRouter,
|
||||
} from '@ionic/react';
|
||||
|
||||
import ExploreContainer from '../components/ExploreContainer';
|
||||
import { chevronBackOutline, refreshOutline } from 'ionicons/icons';
|
||||
|
||||
import './Tab1.css';
|
||||
|
||||
const Tab1 = () => {
|
||||
const router = useIonRouter();
|
||||
|
||||
function handleBackClick() {
|
||||
window.location.href = '/tabs/demo-list';
|
||||
}
|
||||
|
||||
return (
|
||||
<IonPage>
|
||||
<IonHeader>
|
||||
<IonToolbar>
|
||||
<IonTitle>Home</IonTitle>
|
||||
|
||||
<IonButtons slot="start">
|
||||
<IonButton onClick={() => handleBackClick()}>
|
||||
<IonIcon icon={chevronBackOutline} color="primary" />
|
||||
</IonButton>
|
||||
</IonButtons>
|
||||
</IonToolbar>
|
||||
</IonHeader>
|
||||
<IonContent fullscreen>
|
||||
<IonHeader collapse="condense">
|
||||
<IonToolbar>
|
||||
<IonTitle size="large">Home</IonTitle>
|
||||
</IonToolbar>
|
||||
</IonHeader>
|
||||
<ExploreContainer name="Home page" />
|
||||
</IonContent>
|
||||
</IonPage>
|
||||
);
|
||||
};
|
||||
|
||||
export default Tab1;
|
@@ -0,0 +1,25 @@
|
||||
import { IonContent, IonHeader, IonPage, IonTitle, IonToolbar } from '@ionic/react';
|
||||
import ExploreContainer from '../components/ExploreContainer';
|
||||
import './Tab2.css';
|
||||
|
||||
const Tab2 = () => {
|
||||
return (
|
||||
<IonPage>
|
||||
<IonHeader>
|
||||
<IonToolbar>
|
||||
<IonTitle>Profile</IonTitle>
|
||||
</IonToolbar>
|
||||
</IonHeader>
|
||||
<IonContent fullscreen>
|
||||
<IonHeader collapse="condense">
|
||||
<IonToolbar>
|
||||
<IonTitle size="large">Profile</IonTitle>
|
||||
</IonToolbar>
|
||||
</IonHeader>
|
||||
<ExploreContainer name="Profile page" />
|
||||
</IonContent>
|
||||
</IonPage>
|
||||
);
|
||||
};
|
||||
|
||||
export default Tab2;
|
@@ -0,0 +1,25 @@
|
||||
import { IonContent, IonHeader, IonPage, IonTitle, IonToolbar } from '@ionic/react';
|
||||
import ExploreContainer from '../components/ExploreContainer';
|
||||
import './Tab3.css';
|
||||
|
||||
const Tab3 = () => {
|
||||
return (
|
||||
<IonPage>
|
||||
<IonHeader>
|
||||
<IonToolbar>
|
||||
<IonTitle>Settings</IonTitle>
|
||||
</IonToolbar>
|
||||
</IonHeader>
|
||||
<IonContent fullscreen>
|
||||
<IonHeader collapse="condense">
|
||||
<IonToolbar>
|
||||
<IonTitle size="large">Settings</IonTitle>
|
||||
</IonToolbar>
|
||||
</IonHeader>
|
||||
<ExploreContainer name="Settings page" />
|
||||
</IonContent>
|
||||
</IonPage>
|
||||
);
|
||||
};
|
||||
|
||||
export default Tab3;
|
6
03_source/mobile/src/pages/DemoReactSwitchTabs/NOTES.md
Normal file
6
03_source/mobile/src/pages/DemoReactSwitchTabs/NOTES.md
Normal file
@@ -0,0 +1,6 @@
|
||||
# NOTE
|
||||
|
||||
## TODO
|
||||
|
||||
hardcoded back button,
|
||||
tab collision with the main app
|
@@ -0,0 +1,24 @@
|
||||
.container {
|
||||
text-align: center;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
|
||||
.container strong {
|
||||
font-size: 20px;
|
||||
line-height: 26px;
|
||||
}
|
||||
|
||||
.container p {
|
||||
font-size: 16px;
|
||||
line-height: 22px;
|
||||
color: #8c8c8c;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.container a {
|
||||
text-decoration: none;
|
||||
}
|
@@ -0,0 +1,11 @@
|
||||
import './ExploreContainer.css';
|
||||
|
||||
const ExploreContainer = ({ name }) => {
|
||||
return (
|
||||
<div className="container">
|
||||
<strong>{name}</strong>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default ExploreContainer;
|
@@ -0,0 +1,125 @@
|
||||
import {
|
||||
CreateAnimation,
|
||||
IonIcon,
|
||||
IonLabel,
|
||||
IonRouterOutlet,
|
||||
IonTabBar,
|
||||
IonTabButton,
|
||||
IonTabs,
|
||||
} from '@ionic/react';
|
||||
import { IonReactRouter } from '@ionic/react-router';
|
||||
import { home, person, settings } from 'ionicons/icons';
|
||||
import Tab1 from '../AppPages/Tab1';
|
||||
import Tab2 from '../AppPages/Tab2';
|
||||
import Tab3 from '../AppPages/Tab3';
|
||||
import { useRef } from 'react';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { Redirect, Route } from 'react-router';
|
||||
|
||||
const SwitchTabBar = () => {
|
||||
const [activeTab, setActiveTab] = useState('tab0');
|
||||
const switchRefs = useRef([]);
|
||||
|
||||
const tabs = [
|
||||
{
|
||||
label: 'Home',
|
||||
url: '/home',
|
||||
icon: home,
|
||||
color: '#76b140',
|
||||
backgroundColor: '#ddf7c5',
|
||||
component: Tab1,
|
||||
},
|
||||
{
|
||||
label: 'Profile',
|
||||
url: '/profile',
|
||||
icon: person,
|
||||
color: '#e46062',
|
||||
backgroundColor: '#fcddde',
|
||||
component: Tab2,
|
||||
},
|
||||
{
|
||||
label: 'Settings',
|
||||
url: '/settings',
|
||||
icon: settings,
|
||||
color: '#3578e5',
|
||||
backgroundColor: '#e7f0ff',
|
||||
component: Tab3,
|
||||
},
|
||||
];
|
||||
|
||||
const revealAnimation = {
|
||||
property: 'transform',
|
||||
fromValue: 'translateX(-30px)',
|
||||
toValue: 'translateX(0px)',
|
||||
};
|
||||
|
||||
const switchAnimation = {
|
||||
duration: 200,
|
||||
direction: 'normal',
|
||||
iterations: '1',
|
||||
fromTo: [revealAnimation],
|
||||
easing: 'ease-in-out',
|
||||
};
|
||||
|
||||
const getTabButtonStyle = (tab) => {
|
||||
const tabStyle = {
|
||||
backgroundColor: tab.backgroundColor,
|
||||
color: tab.color,
|
||||
transition: '0.5s all ease-in-out',
|
||||
};
|
||||
|
||||
return tabStyle;
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const tabIndex = activeTab.match(/\d+/)[0];
|
||||
switchRefs.current[tabIndex].animation.play();
|
||||
}, [activeTab]);
|
||||
|
||||
return (
|
||||
<IonReactRouter>
|
||||
<IonTabs className="demo-react-switch-tabs">
|
||||
<IonRouterOutlet>
|
||||
{tabs.map((tab, index) => {
|
||||
return (
|
||||
<Route key={index} exact path={`/demo-react-switch-tabs${tab.url}`}>
|
||||
<tab.component />
|
||||
</Route>
|
||||
);
|
||||
})}
|
||||
|
||||
<Redirect exact path="/demo-react-switch-tabs" to="/demo-react-switch-tabs/home" />
|
||||
</IonRouterOutlet>
|
||||
|
||||
<IonTabBar slot="bottom" onIonTabsDidChange={(e) => setActiveTab(e.detail.tab)}>
|
||||
{tabs.map((tab, index) => {
|
||||
const tabStyle = getTabButtonStyle(tab);
|
||||
const isActive = activeTab === `tab${index}`;
|
||||
|
||||
return (
|
||||
<IonTabButton
|
||||
key={index}
|
||||
style={isActive ? tabStyle : {}}
|
||||
tab={`tab${index}`}
|
||||
href={`/demo-react-switch-tabs${tab.url}`}
|
||||
>
|
||||
<IonIcon icon={tab.icon} />
|
||||
|
||||
{isActive && (
|
||||
<CreateAnimation
|
||||
ref={(ref) => (switchRefs.current[index] = ref)}
|
||||
{...switchAnimation}
|
||||
>
|
||||
<IonLabel>{tab.label}</IonLabel>
|
||||
</CreateAnimation>
|
||||
)}
|
||||
</IonTabButton>
|
||||
);
|
||||
})}
|
||||
</IonTabBar>
|
||||
</IonTabs>
|
||||
</IonReactRouter>
|
||||
);
|
||||
};
|
||||
|
||||
export default SwitchTabBar;
|
20
03_source/mobile/src/pages/DemoReactSwitchTabs/index.tsx
Normal file
20
03_source/mobile/src/pages/DemoReactSwitchTabs/index.tsx
Normal file
@@ -0,0 +1,20 @@
|
||||
import { IonIcon, IonLabel, IonRouterOutlet, IonTabBar, IonTabButton, IonTabs } from '@ionic/react';
|
||||
|
||||
import { cloudOutline, searchOutline } from 'ionicons/icons';
|
||||
import { Route, Redirect } from 'react-router';
|
||||
|
||||
import Tab1 from './AppPages/Tab1';
|
||||
import Tab2 from './AppPages/Tab2';
|
||||
import SwitchTabBar from './components/SwitchTabBar';
|
||||
|
||||
import './style.scss';
|
||||
|
||||
function DemoReactSwitchTabs() {
|
||||
return (
|
||||
<>
|
||||
<SwitchTabBar />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export default DemoReactSwitchTabs;
|
97
03_source/mobile/src/pages/DemoReactSwitchTabs/style.scss
Normal file
97
03_source/mobile/src/pages/DemoReactSwitchTabs/style.scss
Normal file
@@ -0,0 +1,97 @@
|
||||
.demo-react-switch-tabs {
|
||||
/* Ionic Variables and Theming. For more info, please see:
|
||||
http://ionicframework.com/docs/theming/ */
|
||||
|
||||
/** Ionic CSS Variables **/
|
||||
:root {
|
||||
/** primary **/
|
||||
--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;
|
||||
|
||||
/** secondary **/
|
||||
--ion-color-secondary: #3dc2ff;
|
||||
--ion-color-secondary-rgb: 61, 194, 255;
|
||||
--ion-color-secondary-contrast: #ffffff;
|
||||
--ion-color-secondary-contrast-rgb: 255, 255, 255;
|
||||
--ion-color-secondary-shade: #36abe0;
|
||||
--ion-color-secondary-tint: #50c8ff;
|
||||
|
||||
/** tertiary **/
|
||||
--ion-color-tertiary: #5260ff;
|
||||
--ion-color-tertiary-rgb: 82, 96, 255;
|
||||
--ion-color-tertiary-contrast: #ffffff;
|
||||
--ion-color-tertiary-contrast-rgb: 255, 255, 255;
|
||||
--ion-color-tertiary-shade: #4854e0;
|
||||
--ion-color-tertiary-tint: #6370ff;
|
||||
|
||||
/** success **/
|
||||
--ion-color-success: #2dd36f;
|
||||
--ion-color-success-rgb: 45, 211, 111;
|
||||
--ion-color-success-contrast: #ffffff;
|
||||
--ion-color-success-contrast-rgb: 255, 255, 255;
|
||||
--ion-color-success-shade: #28ba62;
|
||||
--ion-color-success-tint: #42d77d;
|
||||
|
||||
/** warning **/
|
||||
--ion-color-warning: #ffc409;
|
||||
--ion-color-warning-rgb: 255, 196, 9;
|
||||
--ion-color-warning-contrast: #000000;
|
||||
--ion-color-warning-contrast-rgb: 0, 0, 0;
|
||||
--ion-color-warning-shade: #e0ac08;
|
||||
--ion-color-warning-tint: #ffca22;
|
||||
|
||||
/** danger **/
|
||||
--ion-color-danger: #eb445a;
|
||||
--ion-color-danger-rgb: 235, 68, 90;
|
||||
--ion-color-danger-contrast: #ffffff;
|
||||
--ion-color-danger-contrast-rgb: 255, 255, 255;
|
||||
--ion-color-danger-shade: #cf3c4f;
|
||||
--ion-color-danger-tint: #ed576b;
|
||||
|
||||
/** dark **/
|
||||
--ion-color-dark: #222428;
|
||||
--ion-color-dark-rgb: 34, 36, 40;
|
||||
--ion-color-dark-contrast: #ffffff;
|
||||
--ion-color-dark-contrast-rgb: 255, 255, 255;
|
||||
--ion-color-dark-shade: #1e2023;
|
||||
--ion-color-dark-tint: #383a3e;
|
||||
|
||||
/** medium **/
|
||||
--ion-color-medium: #92949c;
|
||||
--ion-color-medium-rgb: 146, 148, 156;
|
||||
--ion-color-medium-contrast: #ffffff;
|
||||
--ion-color-medium-contrast-rgb: 255, 255, 255;
|
||||
--ion-color-medium-shade: #808289;
|
||||
--ion-color-medium-tint: #9d9fa6;
|
||||
|
||||
/** light **/
|
||||
--ion-color-light: #f4f5f8;
|
||||
--ion-color-light-rgb: 244, 245, 248;
|
||||
--ion-color-light-contrast: #000000;
|
||||
--ion-color-light-contrast-rgb: 0, 0, 0;
|
||||
--ion-color-light-shade: #d7d8da;
|
||||
--ion-color-light-tint: #f5f6f9;
|
||||
}
|
||||
|
||||
ion-tab-bar {
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
ion-tab-button {
|
||||
flex-direction: row;
|
||||
border-radius: 20px;
|
||||
}
|
||||
|
||||
ion-tab-button ion-icon {
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
|
||||
ion-tab-button ion-label {
|
||||
margin-left: 1rem;
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user