refactor: sidebar (#18293)

This commit is contained in:
Jason Rasmussen 2025-05-14 15:11:31 -04:00 committed by GitHub
parent f357f3324f
commit 117b263887
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 24 additions and 24 deletions

View file

@ -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();
});
});

View file

@ -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>

View file

@ -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>