feat(tabs): add icon support for tabs (#926)

* feat(tabs): add icon support for tabs

- Introduced an `icon` property for tabs to display icons alongside tab labels.
- Updated the tabs shortcode and HTML partials to accommodate the new icon feature.
- Enhanced documentation for tabs to include examples of using icons in tab definitions.

* chore: rebuild css

* doc(tabs): add icon support in tab documentation for multiple languages

- Enhanced documentation for tabs to include examples of using the `icon` parameter in Persian, Japanese, and Simplified Chinese.
- Updated the tab shortcode examples to demonstrate how to display icons alongside tab labels.

* chore: regenerate compiled css

* fix(a11y): add aria-hidden to decorative tab icons

Add aria-hidden="true" to tab icon SVGs so screen readers skip
decorative icons and only announce the tab name. Update @example
docblock in tab.html to demonstrate the icon parameter.

* doc(tabs): improve icon section with better examples and icon page link

Rename "Tabs With Icons" heading to "Add Icons" for consistency with
other action-oriented section titles. Replace JSON/YAML/TOML icon
example with Photos/Music/Videos using photograph, music-note, and
film icons that naturally match their labels. Add link to the Icon
shortcode page so users can discover available icon names.
This commit is contained in:
Xin
2026-02-14 21:23:25 +00:00
committed by GitHub
parent 88aa6098f0
commit 62196dd666
9 changed files with 107 additions and 11 deletions

File diff suppressed because one or more lines are too long

View File

@@ -36,9 +36,10 @@
document.querySelectorAll('.hextra-tabs-toggle').forEach((button) => {
button.addEventListener('click', function (e) {
const container = e.target.parentElement;
const targetButton = e.currentTarget;
const container = targetButton.parentElement;
const index = Array.from(container.querySelectorAll('.hextra-tabs-toggle')).indexOf(
e.target
targetButton
);
if (container.dataset.tabGroup) {

View File

@@ -52,6 +52,30 @@ next: /docs/guide/deploy-site
{{< /tabs >}}
### افزودن آیکون
با استفاده از پارامتر `icon` برای هر `tab` می‌توانید قبل از عنوان تب آیکون نمایش دهید.
برای مشاهده لیست آیکون‌های موجود، صفحه [شورت‌کد آیکون](../icon) را ببینید.
```
{{</* tabs */>}}
{{</* tab name="Photos" icon="photograph" */>}}مدیریت و سازماندهی کتابخانه عکس‌های شما.{{</* /tab */>}}
{{</* tab name="Music" icon="music-note" */>}}مرور و پخش آهنگ‌های مورد علاقه شما.{{</* /tab */>}}
{{</* tab name="Videos" icon="film" */>}}تماشا و پخش محتوای ویدیویی.{{</* /tab */>}}
{{</* /tabs */>}}
```
{{< tabs >}}
{{< tab name="Photos" icon="photograph" >}}مدیریت و سازماندهی کتابخانه عکس‌های شما.{{< /tab >}}
{{< tab name="Music" icon="music-note" >}}مرور و پخش آهنگ‌های مورد علاقه شما.{{< /tab >}}
{{< tab name="Videos" icon="film" >}}تماشا و پخش محتوای ویدیویی.{{< /tab >}}
{{< /tabs >}}
### استفاده از Markdown
نحو Markdown شامل بلوک کد نیز پشتیبانی می‌شود:

View File

@@ -52,6 +52,30 @@ next: /docs/guide/deploy-site
{{< /tabs >}}
### アイコンを追加する
各タブに `icon` を指定すると、ラベルの前にアイコンを表示できます。
利用可能なアイコンの一覧は [Icon ショートコード](../icon) ページを参照してください。
```
{{</* tabs */>}}
{{</* tab name="Photos" icon="photograph" */>}}写真ライブラリを管理・整理します。{{</* /tab */>}}
{{</* tab name="Music" icon="music-note" */>}}お気に入りの曲を閲覧・再生します。{{</* /tab */>}}
{{</* tab name="Videos" icon="film" */>}}動画コンテンツを視聴・ストリーミングします。{{</* /tab */>}}
{{</* /tabs */>}}
```
{{< tabs >}}
{{< tab name="Photos" icon="photograph" >}}写真ライブラリを管理・整理します。{{< /tab >}}
{{< tab name="Music" icon="music-note" >}}お気に入りの曲を閲覧・再生します。{{< /tab >}}
{{< tab name="Videos" icon="film" >}}動画コンテンツを視聴・ストリーミングします。{{< /tab >}}
{{< /tabs >}}
### Markdown の使用
コードブロックを含む Markdown 構文もサポートされています:

View File

@@ -47,6 +47,27 @@ The `YAML` tab will be selected by default.
{{< tab name="TOML" >}}**TOML**: TOML aims to be a minimal configuration file format that's easy to read due to obvious semantics.{{< /tab >}}
{{< /tabs >}}
### Add Icons
Use the `icon` property on each `tab` to display an icon before the label.
See the [Icon shortcode](../icon) page for the list of available icons.
```
{{</* tabs */>}}
{{</* tab name="Photos" icon="photograph" */>}}Manage and organize your photo library.{{</* /tab */>}}
{{</* tab name="Music" icon="music-note" */>}}Browse and play your favorite tracks.{{</* /tab */>}}
{{</* tab name="Videos" icon="film" */>}}Watch and stream video content.{{</* /tab */>}}
{{</* /tabs */>}}
```
{{< tabs >}}
{{< tab name="Photos" icon="photograph" >}}Manage and organize your photo library.{{< /tab >}}
{{< tab name="Music" icon="music-note" >}}Browse and play your favorite tracks.{{< /tab >}}
{{< tab name="Videos" icon="film" >}}Watch and stream video content.{{< /tab >}}
{{< /tabs >}}
### Use Markdown

View File

@@ -52,6 +52,30 @@ next: /docs/guide/deploy-site
{{< /tabs >}}
### 添加图标
在每个 `tab` 上使用 `icon` 参数,可以在标签文本前显示图标。
可用图标列表请参阅 [Icon 短代码](../icon) 页面。
```
{{</* tabs */>}}
{{</* tab name="Photos" icon="photograph" */>}}管理和整理您的照片库。{{</* /tab */>}}
{{</* tab name="Music" icon="music-note" */>}}浏览和播放您喜爱的曲目。{{</* /tab */>}}
{{</* tab name="Videos" icon="film" */>}}观看和串流视频内容。{{</* /tab */>}}
{{</* /tabs */>}}
```
{{< tabs >}}
{{< tab name="Photos" icon="photograph" >}}管理和整理您的照片库。{{< /tab >}}
{{< tab name="Music" icon="music-note" >}}浏览和播放您喜爱的曲目。{{< /tab >}}
{{< tab name="Videos" icon="film" >}}观看和串流视频内容。{{< /tab >}}
{{< /tabs >}}
### 使用Markdown
支持包括代码块在内的Markdown语法

1
docs/hugo_stats.json generated
View File

@@ -30,7 +30,6 @@
"h5",
"h6",
"head",
"header",
"hr",
"html",
"iframe",

View File

@@ -4,6 +4,7 @@
The `tabs` parameter is a list of dict with the following keys:
- `id`: (int) the ID of the tab (the Ordinal of the tab shortcode).
- `name`: (string) the name of the tab (the title).
- `icon`: (string) the icon of the tab.
- `content`: (string) the content of the tab.
- `selected`: (bool) whether the tab is selected.
*/ -}}
@@ -34,9 +35,7 @@ The `tabs` parameter is a list of dict with the following keys:
<div class="hextra-scrollbar hx:overflow-x-auto hx:overflow-y-hidden hx:overscroll-x-contain">
<div class="hx:mt-4 hx:flex hx:w-max hx:min-w-full hx:border-b hx:border-gray-200 hx:pb-px hx:dark:border-neutral-800" role="tablist"{{- if $enableSync }} data-tab-group="{{ delimit $dataTabGroup `,` }}"{{- end }}>
{{- range $i, $item := $tabs -}}
<button class="hextra-tabs-toggle hx:cursor-pointer hx:data-[state=selected]:border-primary-500 hx:data-[state=selected]:text-primary-600 hx:data-[state=selected]:dark:border-primary-500 hx:data-[state=selected]:dark:text-primary-600 hx:mr-2 hx:rounded-t hx:p-2 hx:font-medium hx:leading-5 hx:transition-colors hx:-mb-0.5 hx:select-none hx:border-b-2 hx:border-transparent hx:text-gray-600 hx:hover:border-gray-200 hx:hover:text-black hx:dark:text-gray-200 hx:dark:hover:border-neutral-800 hx:dark:hover:text-white hx:hextra-focus-visible-inset" id="tabs-tab-{{ $globalID }}-{{ $item.id }}" role="tab" type="button" aria-controls="tabs-panel-{{ $globalID }}-{{ $item.id }}" aria-selected="{{ if eq $i $selectedIndex }}true{{ else }}false{{ end }}" tabindex="{{ if eq $i $selectedIndex }}0{{ else }}-1{{ end }}"{{- if eq $i $selectedIndex }} data-state="selected"{{- end }}>
{{- $item.name -}}
</button>
<button class="hextra-tabs-toggle hx:cursor-pointer hx:data-[state=selected]:border-primary-500 hx:data-[state=selected]:text-primary-600 hx:data-[state=selected]:dark:border-primary-500 hx:data-[state=selected]:dark:text-primary-600 hx:mr-2 hx:rounded-t hx:p-2 hx:font-medium hx:leading-5 hx:transition-colors hx:-mb-0.5 hx:select-none hx:border-b-2 hx:border-transparent hx:text-gray-600 hx:hover:border-gray-200 hx:hover:text-black hx:dark:text-gray-200 hx:dark:hover:border-neutral-800 hx:dark:hover:text-white hx:hextra-focus-visible-inset" id="tabs-tab-{{ $globalID }}-{{ $item.id }}" role="tab" type="button" aria-controls="tabs-panel-{{ $globalID }}-{{ $item.id }}" aria-selected="{{ if eq $i $selectedIndex }}true{{ else }}false{{ end }}" tabindex="{{ if eq $i $selectedIndex }}0{{ else }}-1{{ end }}"{{- if eq $i $selectedIndex }} data-state="selected"{{- end }}><span class="hx:inline-flex hx:items-center hx:gap-1.5">{{- with $item.icon -}}{{- partial "utils/icon.html" (dict "name" . "attributes" `height=1em class="hx:inline-block hx:shrink-0" aria-hidden="true"`) -}}{{- end -}}<span>{{- $item.name -}}</span></span></button>
{{- end -}}
</div>
</div>

View File

@@ -2,13 +2,16 @@
Create a tab.
@param {string} name The name of the tab.
@param {string} icon The icon of the tab.
@param {string} selected Whether the tab is selected.
@example {{< tab name="Foo" selected=true >}}content{{< /tab >}}
@example {{< tab name="Foo" icon="document-text" selected=true >}}content{{< /tab >}}
*/ -}}
{{- $name := .Get "name" | default (printf "Tab %d" .Ordinal) -}}
{{- $icon := .Get "icon" -}}
{{- $selected := .Get "selected" -}}
{{- if .Parent.Get "defaultIndex" -}}
{{- $selected = eq .Ordinal (int (.Parent.Get "defaultIndex")) -}}
@@ -18,6 +21,7 @@ Create a tab.
{{ .Parent.Store.Set "tabs" ($tabs | append (dict
"id" .Ordinal
"name" $name
"icon" $icon
"content" .InnerDeindent
"selected" $selected
))