mirror of
https://github.com/immich-app/immich
synced 2025-11-07 17:27:20 +00:00
refactor: sidebar (#18293)
This commit is contained in:
parent
f357f3324f
commit
117b263887
6 changed files with 24 additions and 24 deletions
|
|
@ -1,80 +0,0 @@
|
|||
import SideBarSection from '$lib/components/shared-components/side-bar/side-bar-section.svelte';
|
||||
import { sidebarStore } from '$lib/stores/sidebar.svelte';
|
||||
import { render, screen } from '@testing-library/svelte';
|
||||
import { vi } from 'vitest';
|
||||
|
||||
const mocks = vi.hoisted(() => {
|
||||
return {
|
||||
mobileDevice: {
|
||||
isFullSidebar: false,
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
vi.mock('$lib/stores/mobile-device.svelte', () => ({
|
||||
mobileDevice: mocks.mobileDevice,
|
||||
}));
|
||||
|
||||
vi.mock('$lib/stores/sidebar.svelte', () => ({
|
||||
sidebarStore: {
|
||||
isOpen: false,
|
||||
reset: vi.fn(),
|
||||
},
|
||||
}));
|
||||
|
||||
describe('SideBarSection component', () => {
|
||||
beforeEach(() => {
|
||||
vi.resetAllMocks();
|
||||
mocks.mobileDevice.isFullSidebar = false;
|
||||
sidebarStore.isOpen = false;
|
||||
});
|
||||
|
||||
it.each`
|
||||
isFullSidebar | isSidebarOpen | expectedInert
|
||||
${false} | ${false} | ${true}
|
||||
${false} | ${true} | ${false}
|
||||
${true} | ${false} | ${false}
|
||||
${true} | ${true} | ${false}
|
||||
`(
|
||||
'inert is $expectedInert when isFullSidebar=$isFullSidebar and isSidebarOpen=$isSidebarOpen',
|
||||
({ isFullSidebar, isSidebarOpen, expectedInert }) => {
|
||||
// setup
|
||||
mocks.mobileDevice.isFullSidebar = isFullSidebar;
|
||||
sidebarStore.isOpen = isSidebarOpen;
|
||||
|
||||
// when
|
||||
render(SideBarSection);
|
||||
const parent = screen.getByTestId('sidebar-parent');
|
||||
|
||||
// then
|
||||
expect(parent.inert).toBe(expectedInert);
|
||||
},
|
||||
);
|
||||
|
||||
it('should set width when sidebar is expanded', () => {
|
||||
// setup
|
||||
mocks.mobileDevice.isFullSidebar = false;
|
||||
sidebarStore.isOpen = true;
|
||||
|
||||
// when
|
||||
render(SideBarSection);
|
||||
const parent = screen.getByTestId('sidebar-parent');
|
||||
|
||||
// then
|
||||
expect(parent.classList).toContain('sidebar:w-[16rem]'); // sets the initial width for page load
|
||||
expect(parent.classList).toContain('w-[min(100vw,16rem)]');
|
||||
expect(parent.classList).toContain('shadow-2xl');
|
||||
});
|
||||
|
||||
it('should close the sidebar if it is open on initial render', () => {
|
||||
// setup
|
||||
mocks.mobileDevice.isFullSidebar = false;
|
||||
sidebarStore.isOpen = true;
|
||||
|
||||
// when
|
||||
render(SideBarSection);
|
||||
|
||||
// then
|
||||
expect(sidebarStore.reset).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
|
@ -1,51 +0,0 @@
|
|||
<script lang="ts">
|
||||
import { clickOutside } from '$lib/actions/click-outside';
|
||||
import { focusTrap } from '$lib/actions/focus-trap';
|
||||
import { menuButtonId } from '$lib/components/shared-components/navigation-bar/navigation-bar.svelte';
|
||||
import { mobileDevice } from '$lib/stores/mobile-device.svelte';
|
||||
import { sidebarStore } from '$lib/stores/sidebar.svelte';
|
||||
import { onMount, type Snippet } from 'svelte';
|
||||
|
||||
interface Props {
|
||||
ariaLabel?: string;
|
||||
children?: Snippet;
|
||||
}
|
||||
|
||||
let { ariaLabel, children }: Props = $props();
|
||||
|
||||
const isHidden = $derived(!sidebarStore.isOpen && !mobileDevice.isFullSidebar);
|
||||
const isExpanded = $derived(sidebarStore.isOpen && !mobileDevice.isFullSidebar);
|
||||
|
||||
onMount(() => {
|
||||
closeSidebar();
|
||||
});
|
||||
|
||||
const closeSidebar = () => {
|
||||
if (!isExpanded) {
|
||||
return;
|
||||
}
|
||||
sidebarStore.reset();
|
||||
if (isHidden) {
|
||||
document.querySelector<HTMLButtonElement>(`#${menuButtonId}`)?.focus();
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<nav
|
||||
id="sidebar"
|
||||
aria-label={ariaLabel}
|
||||
tabindex="-1"
|
||||
class="immich-scrollbar relative z-[1] w-0 sidebar:w-[16rem] overflow-y-auto overflow-x-hidden pt-8 transition-all duration-200 bg-light"
|
||||
class:shadow-2xl={isExpanded}
|
||||
class:dark:border-e-immich-dark-gray={isExpanded}
|
||||
class:border-r={isExpanded}
|
||||
class:w-[min(100vw,16rem)]={sidebarStore.isOpen}
|
||||
data-testid="sidebar-parent"
|
||||
inert={isHidden}
|
||||
use:clickOutside={{ onOutclick: closeSidebar, onEscape: closeSidebar }}
|
||||
use:focusTrap={{ active: isExpanded }}
|
||||
>
|
||||
<div class="pe-6 flex flex-col gap-1 h-max min-h-full">
|
||||
{@render children?.()}
|
||||
</div>
|
||||
</nav>
|
||||
|
|
@ -1,36 +1,36 @@
|
|||
<script lang="ts">
|
||||
import BottomInfo from '$lib/components/shared-components/side-bar/bottom-info.svelte';
|
||||
import RecentAlbums from '$lib/components/shared-components/side-bar/recent-albums.svelte';
|
||||
import Sidebar from '$lib/components/sidebar/sidebar.svelte';
|
||||
import { recentAlbumsDropdown } from '$lib/stores/preferences.store';
|
||||
import { featureFlags } from '$lib/stores/server-config.store';
|
||||
import { preferences } from '$lib/stores/user.store';
|
||||
import {
|
||||
mdiAccount,
|
||||
mdiAccountOutline,
|
||||
mdiAccountMultiple,
|
||||
mdiAccountMultipleOutline,
|
||||
mdiAccountOutline,
|
||||
mdiArchiveArrowDown,
|
||||
mdiArchiveArrowDownOutline,
|
||||
mdiFolderOutline,
|
||||
mdiHeart,
|
||||
mdiHeartOutline,
|
||||
mdiImageAlbum,
|
||||
mdiImageMultiple,
|
||||
mdiImageMultipleOutline,
|
||||
mdiLink,
|
||||
mdiMagnify,
|
||||
mdiMap,
|
||||
mdiMapOutline,
|
||||
mdiTrashCan,
|
||||
mdiTrashCanOutline,
|
||||
mdiTagMultipleOutline,
|
||||
mdiToolbox,
|
||||
mdiToolboxOutline,
|
||||
mdiFolderOutline,
|
||||
mdiTagMultipleOutline,
|
||||
mdiLink,
|
||||
mdiTrashCan,
|
||||
mdiTrashCanOutline,
|
||||
} from '@mdi/js';
|
||||
import SideBarSection from './side-bar-section.svelte';
|
||||
import SideBarLink from './side-bar-link.svelte';
|
||||
import { t } from 'svelte-i18n';
|
||||
import BottomInfo from '$lib/components/shared-components/side-bar/bottom-info.svelte';
|
||||
import { preferences } from '$lib/stores/user.store';
|
||||
import { recentAlbumsDropdown } from '$lib/stores/preferences.store';
|
||||
import RecentAlbums from '$lib/components/shared-components/side-bar/recent-albums.svelte';
|
||||
import { fly } from 'svelte/transition';
|
||||
import SideBarLink from './side-bar-link.svelte';
|
||||
|
||||
let isArchiveSelected: boolean = $state(false);
|
||||
let isFavoritesSelected: boolean = $state(false);
|
||||
|
|
@ -42,7 +42,7 @@
|
|||
let isUtilitiesSelected: boolean = $state(false);
|
||||
</script>
|
||||
|
||||
<SideBarSection ariaLabel={$t('primary')}>
|
||||
<Sidebar ariaLabel={$t('primary')}>
|
||||
<SideBarLink
|
||||
title={$t('photos')}
|
||||
routeId="/(user)/photos"
|
||||
|
|
@ -138,4 +138,4 @@
|
|||
{/if}
|
||||
|
||||
<BottomInfo />
|
||||
</SideBarSection>
|
||||
</Sidebar>
|
||||
Loading…
Add table
Add a link
Reference in a new issue