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
activeTheme
Currently active theme name (LIGHT_THEME or DARK_THEME)
isDarkMode
Boolean flag indicating if dark mode is currently active
language
Current application language code (en, fr, es, ar, etc.)
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:
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>
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>
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
LanguageDropdown.vue
Language selection dropdown with flag icons
Appearance.vue
Comprehensive appearance settings page
FullLayout.vue
Main application layout with RTL support