mirror of
https://github.com/jeffvli/feishin.git
synced 2026-05-16 05:36:00 +02:00
add basic mobile responsive layout
This commit is contained in:
@@ -0,0 +1,46 @@
|
||||
.container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--mantine-spacing-xs);
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: var(--theme-colors-background-alternate);
|
||||
}
|
||||
|
||||
.scroll-area {
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
padding: 0 var(--theme-spacing-md) var(--theme-spacing-md) var(--theme-spacing-md);
|
||||
}
|
||||
|
||||
.accordion-root {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.accordion-item {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.accordion-control {
|
||||
height: 2.5rem;
|
||||
border-radius: var(--theme-radius-md);
|
||||
|
||||
&:hover {
|
||||
background: var(--theme-colors-background);
|
||||
}
|
||||
}
|
||||
|
||||
.accordion-content {
|
||||
padding: 0;
|
||||
background: var(--theme-colors-background-alternate);
|
||||
}
|
||||
|
||||
.accordion-content:last-child {
|
||||
padding-bottom: var(--theme-spacing-md);
|
||||
}
|
||||
|
||||
.server-selector-wrapper {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
import { useMemo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useLocation } from 'react-router';
|
||||
|
||||
import styles from './mobile-sidebar.module.css';
|
||||
|
||||
import { ActionBar } from '/@/renderer/features/sidebar/components/action-bar';
|
||||
import { ServerSelector } from '/@/renderer/features/sidebar/components/server-selector';
|
||||
import { SidebarIcon } from '/@/renderer/features/sidebar/components/sidebar-icon';
|
||||
import { SidebarItem } from '/@/renderer/features/sidebar/components/sidebar-item';
|
||||
import {
|
||||
SidebarPlaylistList,
|
||||
SidebarSharedPlaylistList,
|
||||
} from '/@/renderer/features/sidebar/components/sidebar-playlist-list';
|
||||
import { SidebarItemType, useGeneralSettings } from '/@/renderer/store/settings.store';
|
||||
import { Accordion } from '/@/shared/components/accordion/accordion';
|
||||
import { Group } from '/@/shared/components/group/group';
|
||||
import { ScrollArea } from '/@/shared/components/scroll-area/scroll-area';
|
||||
import { Text } from '/@/shared/components/text/text';
|
||||
|
||||
export const MobileSidebar = () => {
|
||||
const { t } = useTranslation();
|
||||
const location = useLocation();
|
||||
const { sidebarPlaylistList } = useGeneralSettings();
|
||||
|
||||
const translatedSidebarItemMap = useMemo(
|
||||
() => ({
|
||||
Albums: t('page.sidebar.albums', { postProcess: 'titleCase' }),
|
||||
Artists: t('page.sidebar.albumArtists', { postProcess: 'titleCase' }),
|
||||
'Artists-all': t('page.sidebar.artists', { postProcess: 'titleCase' }),
|
||||
Genres: t('page.sidebar.genres', { postProcess: 'titleCase' }),
|
||||
Home: t('page.sidebar.home', { postProcess: 'titleCase' }),
|
||||
'Now Playing': t('page.sidebar.nowPlaying', { postProcess: 'titleCase' }),
|
||||
Playlists: t('page.sidebar.playlists', { postProcess: 'titleCase' }),
|
||||
Search: t('page.sidebar.search', { postProcess: 'titleCase' }),
|
||||
Settings: t('page.sidebar.settings', { postProcess: 'titleCase' }),
|
||||
Tracks: t('page.sidebar.tracks', { postProcess: 'titleCase' }),
|
||||
}),
|
||||
[t],
|
||||
);
|
||||
|
||||
const { sidebarItems } = useGeneralSettings();
|
||||
|
||||
const sidebarItemsWithRoute: SidebarItemType[] = useMemo(() => {
|
||||
if (!sidebarItems) return [];
|
||||
|
||||
const items = sidebarItems
|
||||
.filter((item) => !item.disabled)
|
||||
.map((item) => ({
|
||||
...item,
|
||||
label:
|
||||
translatedSidebarItemMap[item.id as keyof typeof translatedSidebarItemMap] ??
|
||||
item.label,
|
||||
}));
|
||||
|
||||
return items;
|
||||
}, [sidebarItems, translatedSidebarItemMap]);
|
||||
|
||||
return (
|
||||
<div className={styles.container} id="mobile-sidebar">
|
||||
<Group grow id="global-search-container" style={{ flexShrink: 0 }}>
|
||||
<ActionBar />
|
||||
</Group>
|
||||
<ScrollArea allowDragScroll className={styles.scrollArea}>
|
||||
<Accordion
|
||||
classNames={{
|
||||
content: styles.accordionContent,
|
||||
control: styles.accordionControl,
|
||||
item: styles.accordionItem,
|
||||
root: styles.accordionRoot,
|
||||
}}
|
||||
defaultValue={['library', 'playlists']}
|
||||
multiple
|
||||
>
|
||||
<Accordion.Item value="library">
|
||||
<Accordion.Control>
|
||||
<Text fw={600} variant="secondary">
|
||||
{t('page.sidebar.myLibrary', {
|
||||
postProcess: 'titleCase',
|
||||
})}
|
||||
</Text>
|
||||
</Accordion.Control>
|
||||
<Accordion.Panel>
|
||||
{sidebarItemsWithRoute.map((item) => {
|
||||
return (
|
||||
<SidebarItem key={`sidebar-${item.route}`} to={item.route}>
|
||||
<Group gap="sm">
|
||||
<SidebarIcon
|
||||
active={location.pathname === item.route}
|
||||
route={item.route}
|
||||
/>
|
||||
{item.label}
|
||||
</Group>
|
||||
</SidebarItem>
|
||||
);
|
||||
})}
|
||||
</Accordion.Panel>
|
||||
</Accordion.Item>
|
||||
{sidebarPlaylistList && (
|
||||
<>
|
||||
<SidebarPlaylistList />
|
||||
<SidebarSharedPlaylistList />
|
||||
</>
|
||||
)}
|
||||
</Accordion>
|
||||
</ScrollArea>
|
||||
<div className={styles.serverSelectorWrapper}>
|
||||
<ServerSelector showImage={false} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user