diff --git a/src/app/components/BackRouteHandler.tsx b/src/app/components/BackRouteHandler.tsx
new file mode 100644
index 00000000..fa3d7592
--- /dev/null
+++ b/src/app/components/BackRouteHandler.tsx
@@ -0,0 +1,86 @@
+import { ReactNode, useCallback } from 'react';
+import { matchPath, useLocation, useNavigate } from 'react-router-dom';
+import {
+ getDirectPath,
+ getExplorePath,
+ getHomePath,
+ getInboxPath,
+ getSpacePath,
+} from '../pages/pathUtils';
+import { DIRECT_PATH, EXPLORE_PATH, HOME_PATH, INBOX_PATH, SPACE_PATH } from '../pages/paths';
+
+type BackRouteHandlerProps = {
+ children: (onBack: () => void) => ReactNode;
+};
+export function BackRouteHandler({ children }: BackRouteHandlerProps) {
+ const navigate = useNavigate();
+ const location = useLocation();
+
+ const goBack = useCallback(() => {
+ if (
+ matchPath(
+ {
+ path: HOME_PATH,
+ caseSensitive: true,
+ end: false,
+ },
+ location.pathname
+ )
+ ) {
+ navigate(getHomePath());
+ return;
+ }
+ if (
+ matchPath(
+ {
+ path: DIRECT_PATH,
+ caseSensitive: true,
+ end: false,
+ },
+ location.pathname
+ )
+ ) {
+ navigate(getDirectPath());
+ return;
+ }
+ const spaceMatch = matchPath(
+ {
+ path: SPACE_PATH,
+ caseSensitive: true,
+ end: false,
+ },
+ location.pathname
+ );
+ if (spaceMatch?.params.spaceIdOrAlias) {
+ navigate(getSpacePath(spaceMatch.params.spaceIdOrAlias));
+ return;
+ }
+ if (
+ matchPath(
+ {
+ path: EXPLORE_PATH,
+ caseSensitive: true,
+ end: false,
+ },
+ location.pathname
+ )
+ ) {
+ navigate(getExplorePath());
+ return;
+ }
+ if (
+ matchPath(
+ {
+ path: INBOX_PATH,
+ caseSensitive: true,
+ end: false,
+ },
+ location.pathname
+ )
+ ) {
+ navigate(getInboxPath());
+ }
+ }, [navigate, location]);
+
+ return children(goBack);
+}
diff --git a/src/app/components/page/Page.tsx b/src/app/components/page/Page.tsx
index 4ccb1ec0..a8b9ea04 100644
--- a/src/app/components/page/Page.tsx
+++ b/src/app/components/page/Page.tsx
@@ -87,15 +87,17 @@ export const Page = as<'div'>(({ className, ...props }, ref) => (
/>
));
-export const PageHeader = as<'div'>(({ className, ...props }, ref) => (
-
-));
+export const PageHeader = as<'div', css.PageHeaderVariants>(
+ ({ className, balance, ...props }, ref) => (
+
+ )
+);
export const PageContent = as<'div'>(({ className, ...props }, ref) => (
diff --git a/src/app/components/page/style.css.ts b/src/app/components/page/style.css.ts
index 4807a227..23f2da49 100644
--- a/src/app/components/page/style.css.ts
+++ b/src/app/components/page/style.css.ts
@@ -1,4 +1,5 @@
import { style } from '@vanilla-extract/css';
+import { recipe, RecipeVariants } from '@vanilla-extract/recipes';
import { DefaultReset, color, config, toRem } from 'folds';
export const PageNav = style({
@@ -33,11 +34,21 @@ export const PageNavContent = style({
paddingBottom: config.space.S700,
});
-export const PageHeader = style({
- paddingLeft: config.space.S400,
- paddingRight: config.space.S200,
- borderBottomWidth: config.borderWidth.B300,
+export const PageHeader = recipe({
+ base: {
+ paddingLeft: config.space.S400,
+ paddingRight: config.space.S200,
+ borderBottomWidth: config.borderWidth.B300,
+ },
+ variants: {
+ balance: {
+ true: {
+ paddingLeft: config.space.S200,
+ },
+ },
+ },
});
+export type PageHeaderVariants = RecipeVariants;
export const PageContent = style([
DefaultReset,
diff --git a/src/app/features/join-before-navigate/JoinBeforeNavigate.tsx b/src/app/features/join-before-navigate/JoinBeforeNavigate.tsx
index 1cec6599..028cd560 100644
--- a/src/app/features/join-before-navigate/JoinBeforeNavigate.tsx
+++ b/src/app/features/join-before-navigate/JoinBeforeNavigate.tsx
@@ -1,5 +1,5 @@
import React from 'react';
-import { Box, Scroll, Text, toRem } from 'folds';
+import { Box, Icon, IconButton, Icons, Scroll, Text, toRem } from 'folds';
import { useAtomValue } from 'jotai';
import { RoomCard } from '../../components/room-card';
import { RoomTopicViewer } from '../../components/room-topic-viewer';
@@ -8,6 +8,8 @@ import { RoomSummaryLoader } from '../../components/RoomSummaryLoader';
import { useRoomNavigate } from '../../hooks/useRoomNavigate';
import { useMatrixClient } from '../../hooks/useMatrixClient';
import { allRoomsAtom } from '../../state/room-list/roomList';
+import { ScreenSize, useScreenSizeContext } from '../../hooks/useScreenSize';
+import { BackRouteHandler } from '../../components/BackRouteHandler';
type JoinBeforeNavigateProps = { roomIdOrAlias: string; eventId?: string; viaServers?: string[] };
export function JoinBeforeNavigate({
@@ -18,6 +20,7 @@ export function JoinBeforeNavigate({
const mx = useMatrixClient();
const allRooms = useAtomValue(allRoomsAtom);
const { navigateRoom, navigateSpace } = useRoomNavigate();
+ const screenSize = useScreenSizeContext();
const handleView = (roomId: string) => {
if (mx.getRoom(roomId)?.isSpaceRoom()) {
@@ -29,11 +32,24 @@ export function JoinBeforeNavigate({
return (
-
-
-
- {roomIdOrAlias}
-
+
+
+
+ {screenSize === ScreenSize.Mobile && (
+
+ {(onBack) => (
+
+
+
+ )}
+
+ )}
+
+
+
+ {roomIdOrAlias}
+
+
diff --git a/src/app/features/lobby/LobbyHeader.tsx b/src/app/features/lobby/LobbyHeader.tsx
index e01d3ad5..fa415bd2 100644
--- a/src/app/features/lobby/LobbyHeader.tsx
+++ b/src/app/features/lobby/LobbyHeader.tsx
@@ -31,6 +31,8 @@ import { IPowerLevels, usePowerLevelsAPI } from '../../hooks/usePowerLevels';
import { UseStateProvider } from '../../components/UseStateProvider';
import { LeaveSpacePrompt } from '../../components/leave-space-prompt';
import { stopPropagation } from '../../utils/keyboard';
+import { ScreenSize, useScreenSizeContext } from '../../hooks/useScreenSize';
+import { BackRouteHandler } from '../../components/BackRouteHandler';
type LobbyMenuProps = {
roomId: string;
@@ -123,6 +125,7 @@ export function LobbyHeader({ showProfile, powerLevels }: LobbyHeaderProps) {
const space = useSpace();
const setPeopleDrawer = useSetSetting(settingsAtom, 'isPeopleDrawer');
const [menuAnchor, setMenuAnchor] = useState();
+ const screenSize = useScreenSizeContext();
const name = useRoomName(space);
const avatarMxc = useRoomAvatar(space);
@@ -133,42 +136,72 @@ export function LobbyHeader({ showProfile, powerLevels }: LobbyHeaderProps) {
};
return (
-
+
-
-
- {showProfile && (
- <>
-
- {nameInitials(name)}}
- />
-
-
- {name}
-
- >
+ {screenSize === ScreenSize.Mobile ? (
+ <>
+
+
+ {(onBack) => (
+
+
+
+ )}
+
+
+
+ {showProfile && (
+
+ {name}
+
+ )}
+
+ >
+ ) : (
+ <>
+
+
+ {showProfile && (
+ <>
+
+ {nameInitials(name)}}
+ />
+
+
+ {name}
+
+ >
+ )}
+
+ >
+ )}
+
+ {screenSize !== ScreenSize.Mobile && (
+
+ Members
+
+ }
+ >
+ {(triggerRef) => (
+ setPeopleDrawer((drawer) => !drawer)}>
+
+
+ )}
+
)}
-
-
-
- Members
-
- }
- >
- {(triggerRef) => (
- setPeopleDrawer((drawer) => !drawer)}>
-
-
- )}
-
+
+ {screenSize === ScreenSize.Mobile && (
+
+ {(onBack) => (
+
+
+
+
+
+ )}
+
+ )}
-
- (
-
- )}
- />
-
+ {screenSize !== ScreenSize.Mobile && (
+
+ (
+
+ )}
+ />
+
+ )}
{name}
diff --git a/src/app/pages/client/explore/Featured.tsx b/src/app/pages/client/explore/Featured.tsx
index 4838127f..f056cbb5 100644
--- a/src/app/pages/client/explore/Featured.tsx
+++ b/src/app/pages/client/explore/Featured.tsx
@@ -1,5 +1,5 @@
import React from 'react';
-import { Box, Icon, Icons, Scroll, Text } from 'folds';
+import { Box, Icon, IconButton, Icons, Scroll, Text } from 'folds';
import { useAtomValue } from 'jotai';
import { useClientConfig } from '../../../hooks/useClientConfig';
import { RoomCard, RoomCardGrid } from '../../../components/room-card';
@@ -9,21 +9,38 @@ import {
Page,
PageContent,
PageContentCenter,
+ PageHeader,
PageHero,
PageHeroSection,
} from '../../../components/page';
import { RoomTopicViewer } from '../../../components/room-topic-viewer';
import * as css from './style.css';
import { useRoomNavigate } from '../../../hooks/useRoomNavigate';
+import { ScreenSize, useScreenSizeContext } from '../../../hooks/useScreenSize';
+import { BackRouteHandler } from '../../../components/BackRouteHandler';
export function FeaturedRooms() {
const { featuredCommunities } = useClientConfig();
const { rooms, spaces } = featuredCommunities ?? {};
const allRooms = useAtomValue(allRoomsAtom);
+ const screenSize = useScreenSizeContext();
const { navigateSpace, navigateRoom } = useRoomNavigate();
return (
+ {screenSize === ScreenSize.Mobile && (
+
+
+
+ {(onBack) => (
+
+
+
+ )}
+
+
+
+ )}
diff --git a/src/app/pages/client/explore/Server.tsx b/src/app/pages/client/explore/Server.tsx
index 1a81c225..1f493df1 100644
--- a/src/app/pages/client/explore/Server.tsx
+++ b/src/app/pages/client/explore/Server.tsx
@@ -13,6 +13,7 @@ import {
Button,
Chip,
Icon,
+ IconButton,
Icons,
Input,
Line,
@@ -42,6 +43,8 @@ import { allRoomsAtom } from '../../../state/room-list/roomList';
import { useRoomNavigate } from '../../../hooks/useRoomNavigate';
import { getMxIdServer } from '../../../utils/matrix';
import { stopPropagation } from '../../../utils/keyboard';
+import { ScreenSize, useScreenSizeContext } from '../../../hooks/useScreenSize';
+import { BackRouteHandler } from '../../../components/BackRouteHandler';
const useServerSearchParams = (searchParams: URLSearchParams): ExploreServerPathSearchParams =>
useMemo(
@@ -344,6 +347,7 @@ export function PublicRooms() {
const userServer = userId && getMxIdServer(userId);
const allRooms = useAtomValue(allRoomsAtom);
const { navigateSpace, navigateRoom } = useRoomNavigate();
+ const screenSize = useScreenSizeContext();
const [searchParams] = useSearchParams();
const serverSearchParams = useServerSearchParams(searchParams);
@@ -466,7 +470,7 @@ export function PublicRooms() {
return (
-
+
{isSearch ? (
<>
@@ -482,20 +486,34 @@ export function PublicRooms() {
-
+ {screenSize !== ScreenSize.Mobile && }
Search
-
+
>
) : (
-
-
-
- {server}
-
-
+ <>
+
+ {screenSize === ScreenSize.Mobile && (
+
+ {(onBack) => (
+
+
+
+ )}
+
+ )}
+
+
+ {screenSize !== ScreenSize.Mobile && }
+
+ {server}
+
+
+
+ >
)}
diff --git a/src/app/pages/client/home/Search.tsx b/src/app/pages/client/home/Search.tsx
index af7b1eb9..d5ddfb77 100644
--- a/src/app/pages/client/home/Search.tsx
+++ b/src/app/pages/client/home/Search.tsx
@@ -1,21 +1,38 @@
import React, { useRef } from 'react';
-import { Box, Icon, Icons, Text, Scroll } from 'folds';
+import { Box, Icon, Icons, Text, Scroll, IconButton } from 'folds';
import { Page, PageContent, PageContentCenter, PageHeader } from '../../../components/page';
import { MessageSearch } from '../../../features/message-search';
import { useHomeRooms } from './useHomeRooms';
+import { ScreenSize, useScreenSizeContext } from '../../../hooks/useScreenSize';
+import { BackRouteHandler } from '../../../components/BackRouteHandler';
export function HomeSearch() {
const scrollRef = useRef(null);
const rooms = useHomeRooms();
+ const screenSize = useScreenSizeContext();
return (
-
-
-
-
- Message Search
-
+
+
+
+ {screenSize === ScreenSize.Mobile && (
+
+ {(onBack) => (
+
+
+
+ )}
+
+ )}
+
+
+ {screenSize !== ScreenSize.Mobile && }
+
+ Message Search
+
+
+
diff --git a/src/app/pages/client/inbox/Invites.tsx b/src/app/pages/client/inbox/Invites.tsx
index 06e5f6c6..18993081 100644
--- a/src/app/pages/client/inbox/Invites.tsx
+++ b/src/app/pages/client/inbox/Invites.tsx
@@ -4,6 +4,7 @@ import {
Box,
Button,
Icon,
+ IconButton,
Icons,
Overlay,
OverlayBackdrop,
@@ -39,6 +40,8 @@ import { RoomTopicViewer } from '../../../components/room-topic-viewer';
import { AsyncStatus, useAsyncCallback } from '../../../hooks/useAsyncCallback';
import { useRoomNavigate } from '../../../hooks/useRoomNavigate';
import { useRoomTopic } from '../../../hooks/useRoomMeta';
+import { ScreenSize, useScreenSizeContext } from '../../../hooks/useScreenSize';
+import { BackRouteHandler } from '../../../components/BackRouteHandler';
const COMPACT_CARD_WIDTH = 548;
@@ -205,6 +208,7 @@ export function Invites() {
useCallback(() => containerRef.current, []),
useCallback((width) => setCompact(width <= COMPACT_CARD_WIDTH), [])
);
+ const screenSize = useScreenSizeContext();
const { navigateRoom, navigateSpace } = useRoomNavigate();
@@ -225,12 +229,26 @@ export function Invites() {
return (
-
-
-
-
- Invitations
-
+
+
+
+ {screenSize === ScreenSize.Mobile && (
+
+ {(onBack) => (
+
+
+
+ )}
+
+ )}
+
+
+ {screenSize !== ScreenSize.Mobile && }
+
+ Invitations
+
+
+
diff --git a/src/app/pages/client/inbox/Notifications.tsx b/src/app/pages/client/inbox/Notifications.tsx
index 3425b519..6a8160d8 100644
--- a/src/app/pages/client/inbox/Notifications.tsx
+++ b/src/app/pages/client/inbox/Notifications.tsx
@@ -78,6 +78,8 @@ import { UserAvatar } from '../../../components/user-avatar';
import { EncryptedContent } from '../../../features/room/message';
import { useMentionClickHandler } from '../../../hooks/useMentionClickHandler';
import { useSpoilerClickHandler } from '../../../hooks/useSpoilerClickHandler';
+import { ScreenSize, useScreenSizeContext } from '../../../hooks/useScreenSize';
+import { BackRouteHandler } from '../../../components/BackRouteHandler';
type RoomNotificationsGroup = {
roomId: string;
@@ -484,6 +486,7 @@ export function Notifications() {
const mx = useMatrixClient();
const [mediaAutoLoad] = useSetting(settingsAtom, 'mediaAutoLoad');
const [urlPreview] = useSetting(settingsAtom, 'urlPreview');
+ const screenSize = useScreenSizeContext();
const { navigateRoom } = useRoomNavigate();
const [searchParams, setSearchParams] = useSearchParams();
@@ -549,12 +552,26 @@ export function Notifications() {
return (
-
-
-
-
- Notification Messages
-
+
+
+
+ {screenSize === ScreenSize.Mobile && (
+
+ {(onBack) => (
+
+
+
+ )}
+
+ )}
+
+
+ {screenSize !== ScreenSize.Mobile && }
+
+ Notification Messages
+
+
+
diff --git a/src/app/pages/client/space/Search.tsx b/src/app/pages/client/space/Search.tsx
index 6e7ac57d..017262b5 100644
--- a/src/app/pages/client/space/Search.tsx
+++ b/src/app/pages/client/space/Search.tsx
@@ -1,5 +1,5 @@
import React, { useRef } from 'react';
-import { Box, Icon, Icons, Text, Scroll } from 'folds';
+import { Box, Icon, Icons, Text, Scroll, IconButton } from 'folds';
import { useAtomValue } from 'jotai';
import { Page, PageContent, PageContentCenter, PageHeader } from '../../../components/page';
import { MessageSearch } from '../../../features/message-search';
@@ -9,11 +9,14 @@ import { allRoomsAtom } from '../../../state/room-list/roomList';
import { mDirectAtom } from '../../../state/mDirectList';
import { roomToParentsAtom } from '../../../state/room/roomToParents';
import { useMatrixClient } from '../../../hooks/useMatrixClient';
+import { ScreenSize, useScreenSizeContext } from '../../../hooks/useScreenSize';
+import { BackRouteHandler } from '../../../components/BackRouteHandler';
export function SpaceSearch() {
const mx = useMatrixClient();
const scrollRef = useRef(null);
const space = useSpace();
+ const screenSize = useScreenSizeContext();
const mDirects = useAtomValue(mDirectAtom);
const roomToParents = useAtomValue(roomToParentsAtom);
@@ -25,12 +28,26 @@ export function SpaceSearch() {
return (
-
-
-
-
- Message Search
-
+
+
+
+ {screenSize === ScreenSize.Mobile && (
+
+ {(onBack) => (
+
+
+
+ )}
+
+ )}
+
+
+ {screenSize !== ScreenSize.Mobile && }
+
+ Message Search
+
+
+