Global Components

Global components are centrally managed features that provide consistent user interaction patterns across the entire application. These components are rendered globally in App.vue and controlled via Pinia stores, ensuring a unified user experience.

Overview

All global components follow a centralized architecture pattern:


LoadingOverlay

File: src/components/global/LoadingOverlay.vue
Store: src/stores/loadingOverlay.ts

A full-screen loading overlay that displays during API operations.

Features

Store API

// State
visible: boolean     // Controls overlay visibility
disabled: boolean    // When true, show() calls are ignored

// Actions
show(): void        // Display the loading overlay
hide(): void        // Hide the loading overlay
disable(): void     // Disable overlay and hide if currently visible
enable(): void      // Re-enable overlay functionality

Usage Example

import { useLoadingOverlayStore } from "@/stores/loadingOverlay";

const loadingStore = useLoadingOverlayStore();

// Show loading during API call
const fetchData = async () => {
  try {
    loadingStore.show();
    await apiCall();
  } finally {
    loadingStore.hide();
  }
};

Styling

Note: The application uses a centralized color system (useColors, COLOR_MAP, THEME_CLASS_MAP) for consistent Tailwind fragments across the UI. See the Theme and Colors guide: Theme and Colors.


ErrorDisplay

File: src/components/global/ErrorDisplay.vue
Store: src/stores/errorDisplay.ts

Displays error, warning, and informational messages to users below the application header.

Features

Store API

// Types
interface ErrorMessage {
  id: string
  type: 'error' | 'warning' | 'info'
  text: string
  timestamp: number
}

// State
messages: ErrorMessage[]  // Array of current messages

// Actions
addMessage(type: 'error'|'warning'|'info', text: string): string  // Returns message ID
removeMessage(id: string): void     // Remove specific message
clearAll(): void                    // Clear all messages

Usage Example

import { useErrorDisplayStore } from "@/stores/errorDisplay";

const errorStore = useErrorDisplayStore();

// Add different message types
errorStore.addMessage("info", "Data saved successfully!");
errorStore.addMessage("warning", "Please review your input.");
errorStore.addMessage("error", "Failed to save. Please try again.");

Message Behavior

Styling


DeleteConfirmation

File: src/components/global/DeleteConfirmation.vue
Store: src/stores/deleteConfirmation.ts

A modal dialog for confirming destructive delete operations.

Features

Store API

// State
visible: boolean              // Modal visibility
title: string                // Modal title
description: string          // Modal description text
result: 'cancel'|'delete'|null  // User's choice

// Actions
trigger(title: string, description: string): Promise<'cancel'|'delete'>
resolve(result: 'cancel'|'delete'): void
cancel(): void               // Shorthand for resolve('cancel')
confirmDelete(): void        // Shorthand for resolve('delete')

Usage Example

import { useDeleteConfirmationStore } from "@/stores/deleteConfirmation";

const deleteStore = useDeleteConfirmationStore();

const handleDelete = async (item: Item) => {
  const result = await deleteStore.trigger(
    "Delete Item",
    `Are you sure you want to delete "${item.name}"? This action cannot be undone.`,
  );

  if (result === "delete") {
    await performDelete(item.id);
  }
};

Accessibility


CancelChangesConfirmation

File: src/components/global/CancelChangesConfirmation.vue
Store: src/stores/cancelChangesConfirmation.ts

Prevents accidental data loss by confirming navigation away from forms with unsaved changes.

Features

Store API

// State
visible: boolean                    // Modal visibility
pendingChanges: boolean            // Tracks if there are unsaved changes
title: string                      // Modal title
description: string                // Modal description
result: 'stay'|'leave'|null       // User's choice

// Actions
trigger(title: string, description: string): Promise<'stay'|'leave'>
resolve(result: 'stay'|'leave'): void
stay(): void                       // Shorthand for resolve('stay')
leave(): void                      // Shorthand for resolve('leave')
addChange(): void                  // Mark that changes exist
resetChanges(): void               // Clear pending changes flag

Usage Example

import { useCancelChangesConfirmationStore } from "@/stores/cancelChangesConfirmation";

const cancelChangesStore = useCancelChangesConfirmationStore();

// Track form changes
watch(
  formData,
  () => {
    cancelChangesStore.addChange();
  },
  { deep: true },
);

// Handle navigation with unsaved changes
const handleNavigation = async () => {
  if (cancelChangesStore.pendingChanges) {
    const result = await cancelChangesStore.trigger(
      "Unsaved Changes",
      "You have unsaved changes. Are you sure you want to leave?",
    );

    if (result === "leave") {
      router.push("/other-page");
    }
  }
};

// Reset after successful save
const saveForm = async () => {
  await saveData();
  cancelChangesStore.resetChanges();
};

Integration Patterns


Component Integration

App.vue Structure

<template>
  <div id="app">
    <AppHeader />
    <ErrorDisplay />
    <!-- Positioned below header -->
    <main>
      <RouterView />
    </main>
    <AppFooter />

    <!-- Global Modals -->
    <LoadingOverlay />
    <DeleteConfirmation />
    <CancelChangesConfirmation />
  </div>
</template>

Store Dependencies

All global components require their respective Pinia stores to be imported and used in consuming components:

// In any Vue component
import { useLoadingOverlayStore } from "@/stores/loadingOverlay";
import { useErrorDisplayStore } from "@/stores/errorDisplay";
import { useDeleteConfirmationStore } from "@/stores/deleteConfirmation";
import { useCancelChangesConfirmationStore } from "@/stores/cancelChangesConfirmation";

Best Practices

  1. Loading States: Always show loading during async operations
  2. Error Handling: Provide clear, actionable error messages
  3. Confirmation Dialogs: Use for all destructive actions
  4. Change Tracking: Protect user work with unsaved change detection
  5. Consistent Messaging: Use standardized success/error message patterns
  6. Accessibility: Ensure proper focus management and keyboard navigation

Testing Considerations


Technical Notes

Performance

Browser Compatibility

Maintenance