feat: Lightroom-style workspace UI #2

Merged
iu merged 18 commits from feature/lightroom-workspace-ui into develop 2026-10-10 19:56:23 +00:00
3 changed files with 40 additions and 2 deletions
Showing only changes of commit ba605402ce - Show all commits
@@ -24,13 +24,29 @@
let railWidth = $state(RAIL.def); let railWidth = $state(RAIL.def);
let panelWidth = $state(PANEL.def); let panelWidth = $state(PANEL.def);
let isFullscreen = $state(false);
onMount(() => { onMount(() => {
const r = parseInt(localStorage.getItem(RAIL.key) ?? '', 10); const r = parseInt(localStorage.getItem(RAIL.key) ?? '', 10);
if (r >= RAIL.min && r <= RAIL.max) railWidth = r; if (r >= RAIL.min && r <= RAIL.max) railWidth = r;
const p = parseInt(localStorage.getItem(PANEL.key) ?? '', 10); const p = parseInt(localStorage.getItem(PANEL.key) ?? '', 10);
if (p >= PANEL.min && p <= PANEL.max) panelWidth = p; if (p >= PANEL.min && p <= PANEL.max) panelWidth = p;
const onFs = () => (isFullscreen = !!document.fullscreenElement);
document.addEventListener('fullscreenchange', onFs);
onFs();
return () => document.removeEventListener('fullscreenchange', onFs);
}); });
async function toggleFullscreen() {
try {
if (document.fullscreenElement) await document.exitFullscreen();
else await document.documentElement.requestFullscreen();
} catch {
/* недоступно */
}
}
function startResize(side: 'left' | 'right', ev: PointerEvent) { function startResize(side: 'left' | 'right', ev: PointerEvent) {
ev.preventDefault(); ev.preventDefault();
const cfg = side === 'left' ? RAIL : PANEL; const cfg = side === 'left' ? RAIL : PANEL;
@@ -134,6 +150,16 @@
</a> </a>
{/if} {/if}
<ThemeSwitcher /> <ThemeSwitcher />
<button
type="button"
class="text-text-muted hover:bg-bg-muted hover:text-text inline-flex items-center justify-center rounded-md p-1.5"
aria-label={isFullscreen ? 'Выйти из полноэкранного режима' : 'На весь экран'}
title={isFullscreen ? 'Выйти из полноэкранного режима' : 'На весь экран'}
aria-pressed={isFullscreen}
onclick={toggleFullscreen}
>
<Icon name={isFullscreen ? 'fullscreen_exit' : 'fullscreen'} />
</button>
</div> </div>
</header> </header>
+3 -1
View File
@@ -43,7 +43,9 @@ export const icons = {
check: { path: '<path fill="currentColor" d="m9.55 18l-5.7-5.7l1.425-1.425L9.55 15.15l9.175-9.175L20.15 7.4z"/>' }, check: { path: '<path fill="currentColor" d="m9.55 18l-5.7-5.7l1.425-1.425L9.55 15.15l9.175-9.175L20.15 7.4z"/>' },
menu: { path: '<path fill="currentColor" d="M3 18v-2h18v2zm0-5v-2h18v2zm0-5V6h18v2z"/>' }, menu: { path: '<path fill="currentColor" d="M3 18v-2h18v2zm0-5v-2h18v2zm0-5V6h18v2z"/>' },
grid_view: { path: '<path fill="currentColor" d="M3 3v8h8V3zm10 0v8h8V3zM3 13v8h8v-8zm10 0v8h8v-8z"/>' }, grid_view: { path: '<path fill="currentColor" d="M3 3v8h8V3zm10 0v8h8V3zM3 13v8h8v-8zm10 0v8h8v-8z"/>' },
wallpaper: { path: '<path fill="currentColor" d="M4 4h7V2H4c-1.1 0-2 .9-2 2v7h2zm6 9l-4 5h12l-3-4l-2.03 2.71zm7-4.5c0-.83-.67-1.5-1.5-1.5S14 7.67 14 8.5s.67 1.5 1.5 1.5S17 9.33 17 8.5M20 2h-7v2h7v7h2V4c0-1.1-.9-2-2-2m0 18h-7v2h7c1.1 0 2-.9 2-2v-7h-2zM4 13H2v7c0 1.1.9 2 2 2h7v-2H4z"/>' } wallpaper: { path: '<path fill="currentColor" d="M4 4h7V2H4c-1.1 0-2 .9-2 2v7h2zm6 9l-4 5h12l-3-4l-2.03 2.71zm7-4.5c0-.83-.67-1.5-1.5-1.5S14 7.67 14 8.5s.67 1.5 1.5 1.5S17 9.33 17 8.5M20 2h-7v2h7v7h2V4c0-1.1-.9-2-2-2m0 18h-7v2h7c1.1 0 2-.9 2-2v-7h-2zM4 13H2v7c0 1.1.9 2 2 2h7v-2H4z"/>' },
fullscreen: { path: '<path fill="currentColor" d="M7 14H5v5h5v-2H7zm-2-4h2V7h3V5H5zm12 7h-3v2h5v-5h-2zM14 5v2h3v3h2V5z"/>' },
fullscreen_exit: { path: '<path fill="currentColor" d="M5 16h3v3h2v-5H5zm3-8H5v2h5V5H8zm6 11h2v-3h3v-2h-5zm2-11v3h-2v2h5V5z"/>' }
} satisfies Record<string, IconDef>; } satisfies Record<string, IconDef>;
export type IconName = keyof typeof icons; export type IconName = keyof typeof icons;
@@ -155,7 +155,17 @@
<div <div
class="border-border bg-chrome sticky top-0 z-10 flex items-center justify-between gap-3 border-b px-3 py-2" class="border-border bg-chrome sticky top-0 z-10 flex items-center justify-between gap-3 border-b px-3 py-2"
> >
<div class="flex min-w-0 items-center gap-1">
<a
href="/"
class="text-text-muted hover:bg-bg-muted hover:text-text inline-flex shrink-0 items-center justify-center rounded-md p-1.5"
aria-label="Ко всем альбомам"
title="Ко всем альбомам"
>
<Icon name="arrow_back" class="size-5" />
</a>
<h1 class="text-text truncate text-sm font-medium">{album?.title ?? ''}</h1> <h1 class="text-text truncate text-sm font-medium">{album?.title ?? ''}</h1>
</div>
<div class="flex items-center gap-3"> <div class="flex items-center gap-3">
<DensityControl /> <DensityControl />
{#if canUpload} {#if canUpload}