update demo-react-switch-tabs,
This commit is contained in:
@@ -17,7 +17,7 @@ import { chevronBackOutline, refreshOutline } from 'ionicons/icons';
|
|||||||
|
|
||||||
import './Tab1.css';
|
import './Tab1.css';
|
||||||
|
|
||||||
const Tab1 = () => {
|
const Tab1 = (): React.JSX.Element => {
|
||||||
const router = useIonRouter();
|
const router = useIonRouter();
|
||||||
|
|
||||||
function handleBackClick() {
|
function handleBackClick() {
|
@@ -0,0 +1,25 @@
|
|||||||
|
import { IonContent, IonHeader, IonPage, IonTitle, IonToolbar } from '@ionic/react';
|
||||||
|
import ExploreContainer from '../components/ExploreContainer';
|
||||||
|
import './Tab2.css';
|
||||||
|
|
||||||
|
const Tab2 = (): React.JSX.Element => {
|
||||||
|
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 = (): React.JSX.Element => {
|
||||||
|
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;
|
@@ -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,15 @@
|
|||||||
|
import './ExploreContainer.css';
|
||||||
|
|
||||||
|
interface ExploreContainerProps {
|
||||||
|
name: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ExploreContainer = ({ name }: ExploreContainerProps): React.JSX.Element => {
|
||||||
|
return (
|
||||||
|
<div className="container">
|
||||||
|
<strong>{name}</strong>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ExploreContainer;
|
@@ -16,9 +16,24 @@ import { useRef } from 'react';
|
|||||||
import { useEffect, useState } from 'react';
|
import { useEffect, useState } from 'react';
|
||||||
import { Redirect, Route } from 'react-router';
|
import { Redirect, Route } from 'react-router';
|
||||||
|
|
||||||
const SwitchTabBar = () => {
|
interface TabItem {
|
||||||
|
label: string;
|
||||||
|
url: string;
|
||||||
|
icon: string;
|
||||||
|
color: string;
|
||||||
|
backgroundColor: string;
|
||||||
|
component: React.ComponentType;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface AnimationConfig {
|
||||||
|
property: string;
|
||||||
|
fromValue: string;
|
||||||
|
toValue: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const SwitchTabBar = (): React.JSX.Element => {
|
||||||
const [activeTab, setActiveTab] = useState('tab0');
|
const [activeTab, setActiveTab] = useState('tab0');
|
||||||
const switchRefs = useRef([]);
|
const switchRefs = useRef<(CreateAnimation | null)[]>([]);
|
||||||
|
|
||||||
const tabs = [
|
const tabs = [
|
||||||
{
|
{
|
||||||
@@ -61,8 +76,8 @@ const SwitchTabBar = () => {
|
|||||||
easing: 'ease-in-out',
|
easing: 'ease-in-out',
|
||||||
};
|
};
|
||||||
|
|
||||||
const getTabButtonStyle = (tab) => {
|
const getTabButtonStyle = (tab: TabItem): React.CSSProperties => {
|
||||||
const tabStyle = {
|
const tabStyle: React.CSSProperties = {
|
||||||
backgroundColor: tab.backgroundColor,
|
backgroundColor: tab.backgroundColor,
|
||||||
color: tab.color,
|
color: tab.color,
|
||||||
transition: '0.5s all ease-in-out',
|
transition: '0.5s all ease-in-out',
|
@@ -0,0 +1,121 @@
|
|||||||
|
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 '../pages/Tab1';
|
||||||
|
import Tab2 from '../pages/Tab2';
|
||||||
|
import Tab3 from '../pages/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>
|
||||||
|
<IonRouterOutlet>
|
||||||
|
|
||||||
|
{tabs.map((tab, index) => {
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Route key={index} exact path={tab.url}>
|
||||||
|
<tab.component />
|
||||||
|
</Route>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
|
||||||
|
<Route exact path="/">
|
||||||
|
<Redirect to="/home" />
|
||||||
|
</Route>
|
||||||
|
</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={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;
|
@@ -0,0 +1,25 @@
|
|||||||
|
import { IonContent, IonHeader, IonPage, IonTitle, IonToolbar } from '@ionic/react';
|
||||||
|
import ExploreContainer from '../components/ExploreContainer';
|
||||||
|
import './Tab1.css';
|
||||||
|
|
||||||
|
const Tab1 = () => {
|
||||||
|
return (
|
||||||
|
<IonPage>
|
||||||
|
<IonHeader>
|
||||||
|
<IonToolbar>
|
||||||
|
<IonTitle>Home</IonTitle>
|
||||||
|
</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,99 @@
|
|||||||
|
/* 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