update DemoReactThemeSwitcher,
This commit is contained in:
@@ -1,96 +0,0 @@
|
||||
import {
|
||||
IonButton,
|
||||
IonButtons,
|
||||
IonCol,
|
||||
IonContent,
|
||||
IonHeader,
|
||||
IonIcon,
|
||||
IonPage,
|
||||
IonRow,
|
||||
IonTitle,
|
||||
IonToolbar,
|
||||
useIonRouter,
|
||||
} from '@ionic/react';
|
||||
|
||||
import { Geolocation } from '@capacitor/geolocation';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { SkeletonDashboard } from '../TestComponents/SkeletonDashboard';
|
||||
import { chevronBackOutline, refreshOutline } from 'ionicons/icons';
|
||||
import { CurrentWeather } from '../TestComponents/CurrentWeather';
|
||||
|
||||
function Tab1() {
|
||||
const router = useIonRouter();
|
||||
|
||||
const [currentWeather, setCurrentWeather] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
getCurrentPosition();
|
||||
}, []);
|
||||
|
||||
const getCurrentPosition = async () => {
|
||||
setCurrentWeather(false);
|
||||
const coordinates = await Geolocation.getCurrentPosition();
|
||||
getAddress(coordinates.coords);
|
||||
};
|
||||
|
||||
const getAddress = async (coords) => {
|
||||
const query = `${coords.latitude},${coords.longitude}`;
|
||||
const response = await fetch(
|
||||
`https://api.weatherapi.com/v1/current.json?key=f93eb660b2424258bf5155016210712&q=${query}`
|
||||
);
|
||||
|
||||
const data = await response.json();
|
||||
console.log(data);
|
||||
setCurrentWeather(data);
|
||||
};
|
||||
|
||||
// const router = useIonRouter();
|
||||
function handleBackClick() {
|
||||
router.goBack();
|
||||
}
|
||||
|
||||
return (
|
||||
<IonPage>
|
||||
<IonHeader>
|
||||
<IonToolbar>
|
||||
<IonTitle>My Weather</IonTitle>
|
||||
|
||||
<IonButtons slot="end">
|
||||
<IonButton onClick={() => getCurrentPosition()}>
|
||||
<IonIcon icon={refreshOutline} color="primary" />
|
||||
</IonButton>
|
||||
</IonButtons>
|
||||
|
||||
<IonButtons slot="start">
|
||||
<IonButton onClick={() => handleBackClick()}>
|
||||
<IonIcon icon={chevronBackOutline} color="primary" />
|
||||
</IonButton>
|
||||
</IonButtons>
|
||||
</IonToolbar>
|
||||
</IonHeader>
|
||||
<IonContent fullscreen>
|
||||
<IonHeader collapse="condense">
|
||||
<IonToolbar>
|
||||
<IonTitle size="large">Dashboard</IonTitle>
|
||||
</IonToolbar>
|
||||
</IonHeader>
|
||||
|
||||
<IonRow className="ion-margin-start ion-margin-end ion-justify-content-center ion-text-center">
|
||||
<IonCol size="12">
|
||||
<h4>Here's your location based weather</h4>
|
||||
</IonCol>
|
||||
</IonRow>
|
||||
|
||||
<div style={{ marginTop: '-1.5rem' }}>
|
||||
{currentWeather ? (
|
||||
<CurrentWeather currentWeather={currentWeather} />
|
||||
) : (
|
||||
<SkeletonDashboard />
|
||||
)}
|
||||
</div>
|
||||
</IonContent>
|
||||
</IonPage>
|
||||
);
|
||||
}
|
||||
|
||||
export default Tab1;
|
@@ -1,81 +0,0 @@
|
||||
import {
|
||||
IonButton,
|
||||
IonCol,
|
||||
IonContent,
|
||||
IonHeader,
|
||||
IonPage,
|
||||
IonRow,
|
||||
IonSearchbar,
|
||||
IonTitle,
|
||||
IonToolbar,
|
||||
} from '@ionic/react';
|
||||
import { useState } from 'react';
|
||||
import { CurrentWeather } from '../TestComponents/CurrentWeather';
|
||||
|
||||
function Tab2() {
|
||||
const [search, setSearch] = useState('');
|
||||
const [currentWeather, setCurrentWeather] = useState(false);
|
||||
|
||||
const performSearch = async () => {
|
||||
getAddress(search);
|
||||
};
|
||||
|
||||
const getAddress = async (city) => {
|
||||
const response = await fetch(
|
||||
`https://api.weatherapi.com/v1/current.json?key=f93eb660b2424258bf5155016210712&q=${city}&aqi=no`
|
||||
);
|
||||
const data = await response.json();
|
||||
|
||||
if (data && data.current && data.location) {
|
||||
setCurrentWeather(data);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<IonPage>
|
||||
<IonHeader>
|
||||
<IonToolbar>
|
||||
<IonTitle>Search</IonTitle>
|
||||
</IonToolbar>
|
||||
</IonHeader>
|
||||
<IonContent fullscreen>
|
||||
<IonHeader collapse="condense">
|
||||
<IonToolbar>
|
||||
<IonTitle size="large">Search</IonTitle>
|
||||
</IonToolbar>
|
||||
</IonHeader>
|
||||
|
||||
<IonRow className="ion-justify-content-center ion-margin-top ion-align-items-center">
|
||||
<IonCol size="7">
|
||||
<IonSearchbar
|
||||
placeholder="Try 'London'"
|
||||
animated
|
||||
value={search}
|
||||
onIonChange={(e) => setSearch(e.target.value)}
|
||||
/>
|
||||
</IonCol>
|
||||
|
||||
<IonCol size="5">
|
||||
<IonButton
|
||||
expand="block"
|
||||
className="ion-margin-start ion-margin-end"
|
||||
onClick={performSearch}
|
||||
>
|
||||
Search
|
||||
</IonButton>
|
||||
</IonCol>
|
||||
</IonRow>
|
||||
|
||||
<div style={{ marginTop: '-0.8rem' }}>
|
||||
{currentWeather ? (
|
||||
<CurrentWeather currentWeather={currentWeather} />
|
||||
) : (
|
||||
<h3 className="ion-text-center">Your search result will appear here</h3>
|
||||
)}
|
||||
</div>
|
||||
</IonContent>
|
||||
</IonPage>
|
||||
);
|
||||
}
|
||||
|
||||
export default Tab2;
|
@@ -1,62 +0,0 @@
|
||||
import { IonCardSubtitle, IonCol, IonIcon, IonNote, IonRow } from '@ionic/react';
|
||||
import { pulseOutline, sunnyOutline, thermometerOutline } from 'ionicons/icons';
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
export const WeatherProperty = ({ type, currentWeather }: { type: any; currentWeather: any }) => {
|
||||
const [property, setProperty] = useState(false);
|
||||
|
||||
const properties = {
|
||||
wind: {
|
||||
isIcon: false,
|
||||
icon: '/assets/WeatherDemo/wind.png',
|
||||
alt: 'wind',
|
||||
label: 'Wind',
|
||||
value: `${currentWeather.current.wind_mph}mph`,
|
||||
},
|
||||
feelsLike: {
|
||||
isIcon: true,
|
||||
icon: thermometerOutline,
|
||||
alt: 'feels like',
|
||||
label: 'Feels like',
|
||||
value: `${currentWeather.current.feelslike_c}°C`,
|
||||
},
|
||||
indexUV: {
|
||||
isIcon: true,
|
||||
icon: sunnyOutline,
|
||||
alt: 'index uv',
|
||||
label: 'Index UV',
|
||||
value: currentWeather.current.uv,
|
||||
},
|
||||
pressure: {
|
||||
isIcon: true,
|
||||
icon: pulseOutline,
|
||||
alt: 'pressure',
|
||||
label: 'Pressure',
|
||||
value: `${currentWeather.current.pressure_mb} mbar`,
|
||||
},
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
setProperty(properties[type]);
|
||||
}, [type]);
|
||||
|
||||
return (
|
||||
<IonCol size="6">
|
||||
<IonRow className="ion-justify-content-center ion-align-items-center">
|
||||
<IonCol size="3">
|
||||
{!property.isIcon && (
|
||||
<img alt={property.alt} src={property.icon} height="32" width="32" />
|
||||
)}
|
||||
{property.isIcon && (
|
||||
<IonIcon icon={property.icon} color="medium" style={{ fontSize: '2rem' }} />
|
||||
)}
|
||||
</IonCol>
|
||||
|
||||
<IonCol size="9">
|
||||
<IonCardSubtitle>{property.label}</IonCardSubtitle>
|
||||
<IonNote>{property.value}</IonNote>
|
||||
</IonCol>
|
||||
</IonRow>
|
||||
</IonCol>
|
||||
);
|
||||
};
|
@@ -1,48 +0,0 @@
|
||||
import { IonCard, IonCardContent, IonGrid, IonRow, IonText, IonCardTitle } from '@ionic/react';
|
||||
import { WeatherProperty } from './WeatherProperty';
|
||||
|
||||
export const CurrentWeather = ({ currentWeather }: { currentWeather: any }) => (
|
||||
<IonGrid>
|
||||
<IonCard>
|
||||
<IonCardContent className="ion-text-center">
|
||||
<IonText color="primary">
|
||||
<h1>
|
||||
{currentWeather.location.region},{' '}
|
||||
<span style={{ color: 'gray' }}>{currentWeather.location.country}</span>
|
||||
</h1>
|
||||
</IonText>
|
||||
|
||||
<div className="ion-margin-top">
|
||||
<img
|
||||
alt="condition"
|
||||
src={currentWeather.current.condition.icon.replace('//', 'https://')}
|
||||
/>
|
||||
|
||||
<IonText color="dark">
|
||||
<h1 style={{ fontWeight: 'bold' }}>{currentWeather.current.condition.text}</h1>
|
||||
</IonText>
|
||||
|
||||
<IonText color="medium">
|
||||
<p>{new Date(currentWeather.location.localtime).toDateString()}</p>
|
||||
</IonText>
|
||||
</div>
|
||||
|
||||
<IonCardTitle style={{ fontSize: '3rem' }} className="ion-margin-top">
|
||||
{currentWeather.current.temp_c}℃
|
||||
</IonCardTitle>
|
||||
|
||||
<IonGrid className="ion-margin-top">
|
||||
<IonRow>
|
||||
<WeatherProperty type="wind" currentWeather={currentWeather} />
|
||||
<WeatherProperty type="feelsLike" currentWeather={currentWeather} />
|
||||
</IonRow>
|
||||
|
||||
<IonRow className="ion-margin-top">
|
||||
<WeatherProperty type="indexUV" currentWeather={currentWeather} />
|
||||
<WeatherProperty type="pressure" currentWeather={currentWeather} />
|
||||
</IonRow>
|
||||
</IonGrid>
|
||||
</IonCardContent>
|
||||
</IonCard>
|
||||
</IonGrid>
|
||||
);
|
@@ -1,117 +0,0 @@
|
||||
import {
|
||||
IonCard,
|
||||
IonCardContent,
|
||||
IonCardSubtitle,
|
||||
IonCardTitle,
|
||||
IonCol,
|
||||
IonGrid,
|
||||
IonIcon,
|
||||
IonNote,
|
||||
IonRow,
|
||||
IonSkeletonText,
|
||||
IonText,
|
||||
IonThumbnail,
|
||||
} from '@ionic/react';
|
||||
import { pulseOutline, sunnyOutline, thermometerOutline } from 'ionicons/icons';
|
||||
|
||||
export const SkeletonDashboard = () => (
|
||||
<IonGrid>
|
||||
<IonCard>
|
||||
<IonCardContent className="ion-text-center">
|
||||
<IonText color="primary">
|
||||
<h1>
|
||||
<IonSkeletonText animated style={{ height: '2rem', width: '90%' }} />
|
||||
</h1>
|
||||
</IonText>
|
||||
|
||||
<div className="ion-margin-top">
|
||||
<IonThumbnail>
|
||||
<IonSkeletonText animated style={{ width: '2rem', height: '2rem' }} />
|
||||
</IonThumbnail>
|
||||
|
||||
<IonText color="dark">
|
||||
<h1 style={{ fontWeight: 'bold' }}>
|
||||
<IonSkeletonText animated style={{ height: '2rem', width: '90%' }} />
|
||||
</h1>
|
||||
</IonText>
|
||||
|
||||
<IonText color="medium">
|
||||
<p>
|
||||
<IonSkeletonText animated style={{ height: '2rem', width: '90%' }} />
|
||||
</p>
|
||||
</IonText>
|
||||
</div>
|
||||
|
||||
<IonCardTitle style={{ fontSize: '3rem' }} className="ion-margin-top">
|
||||
<IonSkeletonText animated style={{ height: '3rem', width: '30%', textAlign: 'center' }} />
|
||||
</IonCardTitle>
|
||||
|
||||
<IonGrid className="ion-margin-top">
|
||||
<IonRow>
|
||||
<IonCol size="6">
|
||||
<IonRow className="ion-justify-content-center ion-align-items-center">
|
||||
<IonCol size="3">
|
||||
<img alt="wind" src="/assets/WeatherDemo/wind.png" height="32" width="32" />
|
||||
</IonCol>
|
||||
|
||||
<IonCol size="9">
|
||||
<IonCardSubtitle>Wind</IonCardSubtitle>
|
||||
<IonNote>
|
||||
<IonSkeletonText animated style={{ height: '2rem', width: '90%' }} />
|
||||
</IonNote>
|
||||
</IonCol>
|
||||
</IonRow>
|
||||
</IonCol>
|
||||
|
||||
<IonCol size="6">
|
||||
<IonRow className="ion-justify-content-center ion-align-items-center">
|
||||
<IonCol size="3">
|
||||
<IonIcon icon={thermometerOutline} color="medium" style={{ fontSize: '2rem' }} />
|
||||
</IonCol>
|
||||
|
||||
<IonCol size="9">
|
||||
<IonCardSubtitle>Feels like</IonCardSubtitle>
|
||||
<IonNote>
|
||||
<IonSkeletonText animated style={{ height: '2rem', width: '90%' }} />
|
||||
</IonNote>
|
||||
</IonCol>
|
||||
</IonRow>
|
||||
</IonCol>
|
||||
</IonRow>
|
||||
|
||||
<IonRow className="ion-margin-top">
|
||||
<IonCol size="6">
|
||||
<IonRow className="ion-justify-content-center ion-align-items-center">
|
||||
<IonCol size="3">
|
||||
<IonIcon icon={sunnyOutline} color="medium" style={{ fontSize: '2rem' }} />
|
||||
</IonCol>
|
||||
|
||||
<IonCol size="9">
|
||||
<IonCardSubtitle>Index UV</IonCardSubtitle>
|
||||
<IonNote>
|
||||
<IonSkeletonText animated style={{ height: '2rem', width: '90%' }} />
|
||||
</IonNote>
|
||||
</IonCol>
|
||||
</IonRow>
|
||||
</IonCol>
|
||||
|
||||
<IonCol size="6">
|
||||
<IonRow className="ion-justify-content-center ion-align-items-center">
|
||||
<IonCol size="3">
|
||||
<IonIcon icon={pulseOutline} color="medium" style={{ fontSize: '2rem' }} />
|
||||
</IonCol>
|
||||
|
||||
<IonCol size="9">
|
||||
<IonCardSubtitle>Pressure</IonCardSubtitle>
|
||||
<IonNote>
|
||||
<IonSkeletonText animated style={{ height: '2rem', width: '90%' }} />
|
||||
</IonNote>
|
||||
</IonCol>
|
||||
</IonRow>
|
||||
</IonCol>
|
||||
</IonRow>
|
||||
</IonGrid>
|
||||
</IonCardContent>
|
||||
</IonCard>
|
||||
</IonGrid>
|
||||
);
|
@@ -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,22 @@
|
||||
import React from 'react';
|
||||
import './ExploreContainer.scss';
|
||||
|
||||
const ExploreContainer = ({ name }: { name: string }): React.JSX.Element => {
|
||||
return (
|
||||
<div className="container">
|
||||
<strong>{name}</strong>
|
||||
<p>
|
||||
Explore{' '}
|
||||
<a
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
href="https://ionicframework.com/docs/components"
|
||||
>
|
||||
UI Components
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default ExploreContainer;
|
@@ -1,39 +1,58 @@
|
||||
import { IonIcon, IonLabel, IonRouterOutlet, IonTabBar, IonTabButton, IonTabs } from '@ionic/react';
|
||||
|
||||
import { cloudOutline, searchOutline } from 'ionicons/icons';
|
||||
import {
|
||||
brushOutline,
|
||||
cloudOutline,
|
||||
handLeftOutline,
|
||||
informationCircle,
|
||||
searchOutline,
|
||||
} from 'ionicons/icons';
|
||||
|
||||
import { Route, Redirect } from 'react-router';
|
||||
|
||||
import Tab1 from './AppPages/Tab1';
|
||||
import Tab2 from './AppPages/Tab2';
|
||||
import './theme/variables.scss';
|
||||
|
||||
import './style.scss';
|
||||
import ThemeStore from './store/ThemeStore';
|
||||
import Info from './pages/Info';
|
||||
import Themes from './pages/Themes';
|
||||
import Examples from './pages/Examples';
|
||||
|
||||
function DemoReactThemeSwitcher() {
|
||||
const theme = ThemeStore.useState((s) => s.currentTheme);
|
||||
|
||||
return (
|
||||
<IonTabs>
|
||||
<IonRouterOutlet>
|
||||
<Route exact path="/demo-react-theme-switcher/tab1">
|
||||
<Tab1 />
|
||||
</Route>
|
||||
<Route exact path="/demo-react-theme-switcher/tab2">
|
||||
<Tab2 />
|
||||
</Route>
|
||||
<div className="helloworld" style={theme ? theme : {}}>
|
||||
<IonTabs>
|
||||
<IonRouterOutlet>
|
||||
<Route exact path="/demo-react-theme-switcher/info">
|
||||
<Info />
|
||||
</Route>
|
||||
<Route exact path="/demo-react-theme-switcher/themes">
|
||||
<Themes />
|
||||
</Route>
|
||||
<Route exact path="/demo-react-theme-switcher/examples">
|
||||
<Examples />
|
||||
</Route>
|
||||
|
||||
<Redirect exact path="/demo-react-theme-switcher" to="/demo-react-theme-switcher/tab1" />
|
||||
</IonRouterOutlet>
|
||||
<Redirect exact path="/demo-react-theme-switcher" to="/demo-react-theme-switcher/info" />
|
||||
</IonRouterOutlet>
|
||||
|
||||
{/* */}
|
||||
<IonTabBar slot="bottom">
|
||||
<IonTabButton tab="tab1" href="/demo-react-theme-switcher/tab1">
|
||||
<IonIcon icon={cloudOutline} />
|
||||
<IonLabel>Dashboard</IonLabel>
|
||||
</IonTabButton>
|
||||
<IonTabButton tab="tab2" href="/demo-react-theme-switcher/tab2">
|
||||
<IonIcon icon={searchOutline} />
|
||||
<IonLabel>Search</IonLabel>
|
||||
</IonTabButton>
|
||||
</IonTabBar>
|
||||
</IonTabs>
|
||||
<IonTabBar slot="bottom">
|
||||
<IonTabButton tab="tab1" href="/demo-react-theme-switcher/info">
|
||||
<IonIcon icon={informationCircle} />
|
||||
<IonLabel>Info</IonLabel>
|
||||
</IonTabButton>
|
||||
<IonTabButton tab="tab2" href="/demo-react-theme-switcher/themes">
|
||||
<IonIcon icon={brushOutline} />
|
||||
<IonLabel>Themes</IonLabel>
|
||||
</IonTabButton>
|
||||
<IonTabButton tab="tab3" href="/demo-react-theme-switcher/examples">
|
||||
<IonIcon icon={handLeftOutline} />
|
||||
<IonLabel>Examples</IonLabel>
|
||||
</IonTabButton>
|
||||
</IonTabBar>
|
||||
</IonTabs>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
|
@@ -0,0 +1,126 @@
|
||||
import {
|
||||
IonBadge,
|
||||
IonButton,
|
||||
IonCardSubtitle,
|
||||
IonCardTitle,
|
||||
IonCol,
|
||||
IonContent,
|
||||
IonGrid,
|
||||
IonHeader,
|
||||
IonIcon,
|
||||
IonItem,
|
||||
IonLabel,
|
||||
IonPage,
|
||||
IonRange,
|
||||
IonRow,
|
||||
IonSelect,
|
||||
IonSelectOption,
|
||||
IonSpinner,
|
||||
IonText,
|
||||
IonTitle,
|
||||
IonToggle,
|
||||
IonToolbar,
|
||||
} from '@ionic/react';
|
||||
import { star, sunny } from 'ionicons/icons';
|
||||
import { useGetSelectedTheme } from '../store/ThemeStore';
|
||||
|
||||
import './Examples.scss';
|
||||
|
||||
const Examples = (): React.JSX.Element => {
|
||||
const currentTheme = useGetSelectedTheme();
|
||||
|
||||
return (
|
||||
<IonPage>
|
||||
<IonHeader>
|
||||
<IonToolbar>
|
||||
<IonTitle>Examples</IonTitle>
|
||||
</IonToolbar>
|
||||
</IonHeader>
|
||||
<IonContent fullscreen>
|
||||
<IonGrid>
|
||||
<IonRow
|
||||
className="ion-text-center ion-padding ion-margin-bottom"
|
||||
style={{ backgroundColor: 'var(--ion-color-main-light)' }}
|
||||
>
|
||||
<IonCol size="12">
|
||||
<IonCardSubtitle color="light">Current Theme</IonCardSubtitle>
|
||||
<IonCardTitle color="light">{currentTheme}</IonCardTitle>
|
||||
<IonText color="light">
|
||||
<p>Here are a few examples of how the theme looks on stock Ionic components.</p>
|
||||
</IonText>
|
||||
</IonCol>
|
||||
</IonRow>
|
||||
|
||||
<IonRow className="ion-text-center">
|
||||
<IonCol size="12">
|
||||
<IonCardSubtitle>Buttons</IonCardSubtitle>
|
||||
<IonButton color="main">Main Color button</IonButton>
|
||||
<IonButton color="main-light">Light Color button</IonButton>
|
||||
</IonCol>
|
||||
</IonRow>
|
||||
|
||||
<IonRow className="ion-text-center">
|
||||
<IonCol size="12">
|
||||
<IonCardSubtitle>Toggle</IonCardSubtitle>
|
||||
|
||||
<IonItem lines="none">
|
||||
<IonLabel>Toggle it on/off</IonLabel>
|
||||
<IonToggle />
|
||||
</IonItem>
|
||||
</IonCol>
|
||||
</IonRow>
|
||||
|
||||
<IonRow className="ion-text-center">
|
||||
<IonCol size="12">
|
||||
<IonCardSubtitle>Select</IonCardSubtitle>
|
||||
<IonItem lines="none">
|
||||
<IonLabel>Pick an option</IonLabel>
|
||||
<IonSelect placeholder="Select...">
|
||||
<IonSelectOption value="1">Option 1</IonSelectOption>
|
||||
<IonSelectOption value="2">Option 2</IonSelectOption>
|
||||
</IonSelect>
|
||||
</IonItem>
|
||||
</IonCol>
|
||||
</IonRow>
|
||||
|
||||
<IonRow className="ion-text-center">
|
||||
<IonCol size="12">
|
||||
<IonCardSubtitle>Badge</IonCardSubtitle>
|
||||
<IonItem lines="none">
|
||||
<IonLabel>Awesome badge!!</IonLabel>
|
||||
<IonBadge>
|
||||
<IonIcon icon={star} />
|
||||
Woohoo!
|
||||
</IonBadge>
|
||||
</IonItem>
|
||||
</IonCol>
|
||||
</IonRow>
|
||||
|
||||
<IonRow className="ion-text-center">
|
||||
<IonCol size="12">
|
||||
<IonCardSubtitle>Spinner</IonCardSubtitle>
|
||||
<IonItem lines="none">
|
||||
<IonLabel>Loading, please wait...</IonLabel>
|
||||
<IonBadge>
|
||||
<IonSpinner name="bubbles" />
|
||||
</IonBadge>
|
||||
</IonItem>
|
||||
</IonCol>
|
||||
</IonRow>
|
||||
|
||||
<IonRow className="ion-text-center">
|
||||
<IonCol size="12">
|
||||
<IonCardSubtitle>Range</IonCardSubtitle>
|
||||
<IonRange min={1000} max={2000} step={100} snaps={true} ticks={false} color="main">
|
||||
<IonIcon icon={sunny} size="small" slot="start" />
|
||||
<IonIcon icon={sunny} slot="end" />
|
||||
</IonRange>
|
||||
</IonCol>
|
||||
</IonRow>
|
||||
</IonGrid>
|
||||
</IonContent>
|
||||
</IonPage>
|
||||
);
|
||||
};
|
||||
|
||||
export default Examples;
|
@@ -0,0 +1,83 @@
|
||||
import {
|
||||
IonButton,
|
||||
IonCardSubtitle,
|
||||
IonCardTitle,
|
||||
IonCol,
|
||||
IonContent,
|
||||
IonGrid,
|
||||
IonHeader,
|
||||
IonPage,
|
||||
IonRow,
|
||||
IonText,
|
||||
IonTitle,
|
||||
IonToolbar,
|
||||
} from '@ionic/react';
|
||||
import { useGetSelectedTheme } from '../store/ThemeStore';
|
||||
import './Info.scss';
|
||||
import React from 'react';
|
||||
|
||||
function Info(): React.JSX.Element {
|
||||
const currentTheme = useGetSelectedTheme();
|
||||
|
||||
return (
|
||||
<IonPage>
|
||||
<IonHeader>
|
||||
<IonToolbar>
|
||||
<IonTitle>Info TS</IonTitle>
|
||||
</IonToolbar>
|
||||
</IonHeader>
|
||||
<IonContent fullscreen>
|
||||
<IonGrid>
|
||||
<IonRow
|
||||
className="ion-text-left ion-padding ion-margin-bottom"
|
||||
style={{ backgroundColor: 'var(--ion-color-main-light)' }}
|
||||
>
|
||||
<IonCol size="12">
|
||||
<IonCardSubtitle color="light">Current Theme</IonCardSubtitle>
|
||||
<IonCardTitle color="light">{currentTheme}</IonCardTitle>
|
||||
<IonText color="light">
|
||||
<p>
|
||||
This is an example showing how to easily implement dynamic themes into an Ionic
|
||||
app. We could use the setProperty method, but you'll notice that we can pass a
|
||||
style object into the IonApp component - I feel like we have more control this
|
||||
way. With this in mind, we can utilise all of the Ionic color CSS variables and
|
||||
custom variables.
|
||||
<br />
|
||||
<br />
|
||||
Check out the <code>setTheme</code> function
|
||||
<br />
|
||||
<br />I haven't over-rode every possible Ionic CSS variable, just a few of the
|
||||
core visually noticeable ones for this example.
|
||||
</p>
|
||||
</IonText>
|
||||
</IonCol>
|
||||
</IonRow>
|
||||
|
||||
<IonRow
|
||||
className="ion-text-left ion-padding ion-margin-bottom"
|
||||
style={{ backgroundColor: 'var(--ion-color-main-light)' }}
|
||||
>
|
||||
<IonCol size="12">
|
||||
<IonCardSubtitle color="light">Switching themes</IonCardSubtitle>
|
||||
<IonCardTitle color="light">Using global state</IonCardTitle>
|
||||
<IonText color="light">
|
||||
<p>
|
||||
We now know that our overall theme is controlled via a style object, so we can
|
||||
easily store this in state. In this example I'm using Pullstate, and updating the
|
||||
"currentTheme" on each change. I've mimicked an API call from local JSON data, as
|
||||
if it were a customer/client theme or branding.
|
||||
</p>
|
||||
</IonText>
|
||||
</IonCol>
|
||||
</IonRow>
|
||||
|
||||
<IonButton routerLink="/themes" color="main" expand="full">
|
||||
View Themes →
|
||||
</IonButton>
|
||||
</IonGrid>
|
||||
</IonContent>
|
||||
</IonPage>
|
||||
);
|
||||
}
|
||||
|
||||
export default Info;
|
@@ -0,0 +1,60 @@
|
||||
import {
|
||||
IonButton,
|
||||
IonCol,
|
||||
IonContent,
|
||||
IonHeader,
|
||||
IonIcon,
|
||||
IonPage,
|
||||
IonRow,
|
||||
IonTitle,
|
||||
IonToolbar,
|
||||
} from '@ionic/react';
|
||||
import { checkmark, checkmarkCircle, checkmarkOutline } from 'ionicons/icons';
|
||||
|
||||
import ExploreContainer from '../components/ExploreContainer';
|
||||
|
||||
import ThemeStore, { setTheme } from '../store/ThemeStore';
|
||||
import './Themes.scss';
|
||||
import React from 'react';
|
||||
|
||||
const Themes = (): React.JSX.Element => {
|
||||
const themes = ThemeStore.useState((s: any) => s.themes);
|
||||
const selectedThemeID = ThemeStore.useState((s: any) => s.selectedID);
|
||||
|
||||
return (
|
||||
<IonPage>
|
||||
<IonHeader>
|
||||
<IonToolbar>
|
||||
<IonTitle>Themes</IonTitle>
|
||||
</IonToolbar>
|
||||
</IonHeader>
|
||||
<IonContent fullscreen>
|
||||
{/* <ExploreContainer name="Tab 1 page" /> */}
|
||||
|
||||
<IonRow>
|
||||
{themes.map((theme: any, index: number) => {
|
||||
return (
|
||||
<IonCol
|
||||
size="6"
|
||||
onClick={() => {
|
||||
console.log(theme.file);
|
||||
console.log(theme.id);
|
||||
setTheme(theme.file, theme.id);
|
||||
}}
|
||||
>
|
||||
{theme.id === selectedThemeID && (
|
||||
<div className="selected-theme">
|
||||
<IonIcon icon={checkmark} />
|
||||
</div>
|
||||
)}
|
||||
<img src={theme.cover} alt="" />
|
||||
</IonCol>
|
||||
);
|
||||
})}
|
||||
</IonRow>
|
||||
</IonContent>
|
||||
</IonPage>
|
||||
);
|
||||
};
|
||||
|
||||
export default Themes;
|
@@ -0,0 +1,109 @@
|
||||
import { Store } from 'pullstate';
|
||||
|
||||
const ThemeStore = new Store({
|
||||
selectedID: '',
|
||||
currentTheme: {},
|
||||
themes: [
|
||||
{
|
||||
id: 1,
|
||||
name: 'Leafy Green',
|
||||
file: 'leafygreen.json',
|
||||
cover: '/assets/DemoReactThemeSwitcher/themes/covers/leafygreen.png',
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: 'Moody Blue',
|
||||
file: 'moodyblue.json',
|
||||
cover: '/assets/DemoReactThemeSwitcher/themes/covers/moodyblue.png',
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: 'Earthy Tones',
|
||||
file: 'earthytones.json',
|
||||
cover: '/assets/DemoReactThemeSwitcher/themes/covers/earthytones.png',
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
name: 'Peely Orange',
|
||||
file: 'peelyorange.json',
|
||||
cover: '/assets/DemoReactThemeSwitcher/themes/covers/peelyorange.png',
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
name: 'Firey Red',
|
||||
file: 'fireyred.json',
|
||||
cover: '/assets/DemoReactThemeSwitcher/themes/covers/fireyred.png',
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
name: 'Coffee Brown',
|
||||
file: 'coffeebrown.json',
|
||||
cover: '/assets/DemoReactThemeSwitcher/themes/covers/coffeebrown.png',
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
export default ThemeStore;
|
||||
|
||||
const buildTheme = (theme: any) => {
|
||||
const appTheme = {
|
||||
'--ion-toolbar-background': theme.toolbar_background_color,
|
||||
'--ion-tab-bar-background': theme.tab_bar_background_color,
|
||||
'--ion-toolbar-color': theme.toolbar_color,
|
||||
'--ion-tab-bar-color': theme.tab_bar_color,
|
||||
'--ion-tab-bar-color-selected': theme.tab_bar_activated_color,
|
||||
|
||||
'--ion-color-main-light': theme.light_color,
|
||||
'--ion-color-main-light-shade': theme.light_color_shade,
|
||||
'--ion-color-main-light-tint': theme.light_color_tint,
|
||||
|
||||
'--ion-color-main-color': theme.main_color,
|
||||
|
||||
// Set primary to be the main color as well
|
||||
'--ion-color-primary': theme.main_color,
|
||||
'--ion-color-main-color-shade': theme.main_color_shade,
|
||||
'--ion-color-main-color-tint': theme.main_color_tint,
|
||||
};
|
||||
|
||||
return appTheme;
|
||||
};
|
||||
|
||||
export const useGetSelectedTheme = () => {
|
||||
const themes = ThemeStore.useState((s) => s.themes);
|
||||
const selectedID = ThemeStore.useState((s) => s.selectedID);
|
||||
var themeName = 'Default';
|
||||
|
||||
if (selectedID) {
|
||||
const theme = themes.filter((t: any) => t.id === selectedID);
|
||||
if (theme && theme[0]) {
|
||||
themeName = theme[0].name;
|
||||
} else {
|
||||
themeName = 'false';
|
||||
}
|
||||
}
|
||||
|
||||
return themeName;
|
||||
};
|
||||
|
||||
export const setTheme = async (file: string, id: number) => {
|
||||
const response = await fetch(`/assets/DemoReactThemeSwitcher/themes/${file}`);
|
||||
const data = await response.json();
|
||||
|
||||
const theme = buildTheme(data);
|
||||
ThemeStore.update((s) => {
|
||||
s.currentTheme = theme;
|
||||
});
|
||||
ThemeStore.update((s: any) => {
|
||||
s.selectedID = id.toString();
|
||||
});
|
||||
|
||||
// We could also override the style properties
|
||||
// Using the setProperty method
|
||||
// But i feel, we have more control using global state
|
||||
// see below:
|
||||
|
||||
// for (var themeVar in theme) {
|
||||
|
||||
// document.documentElement.style.setProperty(themeVar, theme[themeVar]);
|
||||
// }
|
||||
};
|
@@ -0,0 +1,130 @@
|
||||
/* Ionic Variables and Theming. For more info, please see:
|
||||
http://ionicframework.com/docs/theming/ */
|
||||
|
||||
/** Ionic CSS Variables **/
|
||||
.helloworld {
|
||||
/** 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-color-main-light: #6439e4;
|
||||
--ion-color-main-light-contrast: #ffffff;
|
||||
--ion-color-main-light-shade: rgb(129, 121, 155);
|
||||
--ion-color-main-light-tint: rgb(70, 61, 97);
|
||||
|
||||
--ion-color-main-color: #4b1cd8;
|
||||
--ion-color-main-color-contrast: #ffffff;
|
||||
--ion-color-main-color-shade: rgb(60, 35, 143);
|
||||
--ion-color-main-color-tint: rgb(35, 23, 66);
|
||||
|
||||
/* --ion-background-color: #464646;
|
||||
--ion-background-color-rgb: 70,70,70; */
|
||||
|
||||
--ion-toolbar-background: var(--ion-color-main-color);
|
||||
--ion-toolbar-color: white;
|
||||
--ion-tab-bar-background: var(--ion-color-main-color);
|
||||
--ion-tab-bar-color: rgb(103, 101, 231);
|
||||
--ion-tab-bar-color-selected: rgb(255, 255, 255);
|
||||
|
||||
.ion-color-main-light {
|
||||
--ion-color-base: var(--ion-color-main-light);
|
||||
--ion-color-base-rgb: var(--ion-color-main-light-rgb);
|
||||
--ion-color-contrast: var(--ion-color-main-light-contrast);
|
||||
--ion-color-contrast-rgb: var(--ion-color-main-light-contrast-rgb);
|
||||
--ion-color-shade: var(--ion-color-main-light-shade);
|
||||
--ion-color-tint: var(--ion-color-main-light-tint);
|
||||
}
|
||||
|
||||
.ion-color-main {
|
||||
--ion-color-base: var(--ion-color-main-color);
|
||||
--ion-color-base-rgb: var(--ion-color-main-color-rgb);
|
||||
--ion-color-contrast: var(--ion-color-main-color-contrast);
|
||||
--ion-color-contrast-rgb: var(--ion-color-main-color-contrast-rgb);
|
||||
--ion-color-shade: var(--ion-color-main-color-shade);
|
||||
--ion-color-tint: var(--ion-color-main-color-tint);
|
||||
}
|
||||
|
||||
.selected-theme {
|
||||
position: absolute;
|
||||
background-color: rgba(77, 77, 77, 0.8);
|
||||
width: 95%;
|
||||
height: 95%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.selected-theme ion-icon {
|
||||
color: white;
|
||||
font-size: 5rem;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user