How-To: Customizing Application UI with useSettings
¶
The useSettings
composable provides a powerful system for customizing the application's visual identity and UI elements in VC-Shell applications. This guide demonstrates how to effectively manage and apply UI customization settings such as logos, titles, and user-specific elements.
Prerequisites¶
- Understanding of Vue 3 Composition API and reactive properties.
- Familiarity with the
useSettings
composable (see useSettings API Reference). - Basic knowledge of VC-Shell's application structure and component hierarchy.
- Understanding of Vue's lifecycle hooks and computed properties.
Core Concept¶
The useSettings
composable provides two main approaches for UI customization:
- Server-Side Settings: Automatically loads UI customization from the backend
- Runtime Customization: Override settings programmatically using
applySettings
- Reactive Updates: All changes are reactive and immediately reflected in the UI
- Default Fallbacks: Graceful handling of missing or undefined settings
The system integrates with VC-Shell's UI components to provide consistent branding across the application.
import { useSettings } from '@vc-shell/framework';
const { uiSettings, loading, applySettings } = useSettings();
// Access current settings
console.log(uiSettings.value.title); // Application title
console.log(uiSettings.value.logo); // Application logo URL
// Override settings
applySettings({
title: 'My Custom App',
logo: '/my-logo.svg'
});
Implementation Strategies¶
1. Main Application Setup¶
Configure the root application component with dynamic UI settings:
<!-- App.vue -->
<template>
<VcApp
:is-ready="isReady"
:logo="uiSettings.logo"
:title="uiSettings.title"
:version="version"
/>
</template>
<script lang="ts" setup>
import { useSettings, useUser } from '@vc-shell/framework';
import { onMounted, ref } from 'vue';
import logoImage from '/assets/logo.svg';
const { isAuthenticated } = useUser();
const { uiSettings, applySettings } = useSettings();
const isReady = ref(false);
const version = import.meta.env.PACKAGE_VERSION;
onMounted(async () => {
try {
if (isAuthenticated.value) {
await customizationHandler();
isReady.value = true;
}
} catch (error) {
console.error('Failed to initialize app:', error);
// Set ready anyway to prevent blocking
isReady.value = true;
}
});
async function customizationHandler() {
// Apply settings with fallbacks
applySettings({
title: uiSettings.value?.title || 'Default App Title',
logo: uiSettings.value?.logo || logoImage,
});
}
</script>
2. Authentication Pages with Branding¶
Apply consistent branding to login and authentication pages through router configuration:
// router/routes.ts
import { RouteRecordRaw } from 'vue-router';
import { Login, Invite, ResetPassword, ChangePasswordPage } from '@vc-shell/framework';
import whiteLogoImage from '/assets/logo-white.svg';
import bgImage from '/assets/background.jpg';
import { useLogin } from '../composables';
const version = import.meta.env.PACKAGE_VERSION;
export const routes: RouteRecordRaw[] = [
// ... other routes
{
name: 'Login',
path: '/login',
component: Login,
meta: {
appVersion: version,
},
props: () => ({
logo: whiteLogoImage,
background: bgImage,
title: 'Vendor Portal',
}),
},
{
name: 'Invite',
path: '/invite',
component: Invite,
props: (route) => ({
userId: route.query.userId,
token: route.query.token,
userName: route.query.userName,
logo: whiteLogoImage,
background: bgImage,
}),
},
{
name: 'ResetPassword',
path: '/resetpassword',
component: ResetPassword,
props: (route) => ({
userId: route.query.userId,
token: route.query.token,
userName: route.query.userName,
logo: whiteLogoImage,
background: bgImage,
}),
},
{
name: 'ChangePassword',
path: '/changepassword',
component: ChangePasswordPage,
meta: {
forced: true,
},
props: () => ({
background: bgImage,
}),
},
];
Key Points:
- Authentication pages receive branding through router props, not
useSettings
- Use
props
function in route configuration to pass logo, background, and title - Framework authentication components (Login, Invite, ResetPassword) accept these props directly
- This approach ensures branding is available immediately without waiting for settings to load
3. Dynamic Settings Based on User Context¶
Customize application settings based on user authentication and context:
<!-- App.vue -->
<script lang="ts" setup>
import { useSettings, useUser } from '@vc-shell/framework';
import { onMounted, ref, watch } from 'vue';
import defaultLogo from '/assets/logo.svg';
const { user, isAuthenticated } = useUser();
const { uiSettings, applySettings } = useSettings();
const isReady = ref(false);
// Watch for authentication changes
watch(isAuthenticated, async (authenticated) => {
if (authenticated) {
await applyUserSpecificSettings();
}
}, { immediate: true });
onMounted(async () => {
if (isAuthenticated.value) {
await applyUserSpecificSettings();
}
isReady.value = true;
});
async function applyUserSpecificSettings() {
try {
// Apply settings based on user context
const customSettings = {
title: determineApplicationTitle(),
logo: determineApplicationLogo(),
avatar: user.value?.avatarUrl,
role: user.value?.roles?.[0] || 'User'
};
applySettings(customSettings);
} catch (error) {
console.error('Failed to apply user settings:', error);
// Apply fallback settings
applySettings({
title: 'Portal',
logo: defaultLogo
});
}
}
function determineApplicationTitle(): string {
// Customize title based on user role or organization
if (user.value?.isAdministrator) {
return 'Admin Portal';
}
if (user.value?.organizationName) {
return `${user.value.organizationName} Portal`;
}
return uiSettings.value?.title || 'Portal';
}
function determineApplicationLogo(): string {
// Customize logo based on user organization or preferences
if (user.value?.organizationLogo) {
return user.value.organizationLogo;
}
return uiSettings.value?.logo || defaultLogo;
}
</script>
Best Practices¶
-
Loading states: Always handle loading states when working with settings to prevent UI flicker.
-
Fallback values: Provide meaningful default values for all UI elements that depend on settings.
-
Error handling: Implement proper error handling for settings loading and application failures.
-
Performance: Use computed properties for reactive settings access to optimize re-rendering.
-
Persistence: Consider implementing local fallbacks for critical UI settings.