diff --git a/README.md b/README.md index cd7673f1..b1299c1b 100644 --- a/README.md +++ b/README.md @@ -141,6 +141,8 @@ Click the following links to generate a new repository with template: - Extended Markdown syntax for **[Font Awesome](https://fontawesome.com/) icons** - Extended Markdown syntax for **ruby annotation** - Extended Markdown syntax for **fraction** +- Multiple **admonitions** shortcode or **alerts** extended Markdown syntax +- **Tabs** and **Tab** shortcode with multiple design styles - **Mathematical formula** supported by [KaTeX](https://katex.org/) or [MathJax](https://www.mathjax.org) - **Diagrams** code fences extended and shortcode supported by [mermaid](https://github.com/knsv/mermaid) - **Interactive data visualization** shortcode and code fences extended supported by [ECharts](https://echarts.apache.org/) @@ -148,7 +150,6 @@ Click the following links to generate a new repository with template: - **Mapbox** shortcode supported by [Mapbox GL JS](https://docs.mapbox.com/mapbox-gl-js) - **Music player** shortcode supported by [APlayer](https://github.com/MoePlayer/APlayer) and [MetingJS](https://github.com/metowolf/MetingJS) - **Bilibili player** and **Douyin player** shortcode -- Kinds of **admonitions** shortcode - **Custom style** shortcode - **Custom script** shortcode - Open more **custom blocks** @@ -292,6 +293,7 @@ Thanks to all the [contributors](https://github.com/hugo-fixit/FixIt/graphs/cont - [crypto-js](https://github.com/brix/crypto-js) - [pace](https://github.com/CodeByZach/pace) - [xxhash-wasm](https://github.com/jungomi/xxhash-wasm) +- [`` element](https://github.com/github/tab-container-element) diff --git a/README.zh-cn.md b/README.zh-cn.md index b1ae3385..48acb62f 100644 --- a/README.zh-cn.md +++ b/README.zh-cn.md @@ -138,9 +138,11 @@ pnpx fixit-cli create my-blog - 支持**代码高亮** - 一键**复制代码**到剪贴板 - 支持基于 [lightgallery](https://github.com/sachinchoolur/lightgallery) 的**图片画廊** -- 支持 **[Font Awesome](https://fontawesome.com/) 图标**的扩展 Markdown 语法 -- 支持**上标注释**的扩展 Markdown 语法 -- 支持**分数**的扩展 Markdown 语法 +- 支持 **[Font Awesome](https://fontawesome.com/) 图标**的 Markdown 扩展语法 +- 支持**上标注释**的 Markdown 扩展语法 +- 支持**分数**的 Markdown 扩展语法 +- 支持多种 **admonitions** shortcode 或 **alerts** 的 Markdown 扩展语法 +- 支持**标签页**的 shortcode,提供多种设计样式 - 支持基于 [KaTeX](https://katex.org/) 或 [MathJax](https://www.mathjax.org) 的**数学公式** - 支持基于 [mermaid](https://github.com/knsv/mermaid) 的**图表** 代码块扩展语法和 shortcode - 支持基于 [ECharts](https://echarts.apache.org/) 的**交互式数据可视化** 代码块扩展语法和 shortcode @@ -148,7 +150,6 @@ pnpx fixit-cli create my-blog - 支持基于 [Mapbox GL JS](https://docs.mapbox.com/mapbox-gl-js) 的 **Mapbox** shortcode - 支持基于 [APlayer](https://github.com/MoePlayer/APlayer) 和 [MetingJS](https://github.com/metowolf/MetingJS) 的**音乐播放器** shortcode - 支持 **Bilibili 视频** 和 **抖音视频** shortcode -- 支持多种**注释**的 shortcode - 支持**自定义样式**的 shortcode - 支持**自定义脚本**的 shortcode - 支持**自定义模板块** @@ -292,6 +293,7 @@ FixIt 主题旨在在**简洁性**和**可扩展性**之间取得平衡。为此 - [crypto-js](https://github.com/brix/crypto-js) - [pace](https://github.com/CodeByZach/pace) - [xxhash-wasm](https://github.com/jungomi/xxhash-wasm) +- [`` element](https://github.com/github/tab-container-element) diff --git a/apps/test/content/posts/tabs-comprehensive-test.md b/apps/test/content/posts/tabs-comprehensive-test.md new file mode 100644 index 00000000..8b971597 --- /dev/null +++ b/apps/test/content/posts/tabs-comprehensive-test.md @@ -0,0 +1,146 @@ +--- +title: Tabs Comprehensive Test Cases +date: 2025-09-09T10:00:00+08:00 +collections: + +- Tests +categories: +- Shortcodes +tags: +- Tabs +- UI Components +--- + +Testing various configurations and nested scenarios for the Tabs shortcode. + +{{< tabs >}} +{{% tab title="Test Cases" %}}See Types section for various test cases.{{% /tab %}} +{{% tab title="Nested Tabs" %}}See Nested Tabs section for examples.{{% /tab %}} +{{< /tabs >}} + + + +## Types + +### Underline (Default) + + + +{{< tabs placement="top" >}} +{{% tab title="Tab 1" %}}Content for underline style tab 1{{% /tab %}} +{{% tab title="Tab 2" %}}Content for underline style tab 2{{% /tab %}} +{{% tab title="Tab 3" %}}Content for underline style tab 3{{% /tab %}} +{{< /tabs >}} + +### Pill + + + +{{< tabs type="pill" placement="top" >}} +{{% tab title="Tab 1" %}}Content for pill style tab 1{{% /tab %}} +{{% tab title="Tab 2" %}}Content for pill style tab 2{{% /tab %}} +{{% tab title="Tab 3" %}}Content for pill style tab 3{{% /tab %}} +{{< /tabs >}} + +### Card + + + +{{< tabs type="card" placement="top" >}} +{{% tab title="Tab 1" %}}Content for card style tab 1{{% /tab %}} +{{% tab title="Tab 2" %}}Content for card style tab 2{{% /tab %}} +{{% tab title="Tab 3" %}}Content for card style tab 3{{% /tab %}} +{{< /tabs >}} + +### Segment + +{{< tabs type="segment" >}} +{{% tab title="Tab 1" %}}Content for segment style tab 1{{% /tab %}} +{{% tab title="Tab 2" %}}Content for segment style tab 2{{% /tab %}} +{{% tab title="Tab 3" %}}Content for segment style tab 3{{% /tab %}} +{{< /tabs >}} + +## Nested Tabs + +{{< tabs defaultTab=0 >}} + +{{% tab title="Outer Tab 1" %}} +This is the first outer tab with simple content. + +**Features:** + +- Basic text content +- No nested components +- Simple layout +{{% /tab %}} + +{{% tab title="Outer Tab 2" %}} +This outer tab contains nested tabs inside: + +{{< tabs type="pill" defaultTab=1 >}} + +{{% tab title="Inner A" %}} +Nested tab A content with **bold text** and _italic text_. + +```javascript +console.log('Hello from nested tab A!') +``` + +{{% /tab %}} + +{{% tab title="Inner B" %}} +Nested tab B content with a list: + +1. First item +2. Second item +3. Third item + +> This is a blockquote inside a nested tab. +{{% /tab %}} + +{{% tab title="Inner C" %}} +Nested tab C with a table: + +| Feature | Status | Notes | +| :--------- | :----- | :--------------------- | +| Responsive | ✅ | Works on all devices | +| Accessible | ✅ | Screen reader friendly | +| Fast | ✅ | Optimized performance | + +{{% /tab %}} + +{{< /tabs >}} + +{{% /tab %}} + +{{% tab title="Outer Tab 3" %}} +This tab contains vertical nested tabs: + +{{< tabs type="card" vertical=true >}} + +{{% tab title="Vertical A" %}} +Content for vertical nested tab A. + +- Feature 1 +- Feature 2 +- Feature 3 +{{% /tab %}} + +{{% tab title="Vertical B" %}} +Content for vertical nested tab B. + +```css +.example { + color: #333; + background: #f5f5f5; + padding: 1rem; +} +``` + +{{% /tab %}} + +{{< /tabs >}} + +{{% /tab %}} + +{{< /tabs >}} diff --git a/assets/css/_core/_base.scss b/assets/css/_core/_base.scss index fa734b85..c3cb8792 100644 --- a/assets/css/_core/_base.scss +++ b/assets/css/_core/_base.scss @@ -77,7 +77,7 @@ details { font-size: $code-font-size; font-family: $code-font-family; color: $code-color; - background-color: rgba(175, 184, 193, 0.2); + background-color: var(#{$rootPrefix}code-inline-background-color); text-decoration: inherit; @include border-radius($global-border-radius); @include overflow-wrap(break-word); @@ -85,7 +85,6 @@ details { [data-theme='dark'] & { color: $code-color-dark; - background-color: rgba(99, 110, 123, 0.4); } } diff --git a/assets/css/_core/_breadcrumb.scss b/assets/css/_core/_breadcrumb.scss index c8241f0e..35b055f8 100644 --- a/assets/css/_core/_breadcrumb.scss +++ b/assets/css/_core/_breadcrumb.scss @@ -42,7 +42,7 @@ } &.active { - color: var(--#{$prefix}secondary); + color: var(#{$rootPrefix}secondary); } } } diff --git a/assets/css/_core/_common.scss b/assets/css/_core/_common.scss index 6aa0474c..e9e4fd7e 100644 --- a/assets/css/_core/_common.scss +++ b/assets/css/_core/_common.scss @@ -41,7 +41,7 @@ @each $color, $value in $theme-colors { .text-#{$color} { - color: var(--#{$prefix}#{$color}) !important; + color: var(#{$rootPrefix}#{$color}) !important; } } diff --git a/assets/css/_core/_media.scss b/assets/css/_core/_media.scss index 669d551b..5c29f081 100644 --- a/assets/css/_core/_media.scss +++ b/assets/css/_core/_media.scss @@ -68,12 +68,12 @@ } // adjust the scroll margin top of the content anchors on the page body:not([data-header-desktop='auto']) &+.fi-container .content [id] { - scroll-margin-top: calc(var(--#{$prefix}scroll-mt) + var(--#{$prefix}breadcrumb-height)); + scroll-margin-top: calc(var(#{$rootPrefix}scroll-mt) + var(#{$rootPrefix}breadcrumb-height)); } } [data-header-desktop='normal'] .page .content [id] { - --#{$prefix}scroll-mt: #{$global-scroll-margin-top}; + #{$rootPrefix}scroll-mt: #{$global-scroll-margin-top}; } } @@ -96,12 +96,12 @@ } // adjust the scroll margin top of the content anchors on the page body:not([data-header-mobile='auto']) &+.fi-container .content [id] { - scroll-margin-top: calc(var(--#{$prefix}scroll-mt) + var(--#{$prefix}breadcrumb-height)); + scroll-margin-top: calc(var(#{$rootPrefix}scroll-mt) + var(#{$rootPrefix}breadcrumb-height)); } } [data-header-mobile='normal'] .page .content [id] { - --#{$prefix}scroll-mt: #{$global-scroll-margin-top}; + #{$rootPrefix}scroll-mt: #{$global-scroll-margin-top}; } %page-style { diff --git a/assets/css/_core/_root.scss b/assets/css/_core/_root.scss index 5c1f7cb6..386a144d 100644 --- a/assets/css/_core/_root.scss +++ b/assets/css/_core/_root.scss @@ -2,6 +2,8 @@ // Note: Custom variable values only support SassScript inside `#{}`. // TODO migrate SCSS variables to CSS variables + interpolate-size: allow-keywords; + #{$rootPrefix}global-font-color: #{$global-font-color}; #{$rootPrefix}global-border-color: #{$global-border-color}; @@ -28,7 +30,7 @@ #{$rootPrefix}scrollbar-width: thin; #{$rootPrefix}scrollbar-width-legacy: 12px; - interpolate-size: allow-keywords; + #{$rootPrefix}code-inline-background-color: rgba(175, 184, 193, 0.2); } // Dark theme @@ -42,4 +44,6 @@ #{$rootPrefix}hr-background-color: #{lighten($global-border-color-dark, 5%)}; #{$rootPrefix}hr-before-color: #{darken($global-link-hover-color-dark, 4%)}; + + #{$rootPrefix}code-inline-background-color: rgba(99, 110, 123, 0.4); } diff --git a/assets/css/_mixin/_index.scss b/assets/css/_mixin/_index.scss index 38861162..906e466d 100644 --- a/assets/css/_mixin/_index.scss +++ b/assets/css/_mixin/_index.scss @@ -1,5 +1,6 @@ +@import '_blur'; @import '_compatibility'; @import '_link'; -@import '_blur'; +@import '_loading'; @import '_scrollbar-width'; @import '_z-index'; diff --git a/assets/css/_mixin/_loading.scss b/assets/css/_mixin/_loading.scss new file mode 100644 index 00000000..3e972e40 --- /dev/null +++ b/assets/css/_mixin/_loading.scss @@ -0,0 +1,15 @@ +// Loading Mixin for before/after pseudo element +@mixin loading { + content: ''; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + backdrop-filter: blur(1rem); + background-position: center; + background-repeat: no-repeat; + background-image: var(#{$rootPrefix}loading-img); + background-size: 60px; + z-index: 1; +} diff --git a/assets/css/_mixin/_scrollbar-width.scss b/assets/css/_mixin/_scrollbar-width.scss index 82fbf7c4..a4f4296b 100644 --- a/assets/css/_mixin/_scrollbar-width.scss +++ b/assets/css/_mixin/_scrollbar-width.scss @@ -1,4 +1,4 @@ @mixin scrollbar-width($width: thin, $widthLegacy: 12px) { - --#{$prefix}scrollbar-width: #{$width}; - --#{$prefix}scrollbar-width-legacy: #{$widthLegacy}; + #{$rootPrefix}scrollbar-width: #{$width}; + #{$rootPrefix}scrollbar-width-legacy: #{$widthLegacy}; } diff --git a/assets/css/_page/_home.scss b/assets/css/_page/_home.scss index aa224861..8617a2dc 100644 --- a/assets/css/_page/_home.scss +++ b/assets/css/_page/_home.scss @@ -82,7 +82,7 @@ .summary { padding-block: 1rem; - color: var(--#{$prefix}global-font-color); + color: var(#{$rootPrefix}global-font-color); &:not(:last-of-type)::after { content: ''; @@ -92,8 +92,8 @@ transform: translateY(18px); background: repeating-linear-gradient( 135deg, - var(--#{$prefix}hr-background-color) 0px, - var(--#{$prefix}hr-background-color) 4px, + var(#{$rootPrefix}hr-background-color) 0px, + var(#{$rootPrefix}hr-background-color) 4px, transparent 4px, transparent 8px ); diff --git a/assets/css/_page/_index.scss b/assets/css/_page/_index.scss index 4d326c03..f09281d3 100644 --- a/assets/css/_page/_index.scss +++ b/assets/css/_page/_index.scss @@ -4,7 +4,7 @@ .content { [id] { - scroll-margin-top: var(--#{$prefix}scroll-mt); + scroll-margin-top: var(#{$rootPrefix}scroll-mt); } } diff --git a/assets/css/_page/_single.scss b/assets/css/_page/_single.scss index 1f81f9dd..0449e09a 100644 --- a/assets/css/_page/_single.scss +++ b/assets/css/_page/_single.scss @@ -17,14 +17,14 @@ width: max-content; transform: rotate(30deg); margin-right: 0.25em; - color: var(--#{$prefix}danger); + color: var(#{$rootPrefix}danger); } .icon-repost { display: inline-block; width: max-content; margin-right: 0.25em; - color: var(--#{$prefix}success); + color: var(#{$rootPrefix}success); } } @@ -100,7 +100,7 @@ position: relative; height: 1em; margin-block: 1em; - background: linear-gradient(to right, var(--#{$prefix}hr-background-color) 50%, transparent 50%); + background: linear-gradient(to right, var(#{$rootPrefix}hr-background-color) 50%, transparent 50%); background-size: 10px 2px; background-position: center; background-repeat: repeat-x; @@ -118,7 +118,7 @@ top: 50%; transform: translateY(-50%); z-index: 1; - color: var(--#{$prefix}hr-before-color); + color: var(#{$rootPrefix}hr-before-color); content: '\f0c4'; font-size: 20px; line-height: 1; @@ -236,31 +236,31 @@ // Task lists li[data-task] { - color: var(--#{$prefix}task-color); + color: var(#{$rootPrefix}task-color); .checkbox-icon { margin-right: 0.25em; - color: var(--#{$prefix}checkbox-color); + color: var(#{$rootPrefix}checkbox-color); } } li[data-task='x'], li[data-task='-'] { - --#{$prefix}task-color: var(--#{$prefix}secondary); + #{$rootPrefix}task-color: var(#{$rootPrefix}secondary); text-decoration: line-through rgba(145, 145, 145, 0.6); } li[data-task='x'] { - --#{$prefix}checkbox-color: var(--#{$prefix}primary); + #{$rootPrefix}checkbox-color: var(#{$rootPrefix}primary); } li[data-task='-'] { opacity: 0.6; } li[data-task='/'] { - --#{$prefix}task-color: var(--#{$prefix}success); + #{$rootPrefix}task-color: var(#{$rootPrefix}success); } li[data-task='!'] { - --#{$prefix}checkbox-color: var(--#{$prefix}danger); + #{$rootPrefix}checkbox-color: var(#{$rootPrefix}danger); } li[data-task='?'] { - --#{$prefix}checkbox-color: var(--#{$prefix}warning); + #{$rootPrefix}checkbox-color: var(#{$rootPrefix}warning); } dl { @@ -290,14 +290,14 @@ mark { padding: 0.14em 0.28em; - background-color: var(--#{$prefix}mark-background-color, mark); - color: var(--#{$prefix}mark-color, marktext); + background-color: var(#{$rootPrefix}mark-background-color, mark); + color: var(#{$rootPrefix}mark-color, marktext); @include border-radius($global-border-radius); @each $color, $value in $theme-colors { &.mark-#{$color} { - --#{$prefix}mark-color: #fff; - --#{$prefix}mark-background-color: var(--#{$prefix}#{$color}); + #{$rootPrefix}mark-color: #fff; + #{$rootPrefix}mark-background-color: var(#{$rootPrefix}#{$color}); } } } @@ -305,10 +305,10 @@ .table-wrapper { position: relative; overflow-x: auto; - --#{$prefix}scrollbar-thumb-color: #{$table-background-color}; + #{$rootPrefix}scrollbar-thumb-color: #{$table-background-color}; [data-theme='dark'] & { - --#{$prefix}scrollbar-thumb-color: #{$table-background-color-dark}; + #{$rootPrefix}scrollbar-thumb-color: #{$table-background-color-dark}; } > table { @@ -449,7 +449,7 @@ } hr { - background-color: var(--#{$prefix}hr-background-color); + background-color: var(#{$rootPrefix}hr-background-color); height: 1px; margin-block: 1em; } diff --git a/assets/css/_partials/_scrollbar.scss b/assets/css/_partials/_scrollbar.scss index b50e82e1..c7bbac59 100644 --- a/assets/css/_partials/_scrollbar.scss +++ b/assets/css/_partials/_scrollbar.scss @@ -1,15 +1,15 @@ /* Modern browsers with `scrollbar-*` support (high priority) */ @supports (scrollbar-width: auto) { * { - scrollbar-color: var(--#{$prefix}scrollbar-thumb-color) var(--#{$prefix}scrollbar-track-color);; - scrollbar-width: var(--#{$prefix}scrollbar-width); + scrollbar-color: var(#{$rootPrefix}scrollbar-thumb-color) var(#{$rootPrefix}scrollbar-track-color);; + scrollbar-width: var(#{$rootPrefix}scrollbar-width); } } /* Legacy browsers with `::-webkit-scrollbar-*` support */ ::-webkit-scrollbar { - height: var(--#{$prefix}scrollbar-width-legacy); - width: var(--#{$prefix}scrollbar-width-legacy); + height: var(#{$rootPrefix}scrollbar-width-legacy); + width: var(#{$rootPrefix}scrollbar-width-legacy); overflow: visible; } ::-webkit-scrollbar-button { @@ -17,16 +17,16 @@ width: 0; } ::-webkit-scrollbar-corner { - background-color: var(--#{$prefix}scrollbar-track-color); + background-color: var(#{$rootPrefix}scrollbar-track-color); } ::-webkit-scrollbar-thumb { - background-color: var(--#{$prefix}scrollbar-thumb-color); + background-color: var(#{$rootPrefix}scrollbar-thumb-color); &:hover { - background-color: var(--#{$prefix}scrollbar-thumb-hover-color); + background-color: var(#{$rootPrefix}scrollbar-thumb-hover-color); } } ::-webkit-scrollbar-track { - background-color: var(--#{$prefix}scrollbar-track-color); + background-color: var(#{$rootPrefix}scrollbar-track-color); } ::-webkit-scrollbar-thumb, ::-webkit-scrollbar-track { diff --git a/assets/css/_partials/_single/_alert.scss b/assets/css/_partials/_single/_alert.scss index dac8fe4a..2aa54fba 100644 --- a/assets/css/_partials/_single/_alert.scss +++ b/assets/css/_partials/_single/_alert.scss @@ -2,7 +2,7 @@ padding: 0.5rem 1rem; margin-block: 1rem; color: inherit; - border-left: 0.25em solid var(--#{$prefix}alert-border-color); + border-left: 0.25em solid var(#{$rootPrefix}alert-border-color); > :first-child { margin-top: 0; @@ -17,7 +17,7 @@ align-items: center; line-height: 1; margin-bottom: 1rem; - color: var(--#{$prefix}alert-color); + color: var(#{$rootPrefix}alert-color); > svg.icon { width: initial; @@ -28,16 +28,16 @@ @each $type, $item in $alert-color-map { &.alert-#{$type} { - --#{$prefix}alert-border-color: #{map-get($item, border-color)}; - --#{$prefix}alert-color: #{map-get($item, color)}; + #{$rootPrefix}alert-border-color: #{map-get($item, border-color)}; + #{$rootPrefix}alert-color: #{map-get($item, color)}; } } [data-theme='dark'] & { @each $type, $item in $alert-color-map-dark { &.alert-#{$type} { - --#{$prefix}alert-border-color: #{map-get($item, border-color)}; - --#{$prefix}alert-color: #{map-get($item, color)}; + #{$rootPrefix}alert-border-color: #{map-get($item, border-color)}; + #{$rootPrefix}alert-color: #{map-get($item, color)}; } } } diff --git a/assets/css/_partials/_single/_code.scss b/assets/css/_partials/_single/_code.scss index 39575490..f6ae663f 100644 --- a/assets/css/_partials/_single/_code.scss +++ b/assets/css/_partials/_single/_code.scss @@ -45,7 +45,7 @@ pre:not([data-processed]) { font-family: $code-font-family; .table-wrapper { - --#{$prefix}scrollbar-thumb-color: initial; + #{$rootPrefix}scrollbar-thumb-color: initial; > table, > table thead, > table tr, @@ -66,7 +66,7 @@ pre:not([data-processed]) { position: relative; .code-header { - --#{$prefix}bg-code-header: #{darken($code-background-color, 3%)}; + #{$rootPrefix}bg-code-header: #{darken($code-background-color, 3%)}; display: flex; justify-content: space-between; align-items: center; @@ -76,7 +76,7 @@ pre:not([data-processed]) { font-weight: bold; line-height: 1.4em; color: $code-info-color; - background-color: var(--#{$prefix}bg-code-header); + background-color: var(#{$rootPrefix}bg-code-header); @include border-radius($global-border-radius); @include transition(border-radius 0.2s ease); @@ -89,7 +89,7 @@ pre:not([data-processed]) { [data-theme='dark'] & { color: $code-info-color-dark; - --#{$prefix}bg-code-header: #{darken($code-background-color-dark, 3%)}; + #{$rootPrefix}bg-code-header: #{darken($code-background-color-dark, 3%)}; } &:hover { @@ -115,7 +115,7 @@ pre:not([data-processed]) { position: absolute; left: 50%; transform: translateX(-50%); - background-color: var(--#{$prefix}bg-code-header); + background-color: var(#{$rootPrefix}bg-code-header); padding-inline: 1em; max-width: 80%; white-space: nowrap; @@ -218,11 +218,11 @@ pre:not([data-processed]) { &.open { .code-header { - --#{$prefix}bg-code-header: #{darken($code-background-color, 6%)}; + #{$rootPrefix}bg-code-header: #{darken($code-background-color, 6%)}; @include border-radius($global-border-radius $global-border-radius 0 0); [data-theme='dark'] & { - --#{$prefix}bg-code-header: #{darken($code-background-color-dark, 6%)}; + #{$rootPrefix}bg-code-header: #{darken($code-background-color-dark, 6%)}; } } diff --git a/assets/css/_partials/_single/_collections.scss b/assets/css/_partials/_single/_collections.scss index 6268649a..b4374dfc 100644 --- a/assets/css/_partials/_single/_collections.scss +++ b/assets/css/_partials/_single/_collections.scss @@ -86,7 +86,7 @@ // Collection aside container .aside-collection { position: sticky; - top: calc(#{$header-height} + var(--#{$prefix}breadcrumb-height)); + top: calc(#{$header-height} + var(#{$rootPrefix}breadcrumb-height)); box-sizing: border-box; @include overflow-wrap(break-word); @include blur; @@ -136,7 +136,7 @@ .collection-count { flex-shrink: 0; - color: var(--#{$prefix}secondary); + color: var(#{$rootPrefix}secondary); } .details-icon { diff --git a/assets/css/_partials/_single/_github-dark-dimmed.scss b/assets/css/_partials/_single/_github-dark-dimmed.scss index bb9df29c..12891478 100644 --- a/assets/css/_partials/_single/_github-dark-dimmed.scss +++ b/assets/css/_partials/_single/_github-dark-dimmed.scss @@ -8,72 +8,72 @@ */ & { // Blob colors - --#{$prefix}color-blob-num: #778491; - --#{$prefix}color-blob-code-inner: #c5d1de; + #{$rootPrefix}color-blob-num: #778491; + #{$rootPrefix}color-blob-code-inner: #c5d1de; // Syntax colors - --#{$prefix}color-prettylights-syntax-comment: #768390; - --#{$prefix}color-prettylights-syntax-constant: #6cb6ff; - --#{$prefix}color-prettylights-syntax-constant-other-reference-link: #96d0ff; - --#{$prefix}color-prettylights-syntax-entity: #dcbdfb; - --#{$prefix}color-prettylights-syntax-storage-modifier-import: #adbac7; - --#{$prefix}color-prettylights-syntax-entity-tag: #8ddb8c; - --#{$prefix}color-prettylights-syntax-keyword: #f47067; - --#{$prefix}color-prettylights-syntax-string: #96d0ff; - --#{$prefix}color-prettylights-syntax-variable: #f69d50; - --#{$prefix}color-prettylights-syntax-brackethighlighter-unmatched: #e5534b; - --#{$prefix}color-prettylights-syntax-brackethighlighter-angle: #768390; - --#{$prefix}color-prettylights-syntax-invalid-illegal-text: #cdd9e5; - --#{$prefix}color-prettylights-syntax-invalid-illegal-bg: #922323; - --#{$prefix}color-prettylights-syntax-carriage-return-text: #cdd9e5; - --#{$prefix}color-prettylights-syntax-carriage-return-bg: #ad2e2c; - --#{$prefix}color-prettylights-syntax-string-regexp: #8ddb8c; - --#{$prefix}color-prettylights-syntax-markup-list: #eac55f; - --#{$prefix}color-prettylights-syntax-markup-heading: #316dca; - --#{$prefix}color-prettylights-syntax-markup-italic: #adbac7; - --#{$prefix}color-prettylights-syntax-markup-bold: #adbac7; - --#{$prefix}color-prettylights-syntax-markup-deleted-text: #ffd8d3; - --#{$prefix}color-prettylights-syntax-markup-deleted-bg: #78191b; - --#{$prefix}color-prettylights-syntax-markup-inserted-text: #b4f1b4; - --#{$prefix}color-prettylights-syntax-markup-inserted-bg: #1b4721; - --#{$prefix}color-prettylights-syntax-markup-changed-text: #ffddb0; - --#{$prefix}color-prettylights-syntax-markup-changed-bg: #682d0f; - --#{$prefix}color-prettylights-syntax-markup-ignored-text: #adbac7; - --#{$prefix}color-prettylights-syntax-markup-ignored-bg: #255ab2; - --#{$prefix}color-prettylights-syntax-meta-diff-range: #dcbdfb; - --#{$prefix}color-prettylights-syntax-sublimelinter-gutter-mark: #545d68; + #{$rootPrefix}color-prettylights-syntax-comment: #768390; + #{$rootPrefix}color-prettylights-syntax-constant: #6cb6ff; + #{$rootPrefix}color-prettylights-syntax-constant-other-reference-link: #96d0ff; + #{$rootPrefix}color-prettylights-syntax-entity: #dcbdfb; + #{$rootPrefix}color-prettylights-syntax-storage-modifier-import: #adbac7; + #{$rootPrefix}color-prettylights-syntax-entity-tag: #8ddb8c; + #{$rootPrefix}color-prettylights-syntax-keyword: #f47067; + #{$rootPrefix}color-prettylights-syntax-string: #96d0ff; + #{$rootPrefix}color-prettylights-syntax-variable: #f69d50; + #{$rootPrefix}color-prettylights-syntax-brackethighlighter-unmatched: #e5534b; + #{$rootPrefix}color-prettylights-syntax-brackethighlighter-angle: #768390; + #{$rootPrefix}color-prettylights-syntax-invalid-illegal-text: #cdd9e5; + #{$rootPrefix}color-prettylights-syntax-invalid-illegal-bg: #922323; + #{$rootPrefix}color-prettylights-syntax-carriage-return-text: #cdd9e5; + #{$rootPrefix}color-prettylights-syntax-carriage-return-bg: #ad2e2c; + #{$rootPrefix}color-prettylights-syntax-string-regexp: #8ddb8c; + #{$rootPrefix}color-prettylights-syntax-markup-list: #eac55f; + #{$rootPrefix}color-prettylights-syntax-markup-heading: #316dca; + #{$rootPrefix}color-prettylights-syntax-markup-italic: #adbac7; + #{$rootPrefix}color-prettylights-syntax-markup-bold: #adbac7; + #{$rootPrefix}color-prettylights-syntax-markup-deleted-text: #ffd8d3; + #{$rootPrefix}color-prettylights-syntax-markup-deleted-bg: #78191b; + #{$rootPrefix}color-prettylights-syntax-markup-inserted-text: #b4f1b4; + #{$rootPrefix}color-prettylights-syntax-markup-inserted-bg: #1b4721; + #{$rootPrefix}color-prettylights-syntax-markup-changed-text: #ffddb0; + #{$rootPrefix}color-prettylights-syntax-markup-changed-bg: #682d0f; + #{$rootPrefix}color-prettylights-syntax-markup-ignored-text: #adbac7; + #{$rootPrefix}color-prettylights-syntax-markup-ignored-bg: #255ab2; + #{$rootPrefix}color-prettylights-syntax-meta-diff-range: #dcbdfb; + #{$rootPrefix}color-prettylights-syntax-sublimelinter-gutter-mark: #545d68; .blob-num { - color: var(--#{$prefix}color-blob-num); + color: var(#{$rootPrefix}color-blob-num); } .blob-code-inner { - color: var(--#{$prefix}color-blob-code-inner); + color: var(#{$rootPrefix}color-blob-code-inner); } .pl-c /* comment, punctuation.definition.comment, string.comment */ { - color: var(--#{$prefix}color-prettylights-syntax-comment); + color: var(#{$rootPrefix}color-prettylights-syntax-comment); } .pl-c1 /* constant, entity.name.constant, variable.other.constant, variable.language, support, meta.property-name, support.constant, support.variable, meta.module-reference, markup.raw, meta.diff.header, meta.output */, .pl-s .pl-v /* string variable */ { - color: var(--#{$prefix}color-prettylights-syntax-constant); + color: var(#{$rootPrefix}color-prettylights-syntax-constant); } .pl-e /* entity */, .pl-en /* entity.name */ { - color: var(--#{$prefix}color-prettylights-syntax-entity); + color: var(#{$rootPrefix}color-prettylights-syntax-entity); } .pl-smi /* variable.parameter.function, storage.modifier.package, storage.modifier.import, storage.type.java, variable.other */, .pl-s .pl-s1 /* string source */ { - color: var(--#{$prefix}color-prettylights-syntax-storage-modifier-import); + color: var(#{$rootPrefix}color-prettylights-syntax-storage-modifier-import); } .pl-ent /* entity.name.tag, markup.quote */ { - color: var(--#{$prefix}color-prettylights-syntax-entity-tag); + color: var(#{$rootPrefix}color-prettylights-syntax-entity-tag); } .pl-k /* keyword, storage, storage.type */ { - color: var(--#{$prefix}color-prettylights-syntax-keyword); + color: var(#{$rootPrefix}color-prettylights-syntax-keyword); } .pl-s /* string */, @@ -83,26 +83,26 @@ .pl-sr .pl-cce /* string.regexp constant.character.escape */, .pl-sr .pl-sre /* string.regexp source.ruby.embedded */, .pl-sr .pl-sra /* string.regexp string.regexp.arbitrary-repitition */ { - color: var(--#{$prefix}color-prettylights-syntax-string); + color: var(#{$rootPrefix}color-prettylights-syntax-string); } .pl-v /* variable */, .pl-smw /* sublimelinter.mark.warning */ { - color: var(--#{$prefix}color-prettylights-syntax-variable); + color: var(#{$rootPrefix}color-prettylights-syntax-variable); } .pl-bu /* invalid.broken, invalid.deprecated, invalid.unimplemented, message.error, brackethighlighter.unmatched, sublimelinter.mark.error */ { - color: var(--#{$prefix}color-prettylights-syntax-brackethighlighter-unmatched); + color: var(#{$rootPrefix}color-prettylights-syntax-brackethighlighter-unmatched); } .pl-ii /* invalid.illegal */ { - color: var(--#{$prefix}color-prettylights-syntax-invalid-illegal-text); - background-color: var(--#{$prefix}color-prettylights-syntax-invalid-illegal-bg); + color: var(#{$rootPrefix}color-prettylights-syntax-invalid-illegal-text); + background-color: var(#{$rootPrefix}color-prettylights-syntax-invalid-illegal-bg); } .pl-c2 /* carriage-return */ { - color: var(--#{$prefix}color-prettylights-syntax-carriage-return-text); - background-color: var(--#{$prefix}color-prettylights-syntax-carriage-return-bg); + color: var(#{$rootPrefix}color-prettylights-syntax-carriage-return-text); + background-color: var(#{$rootPrefix}color-prettylights-syntax-carriage-return-bg); } .pl-c2::before /* carriage-return */ { @@ -111,65 +111,65 @@ .pl-sr .pl-cce /* string.regexp constant.character.escape */ { font-weight: bold; - color: var(--#{$prefix}color-prettylights-syntax-string-regexp); + color: var(#{$rootPrefix}color-prettylights-syntax-string-regexp); } .pl-ml /* markup.list */ { - color: var(--#{$prefix}color-prettylights-syntax-markup-list); + color: var(#{$rootPrefix}color-prettylights-syntax-markup-list); } .pl-mh /* markup.heading */, .pl-mh .pl-en /* markup.heading entity.name */, .pl-ms /* meta.separator */ { font-weight: bold; - color: var(--#{$prefix}color-prettylights-syntax-markup-heading); + color: var(#{$rootPrefix}color-prettylights-syntax-markup-heading); } .pl-mi /* markup.italic */ { font-style: italic; - color: var(--#{$prefix}color-prettylights-syntax-markup-italic); + color: var(#{$rootPrefix}color-prettylights-syntax-markup-italic); } .pl-mb /* markup.bold */ { font-weight: bold; - color: var(--#{$prefix}color-prettylights-syntax-markup-bold); + color: var(#{$rootPrefix}color-prettylights-syntax-markup-bold); } .pl-md /* markup.deleted, meta.diff.header.from-file, punctuation.definition.deleted */ { - color: var(--#{$prefix}color-prettylights-syntax-markup-deleted-text); - background-color: var(--#{$prefix}color-prettylights-syntax-markup-deleted-bg); + color: var(#{$rootPrefix}color-prettylights-syntax-markup-deleted-text); + background-color: var(#{$rootPrefix}color-prettylights-syntax-markup-deleted-bg); } .pl-mi1 /* markup.inserted, meta.diff.header.to-file, punctuation.definition.inserted */ { - color: var(--#{$prefix}color-prettylights-syntax-markup-inserted-text); - background-color: var(--#{$prefix}color-prettylights-syntax-markup-inserted-bg); + color: var(#{$rootPrefix}color-prettylights-syntax-markup-inserted-text); + background-color: var(#{$rootPrefix}color-prettylights-syntax-markup-inserted-bg); } .pl-mc /* markup.changed, punctuation.definition.changed */ { - color: var(--#{$prefix}color-prettylights-syntax-markup-changed-text); - background-color: var(--#{$prefix}color-prettylights-syntax-markup-changed-bg); + color: var(#{$rootPrefix}color-prettylights-syntax-markup-changed-text); + background-color: var(#{$rootPrefix}color-prettylights-syntax-markup-changed-bg); } .pl-mi2 /* markup.ignored, markup.untracked */ { - color: var(--#{$prefix}color-prettylights-syntax-markup-ignored-text); - background-color: var(--#{$prefix}color-prettylights-syntax-markup-ignored-bg); + color: var(#{$rootPrefix}color-prettylights-syntax-markup-ignored-text); + background-color: var(#{$rootPrefix}color-prettylights-syntax-markup-ignored-bg); } .pl-mdr /* meta.diff.range */ { font-weight: bold; - color: var(--#{$prefix}color-prettylights-syntax-meta-diff-range); + color: var(#{$rootPrefix}color-prettylights-syntax-meta-diff-range); } .pl-ba /* brackethighlighter.tag, brackethighlighter.curly, brackethighlighter.round, brackethighlighter.square, brackethighlighter.angle, brackethighlighter.quote */ { - color: var(--#{$prefix}color-prettylights-syntax-brackethighlighter-angle); + color: var(#{$rootPrefix}color-prettylights-syntax-brackethighlighter-angle); } .pl-sg /* sublimelinter.gutter-mark */ { - color: var(--#{$prefix}color-prettylights-syntax-sublimelinter-gutter-mark); + color: var(#{$rootPrefix}color-prettylights-syntax-sublimelinter-gutter-mark); } .pl-corl /* constant.other.reference.link, string.other.link */ { text-decoration: underline; - color: var(--#{$prefix}color-prettylights-syntax-constant-other-reference-link); + color: var(#{$rootPrefix}color-prettylights-syntax-constant-other-reference-link); } } diff --git a/assets/css/_partials/_single/_related.scss b/assets/css/_partials/_single/_related.scss index 73e157e9..751ca3cc 100644 --- a/assets/css/_partials/_single/_related.scss +++ b/assets/css/_partials/_single/_related.scss @@ -5,7 +5,7 @@ display: block; border: 0; padding-top: 1px; - background: var(--#{$prefix}divider-edge-weak); + background: var(#{$rootPrefix}divider-edge-weak); margin-block: 1rem 0.5rem; } @@ -30,7 +30,7 @@ .related-count { flex-shrink: 0; - color: var(--#{$prefix}secondary); + color: var(#{$rootPrefix}secondary); } .details-icon { diff --git a/assets/css/_partials/_single/_toc.scss b/assets/css/_partials/_single/_toc.scss index 7eda1f59..a35227fe 100644 --- a/assets/css/_partials/_single/_toc.scss +++ b/assets/css/_partials/_single/_toc.scss @@ -73,7 +73,7 @@ #toc-auto { display: block; position: sticky; - top: calc(#{$header-height} + var(--#{$prefix}breadcrumb-height)); + top: calc(#{$header-height} + var(#{$rootPrefix}breadcrumb-height)); box-sizing: border-box; visibility: hidden; @include overflow-wrap(break-word); @@ -81,7 +81,7 @@ @extend .print-d-none; [data-header-desktop='normal'] & { - --#{$prefix}scroll-mt: #{$global-scroll-margin-top}; + #{$rootPrefix}scroll-mt: #{$global-scroll-margin-top}; } .toc-title { diff --git a/assets/css/_partials/_widgets/_noscript-warning.scss b/assets/css/_partials/_widgets/_noscript-warning.scss index edb52e8c..d924b7a4 100644 --- a/assets/css/_partials/_widgets/_noscript-warning.scss +++ b/assets/css/_partials/_widgets/_noscript-warning.scss @@ -1,5 +1,5 @@ .noscript-warning { - background-color: var(--#{$prefix}danger); + background-color: var(#{$rootPrefix}danger); color: white; font-size: 1rem; font-weight: bold; @@ -11,6 +11,6 @@ @include z-index(2); [data-theme='dark'] & { - background-color: var(--#{$prefix}danger-dark); + background-color: var(#{$rootPrefix}danger-dark); } } diff --git a/assets/css/_partials/_widgets/_reading-progress.scss b/assets/css/_partials/_widgets/_reading-progress.scss index c8616f88..2c59a476 100644 --- a/assets/css/_partials/_widgets/_reading-progress.scss +++ b/assets/css/_partials/_widgets/_reading-progress.scss @@ -2,12 +2,12 @@ --progress: 0; height: var(--progress-h, 2px); width: var(--progress); - background-color: var(--bg-progress, var(--#{$prefix}info)); + background-color: var(--bg-progress, var(#{$rootPrefix}info)); position: fixed; @include z-index(2); @extend .print-d-none; [data-theme="dark"] & { - background-color: var(--bg-progress-dark, var(--#{$prefix}info-dark)); + background-color: var(--bg-progress-dark, var(#{$rootPrefix}info-dark)); } } diff --git a/assets/css/_shortcodes/_admonition.scss b/assets/css/_shortcodes/_admonition.scss index 0dd07a99..81b5c8fe 100644 --- a/assets/css/_shortcodes/_admonition.scss +++ b/assets/css/_shortcodes/_admonition.scss @@ -53,34 +53,34 @@ right: 0.3rem; } - background-color: var(--#{$prefix}admonition-bg-color); - border-left-color: var(--#{$prefix}admonition-color); + background-color: var(#{$rootPrefix}admonition-bg-color); + border-left-color: var(#{$rootPrefix}admonition-color); > .admonition-title { - border-bottom-color: var(--#{$prefix}admonition-bg-color); - background-color: var(--#{$prefix}admonition-bg-color-collapsed); + border-bottom-color: var(#{$rootPrefix}admonition-bg-color); + background-color: var(#{$rootPrefix}admonition-bg-color-collapsed); i.icon { - color: var(--#{$prefix}admonition-color); + color: var(#{$rootPrefix}admonition-color); } } &.open > .admonition-title { - background-color: var(--#{$prefix}admonition-bg-color); + background-color: var(#{$rootPrefix}admonition-bg-color); } // default admonition type is note - --#{$prefix}admonition-color: #{map-get(map-get($admonition-color-map, note), color)}; - --#{$prefix}admonition-bg-color: #{map-get(map-get($admonition-color-map, note), bg-color)}; - --#{$prefix}admonition-bg-color-collapsed: #{opacify(map-get(map-get($admonition-color-map, note), bg-color), 0.15)}; + #{$rootPrefix}admonition-color: #{map-get(map-get($admonition-color-map, note), color)}; + #{$rootPrefix}admonition-bg-color: #{map-get(map-get($admonition-color-map, note), bg-color)}; + #{$rootPrefix}admonition-bg-color-collapsed: #{opacify(map-get(map-get($admonition-color-map, note), bg-color), 0.15)}; // set color for each admonition type @each $type, $item in $admonition-color-map { @if $type != 'note' { &.#{$type} { - --#{$prefix}admonition-color: #{map-get($item, color)}; - --#{$prefix}admonition-bg-color: #{map-get($item, bg-color)}; - --#{$prefix}admonition-bg-color-collapsed: #{opacify(map-get($item, bg-color), 0.15)}; + #{$rootPrefix}admonition-color: #{map-get($item, color)}; + #{$rootPrefix}admonition-bg-color: #{map-get($item, bg-color)}; + #{$rootPrefix}admonition-bg-color-collapsed: #{opacify(map-get($item, bg-color), 0.15)}; } } } diff --git a/assets/css/_shortcodes/_index.scss b/assets/css/_shortcodes/_index.scss index 98ef296d..7530f5c1 100644 --- a/assets/css/_shortcodes/_index.scss +++ b/assets/css/_shortcodes/_index.scss @@ -7,4 +7,5 @@ @import '_instagram'; @import '_mapbox'; @import '_mermaid'; +@import '_tabs'; @import '_timeline'; diff --git a/assets/css/_shortcodes/_mermaid.scss b/assets/css/_shortcodes/_mermaid.scss index a4c80399..e8f6f6ba 100644 --- a/assets/css/_shortcodes/_mermaid.scss +++ b/assets/css/_shortcodes/_mermaid.scss @@ -10,17 +10,7 @@ } &:not([data-processed])::before { - content: ''; - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; - backdrop-filter: blur(1rem); - background-position: center; - background-repeat: no-repeat; - background-image: var(#{$rootPrefix}loading-img); - background-size: 60px; + @include loading; } svg { diff --git a/assets/css/_shortcodes/_tabs.scss b/assets/css/_shortcodes/_tabs.scss new file mode 100644 index 00000000..8e77894e --- /dev/null +++ b/assets/css/_shortcodes/_tabs.scss @@ -0,0 +1,572 @@ +// ======================================== +// Tabs shortcode - Multiple Design Styles +// ======================================== + +@mixin tab-button-size($padding-inline: 1.25rem, $padding-block: 0.75rem) { + @if $padding-inline !=0 { + padding-inline: $padding-inline; + } + + @if $padding-block !=0 { + padding-block: $padding-block; + } +} + +tab-container { + display: flex; + gap: 0.75rem; + padding-block: 1rem; + position: relative; + + // loading before defined + &:not(:defined) { + &::before { + @include loading; + } + } + + > .tab-button { + position: relative; + display: block; + border: none; + color: inherit; + background: transparent; + font-size: 0.9em; + font-weight: 500; + cursor: pointer; + flex-shrink: 0; + @include transition(all 0.3s ease); + } + + > .tab-panel { + &[hidden] { + display: none; + } + } + + &::part(tablist-tab-wrapper) { + flex: 1 0 auto; + } + + &::part(tablist) { + display: flex; + } + + &[placement='top'], + &[placement='bottom'] { + &::part(tablist-wrapper) { + max-width: 100%; + } + + &::part(tablist) { + gap: 1rem; + } + } + + &[placement='left'], + &[placement='right'] { + max-width: 100%; + overflow: hidden; + + &::part(tablist-wrapper) { + min-height: 100px; + } + + &::part(tablist) { + flex-direction: column; + } + + > .tab-button { + max-width: 300px; + } + + > .tab-panel { + flex: 1; + min-width: 0; + } + } + + &[placement='top'] { + flex-direction: column; + } + + &[placement='bottom'] { + flex-direction: column-reverse; + } + + &[placement='right'] { + flex-direction: row-reverse; + } + + // ======================================== + // Style 1: Underline Style (Default) + // Clean, minimal with bottom border + // ======================================== + &[type='underline'] { + &::part(tablist-tab-wrapper) { + --border-color: #{$global-border-color}; + + [data-theme='dark'] & { + --border-color: #{$global-border-color-dark}; + } + } + + > .tab-button { + --border-color: transparent; + @include tab-button-size(0); + + &[aria-selected='true'], + &[aria-selected='false']:hover { + color: var(#{$rootPrefix}primary); + --border-color: var(#{$rootPrefix}primary); + } + + &[aria-selected='false']:hover { + opacity: 0.7; + } + } + + &[placement='top'], + &[placement='bottom'] { + gap: 0.5rem; + + > .tab-button { + @include tab-button-size(1.5rem, 0); + } + + &::part(tablist-wrapper) { + overflow-x: scroll; + overflow-y: hidden; + } + } + + &[placement='left'], + &[placement='right'] { + > .tab-button { + @include tab-button-size(1rem, 0); + } + } + + // Top placement + &[placement='top'] { + &::part(tablist-tab-wrapper) { + border-bottom: 2px solid var(--border-color); + } + + > .tab-button { + translate: 0 2px; + border-bottom: 2px solid var(--border-color); + } + } + + // Bottom placement + &[placement='bottom'] { + &::part(tablist-tab-wrapper) { + border-top: 2px solid var(--border-color); + } + + > .tab-button { + translate: 0 -2px; + border-top: 2px solid var(--border-color); + } + } + + // Left placement + &[placement='left'] { + &::part(tablist-tab-wrapper) { + border-right: 2px solid var(--border-color); + } + + > .tab-button { + text-align: right; + translate: 2px 0; + border-right: 2px solid var(--border-color); + } + } + + // Right placement + &[placement='right'] { + &::part(tablist-tab-wrapper) { + border-left: 2px solid var(--border-color); + } + + > .tab-button { + text-align: left; + translate: -2px 0; + border-left: 2px solid var(--border-color); + } + } + } + + // ======================================== + // Style 2: Pill Style + // Rounded buttons with background + // ======================================== + &[type='pill'] { + > .tab-button { + background: var(#{$rootPrefix}code-inline-background-color); + @include tab-button-size; + @include border-radius(2em); + + &[aria-selected='true'] { + color: #ffffff; + background: var(#{$rootPrefix}primary); + @include box-shadow(0 0.125rem 0.5rem rgba(0, 0, 0, 0.3)); + + [data-theme='dark'] & { + background: var(#{$rootPrefix}primary); + @include box-shadow(0 0.125rem 0.5rem rgba(255, 255, 255, 0.3)); + } + } + + &[aria-selected='false']:hover { + background: rgba(175, 184, 193, 0.4); + + [data-theme='dark'] & { + background: rgba(99, 110, 123, 0.6); + } + } + } + + &[placement='top'], + &[placement='bottom'] { + &::part(tablist-tab-wrapper) { + max-width: 100%; + } + + &::part(tablist) { + flex-wrap: wrap; + row-gap: 0.5rem; + } + } + + &[placement='left'], + &[placement='right'] { + &::part(tablist) { + gap: 0.75rem; + } + } + + // Top placement + &[placement='top'] { + > .tab-button { + &:hover { + translate: 0 2px; + } + } + } + + // Bottom placement + &[placement='bottom'] { + > .tab-button { + &:hover { + translate: 0 -2px; + } + } + } + + // Left placement + &[placement='left'] { + &::part(tablist) { + margin-left: 0.5rem; + } + + > .tab-button { + &:hover { + translate: 2px 0; + } + } + } + + // Right placement + &[placement='right'] { + &::part(tablist) { + margin-right: 0.5rem; + } + + > .tab-button { + &:hover { + translate: -2px 0; + } + } + } + } + + // ======================================== + // Style 3: Card Style + // Card-like appearance with borders + // ======================================== + &[type='card'] { + gap: 0; + + &::part(tablist-tab-wrapper) { + --border-color: #{$global-border-color}; + + [data-theme='dark'] & { + --border-color: #{$global-border-color-dark}; + } + } + + &::part(tablist) { + gap: 0.25rem; + } + + > .tab-button { + border: 1px solid $global-border-color; + background: $code-background-color; + @include tab-button-size(1.5rem); + + [data-theme='dark'] & { + border-color: $global-border-color-dark; + background: $code-background-color-dark; + } + + &[aria-selected='true'] { + background: $global-background-color; + color: $global-link-color; + z-index: 1; + --border-active-color: #{$global-background-color}; + + [data-theme='dark'] & { + background: $global-background-color-dark; + color: $global-link-color-dark; + --border-active-color: #{$global-background-color-dark}; + } + } + + &[aria-selected='false']:hover { + background: $global-background-color; + color: $global-link-color; + z-index: 1; + + [data-theme='dark'] & { + background: $global-background-color-dark; + color: $global-link-color-dark; + } + } + } + + > .tab-panel { + padding: 0.75rem; + background: $global-background-color; + border: 1px solid $global-border-color; + + [data-theme='dark'] & { + background: $global-background-color-dark; + border-color: $global-border-color-dark; + } + } + + &[placement='top'], + &[placement='bottom'] { + &::part(tablist-wrapper) { + overflow-x: scroll; + overflow-y: hidden; + } + + > .tab-button { + &:first-of-type { + position: sticky; + left: 0; + z-index: 2; + } + + &:last-of-type { + position: sticky; + right: 0; + z-index: 2; + } + } + } + + // Top placement + &[placement='top'] { + &::part(tablist-tab-wrapper) { + border-bottom: 1px solid var(--border-color); + } + + > .tab-button { + translate: 0 1px; + @include border-radius($global-border-radius $global-border-radius 0 0); + + &[aria-selected='true'] { + border-bottom-color: var(--border-active-color); + } + } + + > .tab-panel { + border-top: none; + @include border-radius(0 0 $global-border-radius $global-border-radius); + } + } + + // Bottom placement + &[placement='bottom'] { + &::part(tablist-tab-wrapper) { + border-top: 1px solid var(--border-color); + } + + > .tab-button { + translate: 0 -1px; + @include border-radius(0 0 $global-border-radius $global-border-radius); + + &[aria-selected='true'] { + border-top-color: var(--border-active-color); + } + } + + > .tab-panel { + border-bottom: none; + @include border-radius($global-border-radius $global-border-radius 0 0); + } + } + + // Left placement + &[placement='left'] { + &::part(tablist-tab-wrapper) { + border-right: 1px solid var(--border-color); + } + + > .tab-button { + translate: 1px 0; + @include border-radius($global-border-radius 0 0 $global-border-radius); + + &[aria-selected='true'] { + border-right-color: var(--border-active-color); + } + } + + > .tab-panel { + border-left: none; + @include border-radius(0 $global-border-radius $global-border-radius 0); + } + } + + // Right placement + &[placement='right'] { + &::part(tablist-tab-wrapper) { + border-left: 1px solid var(--border-color); + } + + > .tab-button { + translate: -1px 0; + @include border-radius(0 $global-border-radius $global-border-radius 0); + + &[aria-selected='true'] { + border-left-color: var(--border-active-color); + } + } + + > .tab-panel { + border-right: none; + @include border-radius($global-border-radius 0 0 $global-border-radius); + } + } + } + + // ======================================== + // Style 4: Segment Style + // only top placement support + // ======================================== + &[type='segment'] { + &::part(tablist-wrapper) { + overflow-x: scroll; + overflow-y: hidden; + } + + &::part(tablist-tab-wrapper) { + padding: 0.25rem; + background: $code-background-color; + @include border-radius($global-border-radius); + + [data-theme='dark'] & { + background: $code-background-color-dark; + } + } + + &::part(tablist) { + gap: 0; + } + + > .tab-button { + font-weight: 400; + flex-grow: 1; + + @include tab-button-size; + @include border-radius($global-border-radius); + + &[aria-selected='true'], + &:hover { + font-weight: 500; + } + + &[aria-selected='true'] { + background: $global-background-color; + @include box-shadow(0 0.125rem 0.25rem rgba(0, 0, 0, 0.1)); + + [data-theme='dark'] & { + background: $global-background-color-dark; + @include box-shadow(0 0.125rem 0.25rem rgba(255, 255, 255, 0.1)); + } + } + } + } +} + +// ======================================== +// Responsive design for smaller screens +// ======================================== +@media only screen and (max-width: 680px) { + tab-container { + &[type='underline'] { + &[placement='top'], + &[placement='bottom'] { + > .tab-button { + @include tab-button-size(0.875rem, 0); + } + + &::part(tablist) { + gap: 0; + } + } + } + + &[type='pill'] { + &[placement='top'], + &[placement='bottom'] { + > .tab-button { + @include tab-button-size(1rem, 0); + } + + &::part(tablist) { + gap: 0.375rem 0.5rem; + } + } + } + + &[type='card'] { + > .tab-button { + @include tab-button-size(1rem); + } + } + } +} + +// ======================================== +// Smooth animations +// ======================================== +@keyframes tabSlideIn { + from { + opacity: 0; + transform: translateY(10px); + } + + to { + opacity: 1; + transform: translateY(0); + } +} + +tab-container .tab-panel:not([hidden]) { + animation: tabSlideIn 0.3s ease-out; +} diff --git a/assets/css/_shortcodes/_timeline.scss b/assets/css/_shortcodes/_timeline.scss index 237b489b..216ddf35 100644 --- a/assets/css/_shortcodes/_timeline.scss +++ b/assets/css/_shortcodes/_timeline.scss @@ -36,14 +36,14 @@ @each $color, $value in $theme-colors { &[data-type='#{$color}'] { - --timeline-circle-color: var(--#{$prefix}#{$color}); + --timeline-circle-color: var(#{$rootPrefix}#{$color}); } } .#{$prefix}timeline-item__timestamp { font-size: 0.8125rem; line-height: 1; - color: var(--#{$prefix}secondary); + color: var(#{$rootPrefix}secondary); &.is-top { margin-bottom: 0.25rem; @@ -105,4 +105,4 @@ --timeline-color: #{darken($global-border-color, 50%)}; } } -} \ No newline at end of file +} diff --git a/assets/data/cdn/jsdelivr.yml b/assets/data/cdn/jsdelivr.yml index 44117471..7074e1e7 100644 --- a/assets/data/cdn/jsdelivr.yml +++ b/assets/data/cdn/jsdelivr.yml @@ -61,6 +61,8 @@ libFiles: paceJS: pace-js@1.2.4 # sharer.js@0.5.1 https://github.com/ellisonleao/sharer.js sharerJS: sharer.js@0.5.1/sharer.min.js + # @github/tab-container-element@4.8.2 https://github.com/github/tab-container-element + tabContainerElementJS: '@github/tab-container-element@4.8.2/dist/index.min.js' # twemoji@14.0.2 https://github.com/twitter/twemoji twemojiJS: twemoji@14.0.2/dist/twemoji.min.js # twikoo@1.6.44 https://github.com/imaegoo/twikoo diff --git a/assets/data/cdn/unpkg.yml b/assets/data/cdn/unpkg.yml index cd78537f..2e6e25e4 100644 --- a/assets/data/cdn/unpkg.yml +++ b/assets/data/cdn/unpkg.yml @@ -61,6 +61,8 @@ libFiles: paceJS: pace-js@1.2.4 # sharer.js@0.5.1 https://github.com/ellisonleao/sharer.js sharerJS: sharer.js@0.5.1/sharer.min.js + # @github/tab-container-element@4.8.2 https://github.com/github/tab-container-element + tabContainerElementJS: '@github/tab-container-element@4.8.2/dist/index.js' # twemoji@14.0.2 https://github.com/twitter/twemoji twemojiJS: twemoji@14.0.2/dist/twemoji.min.js # twikoo@1.6.44 https://github.com/imaegoo/twikoo diff --git a/assets/lib/VERSION b/assets/lib/VERSION index 2b6b6b1c..9fd051f8 100644 --- a/assets/lib/VERSION +++ b/assets/lib/VERSION @@ -22,6 +22,7 @@ object-fit-images@3.2.4 https://github.com/fregante/object-fit-images [archived] pangu.js@4.0.7 https://github.com/vinta/pangu.js sharer.js@0.5.1 https://github.com/ellisonleao/sharer.js simple-icons@9.19.0 https://github.com/simple-icons/simple-icons +tab-container-element@4.8.2 https://github.com/github/tab-container-element twemoji@14.0.2 https://github.com/twitter/twemoji twikoo@1.6.44 https://github.com/imaegoo/twikoo typeit@8.8.4 https://github.com/alexmacarthur/typeit diff --git a/assets/lib/tab-container-element/bundle.min.js b/assets/lib/tab-container-element/bundle.min.js new file mode 100644 index 00000000..6c1d01ac --- /dev/null +++ b/assets/lib/tab-container-element/bundle.min.js @@ -0,0 +1,7 @@ +/** + * Minified by jsDelivr using Terser v5.37.0. + * Original file: /npm/@github/tab-container-element@4.8.2/dist/bundle.js + * + * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files + */ +var _a,_TabContainerChangeEvent_tabIndex,_TabContainerChangeEvent_panel,_TabContainerChangeEvent_tab,_TabContainerElement_instances,_TabContainerElement_onTabContainerChange,_TabContainerElement_onTabContainerChanged,_TabContainerElement_tabList_get,_TabContainerElement_tabListWrapper_get,_TabContainerElement_tabListTabWrapper_get,_TabContainerElement_beforeTabsSlot_get,_TabContainerElement_afterTabsSlot_get,_TabContainerElement_afterPanelsSlot_get,_TabContainerElement_tabListSlot_get,_TabContainerElement_panelSlot_get,_TabContainerElement_tabs_get,_TabContainerElement_setupComplete,_TabContainerElement_internals,_TabContainerElement_handleKeydown,_TabContainerElement_handleClick,_TabContainerElement_reflectAttributeToShadow,__defProp=Object.defineProperty,__name=(e,t)=>__defProp(e,"name",{value:t,configurable:!0}),__classPrivateFieldSet=function(e,t,a,n,i){if("m"===n)throw new TypeError("Private method is not writable");if("a"===n&&!i)throw new TypeError("Private accessor was defined without a setter");if("function"==typeof t?e!==t||!i:!t.has(e))throw new TypeError("Cannot write private member to an object whose class did not declare it");return"a"===n?i.call(e,a):i?i.value=a:t.set(e,a),a},__classPrivateFieldGet=function(e,t,a,n){if("a"===a&&!n)throw new TypeError("Private accessor was defined without a getter");if("function"==typeof t?e!==t||!n:!t.has(e))throw new TypeError("Cannot read private member from an object whose class did not declare it");return"m"===a?n:"a"===a?n.call(e):n?n.value:t.get(e)},__rest=function(e,t){var a={};for(var n in e)Object.prototype.hasOwnProperty.call(e,n)&&t.indexOf(n)<0&&(a[n]=e[n]);if(null!=e&&"function"==typeof Object.getOwnPropertySymbols){var i=0;for(n=Object.getOwnPropertySymbols(e);i{e.assign(...t)}:(e,...t)=>{const a=e.getRootNode().host;for(const t of a.querySelectorAll(`[slot="${e.name}"]`))t.removeAttribute("slot");for(const a of t)a.setAttribute("slot",e.name)},_TabContainerChangeEvent=class extends Event{constructor(e,t){var{tabIndex:a,tab:n,panel:i}=t;super(e,__rest(t,["tabIndex","tab","panel"])),_TabContainerChangeEvent_tabIndex.set(this,null),_TabContainerChangeEvent_panel.set(this,null),_TabContainerChangeEvent_tab.set(this,null),__classPrivateFieldSet(this,_TabContainerChangeEvent_tab,n||null,"f"),__classPrivateFieldSet(this,_TabContainerChangeEvent_tabIndex,a||null,"f"),__classPrivateFieldSet(this,_TabContainerChangeEvent_panel,i||null,"f")}get detail(){return console.warn("TabContainerElement.detail is deprecated, please use .panel instead"),{relatedTarget:__classPrivateFieldGet(this,_TabContainerChangeEvent_panel,"f")}}get tabIndex(){return __classPrivateFieldGet(this,_TabContainerChangeEvent_tabIndex,"f")}get panel(){return __classPrivateFieldGet(this,_TabContainerChangeEvent_panel,"f")}get tab(){return __classPrivateFieldGet(this,_TabContainerChangeEvent_tab,"f")}},TabContainerChangeEvent=_TabContainerChangeEvent;__name(_TabContainerChangeEvent,"TabContainerChangeEvent"),_TabContainerChangeEvent_tabIndex=new WeakMap,_TabContainerChangeEvent_panel=new WeakMap,_TabContainerChangeEvent_tab=new WeakMap;var _TabContainerElement=class extends HTMLElement{constructor(){super(...arguments),_TabContainerElement_instances.add(this),_TabContainerElement_onTabContainerChange.set(this,null),_TabContainerElement_onTabContainerChanged.set(this,null),_TabContainerElement_setupComplete.set(this,!1),_TabContainerElement_internals.set(this,void 0)}static define(e="tab-container",t=customElements){return t.define(e,this),this}get onChange(){return this.onTabContainerChange}set onChange(e){this.onTabContainerChange=e}get onTabContainerChange(){return __classPrivateFieldGet(this,_TabContainerElement_onTabContainerChange,"f")}set onTabContainerChange(e){__classPrivateFieldGet(this,_TabContainerElement_onTabContainerChange,"f")&&this.removeEventListener("tab-container-change",__classPrivateFieldGet(this,_TabContainerElement_onTabContainerChange,"f")),__classPrivateFieldSet(this,_TabContainerElement_onTabContainerChange,"object"==typeof e||"function"==typeof e?e:null,"f"),"function"==typeof e&&this.addEventListener("tab-container-change",e)}get onTabContainerChanged(){return __classPrivateFieldGet(this,_TabContainerElement_onTabContainerChanged,"f")}set onTabContainerChanged(e){__classPrivateFieldGet(this,_TabContainerElement_onTabContainerChanged,"f")&&this.removeEventListener("tab-container-changed",__classPrivateFieldGet(this,_TabContainerElement_onTabContainerChanged,"f")),__classPrivateFieldSet(this,_TabContainerElement_onTabContainerChanged,"object"==typeof e||"function"==typeof e?e:null,"f"),"function"==typeof e&&this.addEventListener("tab-container-changed",e)}get onChanged(){return this.onTabContainerChanged}set onChanged(e){this.onTabContainerChanged=e}get activeTab(){return __classPrivateFieldGet(this,_TabContainerElement_instances,"a",_TabContainerElement_tabs_get)[this.selectedTabIndex]}get activePanel(){return __classPrivateFieldGet(this,_TabContainerElement_instances,"a",_TabContainerElement_panelSlot_get).assignedNodes()[0]}get vertical(){var e;return"vertical"===(null===(e=__classPrivateFieldGet(this,_TabContainerElement_instances,"a",_TabContainerElement_tabList_get))||void 0===e?void 0:e.getAttribute("aria-orientation"))}set vertical(e){const t=__classPrivateFieldGet(this,_TabContainerElement_instances,"a",_TabContainerElement_tabList_get);t&&e?t.setAttribute("aria-orientation","vertical"):t.setAttribute("aria-orientation","horizontal")}connectedCallback(){__classPrivateFieldSet(this,_TabContainerElement_internals,__classPrivateFieldGet(this,_TabContainerElement_internals,"f")||(this.attachInternals?this.attachInternals():null),"f");const e=this.shadowRoot||this.attachShadow({mode:"open",slotAssignment:"manual"}),t=document.createElement("slot");t.style.display="flex",t.setAttribute("part","tablist-wrapper"),t.setAttribute("name","tablist-wrapper");const a=document.createElement("div");a.setAttribute("part","tablist-tab-wrapper"),a.setAttribute("name","tablist-tab-wrapper");const n=document.createElement("slot");n.setAttribute("part","tablist"),n.setAttribute("name","tablist"),a.append(n);const i=document.createElement("slot");i.setAttribute("part","panel"),i.setAttribute("name","panel");const r=document.createElement("slot");r.setAttribute("part","before-tabs"),r.setAttribute("name","before-tabs");const s=document.createElement("slot");s.setAttribute("part","after-tabs"),s.setAttribute("name","after-tabs"),t.append(r,a,s);const l=document.createElement("slot");if(l.setAttribute("part","after-panels"),l.setAttribute("name","after-panels"),e.replaceChildren(t,i,l),__classPrivateFieldGet(this,_TabContainerElement_internals,"f")&&"role"in __classPrivateFieldGet(this,_TabContainerElement_internals,"f")?__classPrivateFieldGet(this,_TabContainerElement_internals,"f").role="presentation":this.setAttribute("role","presentation"),this.addEventListener("keydown",this),this.addEventListener("click",this),this.selectTab(-1),!__classPrivateFieldGet(this,_TabContainerElement_setupComplete,"f")){const e=new MutationObserver((()=>{this.selectTab(-1),__classPrivateFieldGet(this,_TabContainerElement_setupComplete,"f")&&e.disconnect()}));e.observe(this,{childList:!0,subtree:!0})}}attributeChangedCallback(e){this.isConnected&&this.shadowRoot&&"vertical"===e&&(this.vertical=this.hasAttribute("vertical"))}handleEvent(e){return"click"===e.type?__classPrivateFieldGet(this,_TabContainerElement_instances,"m",_TabContainerElement_handleClick).call(this,e):"keydown"===e.type?__classPrivateFieldGet(this,_TabContainerElement_instances,"m",_TabContainerElement_handleKeydown).call(this,e):void 0}get selectedTabIndex(){return __classPrivateFieldGet(this,_TabContainerElement_instances,"a",_TabContainerElement_tabs_get).findIndex((e=>e.matches("[aria-selected=true]")))}set selectedTabIndex(e){this.selectTab(e)}get defaultTabIndex(){return Number(this.getAttribute("default-tab")||-1)}set defaultTabIndex(e){this.setAttribute("default-tab",String(e))}selectTab(e){var t;if(!__classPrivateFieldGet(this,_TabContainerElement_setupComplete,"f")){const a=__classPrivateFieldGet(this,_TabContainerElement_instances,"a",_TabContainerElement_tabListSlot_get),n=__classPrivateFieldGet(this,_TabContainerElement_instances,"a",_TabContainerElement_tabListWrapper_get),i=this.querySelector("[role=tablist]"),r=this.querySelector("[slot=tablist-wrapper]");r&&r.closest(this.tagName)===this?assignSlotWithFallback(n,r):i&&i.closest(this.tagName)===this?assignSlotWithFallback(a,i):(__classPrivateFieldGet(this,_TabContainerElement_instances,"a",_TabContainerElement_tabListTabWrapper_get).role="tablist",assignSlotWithFallback(a,...[...this.children].filter((e=>e.matches("[role=tab]")))));const s=__classPrivateFieldGet(this,_TabContainerElement_instances,"a",_TabContainerElement_tabList_get);__classPrivateFieldGet(this,_TabContainerElement_instances,"m",_TabContainerElement_reflectAttributeToShadow).call(this,"aria-description",s),__classPrivateFieldGet(this,_TabContainerElement_instances,"m",_TabContainerElement_reflectAttributeToShadow).call(this,"aria-label",s),this.vertical&&__classPrivateFieldGet(this,_TabContainerElement_instances,"a",_TabContainerElement_tabList_get).setAttribute("aria-orientation","vertical");if(!((null===(t=this.querySelector("[slot=tablist-wrapper]"))||void 0===t?void 0:t.closest(this.tagName))===this)){const e=[],t=[],a=[];let n=e;for(const i of this.children)"tab"!==i.getAttribute("role")&&"tablist"!==i.getAttribute("role")?"tabpanel"!==i.getAttribute("role")?"before-tabs"===i.getAttribute("slot")?e.push(i):"after-tabs"===i.getAttribute("slot")?t.push(i):n.push(i):n=a:n=t;assignSlotWithFallback(__classPrivateFieldGet(this,_TabContainerElement_instances,"a",_TabContainerElement_beforeTabsSlot_get),...e),assignSlotWithFallback(__classPrivateFieldGet(this,_TabContainerElement_instances,"a",_TabContainerElement_afterTabsSlot_get),...t),assignSlotWithFallback(__classPrivateFieldGet(this,_TabContainerElement_instances,"a",_TabContainerElement_afterPanelsSlot_get),...a)}const l=this.defaultTabIndex,o=l>=0?l:this.selectedTabIndex;e=e>=0?e:Math.max(0,o)}const a=__classPrivateFieldGet(this,_TabContainerElement_instances,"a",_TabContainerElement_tabs_get),n=Array.from(this.querySelectorAll('[role="tabpanel"]')).filter((e=>e.closest(this.tagName)===this));if(e>a.length-1)return;const i=a[e],r=n[e];if(i&&r){if(__classPrivateFieldGet(this,_TabContainerElement_setupComplete,"f")){if(!this.dispatchEvent(new TabContainerChangeEvent("tab-container-change",{tabIndex:e,bubbles:!0,cancelable:!0,tab:i,panel:r})))return}for(const e of a)e.setAttribute("aria-selected","false"),e.setAttribute("tabindex","-1");for(const e of n)e.hasAttribute("tabindex")||e.hasAttribute("data-tab-container-no-tabstop")||e.setAttribute("tabindex","0");i.setAttribute("aria-selected","true"),i.setAttribute("tabindex","0"),assignSlotWithFallback(__classPrivateFieldGet(this,_TabContainerElement_instances,"a",_TabContainerElement_panelSlot_get),r),r.hidden=!1,__classPrivateFieldGet(this,_TabContainerElement_setupComplete,"f")&&(i.focus(),this.dispatchEvent(new TabContainerChangeEvent("tab-container-changed",{tabIndex:e,bubbles:!0,tab:i,panel:r}))),__classPrivateFieldSet(this,_TabContainerElement_setupComplete,!0,"f")}}},TabContainerElement=_TabContainerElement;__name(_TabContainerElement,"TabContainerElement"),_TabContainerElement_onTabContainerChange=new WeakMap,_TabContainerElement_onTabContainerChanged=new WeakMap,_TabContainerElement_setupComplete=new WeakMap,_TabContainerElement_internals=new WeakMap,_TabContainerElement_instances=new WeakSet,_TabContainerElement_tabList_get=__name((function(){const e=this.querySelector("[slot=tablist-wrapper]");if((null==e?void 0:e.closest(this.tagName))===this)return e.querySelector("[role=tablist]");const t=__classPrivateFieldGet(this,_TabContainerElement_instances,"a",_TabContainerElement_tabListSlot_get);return __classPrivateFieldGet(this,_TabContainerElement_instances,"a",_TabContainerElement_tabListTabWrapper_get).hasAttribute("role")?__classPrivateFieldGet(this,_TabContainerElement_instances,"a",_TabContainerElement_tabListTabWrapper_get):t.assignedNodes()[0]}),"_TabContainerElement_tabList_get"),_TabContainerElement_tabListWrapper_get=__name((function(){return this.shadowRoot.querySelector('slot[part="tablist-wrapper"]')}),"_TabContainerElement_tabListWrapper_get"),_TabContainerElement_tabListTabWrapper_get=__name((function(){return this.shadowRoot.querySelector('div[part="tablist-tab-wrapper"]')}),"_TabContainerElement_tabListTabWrapper_get"),_TabContainerElement_beforeTabsSlot_get=__name((function(){return this.shadowRoot.querySelector('slot[part="before-tabs"]')}),"_TabContainerElement_beforeTabsSlot_get"),_TabContainerElement_afterTabsSlot_get=__name((function(){return this.shadowRoot.querySelector('slot[part="after-tabs"]')}),"_TabContainerElement_afterTabsSlot_get"),_TabContainerElement_afterPanelsSlot_get=__name((function(){return this.shadowRoot.querySelector('slot[part="after-panels"]')}),"_TabContainerElement_afterPanelsSlot_get"),_TabContainerElement_tabListSlot_get=__name((function(){return this.shadowRoot.querySelector('slot[part="tablist"]')}),"_TabContainerElement_tabListSlot_get"),_TabContainerElement_panelSlot_get=__name((function(){return this.shadowRoot.querySelector('slot[part="panel"]')}),"_TabContainerElement_panelSlot_get"),_TabContainerElement_tabs_get=__name((function(){var e;return __classPrivateFieldGet(this,_TabContainerElement_instances,"a",_TabContainerElement_tabListTabWrapper_get).matches("[role=tablist]")?__classPrivateFieldGet(this,_TabContainerElement_instances,"a",_TabContainerElement_tabListSlot_get).assignedNodes():Array.from((null===(e=__classPrivateFieldGet(this,_TabContainerElement_instances,"a",_TabContainerElement_tabList_get))||void 0===e?void 0:e.querySelectorAll('[role="tab"]'))||[]).filter((e=>e instanceof HTMLElement&&e.closest(this.tagName)===this))}),"_TabContainerElement_tabs_get"),_TabContainerElement_handleKeydown=__name((function(e){var t,a,n;const i=null===(a=null===(t=e.target)||void 0===t?void 0:t.closest)||void 0===a?void 0:a.call(t,'[role="tab"]');if(!i)return;const r=__classPrivateFieldGet(this,_TabContainerElement_instances,"a",_TabContainerElement_tabs_get);if(!r.includes(i))return;const s=this.selectedTabIndex,l="vertical"===(null===(n=i.closest('[role="tablist"]'))||void 0===n?void 0:n.getAttribute("aria-orientation")),o="ArrowLeft"===e.code||l&&"ArrowUp"===e.code;if("ArrowRight"===e.code||l&&"ArrowDown"===e.code){let e=s+1;e>=r.length&&(e=0),this.selectTab(e)}else if(o){let e=s-1;e<0&&(e=r.length-1),this.selectTab(e)}else"Home"===e.code?(this.selectTab(0),e.preventDefault()):"End"===e.code&&(this.selectTab(r.length-1),e.preventDefault())}),"_TabContainerElement_handleKeydown"),_TabContainerElement_handleClick=__name((function(e){var t,a;const n=null===(a=null===(t=e.target)||void 0===t?void 0:t.closest)||void 0===a?void 0:a.call(t,"[role=tab]");if(!n)return;const i=__classPrivateFieldGet(this,_TabContainerElement_instances,"a",_TabContainerElement_tabs_get).indexOf(n);i>=0&&this.selectTab(i)}),"_TabContainerElement_handleClick"),_TabContainerElement_reflectAttributeToShadow=__name((function(e,t){this.hasAttribute(e)&&(t.setAttribute(e,this.getAttribute(e)),this.removeAttribute(e))}),"_TabContainerElement_reflectAttributeToShadow"),TabContainerElement.observedAttributes=["vertical"];var root="undefined"!=typeof globalThis?globalThis:window;try{root.TabContainerElement=TabContainerElement.define()}catch(e){if(!(root.DOMException&&e instanceof DOMException&&"NotSupportedError"===e.name||e instanceof ReferenceError))throw e}var dist_default=TabContainerElement;export{TabContainerChangeEvent,TabContainerElement,dist_default as default}; diff --git a/layouts/_partials/assets.html b/layouts/_partials/assets.html index 8cba98c4..ff4d3798 100644 --- a/layouts/_partials/assets.html +++ b/layouts/_partials/assets.html @@ -181,6 +181,12 @@ {{- dict "Source" $source "Fingerprint" $fingerprint "Defer" true | dict "Page" . "Data" | partial "store/script.html" -}} {{- end -}} +{{- /* Tabs and tab */ -}} +{{- if .Store.Get "hasTabs" -}} + {{- $source := $cdn.tabContainerElementJS | default "lib/tab-container-element/bundle.min.js" -}} + {{- dict "Source" $source "Fingerprint" $fingerprint "Attr" `type="module"` "Defer" true | dict "Page" . "Data" | partial "store/script.html" -}} +{{- end -}} + {{- /* Cookie Consent */ -}} {{- if .Site.Params.cookieconsent | and .Site.Params.cookieconsent.enable -}} {{- $source := $cdn.cookieconsentCSS | default "lib/cookieconsent/cookieconsent.min.css" -}} diff --git a/layouts/_shortcodes/tab.html b/layouts/_shortcodes/tab.html new file mode 100644 index 00000000..c4722a85 --- /dev/null +++ b/layouts/_shortcodes/tab.html @@ -0,0 +1,18 @@ +{{- with $.Parent -}} + {{- if ne $.Parent.Name "tabs" -}} + {{- errorf "Found shortcode %q enclosed inside a %q block, must be enclosed inside a %q block. Error position: %s" $.Name $.Parent.Name "tabs" $.Position -}} + {{- end -}} +{{- else -}} + {{- errorf "shortcode %q must be enclosed inside a %q block, but no parent block was found. Error position: %s" $.Name "tabs" $.Position -}} +{{- end -}} + +{{- $id := dict "Page" .Page | partial "function/id.html" -}} +{{- $title := .Get "title" -}} +{{- .Parent.Store.Add "tabs" (slice (dict "title" $title "id" $id)) -}} +{{- $content := trim .Inner "\r\n" -}} +{{- /* Remove p tags around complete tab-container structure */ -}} +{{- $content = $content | replaceRE `

(]*>[\s\S]*?)

` "$1" -}} + +{{- /* Tab panel */ -}} +
{{ $content | safeHTML }}
+{{- /* EOF */ -}} diff --git a/layouts/_shortcodes/tabs.html b/layouts/_shortcodes/tabs.html new file mode 100644 index 00000000..b719b70c --- /dev/null +++ b/layouts/_shortcodes/tabs.html @@ -0,0 +1,31 @@ +{{- $tabs := .Store.Get "tabs" -}} +{{- if not $tabs -}} + {{- errorf "No tabs found. Please add at least one tab to the tabs shortcode. See %s %s" .Name .Position -}} +{{- end -}} +{{- $lenTabs := len $tabs -}} +{{- $defaultTab := .Get "defaultTab" | default 0 -}} +{{- $type := .Get "type" | default "underline" -}} +{{- $placement := .Get "placement" | default "top" -}} +{{- $placementMap := slice "top" "bottom" "left" "right" -}} +{{- if ge $defaultTab $lenTabs -}} + {{- warnf "The defaultTab value %v is out of range [0, %v]. See %s %s" $defaultTab (sub $lenTabs 1) .Name .Position -}} + {{- $defaultTab = 0 -}} +{{- end -}} +{{- if not (in $placementMap $placement) -}} + {{- warnf "The placement value %q is invalid. Supported values are: %v. See %s %s" $placement (delimit $placementMap ", ") .Name .Position -}} + {{- $placement = "top" -}} +{{- end -}} + +{{- /* Tabs Container */ -}} + + {{- range $index, $tab := $tabs -}} + {{- $title := $tab.title | default (printf "Untitled%v" $index) -}} + {{- $id := $tab.id -}} + + {{- end -}} + {{- .Inner -}} + +{{- .Page.Store.Set "hasTabs" true -}} +{{- if eq hugo.Context.MarkupScope "home" -}} + {{- site.Home.Store.Set "hasTabs" true -}} +{{- end -}}