mirror of
https://github.com/jeffvli/feishin.git
synced 2026-06-17 00:44:23 +02:00
add basic mobile responsive layout
This commit is contained in:
@@ -0,0 +1,55 @@
|
||||
.layout {
|
||||
position: relative;
|
||||
display: grid;
|
||||
grid-template-areas:
|
||||
'window-bar'
|
||||
'main-content'
|
||||
'player';
|
||||
grid-template-rows: 0 calc(100vh - 90px) 90px;
|
||||
grid-template-columns: 1fr;
|
||||
gap: 0;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
overflow: hidden;
|
||||
background: var(--theme-colors-background);
|
||||
}
|
||||
|
||||
.drawer-button {
|
||||
position: absolute;
|
||||
bottom: calc(90px + 0.75rem);
|
||||
left: 0.75rem;
|
||||
z-index: 100;
|
||||
background: color-mix(in srgb, var(--theme-colors-background) 90%, transparent);
|
||||
border: 1px solid var(--theme-colors-border);
|
||||
backdrop-filter: blur(10px);
|
||||
}
|
||||
|
||||
.main-content {
|
||||
position: relative;
|
||||
grid-area: main-content;
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
}
|
||||
|
||||
.full-screen-player-overlay {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
z-index: 200;
|
||||
visibility: hidden;
|
||||
pointer-events: none;
|
||||
background: var(--theme-colors-background);
|
||||
opacity: 0;
|
||||
transition:
|
||||
opacity 0.3s ease-in-out,
|
||||
visibility 0.3s ease-in-out;
|
||||
}
|
||||
|
||||
.full-screen-player-visible {
|
||||
visibility: visible;
|
||||
pointer-events: auto;
|
||||
opacity: 1;
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
import clsx from 'clsx';
|
||||
import { lazy } from 'react';
|
||||
import { Outlet, useNavigate } from 'react-router';
|
||||
|
||||
import styles from './mobile-layout.module.css';
|
||||
|
||||
import { ContextMenuController } from '/@/renderer/features/context-menu/context-menu-controller';
|
||||
import { MobileFullscreenPlayer } from '/@/renderer/features/player/components/mobile-fullscreen-player';
|
||||
import { CommandPalette } from '/@/renderer/features/search/components/command-palette';
|
||||
import { MobileSidebar } from '/@/renderer/features/sidebar/components/mobile-sidebar';
|
||||
import { PlayerBar } from '/@/renderer/layouts/default-layout/player-bar';
|
||||
import { AppRoute } from '/@/renderer/router/routes';
|
||||
import { useFullScreenPlayerStore } from '/@/renderer/store';
|
||||
import { useCommandPalette } from '/@/renderer/store';
|
||||
import { useHotkeySettings } from '/@/renderer/store/settings.store';
|
||||
import { ActionIcon } from '/@/shared/components/action-icon/action-icon';
|
||||
import { Drawer } from '/@/shared/components/drawer/drawer';
|
||||
import { useDisclosure } from '/@/shared/hooks/use-disclosure';
|
||||
import { useHotkeys } from '/@/shared/hooks/use-hotkeys';
|
||||
|
||||
const WindowBar = lazy(() =>
|
||||
import('/@/renderer/layouts/window-bar').then((module) => ({
|
||||
default: module.WindowBar,
|
||||
})),
|
||||
);
|
||||
|
||||
interface MobileLayoutProps {
|
||||
shell?: boolean;
|
||||
}
|
||||
|
||||
export const MobileLayout = ({ shell }: MobileLayoutProps) => {
|
||||
const { opened, ...handlers } = useCommandPalette();
|
||||
const { bindings } = useHotkeySettings();
|
||||
const navigate = useNavigate();
|
||||
const [sidebarOpened, { close: closeSidebar, open: openSidebar }] = useDisclosure(false);
|
||||
const { expanded: isFullScreenPlayerExpanded } = useFullScreenPlayerStore();
|
||||
|
||||
useHotkeys([
|
||||
[bindings.globalSearch.hotkey, () => handlers.open()],
|
||||
[bindings.browserBack.hotkey, () => navigate(-1)],
|
||||
[bindings.browserForward.hotkey, () => navigate(1)],
|
||||
[bindings.navigateHome.hotkey, () => navigate(AppRoute.HOME)],
|
||||
]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className={clsx(styles.layout)} id="mobile-layout">
|
||||
{!shell && <WindowBar />}
|
||||
<ActionIcon
|
||||
className={styles.drawerButton}
|
||||
icon="menu"
|
||||
onClick={openSidebar}
|
||||
size="lg"
|
||||
tooltip={{ label: 'Menu' }}
|
||||
variant="subtle"
|
||||
/>
|
||||
<main className={styles.mainContent}>
|
||||
<Outlet />
|
||||
</main>
|
||||
<PlayerBar />
|
||||
</div>
|
||||
<Drawer
|
||||
onClose={closeSidebar}
|
||||
opened={sidebarOpened}
|
||||
position="left"
|
||||
size="320px"
|
||||
styles={{
|
||||
body: {
|
||||
height: '100%',
|
||||
padding: 0,
|
||||
},
|
||||
content: {
|
||||
height: '100%',
|
||||
width: '100%',
|
||||
},
|
||||
}}
|
||||
withCloseButton={false}
|
||||
>
|
||||
<MobileSidebar />
|
||||
</Drawer>
|
||||
<div
|
||||
className={clsx(styles.fullScreenPlayerOverlay, {
|
||||
[styles.fullScreenPlayerVisible]: isFullScreenPlayerExpanded,
|
||||
})}
|
||||
>
|
||||
<MobileFullscreenPlayer />
|
||||
</div>
|
||||
<CommandPalette modalProps={{ handlers, opened }} />
|
||||
<ContextMenuController.Root />
|
||||
</>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,17 @@
|
||||
import { useIsMobile } from '/@/renderer/hooks/use-is-mobile';
|
||||
import { DefaultLayout } from '/@/renderer/layouts/default-layout';
|
||||
import { MobileLayout } from '/@/renderer/layouts/mobile-layout/mobile-layout';
|
||||
|
||||
interface ResponsiveLayoutProps {
|
||||
shell?: boolean;
|
||||
}
|
||||
|
||||
export const ResponsiveLayout = ({ shell }: ResponsiveLayoutProps) => {
|
||||
const isMobile = useIsMobile();
|
||||
|
||||
if (isMobile) {
|
||||
return <MobileLayout shell={shell} />;
|
||||
}
|
||||
|
||||
return <DefaultLayout shell={shell} />;
|
||||
};
|
||||
Reference in New Issue
Block a user