Overview

The Settings Store is the central hub for global application preferences in Bimble Chat Vue. Built using Pinia's Options API, it manages theme settings, language preferences, RTL layout, sidebar state, and other UI configurations with persistence across sessions.

Key Responsibilities

Dark/Light theme management, multi-language support, RTL layout for Arabic/Urdu, sidebar state, and UI preference persistence.

Store Structure

The Settings Store uses the Options API pattern and is located at src/stores/settingsStore.ts:

import { defineStore } from "pinia";
import config from "@/types/config.ts";

export const useSettingsStore = defineStore("settingsStore", {
  state: () => ({
    setRTLLayout: config.setRTLLayout,
    activeTheme: config.activeTheme,
    isDarkMode: false,
    language: config.language || 'en',
  }),
  
  actions: { 
    SET_THEME(payload: string) {
      this.activeTheme = payload;
      this.isDarkMode = payload === 'DARK_THEME';
    },
    SET_DARK_MODE(payload: boolean) {
      this.isDarkMode = payload;
      this.activeTheme = payload ? 'DARK_THEME' : 'LIGHT_THEME';
    },
    SET_LANGUAGE(payload: string) {
      this.language = payload;
    }
  },
});

State Properties

The Settings Store maintains the following reactive state properties initialized from the config:

setRTLLayout

Enables right-to-left layout for Arabic and Urdu languages

boolean
activeTheme

Currently active theme name (LIGHT_THEME or DARK_THEME)

string
isDarkMode

Boolean flag indicating if dark mode is currently active

boolean
language

Current application language code (en, fr, es, ar, etc.)

string

Configuration Types

The Settings Store uses TypeScript configuration defined in src/types/config.ts:

export type ConfigProps = {
  setRTLLayout: boolean;
  activeTheme: string;
  language?: string; // Optional language setting
};
const config: ConfigProps = {
  setRTLLayout: false,
  activeTheme: 'LIGHT_THEME',
  language: 'en',
};

export default config;

Actions

The Settings Store provides actions for updating global application preferences:

SET_THEME

Sets the active theme and synchronizes dark mode state

SET_THEME(payload: string) {
  this.activeTheme = payload;
  // Keep isDarkMode in sync with activeTheme
  this.isDarkMode = payload === 'DARK_THEME';
}

Payload: 'LIGHT_THEME' or 'DARK_THEME'

SET_DARK_MODE

Toggles dark mode and updates the corresponding theme

SET_DARK_MODE(payload: boolean) {
  this.isDarkMode = payload;
  this.activeTheme = payload ? 'DARK_THEME' : 'LIGHT_THEME';
}

Usage: Primary method for theme switching throughout the application.

SET_LANGUAGE

Updates the application language preference

SET_LANGUAGE(payload: string) {
  this.language = payload;
}

Supported Languages: en, fr, es, ru, zh, ja, pt, hi, ar, ur

Usage Examples

Here are practical examples of using the Settings Store in Vue components:

1
Basic Theme Switcher

Create a simple theme toggle component:

<template>
  <v-btn @click="toggleTheme" icon variant="text">
    <IconSun v-if="settings.isDarkMode" />
    <IconMoon v-else />
  </v-btn>
</template>

<script setup lang="ts">
import { useSettingsStore } from '@/stores/settingsStore'
import { IconMoon, IconSun } from '@tabler/icons-vue'

const settings = useSettingsStore()

const toggleTheme = () => {
  settings.SET_DARK_MODE(!settings.isDarkMode)
}
</script>
2
Language Dropdown Component

Implement a language selection dropdown:

<template>
  <v-select
    v-model="selectedLanguage"
    :items="languages"
    item-title="name"
    item-value="code"
    @update:model-value="changeLanguage"
    label="Language"
  >
    <template #prepend-item>
      <v-list-item>
        <v-avatar size="24">
          <v-img :src="currentFlag" />
        </v-avatar>
      </v-list-item>
    </template>
  </v-select>
</template>

<script setup lang="ts">
import { computed, ref } from 'vue'
import { useSettingsStore } from '@/stores/settingsStore'
import { useI18n } from 'vue-i18n'

const settings = useSettingsStore()
const { locale } = useI18n()

const languages = ref([
  { code: 'en', name: 'English', flag: '/flags/usa.png' },
  { code: 'fr', name: 'Français', flag: '/flags/france.png' },
  { code: 'es', name: 'Español', flag: '/flags/spain.png' },
  { code: 'ar', name: 'العربية', flag: '/flags/uae.png' }
])

const selectedLanguage = computed({
  get: () => settings.language,
  set: (value) => changeLanguage(value)
})

const currentFlag = computed(() => {
  return languages.value.find(lang => lang.code === settings.language)?.flag
})

const changeLanguage = (code: string) => {
  locale.value = code
  settings.SET_LANGUAGE(code)
}
</script>
3
Layout Integration

Use settings in layout components for RTL and theme support:

<template>
  <!-- RTL Layout -->
  <v-locale-provider v-if="settings.setRTLLayout" rtl>
    <v-app :theme="settings.activeTheme">
      <SidebarNav />
      <v-main>
        <RouterView />
      </v-main>
    </v-app>
  </v-locale-provider>

  <!-- LTR Layout -->
  <v-locale-provider v-else>
    <v-app :theme="settings.activeTheme">
      <SidebarNav />
      <v-main>
        <RouterView />
      </v-main>
    </v-app>
  </v-locale-provider>
</template>

<script setup lang="ts">
import { useSettingsStore } from '@/stores/settingsStore'

const settings = useSettingsStore()
</script>

Theme Synchronization

The Settings Store ensures proper synchronization between different theme-related properties:

// Automatic synchronization in actions
SET_THEME(payload: string) {
  this.activeTheme = payload;
  // Automatically sync isDarkMode
  this.isDarkMode = payload === 'DARK_THEME';
}

SET_DARK_MODE(payload: boolean) {
  this.isDarkMode = payload;
  // Automatically sync activeTheme
  this.activeTheme = payload ? 'DARK_THEME' : 'LIGHT_THEME';
}

// Usage patterns
settings.SET_DARK_MODE(true)  // → activeTheme becomes 'DARK_THEME'
settings.SET_THEME('LIGHT_THEME')  // → isDarkMode becomes false
Synchronization Benefits

This dual approach allows components to use either boolean dark mode flags or string theme names, ensuring consistency across the application.

RTL Layout Support

The Settings Store enables complete RTL (Right-to-Left) layout support for Arabic and Urdu languages:

RTL Features
  • Automatic layout direction switching
  • RTL-aware Vuetify components
  • Proper text alignment and spacing
  • Icon and navigation adjustments
  • User preference persistence
RTL Languages
  • Arabic (ar): العربية - UAE
  • Urdu (ur): اردو - Pakistan
  • Automatic RTL activation when these languages are selected

Persistence Strategy

While the Settings Store doesn't include built-in persistence, it integrates with browser storage solutions:

// Example persistence implementation
import { watchEffect } from 'vue'

const settings = useSettingsStore()

// Watch for changes and persist to localStorage
watchEffect(() => {
  localStorage.setItem('app-settings', JSON.stringify({
    isDarkMode: settings.isDarkMode,
    language: settings.language,
    setRTLLayout: settings.setRTLLayout
  }))
})

// Restore settings on app initialization
const savedSettings = localStorage.getItem('app-settings')
if (savedSettings) {
  const parsed = JSON.parse(savedSettings)
  settings.SET_DARK_MODE(parsed.isDarkMode)
  settings.SET_LANGUAGE(parsed.language)
  // RTL layout is typically auto-determined by language
}

Best Practices

Do
  • Use computed properties for two-way binding
  • Leverage automatic theme synchronization
  • Implement persistence for user preferences
  • Handle responsive sidebar behavior
  • Use consistent action naming patterns
Avoid
  • Directly mutating state properties
  • Inconsistent theme synchronization
  • Ignoring RTL layout requirements
  • Hardcoding theme values in components
  • Forgetting to persist user preferences

Component Integration

The Settings Store is used throughout the application in various components:

ThemeSwitcher.vue

Navbar component for quick theme switching

layouts/full/navbar/
LanguageDropdown.vue

Language selection dropdown with flag icons

layouts/full/navbar/
Appearance.vue

Comprehensive appearance settings page

views/main/settings/
FullLayout.vue

Main application layout with RTL support

layouts/full/