diff --git a/assets/js/tabs.js b/assets/js/tabs.js
new file mode 100644
index 0000000..08a10d5
--- /dev/null
+++ b/assets/js/tabs.js
@@ -0,0 +1,20 @@
+document.querySelectorAll('.tabs-toggle').forEach(function (button) {
+ button.addEventListener('click', function (e) {
+ // set parent tabs to unselected
+ const tabs = Array.from(e.target.parentElement.querySelectorAll('.tabs-toggle'));
+ tabs.map(tab => tab.setAttribute('data-state', ''));
+
+ // set current tab to selected
+ e.target.setAttribute('data-state', 'selected');
+
+ // set all panels to unselected
+ const panelsContainer = e.target.parentElement.nextElementSibling;
+ Array.from(panelsContainer.children).forEach(function (panel) {
+ panel.setAttribute('data-state', '');
+ });
+
+ const panelId = e.target.getAttribute('aria-controls');
+ const panel = panelsContainer.querySelector(`#${panelId}`);
+ panel.setAttribute('data-state', 'selected');
+ });
+});
diff --git a/content/docs/components/tabs.md b/content/docs/components/tabs.md
new file mode 100644
index 0000000..2b0b113
--- /dev/null
+++ b/content/docs/components/tabs.md
@@ -0,0 +1,51 @@
+---
+title: Tabs
+---
+
+## Example
+
+{{< tabs items="JSON,YAML,TOML" >}}
+
+{{< tab >}}**JSON**: JavaScript Object Notation (JSON) is a standard text-based format for representing structured data based on JavaScript object syntax.{{< /tab >}}
+{{< tab >}}**YAML**: YAML is a human-readable data serialization language.{{< /tab >}}
+{{< tab >}}**TOML**: TOML aims to be a minimal configuration file format that's easy to read due to obvious semantics.{{< /tab >}}
+
+{{< /tabs >}}
+
+## Usage
+
+### Default
+
+```
+{{* tabs items="JSON,YAML,TOML" */>}}
+
+ {{* tab */>}}**JSON**: JavaScript Object Notation (JSON) is a standard text-based format for representing structured data based on JavaScript object syntax.{{* /tab */>}}
+ {{* tab */>}}**YAML**: YAML is a human-readable data serialization language.{{* /tab */>}}
+ {{* tab */>}}**TOML**: TOML aims to be a minimal configuration file format that's easy to read due to obvious semantics.{{* /tab */>}}
+
+{{* /tabs */>}}
+```
+
+### Specify Selected Index
+
+Use `defaultIndex` property to specify the selected tab. The index starts from 0.
+
+```
+{{* tabs items="JSON,YAML,TOML" defaultIndex="1" */>}}
+
+ {{* tab */>}}**JSON**: JavaScript Object Notation (JSON) is a standard text-based format for representing structured data based on JavaScript object syntax.{{* /tab */>}}
+ {{* tab */>}}**YAML**: YAML is a human-readable data serialization language.{{* /tab */>}}
+ {{* tab */>}}**TOML**: TOML aims to be a minimal configuration file format that's easy to read due to obvious semantics.{{* /tab */>}}
+
+{{* /tabs */>}}
+```
+
+The `YAML` tab will be selected by default.
+
+{{< tabs items="JSON,YAML,TOML" defaultIndex="1" >}}
+
+{{< tab >}}**JSON**: JavaScript Object Notation (JSON) is a standard text-based format for representing structured data based on JavaScript object syntax.{{< /tab >}}
+{{< tab >}}**YAML**: YAML is a human-readable data serialization language.{{< /tab >}}
+{{< tab >}}**TOML**: TOML aims to be a minimal configuration file format that's easy to read due to obvious semantics.{{< /tab >}}
+
+{{< /tabs >}}
diff --git a/layouts/partials/scripts.html b/layouts/partials/scripts.html
index fa7e004..2a3dd2d 100644
--- a/layouts/partials/scripts.html
+++ b/layouts/partials/scripts.html
@@ -13,6 +13,11 @@
{{ end }}
+{{ if .HasShortcode "tabs" }}
+ {{ $tabsJS := resources.Get "js/tabs.js" }}
+
+{{ end }}
+
{{ if .Page.Params.math }}
diff --git a/layouts/partials/sidebar.html b/layouts/partials/sidebar.html
index 03931ee..b67472c 100644
--- a/layouts/partials/sidebar.html
+++ b/layouts/partials/sidebar.html
@@ -1,26 +1,28 @@