Files
web-app-launcher/src/lib/components/layout/MainLayout.svelte
T
alexei.dolgolyov 477c0e4d52 feat(phase2): localization EN/RU + additional widget types
- Add svelte-i18n with 224 translation keys (English + Russian)
- Language switcher in header (EN/RU toggle, persists to localStorage)
- Extract all hardcoded strings from 37 component/page files
- Add 4 new widget types: Bookmark, Note (markdown), Embed (iframe), Status
- WidgetRenderer dispatches by type, WidgetGrid supports full-width widgets
- Type-specific config forms in board editor
- Install marked for markdown rendering
2026-03-24 23:18:05 +03:00

69 lines
1.6 KiB
Svelte

<script lang="ts">
import { t } from 'svelte-i18n';
import type { Snippet } from 'svelte';
import Sidebar from './Sidebar.svelte';
import Header from './Header.svelte';
import AmbientBackground from '$lib/components/background/AmbientBackground.svelte';
import SearchDialog from '$lib/components/search/SearchDialog.svelte';
import { ui } from '$lib/stores/ui.svelte.js';
interface BoardLink {
id: string;
name: string;
icon: string | null;
}
interface UserInfo {
displayName: string;
email: string;
role: string;
avatarUrl?: string | null;
}
interface Props {
user: UserInfo | null;
boards: BoardLink[];
children: Snippet;
}
let { user, boards, children }: Props = $props();
const isAdmin = $derived(user?.role === 'admin');
</script>
<!-- Ambient Background (fixed, behind everything) -->
<AmbientBackground />
<div class="relative z-10 flex h-screen overflow-hidden">
<!-- Mobile overlay -->
{#if ui.isMobile && !ui.sidebarHidden}
<button
type="button"
class="fixed inset-0 z-30 bg-black/50"
onclick={() => ui.closeMobileSidebar()}
aria-label={$t('sidebar.close')}
></button>
{/if}
<!-- Sidebar -->
{#if !ui.sidebarHidden || !ui.isMobile}
<div
class="shrink-0 {ui.isMobile ? 'fixed left-0 top-0 z-40 h-full' : 'relative'}"
>
<Sidebar {boards} {isAdmin} collapsed={ui.isMobile ? false : ui.sidebarCollapsed} />
</div>
{/if}
<!-- Main content area -->
<div class="flex min-w-0 flex-1 flex-col overflow-hidden">
<Header {user} />
<main class="flex-1 overflow-y-auto">
{@render children()}
</main>
</div>
</div>
<!-- Search Dialog (modal, z-50) -->
<SearchDialog />