diff --git a/packages/ui/src/App.tsx b/packages/ui/src/App.tsx
index bea4d67bf..5a5215e04 100644
--- a/packages/ui/src/App.tsx
+++ b/packages/ui/src/App.tsx
@@ -2,6 +2,7 @@ import { SignInMode } from '@logto/schemas';
import { useEffect } from 'react';
import { Route, Routes, BrowserRouter, Navigate } from 'react-router-dom';
+import AppBoundary from './containers/AppBoundary';
import AppContent from './containers/AppContent';
import LoadingLayerProvider from './containers/LoadingLayerProvider';
import usePageContext from './hooks/use-page-context';
@@ -15,6 +16,7 @@ import ErrorPage from './pages/ErrorPage';
import ForgotPassword from './pages/ForgotPassword';
import Passcode from './pages/Passcode';
import PasswordRegisterWithUsername from './pages/PasswordRegisterWithUsername';
+import Profile from './pages/Profile';
import Register from './pages/Register';
import ResetPassword from './pages/ResetPassword';
import SecondaryRegister from './pages/SecondaryRegister';
@@ -57,60 +59,66 @@ const App = () => {
const isSignInOnly = experienceSettings.signInMode === SignInMode.SignIn;
return (
-
-
-
+
+
+
- } />
- } />
- }
- />
-
- }>
- {/* Sign-in */}
+ } />
+ }>
+ } />
+ } />
: }
+ path="/unknown-session"
+ element={}
/>
- } />
- } />
- } />
- {/* Register */}
- : }
- />
- }
- />
- } />
+ }>
+ {/* Sign-in */}
+ : }
+ />
+ } />
+ } />
+ } />
- {/* Forgot password */}
- } />
- } />
+ {/* Register */}
+ : }
+ />
+ }
+ />
+ } />
- {/* Continue set up missing profile */}
- } />
- } />
+ {/* Forgot password */}
+ } />
+ } />
- {/* Social sign-in pages */}
- } />
- } />
- } />
+ {/* Continue set up missing profile */}
+ }
+ />
+ } />
- {/* Always keep route path with param as the last one */}
- } />
+ {/* Social sign-in pages */}
+ } />
+ } />
+ } />
+
+ {/* Always keep route path with param as the last one */}
+ } />
+
+
+ } />
-
- } />
-
-
-
+
+
+
);
};
diff --git a/packages/ui/src/containers/AppBoundary/index.module.scss b/packages/ui/src/containers/AppBoundary/index.module.scss
new file mode 100644
index 000000000..62b82ec69
--- /dev/null
+++ b/packages/ui/src/containers/AppBoundary/index.module.scss
@@ -0,0 +1,22 @@
+@use '@/scss/colors' as colors;
+@use '@/scss/underscore' as _;
+
+body {
+ &.light {
+ @include colors.light;
+ }
+
+ &.dark {
+ @include colors.dark;
+ }
+}
+
+:global(body.mobile) {
+ --max-width: 360px;
+ background: var(--color-bg-body);
+}
+
+:global(body.desktop) {
+ --max-width: 400px;
+ background: var(--color-bg-float-base);
+}
diff --git a/packages/ui/src/containers/AppBoundary/index.tsx b/packages/ui/src/containers/AppBoundary/index.tsx
new file mode 100644
index 000000000..36ef98761
--- /dev/null
+++ b/packages/ui/src/containers/AppBoundary/index.tsx
@@ -0,0 +1,48 @@
+import { conditionalString } from '@silverhand/essentials';
+import type { ReactNode } from 'react';
+import { useCallback, useContext, useEffect } from 'react';
+
+import Toast from '@/components/Toast';
+import useColorTheme from '@/hooks/use-color-theme';
+import { PageContext } from '@/hooks/use-page-context';
+import useTheme from '@/hooks/use-theme';
+
+import ConfirmModalProvider from '../ConfirmModalProvider';
+import * as styles from './index.module.scss';
+
+type Props = {
+ children: ReactNode;
+};
+
+const AppBoundary = ({ children }: Props) => {
+ // Set Primary Color
+ useColorTheme();
+ const theme = useTheme();
+ const { platform, toast, setToast } = useContext(PageContext);
+
+ // Set Theme Mode
+ useEffect(() => {
+ document.body.classList.remove(conditionalString(styles.light), conditionalString(styles.dark));
+ document.body.classList.add(conditionalString(styles[theme]));
+ }, [theme]);
+
+ // Apply Platform Style
+ useEffect(() => {
+ document.body.classList.remove('desktop', 'mobile');
+ document.body.classList.add(platform === 'mobile' ? 'mobile' : 'desktop');
+ }, [platform]);
+
+ // Prevent internal eventListener rebind
+ const hideToast = useCallback(() => {
+ setToast('');
+ }, [setToast]);
+
+ return (
+
+
+ {children}
+
+ );
+};
+
+export default AppBoundary;
diff --git a/packages/ui/src/containers/AppContent/index.module.scss b/packages/ui/src/containers/AppContent/index.module.scss
index a530f8f1d..084d4ad84 100644
--- a/packages/ui/src/containers/AppContent/index.module.scss
+++ b/packages/ui/src/containers/AppContent/index.module.scss
@@ -1,6 +1,4 @@
@use '@/scss/underscore' as _;
-@use '@/scss/colors' as colors;
-@use '@/scss/fonts' as fonts;
/* Preview Settings */
.preview {
@@ -13,30 +11,10 @@
}
}
-/* Foundation */
-body {
- --radius: 8px;
- -webkit-font-smoothing: antialiased;
- -moz-osx-font-smoothing: auto;
- word-break: break-word;
- @include colors.static;
-
- &.light {
- @include colors.light;
- }
-
- &.dark {
- @include colors.dark;
- }
-
- @include fonts.fonts;
-}
-
/* Main Layout */
.container {
position: absolute;
inset: 0;
- color: var(--color-type-primary);
overflow: auto;
@include _.flex_column(center, normal);
}
@@ -51,14 +29,6 @@ body {
}
:global(body.mobile) {
- --max-width: 360px;
- background: var(--color-bg-body);
-
- .container {
- background: var(--color-bg-body);
- font: var(--font-body-2);
- }
-
.main {
flex: 1;
align-self: stretch;
@@ -69,14 +39,6 @@ body {
}
:global(body.desktop) {
- --max-width: 400px;
- background: var(--color-bg-float-base);
-
- .container {
- background: var(--color-bg-float-base);
- font: var(--font-body-2);
- }
-
.main {
width: 640px;
min-height: 640px;
diff --git a/packages/ui/src/containers/AppContent/index.tsx b/packages/ui/src/containers/AppContent/index.tsx
index 2683d2733..04104a9ac 100644
--- a/packages/ui/src/containers/AppContent/index.tsx
+++ b/packages/ui/src/containers/AppContent/index.tsx
@@ -1,52 +1,21 @@
-import { conditionalString } from '@silverhand/essentials';
-import type { ReactNode } from 'react';
-import { useEffect, useCallback, useContext } from 'react';
+import { useContext } from 'react';
+import { Outlet } from 'react-router-dom';
-import Toast from '@/components/Toast';
-import ConfirmModalProvider from '@/containers/ConfirmModalProvider';
-import useColorTheme from '@/hooks/use-color-theme';
import { PageContext } from '@/hooks/use-page-context';
-import useTheme from '@/hooks/use-theme';
import * as styles from './index.module.scss';
-export type Props = {
- children: ReactNode;
-};
-
-const AppContent = ({ children }: Props) => {
- const theme = useTheme();
- const { toast, platform, setToast } = useContext(PageContext);
-
- // Prevent internal eventListener rebind
- const hideToast = useCallback(() => {
- setToast('');
- }, [setToast]);
-
- // Set Primary Color
- useColorTheme();
-
- // Set Theme Mode
- useEffect(() => {
- document.body.classList.remove(conditionalString(styles.light), conditionalString(styles.dark));
- document.body.classList.add(conditionalString(styles[theme]));
- }, [theme]);
-
- // Apply Platform Style
- useEffect(() => {
- document.body.classList.remove('desktop', 'mobile');
- document.body.classList.add(platform === 'mobile' ? 'mobile' : 'desktop');
- }, [platform]);
+const AppContent = () => {
+ const { platform } = useContext(PageContext);
return (
-
-
- {platform === 'web' &&
}
-
{children}
- {platform === 'web' &&
}
-
-
-
+
+ {platform === 'web' &&
}
+
+
+
+ {platform === 'web' &&
}
+
);
};
diff --git a/packages/ui/src/pages/Profile/index.tsx b/packages/ui/src/pages/Profile/index.tsx
new file mode 100644
index 000000000..b023e60ab
--- /dev/null
+++ b/packages/ui/src/pages/Profile/index.tsx
@@ -0,0 +1,5 @@
+const Profile = () => {
+ return <>Profile works!>;
+};
+
+export default Profile;
diff --git a/packages/ui/src/scss/normalized.scss b/packages/ui/src/scss/normalized.scss
index a71811085..c9ff891bf 100644
--- a/packages/ui/src/scss/normalized.scss
+++ b/packages/ui/src/scss/normalized.scss
@@ -1,7 +1,18 @@
+@use '@/scss/colors' as colors;
+@use '@/scss/fonts' as fonts;
+
body {
+ @include colors.static;
+ @include fonts.fonts;
+
+ --radius: 8px;
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: auto;
margin: 0;
padding: 0;
- font-family: sans-serif;
+ word-break: break-word;
+ color: var(--color-type-primary);
+ font: var(--font-body-2);
}
* {