diff --git a/public/locales/en/common.json b/public/locales/en/common.json
index aa4ef1e5..dddc0286 100644
--- a/public/locales/en/common.json
+++ b/public/locales/en/common.json
@@ -19,6 +19,9 @@
"minutes": "m",
"seconds": "s"
},
+ "network": {
+ "offline_mode_notification": "Offline mode. Cached data will be displayed"
+ },
"widget": {
"missing_type": "Missing Widget Type: {{type}}",
"api_error": "API Error",
diff --git a/src/components/topnotification.jsx b/src/components/topnotification.jsx
new file mode 100644
index 00000000..3ecee808
--- /dev/null
+++ b/src/components/topnotification.jsx
@@ -0,0 +1,8 @@
+export default function TopNotification({ icon, children }) {
+ return (
+
+ {icon ?
{icon}
: null}
+
{children}
+
+ );
+}
diff --git a/src/pages/index.jsx b/src/pages/index.jsx
index 92833117..44f3bf15 100644
--- a/src/pages/index.jsx
+++ b/src/pages/index.jsx
@@ -8,6 +8,7 @@ import { useEffect, useContext, useState, useMemo } from "react";
import { BiError } from "react-icons/bi";
import { serverSideTranslations } from "next-i18next/serverSideTranslations";
import { useRouter } from "next/router";
+import { MdOutlineCloudOff } from "react-icons/md";
import Tab, { slugify } from "components/tab";
import FileContent from "components/filecontent";
@@ -27,6 +28,8 @@ import ErrorBoundary from "components/errorboundry";
import themes from "utils/styles/themes";
import QuickLaunch from "components/quicklaunch";
import { getStoredProvider, searchProviders } from "components/widgets/search/search";
+import useOffline from "utils/hooks/offline";
+import TopNotification from "components/topnotification";
const ThemeToggle = dynamic(() => import("components/toggles/theme"), {
ssr: false,
@@ -473,6 +476,9 @@ function Home({ initialSettings }) {
}
export default function Wrapper({ initialSettings, fallback }) {
+ const { isOffline } = useOffline();
+ const { t } = useTranslation();
+
const wrappedStyle = {};
let backgroundBlur = false;
let backgroundSaturate = false;
@@ -507,6 +513,11 @@ export default function Wrapper({ initialSettings, fallback }) {
initialSettings.color && `theme-${initialSettings.color}`,
)}
>
+ {isOffline ? (
+ }>
+ {t('network.offline_mode_notification')}
+
+ ) : null}
@media (min-width: 1800px) { ... }
},
+ keyframes: {
+ 'appear-top': {
+ '0%': { transform: 'translateY(-100%)', opacity: 0 },
+ '100%': { transform: 'translateY(0%)', opacity: 1 },
+ }
+ },
+ animation: {
+ 'appear-top': 'appear-top 250ms ease-out'
+ }
},
},
plugins: [tailwindForms, tailwindScrollbars],