diff --git a/03_source/mobile/src/pages/DemoReactOverlayHooks/TestComponents/Menu.css b/03_source/mobile/src/pages/DemoReactOverlayHooks/TestComponents/Menu.css new file mode 100644 index 0000000..0ca47a2 --- /dev/null +++ b/03_source/mobile/src/pages/DemoReactOverlayHooks/TestComponents/Menu.css @@ -0,0 +1,113 @@ +ion-menu ion-content { + --background: var(--ion-item-background, var(--ion-background-color, #fff)); +} + +ion-menu.md ion-content { + --padding-start: 8px; + --padding-end: 8px; + --padding-top: 20px; + --padding-bottom: 20px; +} + +ion-menu.md ion-list { + padding: 20px 0; +} + +ion-menu.md ion-note { + margin-bottom: 30px; +} + +ion-menu.md ion-list-header, ion-menu.md ion-note { + padding-left: 10px; +} + +ion-menu.md ion-list#inbox-list { + border-bottom: 1px solid var(--ion-color-step-150, #d7d8da); +} + +ion-menu.md ion-list#inbox-list ion-list-header { + font-size: 22px; + font-weight: 600; + min-height: 20px; +} + +ion-menu.md ion-list#labels-list ion-list-header { + font-size: 16px; + margin-bottom: 18px; + color: #757575; + min-height: 26px; +} + +ion-menu.md ion-item { + --padding-start: 10px; + --padding-end: 10px; + border-radius: 4px; +} + +ion-menu.md ion-item.selected { + --background: rgba(var(--ion-color-primary-rgb), 0.14); +} + +ion-menu.md ion-item.selected ion-icon { + color: var(--ion-color-primary); +} + +ion-menu.md ion-item ion-icon { + color: #616e7e; +} + +ion-menu.md ion-item ion-label { + font-weight: 500; +} + +ion-menu.ios ion-content { + --padding-bottom: 20px; +} + +ion-menu.ios ion-list { + padding: 20px 0 0 0; +} + +ion-menu.ios ion-note { + line-height: 24px; + margin-bottom: 20px; +} + +ion-menu.ios ion-item { + --padding-start: 16px; + --padding-end: 16px; + --min-height: 50px; +} + +ion-menu.ios ion-item ion-icon { + font-size: 24px; + color: #73849a; +} + +ion-menu.ios ion-item .selected ion-icon { + color: var(--ion-color-primary); +} + +ion-menu.ios ion-list#labels-list ion-list-header { + margin-bottom: 8px; +} + +ion-menu.ios ion-list-header, +ion-menu.ios ion-note { + padding-left: 16px; + padding-right: 16px; +} + +ion-menu.ios ion-note { + margin-bottom: 8px; +} + +ion-note { + display: inline-block; + font-size: 16px; + color: var(--ion-color-medium-shade); +} + +ion-item.selected { + --color: var(--ion-color-primary); +} \ No newline at end of file diff --git a/03_source/mobile/src/pages/DemoReactOverlayHooks/TestComponents/Menu.jsx b/03_source/mobile/src/pages/DemoReactOverlayHooks/TestComponents/Menu.jsx new file mode 100644 index 0000000..6c33109 --- /dev/null +++ b/03_source/mobile/src/pages/DemoReactOverlayHooks/TestComponents/Menu.jsx @@ -0,0 +1,37 @@ +import { IonContent, IonIcon, IonItem, IonLabel, IonList, IonListHeader, IonMenu, IonMenuToggle, IonNote } from '@ionic/react'; + +import { useLocation } from 'react-router-dom'; +import { star, starOutline } from 'ionicons/icons'; +import './Menu.css'; + +const Menu = ({ pages }) => { + + const location = useLocation(); + + return ( + + + + Overlay Hooks + Choose one below to see a demo + + { pages.map((appPage, index) => { + + const isSelected = location.pathname === appPage.url; + + return ( + + + + { appPage.label } + + + ); + })} + + + + ); +}; + +export default Menu; \ No newline at end of file diff --git a/03_source/mobile/src/pages/DemoReactOverlayHooks/pages/ActionSheet.jsx b/03_source/mobile/src/pages/DemoReactOverlayHooks/pages/ActionSheet.jsx new file mode 100644 index 0000000..ded9d2e --- /dev/null +++ b/03_source/mobile/src/pages/DemoReactOverlayHooks/pages/ActionSheet.jsx @@ -0,0 +1,58 @@ +import { IonButton, IonButtons, IonContent, IonHeader, IonMenuButton, IonPage, IonTitle, IonToolbar, useIonActionSheet } from '@ionic/react'; + +const ActionSheet = () => { + + const [ present, dismiss ] = useIonActionSheet(); + + return ( + + + + + + + Action Sheet + + + + + + + Action Sheet + + + + + present({ + buttons: [{ text: 'Ok' }, { text: 'Cancel' }], + header: 'Action Sheet' + }) + } + > + Show ActionSheet + + + present([{ text: 'Ok' }, { text: 'Cancel' }], 'Action Sheet') + } + > + Show ActionSheet using params + + { + present([{ text: 'Ok' }, { text: 'Cancel' }], 'Action Sheet'); + setTimeout(dismiss, 3000); + }} + > + Show ActionSheet, hide after 3 seconds + + + + ); +}; + +export default ActionSheet; \ No newline at end of file diff --git a/03_source/mobile/src/pages/DemoReactOverlayHooks/pages/Alert.jsx b/03_source/mobile/src/pages/DemoReactOverlayHooks/pages/Alert.jsx new file mode 100644 index 0000000..5842e89 --- /dev/null +++ b/03_source/mobile/src/pages/DemoReactOverlayHooks/pages/Alert.jsx @@ -0,0 +1,53 @@ +import { IonButton, IonButtons, IonContent, IonHeader, IonMenuButton, IonPage, IonTitle, IonToolbar, useIonAlert } from '@ionic/react'; + +const Alert = () => { + + const [ present ] = useIonAlert(); + + return ( + + + + + + + Alert + + + + + + + Alert + + + + + present({ + cssClass: 'my-css', + header: 'Alert', + message: 'alert from hook', + buttons: [ + 'Cancel', + { text: 'Ok', handler: (d) => console.log('ok pressed') }, + ], + onDidDismiss: (e) => console.log('did dismiss'), + }) + } + > + Show Alert + + present('hello with params', [{ text: 'Ok' }])} + > + Show Alert using params + + + + ); +}; + +export default Alert; \ No newline at end of file diff --git a/03_source/mobile/src/pages/DemoReactOverlayHooks/pages/All.jsx b/03_source/mobile/src/pages/DemoReactOverlayHooks/pages/All.jsx new file mode 100644 index 0000000..1b0dad0 --- /dev/null +++ b/03_source/mobile/src/pages/DemoReactOverlayHooks/pages/All.jsx @@ -0,0 +1,54 @@ +import { IonButtons, IonCard, IonCardHeader, IonContent, IonHeader, IonMenuButton, IonPage, IonTitle, IonToolbar, IonCardTitle, IonCardSubtitle, IonCardContent, IonText } from '@ionic/react'; + +const All = () => { + + return ( + + + + + + + All + + + + + + + All + + + + + + Sample usage + Overlay Hooks + + + + +

+ In Ionic React 5.6, the team packaged up a new set of hooks for controlling overlay components that they thought we might like. What is an overlay you ask? It’s the term that Ionic give components that display over your current content, such as alerts, modals, toasts, etc. +

+
+
+ +

+ All of the code is taken from the Ionic Framework docs. You can find the blog post outlining these new overlay hooks here. +

+
+
+ +

+ Check out the samples by navigating to a respective one in the side menu. +

+
+
+
+
+
+ ); +}; + +export default All; \ No newline at end of file diff --git a/03_source/mobile/src/pages/DemoReactOverlayHooks/pages/Loading.jsx b/03_source/mobile/src/pages/DemoReactOverlayHooks/pages/Loading.jsx new file mode 100644 index 0000000..d0e0574 --- /dev/null +++ b/03_source/mobile/src/pages/DemoReactOverlayHooks/pages/Loading.jsx @@ -0,0 +1,46 @@ +import { IonButton, IonButtons, IonContent, IonHeader, IonMenuButton, IonPage, IonTitle, IonToolbar, useIonLoading } from '@ionic/react'; + +const Loading = () => { + + const [ present ] = useIonLoading(); + + return ( + + + + + + + Loading + + + + + + + Loading + + + + + present({ + duration: 3000, + }) + } + > + Show Loading + + present('Loading', 2000, 'dots')} + > + Show Loading using params + + + + ); +}; + +export default Loading; \ No newline at end of file diff --git a/03_source/mobile/src/pages/DemoReactOverlayHooks/pages/Modal.jsx b/03_source/mobile/src/pages/DemoReactOverlayHooks/pages/Modal.jsx new file mode 100644 index 0000000..08f5372 --- /dev/null +++ b/03_source/mobile/src/pages/DemoReactOverlayHooks/pages/Modal.jsx @@ -0,0 +1,68 @@ +import { IonButton, IonButtons, IonContent, IonHeader, IonMenuButton, IonPage, IonText, IonTitle, IonToolbar, useIonModal } from '@ionic/react'; +import { useState } from 'react'; + +const Modal = () => { + + const Body = ({ count, onDismiss, onIncrement }) => ( +
+ Count: { count } + onIncrement() }> + Increment Count + + onDismiss() }> + Close + +
+ ); + + const [count, setCount] = useState(0); + + const handleIncrement = () => { + setCount(count + 1); + }; + + const handleDismiss = () => { + dismiss(); + }; + + const [present, dismiss] = useIonModal(Body, { + count, + onDismiss: handleDismiss, + onIncrement: handleIncrement, + }); + + return ( + + + + + + + Modal + + + + + + + Modal + + + + { + present({ + cssClass: 'my-class', + }); + }} + > + Show Modal + +
Count: {count}
+
+
+ ); +}; + +export default Modal; \ No newline at end of file diff --git a/03_source/mobile/src/pages/DemoReactOverlayHooks/pages/Picker.jsx b/03_source/mobile/src/pages/DemoReactOverlayHooks/pages/Picker.jsx new file mode 100644 index 0000000..9d00e3a --- /dev/null +++ b/03_source/mobile/src/pages/DemoReactOverlayHooks/pages/Picker.jsx @@ -0,0 +1,97 @@ +import { IonButton, IonButtons, IonContent, IonHeader, IonMenuButton, IonPage, IonTitle, IonToolbar, useIonPicker } from '@ionic/react'; +import { useState } from 'react'; + +const Picker = () => { + + const [ present ] = useIonPicker(); + const [ value, setValue ] = useState(''); + + return ( + + + + + + + Picker + + + + + + + Picker + + + + + present({ + buttons: [ + { + text: 'Confirm', + handler: (selected) => { + setValue(selected.animal.value) + }, + }, + ], + columns: [ + { + name: 'animal', + options: [ + { text: 'Dog', value: 'dog' }, + { text: 'Cat', value: 'cat' }, + { text: 'Bird', value: 'bird' }, + ], + }, + ], + }) + } + > + Show Picker + + + present( + [ + { + name: 'animal', + options: [ + { text: 'Dog', value: 'dog' }, + { text: 'Cat', value: 'cat' }, + { text: 'Bird', value: 'bird' }, + ], + }, + { + name: 'vehicle', + options: [ + { text: 'Car', value: 'car' }, + { text: 'Truck', value: 'truck' }, + { text: 'Bike', value: 'bike' }, + ], + }, + ], + [ + { + text: 'Confirm', + handler: (selected) => { + setValue(`${selected.animal.value}, ${selected.vehicle.value}`) + }, + }, + ] + ) + } + > + Show Picker using params + + {value && ( +
Selected Value: {value}
+ )} +
+
+ ); +}; + +export default Picker; \ No newline at end of file diff --git a/03_source/mobile/src/pages/DemoReactOverlayHooks/pages/Popover.jsx b/03_source/mobile/src/pages/DemoReactOverlayHooks/pages/Popover.jsx new file mode 100644 index 0000000..155430e --- /dev/null +++ b/03_source/mobile/src/pages/DemoReactOverlayHooks/pages/Popover.jsx @@ -0,0 +1,53 @@ +import { IonButtons, IonContent, IonHeader, IonItem, IonListHeader, IonMenuButton, IonPage, IonTitle, IonToolbar, IonList, useIonPopover, IonButton } from '@ionic/react'; + +const Popover = () => { + + const PopoverList = ({ onHide }) => ( + + Ionic + Learn Ionic + Documentation + Showcase + GitHub Repo + + Close + + + ); + + const [ present, dismiss ] = useIonPopover(PopoverList, { onHide: () => dismiss() }); + + return ( + + + + + + + Popover + + + + + + + Popover + + + + + present({ + event: e.nativeEvent, + }) + } + > + Show Popover + + + + ); +}; + +export default Popover; \ No newline at end of file diff --git a/03_source/mobile/src/pages/DemoReactOverlayHooks/pages/Toast.jsx b/03_source/mobile/src/pages/DemoReactOverlayHooks/pages/Toast.jsx new file mode 100644 index 0000000..44689fe --- /dev/null +++ b/03_source/mobile/src/pages/DemoReactOverlayHooks/pages/Toast.jsx @@ -0,0 +1,52 @@ +import { IonButton, IonButtons, IonContent, IonHeader, IonMenuButton, IonPage, IonTitle, IonToolbar, useIonToast } from '@ionic/react'; + +const Toast = () => { + + const [ present, dismiss ] = useIonToast(); + + return ( + + + + + + + Toast + + + + + + + Toast + + + + + present({ + buttons: [{ text: 'hide', handler: () => dismiss() }], + message: 'toast from hook, click hide to dismiss', + onDidDismiss: () => console.log('dismissed'), + onWillDismiss: () => console.log('will dismiss'), + }) + } + > + Show Toast + + present('hello from hook', 3000)} + > + Show Toast using params, closes in 3 secs + + + Hide Toast + + + + ); +}; + +export default Toast; \ No newline at end of file diff --git a/03_source/mobile/src/pages/DemoReactOverlayHooks/theme/variables.css b/03_source/mobile/src/pages/DemoReactOverlayHooks/theme/variables.css new file mode 100644 index 0000000..088e83c --- /dev/null +++ b/03_source/mobile/src/pages/DemoReactOverlayHooks/theme/variables.css @@ -0,0 +1,77 @@ +/* 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; +} \ No newline at end of file