Compare commits

..

2 Commits

Author SHA1 Message Date
louiscklaw
b9fbe4e476 update demo-react-marvel-app, 2025-06-08 19:07:38 +08:00
louiscklaw
0d844eed3f update demo-react-login, 2025-06-08 19:07:38 +08:00
24 changed files with 684 additions and 410 deletions

View File

@@ -0,0 +1,21 @@
import { IonCol, IonRouterLink, IonRow } from '@ionic/react';
interface ActionProps {
message: string;
text: string;
link: string;
}
export const Action = (props: ActionProps): React.JSX.Element => (
<IonRow className="ion-text-center ion-justify-content-center">
<IonCol size="12">
<p>
{props.message}
<IonRouterLink className="custom-link" routerLink={props.link}>
{' '}
{props.text} &rarr;
</IonRouterLink>
</p>
</IonCol>
</IonRow>
);

View File

@@ -0,0 +1,29 @@
.field:not(:last-child) {
margin-bottom: 1rem !important;
}
.field {
ion-label {
padding-left: 0.2rem;
padding-right: 0.5rem;
color: #d3a6c7;
display: flex;
justify-content: space-between;
align-content: center;
align-items: center;
p {
color: rgb(236, 149, 35);
}
}
}
.customInput {
--background: #834e76;
--padding-bottom: 1rem;
--padding-top: 1rem;
--padding-start: 1rem;
--padding-end: 1rem;
border-radius: 10px;
margin-top: 0.25rem;
transition: all 0.2s linear;
}

View File

@@ -0,0 +1,38 @@
import { IonInput, IonLabel } from '@ionic/react';
import styles from './CustomField.module.scss';
interface FieldType {
id: string;
label: string;
input: {
props: any;
state: any;
};
}
interface ErrorType {
id: string;
message: string;
}
interface CustomFieldProps {
field: FieldType;
errors?: ErrorType[];
}
const CustomField = ({ field, errors }: CustomFieldProps): React.JSX.Element => {
const error = errors && errors.filter((e) => e.id === field.id)[0];
const errorMessage = error && errors.filter((e) => e.id === field.id)[0].message;
return (
<div className={styles.field}>
<IonLabel className={styles.fieldLabel}>
{field.label}
{error && <p className="animate__animated animate__bounceIn">{errorMessage}</p>}
</IonLabel>
<IonInput className={styles.customInput} {...field.input.props} {...field.input.state} />
</div>
);
};
export default CustomField;

View File

@@ -0,0 +1,13 @@
export const Wave = (): React.JSX.Element => (
<svg
style={{ marginBottom: '-0.5rem' }}
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 1440 320"
>
<path
fill="#7a506f"
fill-opacity="1"
d="M0,288L40,277.3C80,267,160,245,240,224C320,203,400,181,480,176C560,171,640,181,720,181.3C800,181,880,171,960,144C1040,117,1120,75,1200,58.7C1280,43,1360,53,1400,58.7L1440,64L1440,320L1400,320C1360,320,1280,320,1200,320C1120,320,1040,320,960,320C880,320,800,320,720,320C640,320,560,320,480,320C400,320,320,320,240,320C160,320,80,320,40,320L0,320Z"
></path>
</svg>
);

View File

@@ -0,0 +1,82 @@
import { useFormInput } from "./utils";
export const useSignupFields = () => {
return [
{
id: "name",
label: "Name",
required: true,
input: {
props: {
type: "text",
placeholder: "Joe Bloggs"
},
state: useFormInput("")
}
},
{
id: "email",
label: "Email",
required: true,
input: {
props: {
type: "email",
placeholder: "joe@bloggs.com"
},
state: useFormInput("")
}
},
{
id: "password",
label: "Password",
required: true,
input: {
props: {
type: "password",
placeholder: "*********"
},
state: useFormInput("")
}
}
];
}
export const useLoginFields = () => {
return [
{
id: "email",
label: "Email",
required: true,
input: {
props: {
type: "email",
placeholder: "joe@bloggs.com"
},
state: useFormInput("")
}
},
{
id: "password",
label: "Password",
required: true,
input: {
props: {
type: "password",
placeholder: "*******"
},
state: useFormInput("")
}
}
];
}

View File

@@ -0,0 +1,46 @@
import { useState } from "react";
export const useFormInput = (initialValue = "") => {
const [ value, setValue ] = useState(initialValue);
const handleChange = async e => {
const tempValue = await e.currentTarget.value;
setValue(tempValue);
}
return {
value,
reset: (newValue) => setValue(newValue),
onIonChange: handleChange,
onKeyUp: handleChange
};
}
export const validateForm = fields => {
let errors = [];
fields.forEach(field => {
if (field.required) {
const fieldValue = field.input.state.value;
if (fieldValue === "") {
const error = {
id: field.id,
message: `Please check your ${ field.id }`,
};
errors.push(error);
}
}
});
return errors;
}

View File

@@ -1,28 +1,33 @@
import { IonIcon, IonLabel, IonRouterOutlet, IonTabBar, IonTabButton, IonTabs } from '@ionic/react';
import { IonRouterOutlet, 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 './theme/variables.scss';
import './style.scss';
import Home from './pages/Home';
import Login from './pages/Login';
import Signup from './pages/Signup';
function DemoReactLogin() {
return (
<IonTabs>
<IonRouterOutlet>
<Route exact path="/demo-react-login/tab1">
<Tab1 />
</Route>
<Route exact path="/demo-react-login/tab2">
<Tab2 />
<Route exact path="/demo-react-login/home">
<Home />
</Route>
<Redirect exact path="/demo-react-login" to="/demo-react-login/tab1" />
<Route exact path="/demo-react-login/signup">
<Signup />
</Route>
<Route exact path="/demo-react-login/login">
<Login />
</Route>
<Redirect exact path="/demo-react-login" to="/demo-react-login/home" />
</IonRouterOutlet>
{/* */}
{/*
<IonTabBar slot="bottom">
<IonTabButton tab="tab1" href="/demo-react-login/tab1">
<IonIcon icon={cloudOutline} />
@@ -33,6 +38,7 @@ function DemoReactLogin() {
<IonLabel>Search</IonLabel>
</IonTabButton>
</IonTabBar>
*/}
</IonTabs>
);
}

View File

@@ -0,0 +1,9 @@
declare module '*.module.css' {
const classes: { readonly [key: string]: string };
export default classes;
}
declare module '*.module.scss' {
const classes: { readonly [key: string]: string };
export default classes;
}

View File

@@ -0,0 +1,38 @@
.homePage {
ion-header {
ion-img {
border-bottom: 3px solid rgb(236, 149, 35);
}
}
ion-footer {
background-color: #7c3b6a;
color: white;
}
}
.getStarted {
height: 100%;
background-color: #ffffff;
background-image:
radial-gradient(#b8b8b8 1px, transparent 1px), radial-gradient(#b8b8b8 1px, #ffffff 1px);
background-size: 40px 40px;
background-position:
0 0,
20px 20px;
ion-card-title {
color: black !important;
letter-spacing: -0.08rem;
font-weight: 900 !important;
}
}
.heading {
margin-top: 7rem;
}
.getStartedButton {
font-size: 1.2rem;
margin-top: 1rem;
}

View File

@@ -0,0 +1,59 @@
import {
IonButton,
IonCardTitle,
IonCol,
IonContent,
IonFooter,
IonGrid,
IonHeader,
IonImg,
IonPage,
IonRouterLink,
IonRow,
IonToolbar,
} from '@ionic/react';
import { Action } from '../components/Action';
import styles from './Home.module.scss';
const Home = (): React.JSX.Element => {
return (
<IonPage className={styles.homePage}>
<IonHeader>
{/* <IonToolbar className="ion-no-margin ion-no-padding"> */}
<IonImg src="/assets/DemoReactLogin/login2.jpeg" />
{/* </IonToolbar> */}
</IonHeader>
<IonContent fullscreen>
<div className={styles.getStarted}>
<IonGrid>
<IonRow className={`ion-text-center ion-justify-content-center ${styles.heading}`}>
<IonCol size="11" className={styles.headingText}>
<IonCardTitle>
Join millions of other people discovering their creative side
</IonCardTitle>
</IonCol>
</IonRow>
<IonRow className={`ion-text-center ion-justify-content-center`}>
<IonRouterLink routerLink="/signup" className="custom-link">
<IonCol size="11">
<IonButton className={`${styles.getStartedButton} custom-button`}>
Get started &rarr;
</IonButton>
</IonCol>
</IonRouterLink>
</IonRow>
</IonGrid>
</div>
</IonContent>
<IonFooter>
<IonGrid>
<Action message="Already got an account?" text="Login" link="/login" />
</IonGrid>
</IonFooter>
</IonPage>
);
};
export default Home;

View File

@@ -0,0 +1,17 @@
.loginPage {
ion-toolbar {
--border-style: none;
--border-color: transparent;
--padding-top: 1rem;
--padding-bottom: 1rem;
--padding-start: 1rem;
--padding-end: 1rem;
}
}
.headingText {
h5 {
margin-top: 0.2rem;
color: #d3a6c7;
}
}

View File

@@ -0,0 +1,112 @@
import {
IonBackButton,
IonButton,
IonButtons,
IonCardTitle,
IonCol,
IonContent,
IonFooter,
IonGrid,
IonHeader,
IonIcon,
IonPage,
IonRouterLink,
IonRow,
IonToolbar,
} from '@ionic/react';
import styles from './Login.module.scss';
import { arrowBack, shapesOutline } from 'ionicons/icons';
import CustomField from '../components/CustomField';
import { useLoginFields } from '../data/fields';
import { Action } from '../components/Action';
import { Wave } from '../components/Wave';
import { useEffect, useState } from 'react';
import { validateForm } from '../data/utils';
import { useParams } from 'react-router';
interface FieldType {
id: string;
label: string;
input: {
props: any;
state: any;
};
}
interface ErrorType {
id: string;
message: string;
}
const Login = (): React.JSX.Element => {
const params = useParams();
const fields: FieldType[] = useLoginFields();
const [errors, setErrors] = useState<ErrorType[] | false>(false);
const login = (): void => {
const errors = validateForm(fields);
setErrors(errors);
if (!errors.length) {
// Submit your form here
}
};
useEffect(() => {
return () => {
fields.forEach((field) => field.input.state.reset(''));
setErrors(false);
};
}, [params]);
return (
<IonPage className={styles.loginPage}>
<IonHeader>
<IonToolbar>
<IonButtons slot="start">
<IonBackButton icon={arrowBack} text="" className="custom-back" />
</IonButtons>
<IonButtons slot="end">
<IonButton className="custom-button">
<IonIcon icon={shapesOutline} />
</IonButton>
</IonButtons>
</IonToolbar>
</IonHeader>
<IonContent fullscreen>
<IonGrid className="ion-padding">
<IonRow>
<IonCol size="12" className={styles.headingText}>
<IonCardTitle>Log in</IonCardTitle>
<h5>Welcome back, hope you're doing well</h5>
</IonCol>
</IonRow>
<IonRow className="ion-margin-top ion-padding-top">
<IonCol size="12">
{fields.map((field) => {
return <CustomField field={field} errors={errors} />;
})}
<IonButton className="custom-button" expand="block" onClick={login}>
Login
</IonButton>
</IonCol>
</IonRow>
</IonGrid>
</IonContent>
<IonFooter>
<IonGrid className="ion-no-margin ion-no-padding">
<Action message="Don't have an account?" text="Sign up" link="/signup" />
<Wave />
</IonGrid>
</IonFooter>
</IonPage>
);
};
export default Login;

View File

@@ -0,0 +1,17 @@
.signupPage {
ion-toolbar {
--border-style: none;
--border-color: transparent;
--padding-top: 1rem;
--padding-bottom: 1rem;
--padding-start: 1rem;
--padding-end: 1rem;
}
}
.headingText {
h5 {
margin-top: 0.2rem;
color: #d3a6c7;
}
}

View File

@@ -0,0 +1,111 @@
import {
IonBackButton,
IonButton,
IonButtons,
IonCardTitle,
IonCol,
IonContent,
IonFooter,
IonGrid,
IonHeader,
IonIcon,
IonPage,
IonRouterLink,
IonRow,
IonToolbar,
} from '@ionic/react';
import styles from './Signup.module.scss';
import { arrowBack, shapesOutline } from 'ionicons/icons';
import CustomField from '../components/CustomField';
import { useSignupFields } from '../data/fields';
import { Action } from '../components/Action';
import { Wave } from '../components/Wave';
import { useEffect, useState } from 'react';
import { validateForm } from '../data/utils';
import { useParams } from 'react-router';
interface FieldType {
id: string;
label: string;
input: {
props: any;
state: any;
};
}
interface ErrorType {
id: string;
message: string;
}
const Signup = (): React.JSX.Element => {
const params = useParams();
const fields: FieldType[] = useSignupFields();
const [errors, setErrors] = useState<ErrorType[] | false>(false);
const createAccount = (): void => {
const errors = validateForm(fields);
setErrors(errors);
if (!errors.length) {
// Submit your form here
}
};
useEffect(() => {
return () => {
fields.forEach((field) => field.input.state.reset(''));
setErrors(false);
};
}, [params]);
return (
<IonPage className={styles.signupPage}>
<IonHeader>
<IonToolbar>
<IonButtons slot="start">
<IonBackButton icon={arrowBack} text="" className="custom-back" />
</IonButtons>
<IonButtons slot="end">
<IonButton className="custom-button">
<IonIcon icon={shapesOutline} />
</IonButton>
</IonButtons>
</IonToolbar>
</IonHeader>
<IonContent fullscreen>
<IonGrid className="ion-padding">
<IonRow>
<IonCol size="12" className={styles.headingText}>
<IonCardTitle>Sign up</IonCardTitle>
<h5>Lets get to know each other</h5>
</IonCol>
</IonRow>
<IonRow className="ion-margin-top ion-padding-top">
<IonCol size="12">
{fields.map((field) => {
return <CustomField field={field} errors={errors} />;
})}
<IonButton className="custom-button" expand="block" onClick={createAccount}>
Create account
</IonButton>
</IonCol>
</IonRow>
</IonGrid>
</IonContent>
<IonFooter>
<IonGrid className="ion-no-margin ion-no-padding">
<Action message="Already got an account?" text="Login" link="/login" />
<Wave />
</IonGrid>
</IonFooter>
</IonPage>
);
};
export default Signup;

View File

@@ -0,0 +1,19 @@
import { Store } from "pullstate";
const AccountStore = new Store({
logged_in: false,
coffee_ids: []
});
export default AccountStore;
// export const addToCart = (coffeeID) => {
// CartStore.update(s => { s.coffee_ids = [ ...s.coffee_ids, `${ parseInt(coffeeID) }` ]; });
// }
// export const removeFromCart = coffeeIndex => {
// CartStore.update(s => { s.coffee_ids.splice(coffeeIndex, 1) });
// }

View File

@@ -0,0 +1,13 @@
import { createSelector } from 'reselect';
const getState = state => state;
// General getters
// export const getCoffees = createSelector(getState, state => state.coffees);
// export const getOffers = createSelector(getState, state => state.offers);
// export const getCoffeeSizes = createSelector(getState, state => state.sizes);
// export const getCartCoffees = createSelector(getState, state => state.coffee_ids);
// export const getFavouriteCoffees = createSelector(getState, state => state.coffee_ids);
// // More specific getters
// export const getCoffee = id => createSelector(getState, state => state.coffees.filter(c => parseInt(c.id) === parseInt(id))[0]);

View File

@@ -0,0 +1 @@
export { default as AccountStore } from "./AccountStore";

View File

@@ -1,103 +0,0 @@
#about-page {
ion-toolbar {
position: absolute;
top: 0;
left: 0;
right: 0;
--background: transparent;
--color: white;
}
ion-toolbar ion-back-button,
ion-toolbar ion-button,
ion-toolbar ion-menu-button {
--color: white;
}
.about-header {
position: relative;
width: 100%;
height: 30%;
}
.about-header .about-image {
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
background-position: center;
background-size: cover;
background-repeat: no-repeat;
opacity: 0;
transition: opacity 500ms ease-in-out;
}
.about-header .madison {
background-image: url('/assets/WeatherDemo/img/about/madison.jpg');
}
.about-header .austin {
background-image: url('/assets/WeatherDemo/img/about/austin.jpg');
}
.about-header .chicago {
background-image: url('/assets/WeatherDemo/img/about/chicago.jpg');
}
.about-header .seattle {
background-image: url('/assets/WeatherDemo/img/about/seattle.jpg');
}
.about-info {
position: relative;
margin-top: -10px;
border-radius: 10px;
background: var(--ion-background-color, #fff);
z-index: 2; // display rounded border above header image
}
.about-info h3 {
margin-top: 0;
}
.about-info ion-list {
padding-top: 0;
}
.about-info p {
line-height: 130%;
color: var(--ion-color-dark);
}
.about-info ion-icon {
margin-inline-end: 32px;
}
/*
* iOS Only
*/
.ios .about-info {
--ion-padding: 19px;
}
.ios .about-info h3 {
font-weight: 700;
}
}
#date-input-popover {
--offset-y: -var(--ion-safe-area-bottom);
--max-width: 90%;
--width: 336px;
}

View File

@@ -12,7 +12,7 @@ import Info from './pages/Info';
function DemoReactMarvelApp() {
return (
<IonTabs>
<IonTabs className="demo-react-marvel-app">
<IonRouterOutlet>
<Route exact path="/demo-react-marvel-app/home">
<Home />

View File

@@ -1,32 +1,30 @@
.character-container {
.demo-react-marvel-app {
.character-container {
position: relative;
text-align: center;
color: white;
}
.character-name-container {
}
.character-name-container {
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
align-content: center;
position:absolute;
position: absolute;
z-index: 99999;
background-color: rgba(0,0,0,0.7);
background-color: rgba(0, 0, 0, 0.7);
bottom: 0;
width: 100%;
padding-left: 1rem;
padding-right: 1rem;
}
.character-name-container ion-icon {
}
.character-name-container ion-icon {
margin-top: 0.5rem;
}
.character-name-container ion-label {
}
.character-name-container ion-label {
font-size: 1rem;
font-weight: 500;
}
}
}

View File

@@ -15,7 +15,7 @@ import {
useIonRouter,
} from '@ionic/react';
import './Home.css';
import './Home.scss';
import {
addOutline,
chevronBackOutline,

View File

@@ -1,59 +1,52 @@
.characterContainer {
position: relative;
text-align: center;
color: white;
position: relative;
text-align: center;
color: white;
}
ion-item {
--padding-start: 0;
--inner-padding-end: 0;
--padding-start: 0;
--inner-padding-end: 0;
}
ion-label {
margin-top: 12px;
margin-bottom: 12px;
margin-top: 12px;
margin-bottom: 12px;
}
.characterNameContainer {
display: flex;
flex-direction: row;
justify-content: center;
position: absolute;
z-index: 99999;
background-color: rgba(0, 0, 0, 0.7);
bottom: 0;
width: 100%;
display: flex;
flex-direction: row;
justify-content: center;
position: absolute;
z-index: 99999;
background-color: rgba(0, 0, 0, 0.7);
bottom: 0;
width: 100%;
}
.characterNameContainer ion-label {
font-size: 1rem !important;
font-weight: 500;
font-size: 1rem !important;
font-weight: 500;
}
.characterStats {
text-align: center;
margin-top: 1.5rem;
margin-bottom: 1.5rem;
text-align: center;
margin-top: 1.5rem;
margin-bottom: 1.5rem;
}
.characterStat {
background-color: var(--ion-color-primary);
padding: 1rem;
background-color: var(--ion-color-primary);
padding: 1rem;
}
.characterStat ion-card-title {
font-size: 1rem;
--color: white;
font-size: 1rem;
--color: white;
}
.characterStat ion-card-subtitle {
font-size: 1rem;
--color: white;
}
font-size: 1rem;
--color: white;
}

View File

@@ -1,245 +0,0 @@
.demo-react-marvel-app {
/* 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;
}
/* @media (prefers-color-scheme: dark) { */
/*
* Dark Colors
* -------------------------------------------
*/
body {
--ion-color-primary: #ee0000;
--ion-color-primary-rgb: 66, 140, 255;
--ion-color-primary-contrast: #ffffff;
--ion-color-primary-contrast-rgb: 255, 255, 255;
--ion-color-primary-shade: #3a7be0;
--ion-color-primary-tint: #5598ff;
--ion-color-secondary: #50c8ff;
--ion-color-secondary-rgb: 80, 200, 255;
--ion-color-secondary-contrast: #ffffff;
--ion-color-secondary-contrast-rgb: 255, 255, 255;
--ion-color-secondary-shade: #46b0e0;
--ion-color-secondary-tint: #62ceff;
--ion-color-tertiary: #6a64ff;
--ion-color-tertiary-rgb: 106, 100, 255;
--ion-color-tertiary-contrast: #ffffff;
--ion-color-tertiary-contrast-rgb: 255, 255, 255;
--ion-color-tertiary-shade: #5d58e0;
--ion-color-tertiary-tint: #7974ff;
--ion-color-success: #2fdf75;
--ion-color-success-rgb: 47, 223, 117;
--ion-color-success-contrast: #000000;
--ion-color-success-contrast-rgb: 0, 0, 0;
--ion-color-success-shade: #29c467;
--ion-color-success-tint: #44e283;
--ion-color-warning: #ffd534;
--ion-color-warning-rgb: 255, 213, 52;
--ion-color-warning-contrast: #000000;
--ion-color-warning-contrast-rgb: 0, 0, 0;
--ion-color-warning-shade: #e0bb2e;
--ion-color-warning-tint: #ffd948;
--ion-color-danger: #ee0000;
--ion-color-danger-rgb: 255, 73, 97;
--ion-color-danger-contrast: #ffffff;
--ion-color-danger-contrast-rgb: 255, 255, 255;
--ion-color-danger-shade: #e04055;
--ion-color-danger-tint: #ff5b71;
--ion-color-dark: #f4f5f8;
--ion-color-dark-rgb: 244, 245, 248;
--ion-color-dark-contrast: #000000;
--ion-color-dark-contrast-rgb: 0, 0, 0;
--ion-color-dark-shade: #d7d8da;
--ion-color-dark-tint: #f5f6f9;
--ion-color-medium: #989aa2;
--ion-color-medium-rgb: 152, 154, 162;
--ion-color-medium-contrast: #000000;
--ion-color-medium-contrast-rgb: 0, 0, 0;
--ion-color-medium-shade: #86888f;
--ion-color-medium-tint: #a2a4ab;
--ion-color-light: #222428;
--ion-color-light-rgb: 34, 36, 40;
--ion-color-light-contrast: #ffffff;
--ion-color-light-contrast-rgb: 255, 255, 255;
--ion-color-light-shade: #1e2023;
--ion-color-light-tint: #383a3e;
}
/*
* iOS Dark Theme
* -------------------------------------------
*/
.ios body {
--ion-background-color: #000000;
--ion-background-color-rgb: 0, 0, 0;
--ion-text-color: #ffffff;
--ion-text-color-rgb: 255, 255, 255;
--ion-color-step-50: #0d0d0d;
--ion-color-step-100: #1a1a1a;
--ion-color-step-150: #262626;
--ion-color-step-200: #333333;
--ion-color-step-250: #404040;
--ion-color-step-300: #4d4d4d;
--ion-color-step-350: #595959;
--ion-color-step-400: #666666;
--ion-color-step-450: #737373;
--ion-color-step-500: #808080;
--ion-color-step-550: #8c8c8c;
--ion-color-step-600: #999999;
--ion-color-step-650: #a6a6a6;
--ion-color-step-700: #b3b3b3;
--ion-color-step-750: #bfbfbf;
--ion-color-step-800: #cccccc;
--ion-color-step-850: #d9d9d9;
--ion-color-step-900: #e6e6e6;
--ion-color-step-950: #f2f2f2;
--ion-item-background: #000000;
--ion-card-background: #1c1c1d;
}
.ios ion-modal {
--ion-background-color: var(--ion-color-step-100);
--ion-toolbar-background: var(--ion-color-step-150);
--ion-toolbar-border-color: var(--ion-color-step-250);
}
/*
* Material Design Dark Theme
* -------------------------------------------
*/
.md body {
--ion-background-color: #121212;
--ion-background-color-rgb: 18, 18, 18;
--ion-text-color: #ffffff;
--ion-text-color-rgb: 255, 255, 255;
--ion-border-color: #222222;
--ion-color-step-50: #1e1e1e;
--ion-color-step-100: #2a2a2a;
--ion-color-step-150: #363636;
--ion-color-step-200: #414141;
--ion-color-step-250: #4d4d4d;
--ion-color-step-300: #595959;
--ion-color-step-350: #656565;
--ion-color-step-400: #717171;
--ion-color-step-450: #7d7d7d;
--ion-color-step-500: #898989;
--ion-color-step-550: #949494;
--ion-color-step-600: #a0a0a0;
--ion-color-step-650: #acacac;
--ion-color-step-700: #b8b8b8;
--ion-color-step-750: #c4c4c4;
--ion-color-step-800: #d0d0d0;
--ion-color-step-850: #dbdbdb;
--ion-color-step-900: #e7e7e7;
--ion-color-step-950: #f3f3f3;
--ion-item-background: #1e1e1e;
--ion-toolbar-background: #1f1f1f;
--ion-tab-bar-background: #1f1f1f;
--ion-card-background: #1e1e1e;
}
/* } */
.non-link {
text-decoration: none;
}
.hidden {
display: none;
}
}