diff --git a/package-lock.json b/package-lock.json
index 6cf781cd..1521e276 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -11,7 +11,7 @@
"@babel/preset-env": "^7.24.5",
"@deriv-com/api-hooks": "^0.1.24",
"@deriv-com/translations": "^1.2.4",
- "@deriv-com/ui": "^1.26.0",
+ "@deriv-com/ui": "^1.27.5",
"@deriv-com/utils": "latest",
"@deriv/deriv-api": "^1.0.15",
"@deriv/quill-design": "^1.2.24",
@@ -2723,11 +2723,10 @@
}
},
"node_modules/@deriv-com/ui": {
- "version": "1.26.0",
- "resolved": "https://registry.npmjs.org/@deriv-com/ui/-/ui-1.26.0.tgz",
- "integrity": "sha512-nk6NVpuqE/ibvuJ82+Eu5pqfaMVWTVOMj0lyMouD7oTcI1etkat2TdQ0qObDp9KGrLRhhNKrTlC6OT2gQpBgog==",
+ "version": "1.27.5",
+ "resolved": "https://registry.npmjs.org/@deriv-com/ui/-/ui-1.27.5.tgz",
+ "integrity": "sha512-jn1M0uowKOGfvEjadGRfLfUOUK/OkQjEPskRedpZJl6a8xFyJQpCG44nMxIyPK28pz4DRnNkbugReRwRzP5jfw==",
"dependencies": {
- "@deriv/quill-icons": "^1.22.5",
"@types/react-modal": "^3.16.3",
"react-tiny-popover": "^8.0.4"
},
@@ -22702,11 +22701,10 @@
}
},
"@deriv-com/ui": {
- "version": "1.26.0",
- "resolved": "https://registry.npmjs.org/@deriv-com/ui/-/ui-1.26.0.tgz",
- "integrity": "sha512-nk6NVpuqE/ibvuJ82+Eu5pqfaMVWTVOMj0lyMouD7oTcI1etkat2TdQ0qObDp9KGrLRhhNKrTlC6OT2gQpBgog==",
+ "version": "1.27.5",
+ "resolved": "https://registry.npmjs.org/@deriv-com/ui/-/ui-1.27.5.tgz",
+ "integrity": "sha512-jn1M0uowKOGfvEjadGRfLfUOUK/OkQjEPskRedpZJl6a8xFyJQpCG44nMxIyPK28pz4DRnNkbugReRwRzP5jfw==",
"requires": {
- "@deriv/quill-icons": "^1.22.5",
"@rollup/rollup-linux-x64-gnu": "^4.13.0",
"@types/react-modal": "^3.16.3",
"react-tiny-popover": "^8.0.4"
diff --git a/package.json b/package.json
index 29ace1be..6fd2399f 100644
--- a/package.json
+++ b/package.json
@@ -17,7 +17,7 @@
"@babel/preset-env": "^7.24.5",
"@deriv-com/api-hooks": "^0.1.24",
"@deriv-com/translations": "^1.2.4",
- "@deriv-com/ui": "^1.26.0",
+ "@deriv-com/ui": "^1.27.5",
"@deriv-com/utils": "latest",
"@deriv/deriv-api": "^1.0.15",
"@deriv/quill-design": "^1.2.24",
diff --git a/src/components/AppFooter/AppFooter.scss b/src/components/AppFooter/AppFooter.scss
index a4ab0a7e..07c5f083 100644
--- a/src/components/AppFooter/AppFooter.scss
+++ b/src/components/AppFooter/AppFooter.scss
@@ -36,8 +36,19 @@
width: 0.8rem;
height: 0.8rem;
border-radius: 100%;
- background-color: #4bb4b3;
margin-left: 2rem;
+
+ &-online {
+ background-color: #4bb4b3;
+ }
+
+ &-offline {
+ background-color: #ff444f;
+ }
+
+ &-blinking {
+ animation: blink 1s infinite alternate;
+ }
}
&__endpoint {
@@ -45,3 +56,12 @@
text-decoration: underline;
}
}
+
+@keyframes blink {
+ 0% {
+ opacity: 1;
+ }
+ 100% {
+ opacity: 0.2;
+ }
+}
diff --git a/src/components/AppFooter/AppFooter.tsx b/src/components/AppFooter/AppFooter.tsx
index df92dfe2..176a1d09 100644
--- a/src/components/AppFooter/AppFooter.tsx
+++ b/src/components/AppFooter/AppFooter.tsx
@@ -10,7 +10,7 @@ import FullScreen from './FullScreen';
import HelpCentre from './HelpCentre';
import LanguageSettings from './LanguageSettings';
import Livechat from './Livechat';
-import { NetworkStatus } from './NetworkStatus';
+import NetworkStatus from './NetworkStatus';
import ResponsibleTrading from './ResponsibleTrading';
import { ServerTime } from './ServerTime';
import WhatsApp from './WhatsApp';
diff --git a/src/components/AppFooter/NetworkStatus.tsx b/src/components/AppFooter/NetworkStatus.tsx
index df87c97b..3b29efb2 100644
--- a/src/components/AppFooter/NetworkStatus.tsx
+++ b/src/components/AppFooter/NetworkStatus.tsx
@@ -1,17 +1,33 @@
+import { useMemo } from 'react';
+import clsx from 'clsx';
+import { useNetworkStatus } from '@/hooks';
import { useTranslations } from '@deriv-com/translations';
import { TooltipMenuIcon } from '@deriv-com/ui';
-export const NetworkStatus = () => {
+const statusConfigs = {
+ blinking: {
+ className: 'app-footer__network-status-online app-footer__network-status-blinking',
+ tooltip: 'Connecting to server',
+ },
+ offline: { className: 'app-footer__network-status-offline', tooltip: 'Offline' },
+ online: { className: 'app-footer__network-status-online', tooltip: 'Online' },
+};
+
+const NetworkStatus = () => {
+ const status = useNetworkStatus();
const { localize } = useTranslations();
+ const { className, tooltip } = useMemo(() => statusConfigs[status], [status]);
return (
-
+
);
};
+
+export default NetworkStatus;
diff --git a/src/hooks/custom-hooks/index.ts b/src/hooks/custom-hooks/index.ts
index dd9862cc..d86e52e5 100644
--- a/src/hooks/custom-hooks/index.ts
+++ b/src/hooks/custom-hooks/index.ts
@@ -8,6 +8,8 @@ export { default as useFullScreen } from './useFullScreen';
export { default as useIsAdvertiser } from './useIsAdvertiser';
export { default as useIsAdvertiserBarred } from './useIsAdvertiserBarred';
export { default as useModalManager } from './useModalManager';
+export { default as useNavigatorOnline } from './useNavigatorOnline';
+export { default as useNetworkStatus } from './useNetworkStatus';
export { default as usePoiPoaStatus } from './usePoiPoaStatus';
export { default as useQueryString } from './useQueryString';
export { default as useSendbird } from './useSendbird';
diff --git a/src/hooks/custom-hooks/useNavigatorOnline.ts b/src/hooks/custom-hooks/useNavigatorOnline.ts
new file mode 100644
index 00000000..753e5cf6
--- /dev/null
+++ b/src/hooks/custom-hooks/useNavigatorOnline.ts
@@ -0,0 +1,33 @@
+import { useEffect, useState } from 'react';
+
+/**
+ * Retrieves the current online status of the browser.
+ * @returns {boolean} The online status of the browser.
+ */
+const getOnlineStatus = () =>
+ typeof navigator !== 'undefined' && typeof navigator.onLine === 'boolean' ? navigator.onLine : true;
+
+/**
+ * A custom React hook that tracks the online status of the browser.
+ * @returns {boolean} The current online status of the browser.
+ */
+const useNavigatorOnline = () => {
+ const [status, setStatus] = useState(getOnlineStatus());
+
+ const setOnline = () => setStatus(true);
+ const setOffline = () => setStatus(false);
+
+ useEffect(() => {
+ window.addEventListener('online', setOnline);
+ window.addEventListener('offline', setOffline);
+
+ return () => {
+ window.removeEventListener('online', setOnline);
+ window.removeEventListener('offline', setOffline);
+ };
+ }, []);
+
+ return status;
+};
+
+export default useNavigatorOnline;
diff --git a/src/hooks/custom-hooks/useNetworkStatus.ts b/src/hooks/custom-hooks/useNetworkStatus.ts
new file mode 100644
index 00000000..59432698
--- /dev/null
+++ b/src/hooks/custom-hooks/useNetworkStatus.ts
@@ -0,0 +1,22 @@
+import { useEffect, useState } from 'react';
+import useNavigatorOnline from './useNavigatorOnline';
+
+type TStatus = 'blinking' | 'offline' | 'online';
+
+const useNetworkStatus = () => {
+ const [status, setStatus] = useState('online');
+ const networkStatus = useNavigatorOnline();
+
+ // TODO we need socket connection state from api-hooks whenever it finished we can update this part and check
+ // both navigatorStatus and socket Status
+ // for now we just check the user network status.
+
+ useEffect(() => {
+ if (networkStatus) setStatus('online');
+ else setStatus('offline');
+ }, [networkStatus]);
+
+ return status;
+};
+
+export default useNetworkStatus;