Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion docs/_docset.yml
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ toc:
- file: headings.md
- file: admonitions.md
- file: applies.md
- file: applies-switch.md
- file: automated_settings.md
- file: code.md
- file: comments.md
Expand Down Expand Up @@ -156,4 +157,4 @@ toc:
- file: bar.md
- folder: baz
children:
- file: qux.md
- file: qux.md
120 changes: 120 additions & 0 deletions docs/syntax/applies-switch.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
# Applies switch

The applies-switch directive creates tabbed content where each tab displays an applies_to badge instead of a text title. This is useful for showing content that varies by deployment type, version, or other applicability criteria.

## Basic usage

::::::{tab-set}
:::::{tab-item} Output

::::{applies-switch}

:::{applies-item} stack:
Content for Stack
:::

:::{applies-item} serverless:
Content for Serverless
:::

::::

:::::
:::::{tab-item} Markdown

```markdown
::::{applies-switch}

:::{applies-item} stack:
Content for Stack
:::

:::{applies-item} serverless:
Content for Serverless
:::

::::
```
:::::
::::::

## Multiple `applies_to` definitions

You can specify multiple `applies_to` definitions in a single `applies-item` using YAML object notation with curly braces `{}`.
This is useful when content applies to multiple deployment types or versions simultaneously.

::::::{tab-set}
:::::{tab-item} Output

::::{applies-switch}

:::{applies-item} { ece:, ess: }
Content for ECE and ECH
:::

:::{applies-item} serverless:
Content for Serverless
:::

::::

:::::
:::::{tab-item} Markdown

```markdown
::::{applies-switch}

:::{applies-item} { ece:, ess: }
Content for ECE and ECH
:::

:::{applies-item} serverless:
Content for Serverless
:::

::::
```
:::::
::::::

## Automatic grouping

Applies switches are automatically grouped together by default. This means all applies switches on a page will sync with each other - when you select a version in one switch, all other switches will automatically switch to the same version.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This means all applies switches on a page will sync with each other

Amazing.


Items with the same applies_to definition will sync together across all switches on the page. For example, if you have `stack: preview 9.1` in multiple switches, selecting it in one will select it in all others.

In the following example we have two applies switch sets that are automatically grouped together.
Hence, both switch sets will be in sync.

::::{applies-switch}
:::{applies-item} stack: ga 9.0
Other content for 9.0 version
:::
:::{applies-item} stack: ga 9.1
Other content for 9.1 version
:::
::::

::::{applies-switch}
:::{applies-item} stack: ga 9.0
Other content for 9.0 version
:::
:::{applies-item} stack: ga 9.1
Other content for 9.1 version
:::
::::

## Supported `applies_to` definitions

The `applies-item` directive accepts any valid applies_to definition that would work with the `{applies_to}` role.

See the [](applies.md) page for more details on valid `applies_to` definitions.

## When to use

Use applies switches when:

- Content varies significantly by deployment type, version, or other applicability criteria
- You want to show applies_to badges as tab titles instead of text
- You need to group related content that differs by applicability
- You want to provide a clear visual indication of what each content section applies to
88 changes: 88 additions & 0 deletions src/Elastic.Documentation.Site/Assets/applicability-switch.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
// TODO: refactor to typescript. this was copied from the tabs implementation

// @ts-check

// Extra JS capability for selected applies switches to be synced
// The selection is stored in local storage so that it persists across page loads.

const as_id_to_elements = {}
const storageKeyPrefix = 'sphinx-design-applies-switch-id-'

function create_key(el: HTMLElement) {
const syncId = el.getAttribute('data-sync-id')
const syncGroup = el.getAttribute('data-sync-group')
if (!syncId || !syncGroup) return null
return [syncGroup, syncId, syncGroup + '--' + syncId]
}

/**
* Initialize the applies switch selection.
*
*/
function ready() {
// Find all applies switches with sync data

const groups = []

document.querySelectorAll('.applies-switch-label').forEach((label) => {
if (label instanceof HTMLElement) {
const data = create_key(label)
if (data) {
const [group, id, key] = data

// add click event listener
label.onclick = onAppliesSwitchLabelClick

// store map of key to elements
if (!as_id_to_elements[key]) {
as_id_to_elements[key] = []
}
as_id_to_elements[key].push(label)

if (groups.indexOf(group) === -1) {
groups.push(group)
// Check if a specific switch has been selected via URL parameter
const switchParam = new URLSearchParams(
window.location.search
).get(group)
if (switchParam) {
window.sessionStorage.setItem(
storageKeyPrefix + group,
switchParam
)
}
}

// Check is a specific switch has been selected previously
const previousId = window.sessionStorage.getItem(
storageKeyPrefix + group
)
if (previousId === id) {
;(
label.previousElementSibling as HTMLInputElement
).checked = true
}
}
}
})
}

/**
* Activate other switches with the same sync id.
*
* @this {HTMLElement} - The element that was clicked.
*/
function onAppliesSwitchLabelClick() {
const data = create_key(this)
if (!data) return
const [group, id, key] = data
for (const label of as_id_to_elements[key]) {
if (label === this) continue
label.previousElementSibling.checked = true
}
window.sessionStorage.setItem(storageKeyPrefix + group, id)
}

export function initAppliesSwitch() {
ready()
}
88 changes: 88 additions & 0 deletions src/Elastic.Documentation.Site/Assets/applies-switch.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
// TODO: refactor to typescript. this was copied from the tabs implementation

// @ts-check

// Extra JS capability for selected applies switches to be synced
// The selection is stored in local storage so that it persists across page loads.

const as_id_to_elements = {}
const storageKeyPrefix = 'sphinx-design-applies-switch-id-'

function create_key(el: HTMLElement) {
const syncId = el.getAttribute('data-sync-id')
const syncGroup = el.getAttribute('data-sync-group')
if (!syncId || !syncGroup) return null
return [syncGroup, syncId, syncGroup + '--' + syncId]
}

/**
* Initialize the applies switch selection.
*
*/
function ready() {
// Find all applies switches with sync data

const groups = []

document.querySelectorAll('.applies-switch-label').forEach((label) => {
if (label instanceof HTMLElement) {
const data = create_key(label)
if (data) {
const [group, id, key] = data

// add click event listener
label.onclick = onAppliesSwitchLabelClick

// store map of key to elements
if (!as_id_to_elements[key]) {
as_id_to_elements[key] = []
}
as_id_to_elements[key].push(label)

if (groups.indexOf(group) === -1) {
groups.push(group)
// Check if a specific switch has been selected via URL parameter
const switchParam = new URLSearchParams(
window.location.search
).get(group)
if (switchParam) {
window.sessionStorage.setItem(
storageKeyPrefix + group,
switchParam
)
}
}

// Check is a specific switch has been selected previously
const previousId = window.sessionStorage.getItem(
storageKeyPrefix + group
)
if (previousId === id) {
;(
label.previousElementSibling as HTMLInputElement
).checked = true
}
}
}
})
}

/**
* Activate other switches with the same sync id.
*
* @this {HTMLElement} - The element that was clicked.
*/
function onAppliesSwitchLabelClick() {
const data = create_key(this)
if (!data) return
const [group, id, key] = data
for (const label of as_id_to_elements[key]) {
if (label === this) continue
label.previousElementSibling.checked = true
}
window.sessionStorage.setItem(storageKeyPrefix + group, id)
}

export function initAppliesSwitch() {
ready()
}
2 changes: 2 additions & 0 deletions src/Elastic.Documentation.Site/Assets/main.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { initAppliesSwitch } from './applies-switch'
import { initCopyButton } from './copybutton'
import { initHighlight } from './hljs'
import { initImageCarousel } from './image-carousel'
Expand All @@ -21,6 +22,7 @@ document.addEventListener('htmx:load', function (event) {
initHighlight()
initCopyButton()
initTabs()
initAppliesSwitch()

// We do this so that the navigation is not initialized twice
if (isLazyLoadNavigationEnabled) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
@layer components {
.applies-switch {
@apply relative mt-4 flex flex-wrap overflow-hidden;
Copy link

Copilot AI Sep 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file appears to be a duplicate of applies-switch.css with minor differences. Having two CSS files with similar content creates maintenance overhead. Consider consolidating into one file or clearly documenting the differences.

Copilot uses AI. Check for mistakes.

.applicable-info {
@apply border-none bg-transparent;
}

.applicable-name,
.applicable-meta {
@apply text-sm!;
}

.applies-switch-label {
@apply text-ink-light border-grey-20 z-20 -mb-[1px] flex cursor-pointer items-center border-1 px-6 py-2;
&:not(:nth-of-type(1)) {
margin-left: -1px;
}

&:hover {
@apply bg-grey-10 border-b-1 border-b-black text-black;
}
}

.applies-switch-input {
@apply absolute opacity-0;
}

.applies-switch-content {
@apply border-grey-20 z-0 order-99 hidden w-full border-1 px-6 pt-2 pb-6;
}

.applies-switch-input:checked
+ .applies-switch-label
+ .applies-switch-content {
@apply block;
}

.applies-switch-input:checked + .applies-switch-label,
.applies-switch-label:active {
@apply border-b-blue-elastic text-blue-elastic border-b-1;
}

.applies-switch-input:focus-visible + .applies-switch-label {
outline: var(--outline-size) var(--outline-style)
var(--outline-color);
outline-offset: var(--outline-offset, var(--outline-size));
}

.applies-switch-fallback {
@apply text-sm font-medium;
}
}
}
Loading
Loading