1
0
mirror of https://github.com/tabler/tabler.git synced 2025-12-21 17:34:25 +04:00

feat: Add language selector dropdown to navbar (#2526)

This commit is contained in:
Paweł Kuna
2025-11-02 20:49:13 +01:00
committed by GitHub
parent 6e656ad1de
commit 8d8727f587
16 changed files with 238 additions and 96 deletions

View File

@@ -0,0 +1,6 @@
---
"@tabler/core": minor
"@tabler/preview": minor
---
Added language selector dropdown to navbar with flag indicators for multilingual support.

View File

@@ -302,6 +302,7 @@ $backdrops: (
$border-width: 1px !default; $border-width: 1px !default;
$border-width-wide: 2px !default; $border-width-wide: 2px !default;
$border-radius-xs: 2px !default;
$border-radius-sm: 4px !default; $border-radius-sm: 4px !default;
$border-radius: 6px !default; $border-radius: 6px !default;
$border-radius-lg: 8px !default; $border-radius-lg: 8px !default;
@@ -309,6 +310,7 @@ $border-radius-pill: 100rem !default;
$border-radiuses: ( $border-radiuses: (
0: 0, 0: 0,
xs: $border-radius-xs,
sm: $border-radius-sm, sm: $border-radius-sm,
md: $border-radius, md: $border-radius,
lg: $border-radius-lg, lg: $border-radius-lg,
@@ -365,6 +367,7 @@ $avatar-sizes: (
icon-size: 0.75rem, icon-size: 0.75rem,
status-size: 0.375rem, status-size: 0.375rem,
brand-size: 0.75rem, brand-size: 0.75rem,
border-radius: $border-radius-xs,
), ),
"sm": ( "sm": (
size: 2rem, size: 2rem,
@@ -740,7 +743,7 @@ $dropdown-divider-margin-y: var(--#{$prefix}spacer-2) !default;
$tooltip-bg: var(--#{$prefix}bg-surface-inverted) !default; $tooltip-bg: var(--#{$prefix}bg-surface-inverted) !default;
$tooltip-color: var(--#{$prefix}text-inverted) !default; $tooltip-color: var(--#{$prefix}text-inverted) !default;
$tooltip-padding-y: var(--#{$prefix}spacer-1) !default; $tooltip-padding-y: var(--#{$prefix}spacer-1) !default;
$tooltip-padding-x: var(--#{$prefix}spacer-3) !default; $tooltip-padding-x: var(--#{$prefix}spacer-2) !default;
// Loader // Loader
$loader-size: 2.5rem !default; $loader-size: 2.5rem !default;
@@ -1026,7 +1029,7 @@ $legend-border-radius: var(--#{$prefix}border-radius-sm) !default;
// Flags // Flags
$flag-box-shadow: var(--#{$prefix}shadow-border) !default; $flag-box-shadow: var(--#{$prefix}shadow-border) !default;
$flag-border-radius: var(--#{$prefix}border-radius) !default; $flag-border-radius: var(--#{$prefix}border-radius-sm) !default;
$flag-sizes: $avatar-sizes !default; $flag-sizes: $avatar-sizes !default;
// Payments // Payments

View File

@@ -63,6 +63,10 @@
--#{$prefix}avatar-icon-size: #{map.get($size, icon-size)}; --#{$prefix}avatar-icon-size: #{map.get($size, icon-size)};
--#{$prefix}avatar-brand-size: #{map.get($size, brand-size)}; --#{$prefix}avatar-brand-size: #{map.get($size, brand-size)};
@if map.has-key($size, border-radius) {
border-radius: map.get($size, border-radius);
}
.badge:empty { .badge:empty {
width: map.get($size, status-size); width: map.get($size, status-size);
height: map.get($size, status-size); height: map.get($size, status-size);

View File

@@ -1,4 +1,7 @@
.dropdown-menu { .dropdown-menu {
--#{$prefix}dropdown-item-gap: .5rem;
--#{$prefix}dropdown-item-icon-size: #{$icon-size};
--#{$prefix}dropdown-item-icon-color: var(--#{$prefix}tertiary);
user-select: none; user-select: none;
background-clip: border-box; background-clip: border-box;
@@ -19,21 +22,17 @@
align-items: center; align-items: center;
margin: 0; margin: 0;
line-height: $line-height-base; line-height: $line-height-base;
gap: .5rem; gap: var(--#{$prefix}dropdown-item-gap);
} }
.dropdown-item-icon { .dropdown-item-icon {
width: $icon-size !important; width: var(--#{$prefix}dropdown-item-icon-size) !important;
height: $icon-size !important; height: var(--#{$prefix}dropdown-item-icon-size) !important;
margin-right: .5rem; color: var(--#{$prefix}dropdown-item-icon-color);
color: var(--#{$prefix}secondary);
opacity: $text-secondary-opacity;
text-align: center; text-align: center;
} }
.dropdown-item-indicator { .dropdown-item-indicator {
margin-right: .5rem;
margin-left: -.25rem;
height: 1.25rem; height: 1.25rem;
display: inline-flex; display: inline-flex;
line-height: 1; line-height: 1;

View File

@@ -7,7 +7,7 @@ $countries: (
.flag { .flag {
position: relative; position: relative;
display: inline-block; display: inline-block;
height: $avatar-size; width: $avatar-size;
aspect-ratio: 1.33333; aspect-ratio: 1.33333;
background: no-repeat center/cover; background: no-repeat center/cover;
box-shadow: $flag-box-shadow; box-shadow: $flag-box-shadow;
@@ -28,6 +28,10 @@ $countries: (
@each $flag-size, $size in $flag-sizes { @each $flag-size, $size in $flag-sizes {
.flag-#{$flag-size} { .flag-#{$flag-size} {
height: map.get($size, size); width: map.get($size, size);
@if map.has-key($size, border-radius) {
border-radius: map.get($size, border-radius);
}
} }
} }

View File

@@ -36,6 +36,7 @@ permalink: dropdowns.html
{% include "ui/dropdown-menu.html" show=true check=true %} {% include "ui/dropdown-menu.html" show=true check=true %}
{% include "ui/dropdown-menu.html" show=true radio=true %} {% include "ui/dropdown-menu.html" show=true radio=true %}
{% include "ui/dropdown-menu.html" show=true people=true %} {% include "ui/dropdown-menu.html" show=true people=true %}
{% include "ui/dropdown-menu.html" show=true flag=true %}
</div> </div>
</div> </div>

View File

@@ -0,0 +1,53 @@
[
{
"name": "United States",
"flag": "us",
"code": "us"
},
{
"name": "United Kingdom",
"flag": "gb",
"code": "gb"
},
{
"name": "Germany",
"flag": "de",
"code": "de"
},
{
"name": "France",
"flag": "fr",
"code": "fr"
},
{
"name": "Poland",
"flag": "pl",
"code": "pl"
},
{
"name": "Spain",
"flag": "es",
"code": "es"
},
{
"name": "Italy",
"flag": "it",
"code": "it"
},
{
"name": "Canada",
"flag": "ca",
"code": "ca"
},
{
"name": "Australia",
"flag": "au",
"code": "au"
},
{
"name": "Japan",
"flag": "jp",
"code": "jp"
}
]

View File

@@ -1,94 +1,112 @@
[ [
{
"name": "العربية",
"flag": "ar"
},
{ {
"name": "Čeština", "name": "Čeština",
"flag": "cz" "flag": "cz",
"code": "cs"
}, },
{ {
"name": "Deutsch", "name": "Deutsch",
"flag": "de" "flag": "de",
"code": "de"
}, },
{ {
"name": "Ελληνικά", "name": "Ελληνικά",
"flag": "gr" "flag": "gr",
"code": "el"
}, },
{ {
"name": "English", "name": "English",
"flag": "gb" "flag": "gb",
"code": "en"
}, },
{ {
"name": "Español", "name": "Español",
"flag": "es" "flag": "es",
"code": "es"
}, },
{ {
"name": "Français", "name": "Français",
"flag": "fr" "flag": "fr",
"code": "fr"
}, },
{ {
"name": "हिंदी", "name": "हिंदी",
"flag": "in" "flag": "in",
"code": "hi"
}, },
{ {
"name": "Magyar", "name": "Magyar",
"flag": "hu" "flag": "hu",
"code": "hu"
}, },
{ {
"name": "Bahasa Indonesia", "name": "Bahasa Indonesia",
"flag": "in" "flag": "id",
"code": "id"
}, },
{ {
"name": "Italiano", "name": "Italiano",
"flag": "it" "flag": "it",
"code": "it"
}, },
{ {
"name": "日本語", "name": "日本語",
"flag": "jp" "flag": "jp",
"code": "ja"
}, },
{ {
"name": "한국어", "name": "한국어",
"flag": "kr" "flag": "kr",
"code": "ko"
}, },
{ {
"name": "Nederlands (Nederland)", "name": "Nederlands (Nederland)",
"flag": "ne" "flag": "ne",
"code": "nl"
}, },
{ {
"name": "Polski", "name": "Polski",
"flag": "pl" "flag": "pl",
"code": "pl"
}, },
{ {
"name": "Português", "name": "Português",
"flag": "pt" "flag": "pt",
"code": "pt"
}, },
{ {
"name": "Română", "name": "Română",
"flag": "ro" "flag": "ro",
"code": "ro"
}, },
{ {
"name": "Русский", "name": "Русский",
"flag": "ru" "flag": "ru",
"code": "ru"
}, },
{ {
"name": "ภาษาไทย", "name": "ภาษาไทย",
"flag": "th" "flag": "th",
"code": "th"
}, },
{ {
"name": "Türkçe", "name": "Türkçe",
"flag": "tr" "flag": "tr",
"code": "tr"
}, },
{ {
"name": "Українською", "name": "Українською",
"flag": "ua" "flag": "ua",
"code": "uk"
}, },
{ {
"name": "Tiếng Việt", "name": "Tiếng Việt",
"flag": "vn" "flag": "vn",
"code": "vi"
}, },
{ {
"name": "中文", "name": "中文",
"flag": "cn" "flag": "cn",
"code": "zh"
} }
] ]

View File

@@ -0,0 +1,14 @@
<!-- BEGIN APPS -->
<div class="nav-item dropdown d-none d-md-flex">
<span data-bs-toggle="tooltip" title="Apps" data-bs-placement="bottom">
<a href="#" class="nav-link px-0" data-bs-toggle="dropdown" tabindex="-1" aria-label="Show app menu" data-bs-auto-close="outside" aria-expanded="false">
{% include "ui/icon.html" icon="apps" %}
</a>
</span>
<!-- BEGIN NAVBAR APPS -->
<div class="dropdown-menu dropdown-menu-arrow dropdown-menu-end dropdown-menu-card">
{% include "cards/navbar-apps.html" %}
</div>
<!-- END NAVBAR APPS -->
</div>
<!-- END APPS -->

View File

@@ -0,0 +1,17 @@
<!-- BEGIN LANGUAGE SELECTOR -->
<div class="nav-item dropdown d-none d-md-flex">
<span data-bs-toggle="tooltip" title="Select language" data-bs-placement="bottom">
<a href="#" class="nav-link px-0" data-bs-toggle="dropdown" tabindex="-1" aria-label="Select language"
data-bs-auto-close="outside" aria-expanded="false">
EN
</a>
</span>
<div class="dropdown-menu dropdown-menu-arrow dropdown-menu-end">
{% for language in languages %}
<a class="dropdown-item" href="#" data-lang="{{ language.code }}">
{{ language.name }}
</a>
{% endfor %}
</div>
</div>
<!-- END LANGUAGE SELECTOR -->

View File

@@ -0,0 +1,15 @@
<!-- BEGIN NOTIFICATIONS -->
<div class="nav-item dropdown d-none d-md-flex">
<span data-bs-toggle="tooltip" title="Notifications" data-bs-placement="bottom">
<a href="#" class="nav-link px-0" data-bs-toggle="dropdown" tabindex="-1" aria-label="Show notifications" data-bs-auto-close="outside" aria-expanded="false">
{% include "ui/icon.html" icon="bell" %}
<span class="badge bg-red"></span>
</a>
</span>
<!-- BEGIN NAVBAR NOTIFICATIONS -->
<div class="dropdown-menu dropdown-menu-arrow dropdown-menu-end dropdown-menu-card">
{% include "cards/navbar-notifications.html" %}
</div>
<!-- END NAVBAR NOTIFICATIONS -->
</div>
<!-- END NOTIFICATIONS -->

View File

@@ -0,0 +1,13 @@
<!-- BEGIN THEME TOGGLE -->
<div class="nav-item">
<a href="?theme=dark" class="nav-link px-0 hide-theme-dark" title="Enable dark mode" data-bs-toggle="tooltip"
data-bs-placement="bottom">
{% include "ui/icon.html" icon="moon" %}
</a>
<a href="?theme=light" class="nav-link px-0 hide-theme-light" title="Enable light mode" data-bs-toggle="tooltip"
data-bs-placement="bottom">
{% include "ui/icon.html" icon="sun" %}
</a>
</div>
<!-- END THEME TOGGLE -->

View File

@@ -0,0 +1,24 @@
<!-- BEGIN USER MENU -->
{% assign person-id = include.person-id | default: 1 %}
{% assign person = people[person-id] %}
<div class="nav-item dropdown">
<a href="#" class="nav-link d-flex lh-1 p-0 px-2" data-bs-toggle="dropdown" aria-label="Open user menu">
{% include "ui/avatar.html" person-id=person-id size="sm" %}
{% unless include.hide-username %}
<div class="d-none d-xl-block ps-2">
<div>{{ person.full_name }}</div>
<div class="mt-1 small text-secondary">{{ person.job_title }}</div>
</div>
{% endunless %}
</a>
<div class="dropdown-menu dropdown-menu-end dropdown-menu-arrow"{% if include.dark %} data-bs-theme="light"{% endif %}>
<a class="dropdown-item" href="{{ page | relative }}/profile.html">{% include "ui/icon.html" icon="user" class="dropdown-item-icon" %} Profile</a>
<a class="dropdown-item" href="#">{% include "ui/icon.html" icon="chart-pie" class="dropdown-item-icon" %} Analytics</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item" href="{{ page | relative }}/settings.html">Settings &amp; Privacy</a>
<a class="dropdown-item" href="#">Help</a>
<a class="dropdown-item" href="{{ page | relative }}/sign-in.html">Sign out</a>
</div>
</div>
<!-- END USER MENU -->

View File

@@ -11,62 +11,24 @@
</div> </div>
{% endunless %} {% endunless %}
<div class="d-none d-{{ include.breakpoint }}-flex"> {% if include.show-theme-toggle or include.show-notifications or include.show-apps or include.show-language-selector %}
<div class="nav-item"> <div class="d-none d-{{ include.breakpoint }}-flex me-3">
<a href="?theme=dark" class="nav-link px-0 hide-theme-dark" title="Enable dark mode" data-bs-toggle="tooltip" {% if include.show-theme-toggle %}
data-bs-placement="bottom"> {% include "layout/navbar-side-theme.html" %}
{% include "ui/icon.html" icon="moon" %} {% endif %}
</a> {% if include.show-notifications %}
{% include "layout/navbar-side-notifications.html" %}
{% endif %}
{% if include.show-apps %}
{% include "layout/navbar-side-apps.html" %}
{% endif %}
{% if include.show-language-selector %}
{% include "layout/navbar-side-language.html" %}
{% endif %}
</div>
{% endif %}
<a href="?theme=light" class="nav-link px-0 hide-theme-light" title="Enable light mode" data-bs-toggle="tooltip" {% if include.show-user %}
data-bs-placement="bottom"> {% include "layout/navbar-side-user.html" person-id=person-id hide-username=include.hide-username dark=include.dark %}
{% include "ui/icon.html" icon="sun" %} {% endif %}
</a>
</div>
<div class="nav-item dropdown d-none d-md-flex">
<a href="#" class="nav-link px-0" data-bs-toggle="dropdown" tabindex="-1" aria-label="Show notifications" data-bs-auto-close="outside" aria-expanded="false">
{% include "ui/icon.html" icon="bell" %}
<span class="badge bg-red"></span>
</a>
<!-- BEGIN NAVBAR NOTIFICATIONS -->
<div class="dropdown-menu dropdown-menu-arrow dropdown-menu-end dropdown-menu-card">
{% include "cards/navbar-notifications.html" %}
</div>
<!-- END NAVBAR NOTIFICATIONS -->
</div>
<div class="nav-item dropdown d-none d-md-flex me-3">
<a href="#" class="nav-link px-0" data-bs-toggle="dropdown" tabindex="-1" aria-label="Show app menu" data-bs-auto-close="outside" aria-expanded="false">
{% include "ui/icon.html" icon="apps" %}
</a>
<!-- BEGIN NAVBAR APPS -->
<div class="dropdown-menu dropdown-menu-arrow dropdown-menu-end dropdown-menu-card">
{% include "cards/navbar-apps.html" %}
</div>
<!-- END NAVBAR APPS -->
</div>
</div>
<div class="nav-item dropdown">
<a href="#" class="nav-link d-flex lh-1 p-0 px-2" data-bs-toggle="dropdown" aria-label="Open user menu">
{% include "ui/avatar.html" person-id=person-id size="sm" %}
{% unless include.hide-username %}
<div class="d-none d-xl-block ps-2">
<div>{{ person.full_name }}</div>
<div class="mt-1 small text-secondary">{{ person.job_title }}</div>
</div>
{% endunless %}
</a>
<!-- BEGIN USER MENU -->
<div class="dropdown-menu dropdown-menu-end dropdown-menu-arrow"{% if include.dark %} data-bs-theme="light"{% endif %}>
<a href="#" class="dropdown-item">Status</a>
<a href="{{ page | relative }}/profile.html" class="dropdown-item">Profile</a>
<a href="#" class="dropdown-item">Feedback</a>
<div class="dropdown-divider"></div>
<a href="{{ page | relative }}/settings.html" class="dropdown-item">Settings</a>
<a href="{{ page | relative }}/sign-in.html" class="dropdown-item">Logout</a>
</div>
<!-- END USER MENU -->
</div>
</div> </div>

View File

@@ -1,5 +1,10 @@
{% assign breakpoint = include.breakpoint | default: 'md' %} {% assign breakpoint = include.breakpoint | default: 'md' %}
{% assign condensed = include.condensed | default: false %} {% assign condensed = include.condensed | default: false %}
{% assign show-theme = include.show-theme | default: true %}
{% assign show-notifications = include.show-notifications | default: true %}
{% assign show-apps = include.show-apps | default: true %}
{% assign show-language = include.show-language | default: true %}
{% assign show-user = include.show-user | default: true %}
{% if include.sticky %} {% if include.sticky %}
<div class="sticky-top"> <div class="sticky-top">
@@ -13,7 +18,7 @@
{% include "layout/navbar-logo.html" small-logo=include.small-logo hide-logo=include.hide-logo class="d-none-navbar-horizontal pe-0 pe-md-3" breakpoint=breakpoint show-title=include.show-title header=true %} {% include "layout/navbar-logo.html" small-logo=include.small-logo hide-logo=include.hide-logo class="d-none-navbar-horizontal pe-0 pe-md-3" breakpoint=breakpoint show-title=include.show-title header=true %}
{% endunless %} {% endunless %}
{% include "layout/navbar-side.html" class="order-md-last" hide-username=include.hide-username condensed=condensed person-id=include.person-id breakpoint=breakpoint dark=include.dark %} {% include "layout/navbar-side.html" class="order-md-last" hide-username=include.hide-username condensed=condensed person-id=include.person-id breakpoint=breakpoint dark=include.dark show-theme-toggle=show-theme show-notifications=show-notifications show-apps=show-apps show-language-selector=show-language show-user=show-user %}
{% if condensed %} {% if condensed %}
<div class="collapse navbar-collapse" id="navbar-menu"> <div class="collapse navbar-collapse" id="navbar-menu">

View File

@@ -24,7 +24,11 @@
{% endfor %} {% endfor %}
{% elsif include.people %} {% elsif include.people %}
{% for person in people limit: 5 %} {% for person in people limit: 5 %}
<a href="#" class="dropdown-item">{% include "ui/avatar.html" person-id=person.id class="rounded me-2" size="xs" %} {{ person.full_name }}</a> <a href="#" class="dropdown-item">{% include "ui/avatar.html" person-id=person.id size="xs" %} {{ person.full_name }}</a>
{% endfor %}
{% elsif include.flag %}
{% for country in countries limit: 5 %}
<a href="#" class="dropdown-item">{% include "ui/flag.html" flag=country.flag size="xs" %} {{ country.name }}</a>
{% endfor %} {% endfor %}
{% elsif include.type == 'text' %} {% elsif include.type == 'text' %}