mirror of
https://github.com/imfing/hextra.git
synced 2025-08-23 02:36:57 -04:00
feat(navbar): language switcher (#760)
* feat(navbar): language switcher * docs: add language-switch * chore: just for the demo * fix: drop conflicting CSS * fix: use constant * fix: pre-existing bug with rtl on mobile * docs: add comment to explain the algo * chore: more readable algo * review Co-authored-by: Xin <5097752+imfing@users.noreply.github.com> * feat: different icons * feat: icon as param * fix: inconsitency with rtl * fix: render inside the sidebar * chore: remove the demo --------- Co-authored-by: Xin <5097752+imfing@users.noreply.github.com>
This commit is contained in:

committed by
GitHub

parent
b2ff662c8e
commit
363b1e50ff
@@ -7,11 +7,32 @@
|
||||
const optionsElement = switcher.nextElementSibling;
|
||||
optionsElement.classList.toggle('hx:hidden');
|
||||
|
||||
// Calculate position of language options element
|
||||
// Calculate the position of a language options element.
|
||||
const switcherRect = switcher.getBoundingClientRect();
|
||||
const translateY = switcherRect.top - window.innerHeight - 15;
|
||||
optionsElement.style.transform = `translate3d(${switcherRect.left}px, ${translateY}px, 0)`;
|
||||
|
||||
// Must be called before optionsElement.clientWidth.
|
||||
optionsElement.style.minWidth = `${Math.max(switcherRect.width, 50)}px`;
|
||||
|
||||
const isOnTop = switcher.dataset.location === 'top';
|
||||
const isRTL = document.body.dir === 'rtl'
|
||||
|
||||
// Stuck on the left side of the switcher.
|
||||
let translateX = switcherRect.left;
|
||||
|
||||
if (isOnTop && !isRTL || !isOnTop && isRTL) {
|
||||
// Stuck on the right side of the switcher.
|
||||
translateX = switcherRect.right - optionsElement.clientWidth;
|
||||
}
|
||||
|
||||
// Stuck on the top of the switcher.
|
||||
let translateY = switcherRect.top - window.innerHeight - 15;
|
||||
|
||||
if (isOnTop) {
|
||||
// Stuck on the bottom of the switcher.
|
||||
translateY = switcherRect.top - window.innerHeight + 180;
|
||||
}
|
||||
|
||||
optionsElement.style.transform = `translate3d(${translateX}px, ${translateY}px, 0)`;
|
||||
});
|
||||
});
|
||||
|
||||
|
@@ -69,6 +69,15 @@ menu:
|
||||
- name: Theme Toggle
|
||||
params:
|
||||
type: theme-toggle
|
||||
label: true # optional, default is false
|
||||
```
|
||||
6. مُبدِّل اللغة
|
||||
```yaml
|
||||
- name: مُبدِّل اللغة
|
||||
params:
|
||||
type: language-switch
|
||||
label: true # optional, default is false
|
||||
icon: "globe-alt" # optional, default is "translate"
|
||||
```
|
||||
|
||||
این آیتمهای منو را میتوان با تنظیم پارامتر `weight` مرتب کرد.
|
||||
|
@@ -69,6 +69,15 @@ menu:
|
||||
- name: Theme Toggle
|
||||
params:
|
||||
type: theme-toggle
|
||||
label: true # optional, default is false
|
||||
```
|
||||
6. 言語スイッチャー
|
||||
```yaml
|
||||
- name: 言語スイッチャー
|
||||
params:
|
||||
type: language-switch
|
||||
label: true # optional, default is false
|
||||
icon: "globe-alt" # optional, default is "translate"
|
||||
```
|
||||
|
||||
これらのメニュー項目は `weight` パラメータを設定することで並べ替えられます。
|
||||
|
@@ -69,6 +69,15 @@ There are different types of menu items:
|
||||
- name: Theme Toggle
|
||||
params:
|
||||
type: theme-toggle
|
||||
label: true # optional, default is false
|
||||
```
|
||||
6. Language Switcher
|
||||
```yaml
|
||||
- name: Language Switcher
|
||||
params:
|
||||
type: language-switch
|
||||
label: true # optional, default is false
|
||||
icon: "globe-alt" # optional, default is "translate"
|
||||
```
|
||||
|
||||
These menu items can be sorted by setting the `weight` parameter.
|
||||
|
@@ -69,6 +69,15 @@ menu:
|
||||
- name: Theme Toggle
|
||||
params:
|
||||
type: theme-toggle
|
||||
label: true # optional, default is false
|
||||
```
|
||||
6. 语言切换器
|
||||
```yaml
|
||||
- name: 语言切换器
|
||||
params:
|
||||
type: language-switch
|
||||
label: true # optional, default is false
|
||||
icon: "globe-alt" # optional, default is "translate"
|
||||
```
|
||||
|
||||
通过设置 `weight` 参数可以调整菜单项的排序。
|
||||
|
@@ -1,4 +1,9 @@
|
||||
{{- $page := .context -}}
|
||||
{{- $iconName := .iconName | default "globe-alt" -}}
|
||||
{{- $iconHeight := .iconHeight | default 12 -}}
|
||||
{{- $location := .location -}}
|
||||
|
||||
{{- $class := .class | default "hx:h-7 hx:px-2 hx:text-xs hx:text-gray-600 hx:transition-colors hx:dark:text-gray-400 hx:hover:bg-gray-100 hx:hover:text-gray-900 hx:dark:hover:bg-primary-100/5 hx:dark:hover:text-gray-50" -}}
|
||||
|
||||
{{- $grow := .grow -}}
|
||||
{{- $hideLabel := .hideLabel | default false -}}
|
||||
@@ -10,12 +15,13 @@
|
||||
<button
|
||||
title="{{ $changeLanguage }}"
|
||||
data-state="closed"
|
||||
class="hextra-language-switcher hx:cursor-pointer hx:h-7 hx:rounded-md hx:px-2 hx:text-left hx:text-xs hx:font-medium hx:text-gray-600 hx:transition-colors hx:dark:text-gray-400 hx:hover:bg-gray-100 hx:hover:text-gray-900 hx:dark:hover:bg-primary-100/5 hx:dark:hover:text-gray-50 hx:grow"
|
||||
data-location="{{ $location }}"
|
||||
class="hextra-language-switcher hx:cursor-pointer hx:rounded-md hx:text-left hx:font-medium {{ $class }} hx:grow"
|
||||
type="button"
|
||||
aria-label="{{ $changeLanguage }}"
|
||||
>
|
||||
<div class="hx:flex hx:items-center hx:gap-2 hx:capitalize">
|
||||
{{- partial "utils/icon" (dict "name" "globe-alt" "attributes" "height=12") -}}
|
||||
{{- partial "utils/icon" (dict "name" $iconName "attributes" (printf "height=%d" $iconHeight)) -}}
|
||||
{{- if not $hideLabel }}<span>{{ site.Language.LanguageName }}</span>{{ end -}}
|
||||
</div>
|
||||
</button>
|
||||
|
@@ -7,6 +7,7 @@
|
||||
{{ end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- $page := . -}}
|
||||
{{- $iconHeight := 24 -}}
|
||||
|
||||
<div class="hextra-nav-container hx:sticky hx:top-0 hx:z-20 hx:w-full hx:bg-transparent hx:print:hidden">
|
||||
@@ -39,6 +40,8 @@
|
||||
</a>
|
||||
{{- else if eq .Params.type "theme-toggle" -}}
|
||||
{{- partial "theme-toggle.html" (dict "iconHeight" $iconHeight "class" "hx:p-2" "hideLabel" (not .Params.label)) -}}
|
||||
{{- else if eq .Params.type "language-switch" -}}
|
||||
{{- partial "language-switch" (dict "context" $page "grow" false "hideLabel" (not .Params.label) "iconName" (.Params.icon | default "translate") "iconHeight" $iconHeight "location" "top" "class" "hx:p-2") -}}
|
||||
{{- else -}}
|
||||
{{- $active := or ($currentPage.HasMenuCurrent "main" .) ($currentPage.IsMenuCurrent "main" .) -}}
|
||||
{{- $activeClass := cond $active "hx:font-medium" "hx:text-gray-600 hx:hover:text-gray-800 hx:dark:text-gray-400 hx:dark:hover:text-gray-200" -}}
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{{- $hideLabel := .hideLabel -}}
|
||||
{{- $iconHeight := .iconHeight | default 12 -}}
|
||||
{{- $class := .class | default "hx:px-2 hx:text-xs hx:hover:bg-gray-100 hx:hover:text-gray-900 hx:dark:hover:bg-primary-100/5 hx:dark:hover:text-gray-50 hx:font-medium hx:text-gray-600 hx:transition-colors hx:dark:text-gray-400" -}}
|
||||
{{- $class := .class | default "hx:h-7 hx:px-2 hx:text-xs hx:hover:bg-gray-100 hx:hover:text-gray-900 hx:dark:hover:bg-primary-100/5 hx:dark:hover:text-gray-50 hx:font-medium hx:text-gray-600 hx:transition-colors hx:dark:text-gray-400" -}}
|
||||
|
||||
{{- $changeTheme := (T "changeTheme") | default "Change theme" -}}
|
||||
{{- $light := (T "light") | default "Light" -}}
|
||||
|
Reference in New Issue
Block a user