From 8d8727f587805f466932b82e582c6b81ede19908 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Kuna?= <1282324+codecalm@users.noreply.github.com> Date: Sun, 2 Nov 2025 20:49:13 +0100 Subject: [PATCH] feat: Add language selector dropdown to navbar (#2526) --- .changeset/language-selector.md | 6 ++ core/scss/_variables.scss | 7 +- core/scss/ui/_avatars.scss | 4 + core/scss/ui/_dropdowns.scss | 15 ++-- core/scss/ui/_flags.scss | 8 +- preview/pages/dropdowns.html | 1 + shared/data/countries.json | 53 +++++++++++++ shared/data/languages.json | 70 +++++++++++------- shared/includes/layout/navbar-side-apps.html | 14 ++++ .../includes/layout/navbar-side-language.html | 17 +++++ .../layout/navbar-side-notifications.html | 15 ++++ shared/includes/layout/navbar-side-theme.html | 13 ++++ shared/includes/layout/navbar-side-user.html | 24 ++++++ shared/includes/layout/navbar-side.html | 74 +++++-------------- shared/includes/layout/navbar.html | 7 +- shared/includes/ui/dropdown-menu.html | 6 +- 16 files changed, 238 insertions(+), 96 deletions(-) create mode 100644 .changeset/language-selector.md create mode 100644 shared/data/countries.json create mode 100644 shared/includes/layout/navbar-side-apps.html create mode 100644 shared/includes/layout/navbar-side-language.html create mode 100644 shared/includes/layout/navbar-side-notifications.html create mode 100644 shared/includes/layout/navbar-side-theme.html create mode 100644 shared/includes/layout/navbar-side-user.html diff --git a/.changeset/language-selector.md b/.changeset/language-selector.md new file mode 100644 index 000000000..8e1eb38d9 --- /dev/null +++ b/.changeset/language-selector.md @@ -0,0 +1,6 @@ +--- +"@tabler/core": minor +"@tabler/preview": minor +--- + +Added language selector dropdown to navbar with flag indicators for multilingual support. diff --git a/core/scss/_variables.scss b/core/scss/_variables.scss index 39c2659ca..66f4cb461 100644 --- a/core/scss/_variables.scss +++ b/core/scss/_variables.scss @@ -302,6 +302,7 @@ $backdrops: ( $border-width: 1px !default; $border-width-wide: 2px !default; +$border-radius-xs: 2px !default; $border-radius-sm: 4px !default; $border-radius: 6px !default; $border-radius-lg: 8px !default; @@ -309,6 +310,7 @@ $border-radius-pill: 100rem !default; $border-radiuses: ( 0: 0, + xs: $border-radius-xs, sm: $border-radius-sm, md: $border-radius, lg: $border-radius-lg, @@ -365,6 +367,7 @@ $avatar-sizes: ( icon-size: 0.75rem, status-size: 0.375rem, brand-size: 0.75rem, + border-radius: $border-radius-xs, ), "sm": ( size: 2rem, @@ -740,7 +743,7 @@ $dropdown-divider-margin-y: var(--#{$prefix}spacer-2) !default; $tooltip-bg: var(--#{$prefix}bg-surface-inverted) !default; $tooltip-color: var(--#{$prefix}text-inverted) !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-size: 2.5rem !default; @@ -1026,7 +1029,7 @@ $legend-border-radius: var(--#{$prefix}border-radius-sm) !default; // Flags $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; // Payments diff --git a/core/scss/ui/_avatars.scss b/core/scss/ui/_avatars.scss index 900cfee81..89b5f6983 100644 --- a/core/scss/ui/_avatars.scss +++ b/core/scss/ui/_avatars.scss @@ -63,6 +63,10 @@ --#{$prefix}avatar-icon-size: #{map.get($size, icon-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 { width: map.get($size, status-size); height: map.get($size, status-size); diff --git a/core/scss/ui/_dropdowns.scss b/core/scss/ui/_dropdowns.scss index ddf31bf64..54004a9ea 100644 --- a/core/scss/ui/_dropdowns.scss +++ b/core/scss/ui/_dropdowns.scss @@ -1,4 +1,7 @@ .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; background-clip: border-box; @@ -19,21 +22,17 @@ align-items: center; margin: 0; line-height: $line-height-base; - gap: .5rem; + gap: var(--#{$prefix}dropdown-item-gap); } .dropdown-item-icon { - width: $icon-size !important; - height: $icon-size !important; - margin-right: .5rem; - color: var(--#{$prefix}secondary); - opacity: $text-secondary-opacity; + width: var(--#{$prefix}dropdown-item-icon-size) !important; + height: var(--#{$prefix}dropdown-item-icon-size) !important; + color: var(--#{$prefix}dropdown-item-icon-color); text-align: center; } .dropdown-item-indicator { - margin-right: .5rem; - margin-left: -.25rem; height: 1.25rem; display: inline-flex; line-height: 1; diff --git a/core/scss/ui/_flags.scss b/core/scss/ui/_flags.scss index 141dda1d5..43c81a9b1 100644 --- a/core/scss/ui/_flags.scss +++ b/core/scss/ui/_flags.scss @@ -7,7 +7,7 @@ $countries: ( .flag { position: relative; display: inline-block; - height: $avatar-size; + width: $avatar-size; aspect-ratio: 1.33333; background: no-repeat center/cover; box-shadow: $flag-box-shadow; @@ -28,6 +28,10 @@ $countries: ( @each $flag-size, $size in $flag-sizes { .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); + } } } \ No newline at end of file diff --git a/preview/pages/dropdowns.html b/preview/pages/dropdowns.html index de2824a03..1733476bf 100644 --- a/preview/pages/dropdowns.html +++ b/preview/pages/dropdowns.html @@ -36,6 +36,7 @@ permalink: dropdowns.html {% 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 people=true %} + {% include "ui/dropdown-menu.html" show=true flag=true %} diff --git a/shared/data/countries.json b/shared/data/countries.json new file mode 100644 index 000000000..c8f9b6fbb --- /dev/null +++ b/shared/data/countries.json @@ -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" + } +] + diff --git a/shared/data/languages.json b/shared/data/languages.json index 8e44b6132..5322a519b 100644 --- a/shared/data/languages.json +++ b/shared/data/languages.json @@ -1,94 +1,112 @@ [ - { - "name": "العربية", - "flag": "ar" - }, { "name": "Čeština", - "flag": "cz" + "flag": "cz", + "code": "cs" }, { "name": "Deutsch", - "flag": "de" + "flag": "de", + "code": "de" }, { "name": "Ελληνικά", - "flag": "gr" + "flag": "gr", + "code": "el" }, { "name": "English", - "flag": "gb" + "flag": "gb", + "code": "en" }, { "name": "Español", - "flag": "es" + "flag": "es", + "code": "es" }, { "name": "Français", - "flag": "fr" + "flag": "fr", + "code": "fr" }, { "name": "हिंदी", - "flag": "in" + "flag": "in", + "code": "hi" }, { "name": "Magyar", - "flag": "hu" + "flag": "hu", + "code": "hu" }, { "name": "Bahasa Indonesia", - "flag": "in" + "flag": "id", + "code": "id" }, { "name": "Italiano", - "flag": "it" + "flag": "it", + "code": "it" }, { "name": "日本語", - "flag": "jp" + "flag": "jp", + "code": "ja" }, { "name": "한국어", - "flag": "kr" + "flag": "kr", + "code": "ko" }, { "name": "Nederlands (Nederland)", - "flag": "ne" + "flag": "ne", + "code": "nl" }, { "name": "Polski", - "flag": "pl" + "flag": "pl", + "code": "pl" }, { "name": "Português", - "flag": "pt" + "flag": "pt", + "code": "pt" }, { "name": "Română", - "flag": "ro" + "flag": "ro", + "code": "ro" }, { "name": "Русский", - "flag": "ru" + "flag": "ru", + "code": "ru" }, { "name": "ภาษาไทย", - "flag": "th" + "flag": "th", + "code": "th" }, { "name": "Türkçe", - "flag": "tr" + "flag": "tr", + "code": "tr" }, { "name": "Українською", - "flag": "ua" + "flag": "ua", + "code": "uk" }, { "name": "Tiếng Việt", - "flag": "vn" + "flag": "vn", + "code": "vi" }, { "name": "中文", - "flag": "cn" + "flag": "cn", + "code": "zh" } ] \ No newline at end of file diff --git a/shared/includes/layout/navbar-side-apps.html b/shared/includes/layout/navbar-side-apps.html new file mode 100644 index 000000000..1f7b2c815 --- /dev/null +++ b/shared/includes/layout/navbar-side-apps.html @@ -0,0 +1,14 @@ + +
+ diff --git a/shared/includes/layout/navbar-side-language.html b/shared/includes/layout/navbar-side-language.html new file mode 100644 index 000000000..a056c0758 --- /dev/null +++ b/shared/includes/layout/navbar-side-language.html @@ -0,0 +1,17 @@ + + + diff --git a/shared/includes/layout/navbar-side-notifications.html b/shared/includes/layout/navbar-side-notifications.html new file mode 100644 index 000000000..0a3f064f4 --- /dev/null +++ b/shared/includes/layout/navbar-side-notifications.html @@ -0,0 +1,15 @@ + + + diff --git a/shared/includes/layout/navbar-side-theme.html b/shared/includes/layout/navbar-side-theme.html new file mode 100644 index 000000000..f1a762e16 --- /dev/null +++ b/shared/includes/layout/navbar-side-theme.html @@ -0,0 +1,13 @@ + + + diff --git a/shared/includes/layout/navbar-side-user.html b/shared/includes/layout/navbar-side-user.html new file mode 100644 index 000000000..731773760 --- /dev/null +++ b/shared/includes/layout/navbar-side-user.html @@ -0,0 +1,24 @@ + +{% assign person-id = include.person-id | default: 1 %} +{% assign person = people[person-id] %} + + diff --git a/shared/includes/layout/navbar-side.html b/shared/includes/layout/navbar-side.html index ff64ea27f..15dd1aa6f 100644 --- a/shared/includes/layout/navbar-side.html +++ b/shared/includes/layout/navbar-side.html @@ -11,62 +11,24 @@ {% endunless %} -