feat: add language switcher component with flag icons for English and Thai locales.

This commit is contained in:
supalerk-ar66 2026-01-19 16:09:07 +07:00
parent ada40b05e8
commit 38137f62c1
3 changed files with 39 additions and 18 deletions

View file

@ -15,10 +15,8 @@ const availableLocales = computed(() => {
}))
})
// Get current locale display (TH or EN)
const currentLocaleDisplay = computed(() => {
return locale.value.toUpperCase()
})
// Get flag image path for a locale
const getFlagPath = (code: string) => `/flags/${code}.png`
// Handle locale change
const changeLocale = async (code: string) => {
@ -34,14 +32,19 @@ const changeLocale = async (code: string) => {
class="language-btn"
:aria-label="$t('language.label')"
>
<span class="language-text">{{ currentLocaleDisplay }}</span>
<!-- Show current locale flag -->
<img
:src="getFlagPath(locale)"
:alt="locale.toUpperCase()"
class="flag-icon"
/>
<q-menu
anchor="bottom right"
self="top right"
class="language-menu"
>
<q-list style="min-width: 150px">
<q-list style="min-width: 180px">
<q-item-label header class="text-xs font-bold uppercase tracking-wider" style="color: var(--text-secondary);">
{{ $t('language.label') }}
</q-item-label>
@ -56,7 +59,11 @@ const changeLocale = async (code: string) => {
class="language-item"
>
<q-item-section avatar>
<span class="text-lg">{{ loc.code === 'th' ? '🇹🇭' : '🇺🇸' }}</span>
<img
:src="getFlagPath(loc.code)"
:alt="loc.code.toUpperCase()"
class="flag-icon-menu"
/>
</q-item-section>
<q-item-section>
<q-item-label class="font-semibold" style="color: var(--text-primary);">
@ -81,21 +88,33 @@ const changeLocale = async (code: string) => {
.language-btn {
width: 40px;
height: 40px;
background: linear-gradient(135deg, var(--primary) 0%, #2f5ed7 100%);
color: white;
background: #ffffff;
border: 2px solid var(--border-color);
transition: all 0.3s ease;
box-shadow: 0 2px 8px rgba(75, 130, 247, 0.3);
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
overflow: hidden;
padding: 0;
}
.language-btn:hover {
transform: scale(1.05);
box-shadow: 0 4px 12px rgba(75, 130, 247, 0.4);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
border-color: var(--primary);
}
.language-text {
font-size: 12px;
font-weight: 800;
letter-spacing: 0.5px;
.flag-icon {
width: 28px;
height: 28px;
object-fit: cover;
border-radius: 50%;
}
.flag-icon-menu {
width: 28px;
height: 20px;
object-fit: cover;
border-radius: 4px;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
}
.language-item {
@ -120,12 +139,14 @@ const changeLocale = async (code: string) => {
}
:global(.dark) .language-btn {
background: linear-gradient(135deg, #3b82f6 0%, #1e40af 100%);
box-shadow: 0 2px 8px rgba(59, 130, 246, 0.4);
background: #1e293b;
border-color: rgba(255, 255, 255, 0.15);
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
}
:global(.dark) .language-btn:hover {
box-shadow: 0 4px 12px rgba(59, 130, 246, 0.5);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.4);
border-color: var(--primary);
}
:global(.dark) :deep(.language-menu) {

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB