Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/matcornic/hugo-theme-learn.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSwen Wenzel <5111028+swenzel@users.noreply.github.com>2021-03-16 20:21:57 +0300
committerGitHub <noreply@github.com>2021-03-16 20:21:57 +0300
commit0b5bb6e7b3a53f36872bc49e7c40da999eda02c0 (patch)
tree5b474578d520851601fae160fcafc9e67a69db17
parent0c0b906ae12f740c89c2d746060e58a3bf5ffb99 (diff)
Implement tab views (#386)
Tab views from @swenzel
-rw-r--r--exampleSite/content/shortcodes/tabs.en.md119
-rw-r--r--layouts/partials/header.html1
-rw-r--r--layouts/shortcodes/tab.html12
-rw-r--r--layouts/shortcodes/tabs.html21
-rw-r--r--static/css/tabs.css43
-rw-r--r--static/js/learn.js59
6 files changed, 252 insertions, 3 deletions
diff --git a/exampleSite/content/shortcodes/tabs.en.md b/exampleSite/content/shortcodes/tabs.en.md
new file mode 100644
index 0000000..d664eea
--- /dev/null
+++ b/exampleSite/content/shortcodes/tabs.en.md
@@ -0,0 +1,119 @@
+---
+title: Tabbed views
+description : "Synchronize selection of content in different tabbed views"
+---
+
+Choose which content to see across the page. Very handy for providing code
+snippets for multiple languages or providing configuration in different formats.
+
+## Code example
+
+ {{</* tabs */>}}
+ {{%/* tab name="python" */%}}
+ ```python
+ print("Hello World!")
+ ```
+ {{%/* /tab */%}}
+ {{%/* tab name="R" */%}}
+ ```R
+ > print("Hello World!")
+ ```
+ {{%/* /tab */%}}
+ {{%/* tab name="Bash" */%}}
+ ```Bash
+ echo "Hello World!"
+ ```
+ {{%/* /tab */%}}
+ {{</* /tabs */>}}
+
+Renders as:
+
+{{< tabs >}}
+{{% tab name="python" %}}
+```python
+print("Hello World!")
+```
+{{% /tab %}}
+{{% tab name="R" %}}
+```R
+> print("Hello World!")
+```
+{{% /tab %}}
+{{% tab name="Bash" %}}
+```Bash
+echo "Hello World!"
+```
+{{% /tab %}}
+{{< /tabs >}}
+
+Tab views with the same tabs that belong to the same group sychronize their selection:
+
+{{< tabs >}}
+{{% tab name="python" %}}
+```python
+print("Hello World!")
+```
+{{% /tab %}}
+{{% tab name="R" %}}
+```R
+> print("Hello World!")
+```
+{{% /tab %}}
+{{% tab name="Bash" %}}
+```Bash
+echo "Hello World!"
+```
+{{% /tab %}}
+{{< /tabs >}}
+
+## Config example
+
+ {{</* tabs groupId="config" */>}}
+ {{%/* tab name="json" */%}}
+ ```json
+ {
+ "Hello": "World"
+ }
+ ```
+ {{%/* /tab */%}}
+ {{%/* tab name="XML" */%}}
+ ```xml
+ <Hello>World</Hello>
+ ```
+ {{%/* /tab */%}}
+ {{%/* tab name="properties" */%}}
+ ```properties
+ Hello = World
+ ```
+ {{%/* /tab */%}}
+ {{</* /tabs */>}}
+
+Renders as:
+
+{{< tabs groupId="config" >}}
+{{% tab name="json" %}}
+```json
+{
+ "Hello": "World"
+}
+```
+{{% /tab %}}
+{{% tab name="XML" %}}
+```xml
+<Hello>World</Hello>
+```
+{{% /tab %}}
+{{% tab name="properties" %}}
+```properties
+Hello = World
+```
+{{% /tab %}}
+{{< /tabs >}}
+
+{{% notice warning %}}
+When using tab views with different content sets, make sure to use a common `groupId` for equal sets but distinct
+`groupId` for different sets. The `groupId` defaults to `'default'`.
+**Take this into account across the whole site!**
+The tab selection is restored automatically based on the `groupId` and if it cannot find a tab item because it came
+ from the `'default'` group on a different page then all tabs will be empty at first.
+{{% /notice %}}
diff --git a/layouts/partials/header.html b/layouts/partials/header.html
index 2f97f76..8ee0334 100644
--- a/layouts/partials/header.html
+++ b/layouts/partials/header.html
@@ -17,6 +17,7 @@
<link href="{{"css/auto-complete.css" | relURL}}{{ if $assetBusting }}?{{ now.Unix }}{{ end }}" rel="stylesheet">
<link href="{{"css/atom-one-dark-reasonable.css" | relURL}}{{ if $assetBusting }}?{{ now.Unix }}{{ end }}" rel="stylesheet">
<link href="{{"css/theme.css" | relURL}}{{ if $assetBusting }}?{{ now.Unix }}{{ end }}" rel="stylesheet">
+ <link href="{{"css/tabs.css" | relURL}}{{ if $assetBusting }}?{{ now.Unix }}{{ end }}" rel="stylesheet">
<link href="{{"css/hugo-theme.css" | relURL}}{{ if $assetBusting }}?{{ now.Unix }}{{ end }}" rel="stylesheet">
{{with .Site.Params.themeVariant}}
<link href="{{(printf "css/theme-%s.css" .) | relURL}}{{ if $assetBusting }}?{{ now.Unix }}{{ end }}" rel="stylesheet">
diff --git a/layouts/shortcodes/tab.html b/layouts/shortcodes/tab.html
new file mode 100644
index 0000000..d258e00
--- /dev/null
+++ b/layouts/shortcodes/tab.html
@@ -0,0 +1,12 @@
+{{ if .Parent }}
+ {{ $name := trim (.Get "name") " " }}
+ {{ if not (.Parent.Scratch.Get "tabs") }}
+ {{ .Parent.Scratch.Set "tabs" slice }}
+ {{ end }}
+ {{ with .Inner }}
+ {{ $.Parent.Scratch.Add "tabs" (dict "name" $name "content" . ) }}
+ {{ end }}
+{{ else }}
+ {{- errorf "[%s] %q: tab shortcode missing its parent" site.Language.Lang .Page.Path -}}
+{{ end}}
+
diff --git a/layouts/shortcodes/tabs.html b/layouts/shortcodes/tabs.html
new file mode 100644
index 0000000..417a808
--- /dev/null
+++ b/layouts/shortcodes/tabs.html
@@ -0,0 +1,21 @@
+{{ with .Inner }}{{/* don't do anything, just call it */}}{{ end }}
+{{ $groupId := default "default" (.Get "groupId") }}
+<div class="tab-panel">
+ <div class="tab-nav">
+ {{ range $idx, $tab := .Scratch.Get "tabs" }}
+ <button
+ data-tab-item="{{ .name }}"
+ data-tab-group="{{ $groupId }}"
+ class="tab-nav-button btn {{ cond (eq $idx 0) "active" ""}}"
+ onclick="switchTab('{{ $groupId }}','{{ .name }}')"
+ >{{ .name }}</button>
+ {{ end }}
+ </div>
+ <div class="tab-content">
+ {{ range $idx, $tab := .Scratch.Get "tabs" }}
+ <div data-tab-item="{{ .name }}" data-tab-group="{{ $groupId }}" class="tab-item {{ cond (eq $idx 0) "active" ""}}">
+ {{ .content }}
+ </div>
+ {{ end }}
+ </div>
+</div>
diff --git a/static/css/tabs.css b/static/css/tabs.css
new file mode 100644
index 0000000..2ad2728
--- /dev/null
+++ b/static/css/tabs.css
@@ -0,0 +1,43 @@
+#body .tab-nav-button {
+ border-width: 1px 1px 1px 1px !important;
+ border-color: #ccc !important;
+ border-radius: 4px 4px 0 0 !important;
+ background-color: #ddd !important;
+ float: left;
+ display: block;
+ position: relative;
+ margin-left: 4px;
+ bottom: -1px;
+}
+#body .tab-nav-button:first-child {
+ margin-left: 0px;
+}
+#body .tab-nav-button.active {
+ background-color: #fff !important;
+ border-bottom-color: #fff !important;
+}
+
+#body .tab-panel {
+ margin-top: 32px;
+ margin-bottom: 32px;
+}
+#body .tab-content {
+ display: block;
+ clear: both;
+ padding: 8px;
+ border-width: 1px;
+ border-style: solid;
+ border-color: #ccc;
+}
+#body .tab-content .tab-item{
+ display: none;
+}
+
+#body .tab-content .tab-item.active{
+ display: block;
+}
+
+#body .tab-item pre{
+ margin-bottom: 0;
+ margin-top: 0;
+}
diff --git a/static/js/learn.js b/static/js/learn.js
index b0d199d..85e09d5 100644
--- a/static/js/learn.js
+++ b/static/js/learn.js
@@ -47,6 +47,57 @@ function fallbackMessage(action) {
return actionMsg;
}
+function switchTab(tabGroup, tabId) {
+ allTabItems = jQuery("[data-tab-group='"+tabGroup+"']");
+ targetTabItems = jQuery("[data-tab-group='"+tabGroup+"'][data-tab-item='"+tabId+"']");
+
+ // if event is undefined then switchTab was called from restoreTabSelection
+ // so it's not a button event and we don't need to safe the selction or
+ // prevent page jump
+ var isButtonEvent = event != undefined;
+
+ if(isButtonEvent){
+ // save button position relative to viewport
+ var yposButton = event.target.getBoundingClientRect().top;
+ }
+
+ allTabItems.removeClass("active");
+ targetTabItems.addClass("active");
+
+ if(isButtonEvent){
+ // reset screen to the same position relative to clicked button to prevent page jump
+ var yposButtonDiff = event.target.getBoundingClientRect().top - yposButton;
+ window.scrollTo(window.scrollX, window.scrollY+yposButtonDiff);
+
+ // Store the selection to make it persistent
+ if(window.localStorage){
+ var selectionsJSON = window.localStorage.getItem("tabSelections");
+ if(selectionsJSON){
+ var tabSelections = JSON.parse(selectionsJSON);
+ }else{
+ var tabSelections = {};
+ }
+ tabSelections[tabGroup] = tabId;
+ window.localStorage.setItem("tabSelections", JSON.stringify(tabSelections));
+ }
+ }
+}
+
+function restoreTabSelections() {
+ if(window.localStorage){
+ var selectionsJSON = window.localStorage.getItem("tabSelections");
+ if(selectionsJSON){
+ var tabSelections = JSON.parse(selectionsJSON);
+ }else{
+ var tabSelections = {};
+ }
+ Object.keys(tabSelections).forEach(function(tabGroup) {
+ var tabItem = tabSelections[tabGroup];
+ switchTab(tabGroup, tabItem);
+ });
+ }
+}
+
// for the window resize
$(window).resize(function() {
setMenuHeight();
@@ -83,6 +134,8 @@ $(window).resize(function() {
jQuery(document).ready(function() {
+ restoreTabSelections();
+
jQuery('#sidebar .category-icon').on('click', function() {
$( this ).toggleClass("fa-angle-down fa-angle-right") ;
$( this ).parent().parent().children('ul').toggle() ;
@@ -229,7 +282,7 @@ jQuery(document).ready(function() {
e.stopPropagation();
}
});
-
+
jQuery(document).keydown(function(e) {
// prev links - left arrow key
if(e.which == '37') {
@@ -264,7 +317,7 @@ jQuery(document).ready(function() {
});
}
- /**
+ /**
* Fix anchor scrolling that hides behind top nav bar
* Courtesy of https://stackoverflow.com/a/13067009/28106
*
@@ -346,7 +399,7 @@ jQuery(document).ready(function() {
$(document).ready($.proxy(anchorScrolls, 'init'));
})(window.document, window.history, window.location);
-
+
});
jQuery(window).on('load', function() {