Layout Components

Application structure and navigation components

Layout Components Overview

Layout components define the overall structure and navigation of the DesQTA application. These components are located in src/lib/components/ and handle app-wide concerns like headers, sidebars, and navigation.

Main Layout Components

AppHeader

The main application header with navigation, search, and user controls.

<script lang="ts">
  import AppHeader from '$lib/components/AppHeader.svelte';
  
  let sidebarOpen = $state(false);
  let weatherEnabled = $state(true);
  let weatherData = $state<any>(null);
  let userInfo = $state<UserInfo | undefined>(undefined);
  let showUserDropdown = $state(false);
  
  function toggleSidebar() {
    sidebarOpen = !sidebarOpen;
  }
  
  function toggleUserDropdown() {
    showUserDropdown = !showUserDropdown;
  }
  
  function handleLogout() {
    // Logout logic
  }
  
  function showAbout() {
    // Show about modal
  }
</script>

<AppHeader
  {sidebarOpen}
  {weatherEnabled}
  {weatherData}
  {userInfo}
  {showUserDropdown}
  onToggleSidebar={toggleSidebar}
  onToggleUserDropdown={toggleUserDropdown}
  onLogout={handleLogout}
  onShowAbout={showAbout}
/>

Props:

  • sidebarOpen: boolean - Sidebar visibility state
  • weatherEnabled: boolean - Show weather widget
  • weatherData: any - Weather data object
  • userInfo: UserInfo | undefined - Current user information
  • showUserDropdown: boolean - User dropdown visibility
  • onToggleSidebar: () => void - Toggle sidebar callback
  • onToggleUserDropdown: () => void - Toggle user dropdown callback
  • onLogout: () => void - Logout callback
  • onShowAbout: () => void - Show about modal callback
  • disableSchoolPicture: boolean - Hide school picture

Features:

  • Global search
  • Sidebar toggle
  • Weather widget
  • User dropdown
  • Window controls (minimize, maximize, close)
  • Notification bell
  • Pages menu

AppSidebar

Navigation sidebar with menu items and collapsible sections.

<script lang="ts">
  import AppSidebar from '$lib/components/AppSidebar.svelte';
  
  let open = $state(true);
  let currentPath = $state('/dashboard');
</script>

<AppSidebar {open} {currentPath} />

Props:

  • open: boolean - Sidebar visibility
  • currentPath: string - Current route path

Features:

  • Collapsible navigation
  • Active route highlighting
  • Icon support
  • Nested menu items
  • Keyboard navigation

PagesMenu

Dropdown menu for quick navigation to main pages.

<script lang="ts">
  import PagesMenu from '$lib/components/PagesMenu.svelte';
</script>

<PagesMenu />

Menu Items:

  • Dashboard
  • Assessments
  • Timetable
  • Messages
  • Courses
  • Study
  • Folios
  • Settings

UserDropdown

User profile dropdown with account options.

<script lang="ts">
  import UserDropdown from '$lib/components/UserDropdown.svelte';
  
  let userInfo = $state<UserInfo | undefined>(undefined);
  let open = $state(false);
  
  function handleLogout() {
    // Logout logic
  }
  
  function showProfile() {
    // Show profile
  }
  
  function showSettings() {
    // Show settings
  }
</script>

<UserDropdown
  {userInfo}
  {open}
  onLogout={handleLogout}
  onShowProfile={showProfile}
  onShowSettings={showSettings}
/>

Props:

  • userInfo: UserInfo | undefined - User information
  • open: boolean - Dropdown visibility
  • onLogout: () => void - Logout callback
  • onShowProfile: () => void - Show profile callback
  • onShowSettings: () => void - Show settings callback

Menu Items:

  • Profile
  • Settings
  • About
  • Logout

ProfileSwitcher

Component for switching between user profiles (if multiple profiles are available).

<script lang="ts">
  import ProfileSwitcher from '$lib/components/ProfileSwitcher.svelte';
  
  let profiles = $state<Profile[]>([]);
  let currentProfile = $state<Profile | null>(null);
  
  function switchProfile(profile: Profile) {
    currentProfile = profile;
    // Switch logic
  }
</script>

<ProfileSwitcher
  {profiles}
  {currentProfile}
  onSwitch={switchProfile}
/>

Props:

  • profiles: Profile[] - Available profiles
  • currentProfile: Profile | null - Currently active profile
  • onSwitch: (profile: Profile) => void - Profile switch callback

LanguageSelector

Language selection component for i18n.

<script lang="ts">
  import LanguageSelector from '$lib/components/LanguageSelector.svelte';
  
  let currentLanguage = $state('en');
  let availableLanguages = $state(['en', 'fr', 'es']);
  
  function changeLanguage(lang: string) {
    currentLanguage = lang;
    // Change language logic
  }
</script>

<LanguageSelector
  {currentLanguage}
  {availableLanguages}
  onChange={changeLanguage}
/>

Props:

  • currentLanguage: string - Current language code
  • availableLanguages: string[] - Available language codes
  • onChange: (lang: string) => void - Language change callback

Search Components

GlobalSearchOptimized

Optimized global search component with debouncing and result caching.

<script lang="ts">
  import GlobalSearchOptimized from '$lib/components/search/GlobalSearchOptimized.svelte';
  
  let open = $state(false);
  let query = $state('');
</script>

<GlobalSearchOptimized bind:open bind:query />

Props:

  • open: boolean - Search modal visibility (use bind:open)
  • query: string - Search query (use bind:query)

Features:

  • Debounced search
  • Result caching
  • Keyboard shortcuts (Ctrl+K / Cmd+K)
  • Recent searches
  • Quick actions

SearchModal

Modal wrapper for the search interface.

<script lang="ts">
  import SearchModal from '$lib/components/search/SearchModal.svelte';
  
  let open = $state(false);
</script>

<SearchModal bind:open />

Props:

  • open: boolean - Modal visibility (use bind:open)

Widget Components

WeatherWidget

Weather display widget for the header.

<script lang="ts">
  import WeatherWidget from '$lib/components/WeatherWidget.svelte';
  
  let weatherData = $state({
    temperature: 22,
    condition: 'Sunny',
    icon: 'sun'
  });
</script>

<WeatherWidget {weatherData} />

Props:

  • weatherData: WeatherData - Weather information

WeatherData Interface:

interface WeatherData {
  temperature: number;
  condition: string;
  icon: string;
  location?: string;
}

ShortcutsWidget

Keyboard shortcuts reference widget.

<script lang="ts">
  import ShortcutsWidget from '$lib/components/ShortcutsWidget.svelte';
  
  let open = $state(false);
</script>

<ShortcutsWidget bind:open />

Props:

  • open: boolean - Widget visibility (use bind:open)

Shortcuts:

  • Ctrl/Cmd + K: Global search
  • Ctrl/Cmd + B: Toggle sidebar
  • Ctrl/Cmd + ,: Settings
  • Esc: Close modals

WelcomePortal

Welcome screen shown on first launch or when logged out.

<script lang="ts">
  import WelcomePortal from '$lib/components/WelcomePortal.svelte';
  
  function handleLogin() {
    // Login logic
  }
</script>

<WelcomePortal onLogin={handleLogin} />

Props:

  • onLogin: () => void - Login callback

Base modal component for dialogs and overlays.

<script lang="ts">
  import Modal from '$lib/components/Modal.svelte';
  
  let open = $state(false);
  let title = $state('Modal Title');
</script>

<Modal bind:open {title}>
  {#snippet children()}
    <p>Modal content goes here</p>
  {/snippet}
  
  {#snippet footer()}
    <Button onclick={() => open = false}>Close</Button>
  {/snippet}
</Modal>

Props:

  • open: boolean - Modal visibility (use bind:open)
  • title: string - Modal title
  • size: 'sm' | 'md' | 'lg' | 'xl' | 'full' - Modal size
  • closable: boolean - Show close button
  • onClose: () => void - Close callback
  • children: Snippet - Main content
  • footer: Snippet - Footer content

AboutModal

About dialog showing app information and version.

<script lang="ts">
  import AboutModal from '$lib/components/AboutModal.svelte';
  
  let open = $state(false);
</script>

<AboutModal bind:open />

Props:

  • open: boolean - Modal visibility (use bind:open)

Displays:

  • App name and version
  • License information
  • Credits
  • Links to documentation

CloudSyncModal

Modal for managing cloud sync settings.

<script lang="ts">
  import CloudSyncModal from '$lib/components/CloudSyncModal.svelte';
  
  let open = $state(false);
</script>

<CloudSyncModal bind:open />

Props:

  • open: boolean - Modal visibility (use bind:open)

Features:

  • Enable/disable sync
  • Sync status
  • Last sync time
  • Manual sync trigger

TroubleshootingModal

Modal with troubleshooting information and diagnostics.

<script lang="ts">
  import TroubleshootingModal from '$lib/components/TroubleshootingModal.svelte';
  
  let open = $state(false);
</script>

<TroubleshootingModal bind:open />

Props:

  • open: boolean - Modal visibility (use bind:open)

Features:

  • Common issues and solutions
  • Diagnostic information
  • Log viewer
  • Reset options

Dialog for customizing menu item order.

<script lang="ts">
  import MenuOrderDialog from '$lib/components/MenuOrderDialog.svelte';
  
  let open = $state(false);
  let menuItems = $state<MenuItem[]>([]);
</script>

<MenuOrderDialog bind:open {menuItems} />

Props:

  • open: boolean - Dialog visibility (use bind:open)
  • menuItems: MenuItem[] - Menu items to reorder

Features:

  • Drag and drop reordering
  • Save/cancel actions
  • Reset to default

Onboarding Components

Onboarding

First-time user onboarding flow.

<script lang="ts">
  import Onboarding from '$lib/components/Onboarding.svelte';
  
  let open = $state(true);
  
  function completeOnboarding() {
    open = false;
    // Save onboarding completion
  }
</script>

<Onboarding bind:open onComplete={completeOnboarding} />

Props:

  • open: boolean - Onboarding visibility (use bind:open)
  • onComplete: () => void - Completion callback

Steps:

  1. Welcome
  2. Features overview
  3. Settings setup
  4. Quick tour

Layout Patterns

Standard Page Layout

<script lang="ts">
  import AppHeader from '$lib/components/AppHeader.svelte';
  import AppSidebar from '$lib/components/AppSidebar.svelte';
  
  let sidebarOpen = $state(true);
  let currentPath = $state('/dashboard');
</script>

<div class="flex flex-col h-screen">
  <AppHeader {sidebarOpen} onToggleSidebar={() => sidebarOpen = !sidebarOpen} />
  
  <div class="flex flex-1 overflow-hidden">
    <AppSidebar {open} {currentPath} />
    
    <main class="flex-1 overflow-auto p-6">
      <!-- Page content -->
    </main>
  </div>
</div>
<script lang="ts">
  import Modal from '$lib/components/Modal.svelte';
  import { Button } from '$lib/components/ui';
  
  let modalOpen = $state(false);
</script>

<Modal bind:open={modalOpen} title="Example Modal">
  {#snippet children()}
    <p>Modal content</p>
  {/snippet}
  
  {#snippet footer()}
    <div class="flex gap-2 justify-end">
      <Button variant="ghost" onclick={() => modalOpen = false}>Cancel</Button>
      <Button variant="primary" onclick={() => modalOpen = false}>Save</Button>
    </div>
  {/snippet}
</Modal>

Full-Screen Layout

<script lang="ts">
  import AppHeader from '$lib/components/AppHeader.svelte';
</script>

<div class="flex flex-col h-screen">
  <AppHeader />
  
  <main class="flex-1 overflow-auto">
    <!-- Full-screen content -->
  </main>
</div>

Responsive Behavior

Mobile Layout

On mobile devices:

  • Sidebar becomes a drawer
  • Header adjusts for smaller screens
  • Modals become full-screen
  • Navigation uses bottom tabs

Desktop Layout

On desktop:

  • Sidebar is always visible (can be collapsed)
  • Header shows all controls
  • Modals are centered
  • Navigation uses sidebar

Best Practices

  1. Consistent Layout: Use the standard layout pattern for all pages
  2. Responsive Design: Ensure layouts work on all screen sizes
  3. Keyboard Navigation: Support keyboard shortcuts for common actions
  4. Accessibility: Include proper ARIA labels and roles
  5. State Management: Keep layout state at the appropriate level
  6. Performance: Lazy load heavy components like modals

Next Steps