Files

1268 lines
58 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!doctype html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Styleguide Interactive Elements</title>
<link rel="stylesheet" href="../styleguide.css">
</head>
<body>
<h1 class="sg-main-heading">Components Interactive Elements</h1>
<p class="sg-body">
Formular-Layout-Regel: Wenn Pulldowns, Slider, Radio-Felder, Checkbox-Felder oder Eingabefelder direkt untereinander als Gruppe dargestellt werden, nutzen alle Zeilen dieselbe Label-Spaltenbreite und denselben horizontalen Abstand zwischen Label und Interaktionselement. Auf Mobile erfolgt der Umbruch komponentenspezifisch in eine einspaltige Darstellung.
</p>
<!-- Component: Link Buttons -->
<section id="component-link-buttons">
<p class="sg-preview-label">Component: Link-Buttons</p>
<div class="sg-component-row">
<button class="sg-interaction-element sg-button sg-button--inactive" type="button" data-component="button" data-component-state="inactive" disabled aria-disabled="true">
Link-Button inaktiv
</button>
<button class="sg-interaction-element sg-button sg-button--active" type="button" data-component="button" data-component-state="active">
Link-Button aktiv
</button>
</div>
</section>
<!-- Component: Prozessbutton -->
<section id="component-process-button">
<p class="sg-preview-label">Component: Prozessbutton</p>
<div class="sg-component-row">
<button class="sg-interaction-element sg-button sg-button--process sg-button--process-inactive" type="button" data-component="button" data-component-variant="process" data-component-state="inactive" disabled aria-disabled="true">
Prozess Button inaktiv
</button>
<button class="sg-interaction-element sg-button sg-button--process" type="button" data-component="button" data-component-variant="process" data-component-state="active">
Prozess Button
</button>
</div>
</section>
<!-- Component: Button Tab Navigation -->
<section id="component-button-tab-navigation">
<p class="sg-preview-label">Component: Tasten-Navigation-gross</p>
<div class="sg-tab-button-group" role="tablist" aria-label="Tasten Navigation" data-component="tab-navigation" data-component-size="large">
<button class="sg-interaction-element sg-button sg-tab-button" type="button" role="tab" aria-selected="false" data-component-part="tab-button">Gesamtbewertung</button>
<button class="sg-interaction-element sg-button sg-tab-button" type="button" role="tab" aria-selected="true" data-component-part="tab-button">Marktbewertung</button>
<button class="sg-interaction-element sg-button sg-tab-button" type="button" role="tab" aria-selected="false" data-component-part="tab-button">Wachstum</button>
<button class="sg-interaction-element sg-button sg-tab-button" type="button" role="tab" aria-selected="false" data-component-part="tab-button">Profitabilität</button>
<button class="sg-interaction-element sg-button sg-tab-button" type="button" role="tab" aria-selected="false" data-component-part="tab-button">Stabilität</button>
</div>
</section>
<!-- Component: Link Menu Items -->
<section id="component-linksmenu-items">
<p class="sg-preview-label">Component: Linksmenue-Items</p>
<div class="sg-tab-button-group" role="tablist" aria-label="Linksmenue Items" data-component="tab-navigation" data-component-size="large" data-component-variant="linksmenu-items">
<button class="sg-interaction-element sg-button sg-tab-button" type="button" role="tab" aria-selected="false" data-component-part="tab-button">Gesamtbewertung</button>
<button class="sg-interaction-element sg-button sg-tab-button" type="button" role="tab" aria-selected="true" data-component-part="tab-button">Marktbewertung</button>
<button class="sg-interaction-element sg-button sg-tab-button" type="button" role="tab" aria-selected="false" data-component-part="tab-button">Wachstum</button>
<button class="sg-interaction-element sg-button sg-tab-button" type="button" role="tab" aria-selected="false" data-component-part="tab-button">Profitabilität</button>
<button class="sg-interaction-element sg-button sg-tab-button" type="button" role="tab" aria-selected="false" data-component-part="tab-button">Stabilität</button>
</div>
</section>
<!-- Component: Button Tab Navigation In Content -->
<section id="component-button-tab-navigation-in-content">
<p class="sg-preview-label">Component: Tasten-Navigation-gross in content</p>
<div class="sg-tab-button-group" role="tablist" aria-label="Tasten Navigation im Content" data-component="tab-navigation" data-component-size="large" data-component-context="content">
<button class="sg-interaction-element sg-button sg-tab-button" type="button" role="tab" aria-selected="false" data-component-part="tab-button">Gesamtbewertung</button>
<button class="sg-interaction-element sg-button sg-tab-button" type="button" role="tab" aria-selected="true" data-component-part="tab-button">Marktbewertung</button>
<button class="sg-interaction-element sg-button sg-tab-button" type="button" role="tab" aria-selected="false" data-component-part="tab-button">Wachstum</button>
<button class="sg-interaction-element sg-button sg-tab-button" type="button" role="tab" aria-selected="false" data-component-part="tab-button">Profitabilität</button>
<button class="sg-interaction-element sg-button sg-tab-button" type="button" role="tab" aria-selected="false" data-component-part="tab-button">Stabilität</button>
</div>
</section>
<!-- Component: Compact Button Tab Navigation -->
<section id="component-button-tab-navigation-compact">
<p class="sg-preview-label">Component: Tasten-Navigation-schmal</p>
<div class="sg-tab-button-group" role="tablist" aria-label="Schmale Tasten Navigation" data-component="tab-navigation" data-component-size="compact">
<button class="sg-interaction-element sg-button sg-tab-button sg-tab-button--compact" type="button" role="tab" aria-selected="true" data-component-part="tab-button">PE</button>
<button class="sg-interaction-element sg-button sg-tab-button sg-tab-button--compact" type="button" role="tab" aria-selected="false" data-component-part="tab-button">PE Forward</button>
<button class="sg-interaction-element sg-button sg-tab-button sg-tab-button--compact" type="button" role="tab" aria-selected="false" data-component-part="tab-button">PEG</button>
<button class="sg-interaction-element sg-button sg-tab-button sg-tab-button--compact" type="button" role="tab" aria-selected="false" data-component-part="tab-button">FCF Yield</button>
</div>
</section>
<!-- Component: Pulldown -->
<section id="component-pulldown">
<p class="sg-preview-label">Component: Pulldown</p>
<!--
Pulldown examples are shown on the form-area preview background.
This wrapper is only the evaluation surface; it is not part of the pulldown component.
State meaning:
- form-inactive-selectable: selectable but not currently active.
- form-active / selected: currently selected and opens the option panel.
- form-disabled: technically unavailable and cannot be operated.
-->
<div class="sg-form-preview-area">
<div class="sg-state-example">
<p class="sg-state-example__label sg-table-label">Komponente normal</p>
<div class="sg-labeled-input-row">
<span class="sg-label">Label</span>
<div class="sg-pulldown-demo" data-open="false" data-align="left" data-selection-mode="single" data-component="pulldown" data-component-state="inactive-selectable">
<!--
Inactive selectable pulldowns use the same overlay behavior as active pulldowns.
The option panel opens below the trigger and may be aligned left or right to remain visible inside the viewport.
-->
<button class="sg-interaction-element sg-pulldown sg-pulldown--inactive-selectable sg-pulldown-demo__trigger" type="button" aria-expanded="false" aria-label="Pulldown ohne aktive Auswahl" data-component-part="pulldown-trigger">
Auswahl
</button>
<div class="sg-pulldown-panel" aria-label="Geöffnetes inaktives Pulldown" data-component-part="pulldown-panel">
<ul class="sg-pulldown-option-list" aria-label="Verfügbare Optionen im inaktiven Pulldown">
<li class="sg-pulldown-option" role="checkbox" aria-checked="false" data-pulldown-option>
<span>Menüpunkt 1</span>
</li>
<li class="sg-pulldown-option" role="checkbox" aria-checked="false" data-pulldown-option>
<span>Menüpunkt 2</span>
</li>
<li class="sg-pulldown-option" role="checkbox" aria-checked="false" data-pulldown-option>
<span>Menüpunkt 3</span>
</li>
<li class="sg-pulldown-option" role="checkbox" aria-checked="false" data-pulldown-option>
<span>Menüpunkt 4</span>
</li>
<li class="sg-pulldown-option sg-pulldown-option--disabled">
<span>Menüpunkt 5</span>
</li>
</ul>
</div>
</div>
</div>
</div>
<div class="sg-state-example">
<p class="sg-state-example__label sg-table-label">Variante aktivierbar</p>
<div class="sg-activatable-row">
<div class="sg-pulldown-activatable-header">
<button class="sg-mode-toggle sg-mode-toggle--local sg-activation-mode-toggle" type="button" data-active="absolute" aria-label="Aktivierung: aus" data-activation-target="component-pulldown-activatable">
<span class="sg-mode-toggle__switch" aria-hidden="true" data-component-part="toggle-track">
<span class="sg-activation-mode-toggle__switch-label sg-activation-mode-toggle__switch-label--left">aus</span>
<span class="sg-activation-mode-toggle__switch-label sg-activation-mode-toggle__switch-label--right">an</span>
<span class="sg-mode-toggle__handle" data-component-part="toggle-handle"></span>
</span>
</button>
<span class="sg-label">Label</span>
</div>
<div class="sg-pulldown-demo" id="component-pulldown-activatable" data-open="false" data-align="left" data-selection-mode="multiple" data-component="pulldown" data-component-state="inactive-selectable" data-activatable="true">
<!--
The number in brackets shows the count of currently selected options inside this pulldown.
Initial state: the activation toggle is off, therefore the trigger starts as inactive selectable.
Switching the activation toggle to "an" applies the active default selection and shows the selected count.
-->
<span class="sg-activatable-control">
<button class="sg-interaction-element sg-pulldown sg-pulldown--inactive-selectable sg-pulldown-demo__trigger" type="button" aria-expanded="false" aria-label="Pulldown ohne aktive Auswahl" data-label-base="Auswahl" data-component-part="pulldown-trigger">
Auswahl
</button>
</span>
<div class="sg-pulldown-panel" aria-label="Geöffnetes Pulldown" data-component-part="pulldown-panel">
<!--
Interactive styleguide variant:
The panel opens and closes via the pulldown button above.
It closes when clicking outside, when another pulldown opens, or when a sandwich menu opens.
If the panel is wider than the trigger or would overflow the viewport, it aligns from the opposite side of the trigger.
Cross-dependencies between pulldowns are application logic and are not defined in this component.
-->
<div class="sg-checkbox-field-list sg-pulldown-panel__checkbox-list" aria-label="Checkboxen im Pulldown">
<label class="sg-checkbox-field-option sg-body" data-component="checkbox-field" data-component-state="inactive-selectable">
<button class="sg-checkbox-field sg-checkbox-field--on-grey sg-checkbox-field--inactive-selectable" type="button" role="checkbox" aria-checked="false" aria-label="Checkbox 1" data-pulldown-option>
<span class="sg-checkbox-field__mark" aria-hidden="true"></span>
</button>
<span>Checkbox 1</span>
</label>
<label class="sg-checkbox-field-option sg-body" data-component="checkbox-field" data-component-state="inactive-selectable">
<button class="sg-checkbox-field sg-checkbox-field--on-grey sg-checkbox-field--inactive-selectable" type="button" role="checkbox" aria-checked="false" aria-label="Checkbox 2" data-pulldown-option>
<span class="sg-checkbox-field__mark" aria-hidden="true"></span>
</button>
<span>Checkbox 2</span>
</label>
<label class="sg-checkbox-field-option sg-body" data-component="checkbox-field" data-component-state="inactive-selectable">
<button class="sg-checkbox-field sg-checkbox-field--on-grey sg-checkbox-field--inactive-selectable" type="button" role="checkbox" aria-checked="false" aria-label="Checkbox 3" data-pulldown-option>
<span class="sg-checkbox-field__mark" aria-hidden="true"></span>
</button>
<span>Checkbox 3</span>
</label>
</div>
</div>
</div>
</div>
</div>
<div class="sg-state-example">
<p class="sg-state-example__label sg-table-label">form-disabled</p>
<label class="sg-labeled-input-row">
<span class="sg-label">Label</span>
<select class="sg-interaction-element sg-pulldown sg-pulldown--disabled" aria-label="Deaktivierter Pulldown" disabled data-component="pulldown" data-component-state="disabled">
<option>Nicht verfügbar</option>
</select>
</label>
</div>
<div class="sg-state-example">
<p class="sg-state-example__label sg-table-label">Variante ohne Label</p>
<div class="sg-labeled-input-row">
<div class="sg-pulldown-demo" data-open="false" data-align="left" data-selection-mode="single" data-component="pulldown" data-component-state="inactive-selectable">
<button class="sg-interaction-element sg-pulldown sg-pulldown--inactive-selectable sg-pulldown-demo__trigger" type="button" aria-expanded="false" aria-label="Pulldown ohne Label ohne aktive Auswahl" data-component-part="pulldown-trigger">
Auswahl
</button>
</div>
</div>
</div>
</div>
</section>
<!-- Component: Search Field -->
<section id="component-input-single-line" class="sg-input-component">
<p class="sg-preview-label">Component: Suchfeld</p>
<!--
Input examples are shown on the form-area preview background.
This wrapper is only the evaluation surface; it is not part of the input component.
State meaning:
- form-inactive-selectable: empty, selectable input with placeholder text.
- form-active / selected: input with current value and visible remove button.
- form-disabled: unavailable input; no value can be entered and no remove button is shown.
-->
<div class="sg-form-preview-area">
<div class="sg-state-example">
<p class="sg-state-example__label sg-table-label">form-inactive-selectable</p>
<span class="sg-search-field-row">
<span class="sg-input-single-line-wrap" data-has-value="false" data-component="single-line-input" data-component-state="inactive-selectable">
<input
class="sg-interaction-element sg-input-single-line sg-search-field-input sg-input-single-line--inactive-selectable sg-form-inactive-selectable"
type="text"
placeholder="Suchfeld"
aria-label="Suchfeld ohne Eingabe"
>
<button class="sg-input-clear-button" type="button" aria-label="Eingabe löschen">×</button>
</span>
<span class="sg-search-result-count">0 Treffer</span>
</span>
</div>
<div class="sg-state-example">
<p class="sg-state-example__label sg-table-label">form-active / selected</p>
<span class="sg-search-field-row">
<span class="sg-input-single-line-wrap" data-has-value="true" data-component="single-line-input" data-component-state="active">
<input
class="sg-interaction-element sg-input-single-line sg-search-field-input sg-form-active"
type="text"
value="Produkt"
aria-label="Suchfeld mit Eingabe"
>
<button class="sg-input-clear-button" type="button" aria-label="Eingabe löschen">×</button>
</span>
<span class="sg-search-result-count">12 Treffer</span>
</span>
</div>
<div class="sg-state-example">
<p class="sg-state-example__label sg-table-label">form-disabled</p>
<span class="sg-search-field-row">
<input
class="sg-interaction-element sg-input-single-line sg-search-field-input sg-input-single-line--disabled sg-form-disabled"
type="text"
value="Nicht verfügbar"
aria-label="Deaktiviertes Suchfeld"
disabled
data-component="single-line-input"
data-component-state="disabled"
>
</span>
</div>
</div>
</section>
<!-- Component: Single Line Input -->
<section id="component-input-field-single-line" class="sg-input-component">
<p class="sg-preview-label">Component: Eingabefeld einzeilig</p>
<div class="sg-form-preview-area">
<div class="sg-state-example">
<p class="sg-state-example__label sg-table-label">form-inactive-selectable</p>
<label class="sg-labeled-input-row">
<span class="sg-label">Label</span>
<input
class="sg-interaction-element sg-input-single-line sg-input-single-line--inactive-selectable sg-form-inactive-selectable"
type="text"
placeholder="Einzeiliges Eingabefeld"
aria-label="Einzeiliges Eingabefeld ohne Eingabe"
>
</label>
</div>
<div class="sg-state-example">
<p class="sg-state-example__label sg-table-label">form-active / selected</p>
<label class="sg-labeled-input-row">
<span class="sg-label">Label</span>
<input
class="sg-interaction-element sg-input-single-line sg-form-active"
type="text"
value="Aktive Eingabe"
aria-label="Einzeiliges Eingabefeld mit aktiver Eingabe"
>
</label>
</div>
<div class="sg-state-example">
<p class="sg-state-example__label sg-table-label">form-invalid</p>
<label class="sg-labeled-input-row">
<span class="sg-label">Label</span>
<span class="sg-input-validation-stack">
<input
class="sg-interaction-element sg-input-single-line sg-form-active"
type="text"
value="Ungültige Eingabe"
aria-label="Einzeiliges Eingabefeld mit Validierung"
aria-invalid="true"
aria-describedby="single-line-invalid-feedback"
>
<span class="sg-form-validation-text" id="single-line-invalid-feedback">Bitte eine gültige Eingabe machen.</span>
</span>
</label>
</div>
<div class="sg-state-example">
<p class="sg-state-example__label sg-table-label">form-disabled</p>
<label class="sg-labeled-input-row">
<span class="sg-label">Label</span>
<input
class="sg-interaction-element sg-input-single-line sg-input-single-line--disabled sg-form-disabled"
type="text"
value="Nicht verfügbar"
aria-label="Deaktiviertes einzeiliges Eingabefeld"
disabled
>
</label>
</div>
<div class="sg-state-example">
<p class="sg-state-example__label sg-table-label">Variante ohne Label</p>
<div class="sg-labeled-input-row">
<input
class="sg-interaction-element sg-input-single-line sg-input-single-line--inactive-selectable sg-form-inactive-selectable"
type="text"
placeholder="Einzeiliges Eingabefeld"
aria-label="Einzeiliges Eingabefeld ohne Label ohne Eingabe"
>
</div>
</div>
</div>
</section>
<!-- Component: Multi Line Input -->
<section id="component-input-field-multi-line" class="sg-input-component">
<p class="sg-preview-label">Component: Eingabefeld mehrzeilig</p>
<div class="sg-form-preview-area">
<div class="sg-state-example">
<p class="sg-state-example__label sg-table-label">form-inactive-selectable</p>
<label class="sg-labeled-input-row">
<span class="sg-label">Label</span>
<textarea
class="sg-input-multi-line sg-form-inactive-selectable"
rows="3"
placeholder="Mehrzeiliges Eingabefeld"
aria-label="Mehrzeiliges Eingabefeld ohne Eingabe"
></textarea>
</label>
</div>
<div class="sg-state-example">
<p class="sg-state-example__label sg-table-label">form-active / selected</p>
<label class="sg-labeled-input-row">
<span class="sg-label">Label</span>
<textarea
class="sg-input-multi-line sg-form-active"
rows="3"
aria-label="Mehrzeiliges Eingabefeld mit aktiver Eingabe"
>Aktive Eingabe über mehrere Zeilen</textarea>
</label>
</div>
<div class="sg-state-example">
<p class="sg-state-example__label sg-table-label">form-invalid</p>
<label class="sg-labeled-input-row">
<span class="sg-label">Label</span>
<span class="sg-input-validation-stack">
<textarea
class="sg-input-multi-line sg-form-active"
rows="3"
aria-label="Mehrzeiliges Eingabefeld mit Validierung"
aria-invalid="true"
aria-describedby="multi-line-invalid-feedback"
>Ungültige Eingabe über mehrere Zeilen</textarea>
<span class="sg-form-validation-text" id="multi-line-invalid-feedback">Bitte einen längeren Text eingeben.</span>
</span>
</label>
</div>
<div class="sg-state-example">
<p class="sg-state-example__label sg-table-label">form-disabled</p>
<label class="sg-labeled-input-row">
<span class="sg-label">Label</span>
<textarea
class="sg-input-multi-line sg-form-disabled"
rows="3"
aria-label="Deaktiviertes mehrzeiliges Eingabefeld"
disabled
>Nicht verfügbar</textarea>
</label>
</div>
<div class="sg-state-example">
<p class="sg-state-example__label sg-table-label">Variante ohne Label</p>
<div class="sg-labeled-input-row">
<textarea
class="sg-input-multi-line sg-form-inactive-selectable"
rows="3"
placeholder="Mehrzeiliges Eingabefeld"
aria-label="Mehrzeiliges Eingabefeld ohne Label ohne Eingabe"
></textarea>
</div>
</div>
</div>
</section>
<!-- Component: Checkbox Field -->
<section id="component-checkbox-field">
<p class="sg-preview-label">Component: Kreuzchenfeld / Multiple Choice</p>
<!--
Checkbox examples are shown on the form-area preview background.
This wrapper is only the evaluation surface; it is not part of the checkbox component.
State meaning:
- form-inactive-selectable: not checked, but selectable.
- form-active / selected: checked and currently selected.
- form-disabled: technically unavailable and cannot be toggled.
-->
<div class="sg-form-preview-area sg-checkbox-field-list">
<label class="sg-checkbox-field-option sg-body" data-component="checkbox-field" data-component-state="default">
<span class="sg-state-example__label sg-table-label">Komponente normal</span>
<button class="sg-checkbox-field" type="button" role="checkbox" aria-checked="false" aria-label="Standard Checkbox">
<span class="sg-checkbox-field__mark" aria-hidden="true"></span>
</button>
<span>Standard Checkbox</span>
</label>
<div class="sg-checkbox-field-option sg-checkbox-field-option--inactive-selectable sg-body" id="component-checkbox-activatable" data-component="checkbox-field" data-component-state="inactive-selectable" data-activatable="true">
<span class="sg-state-example__label sg-table-label">Variante aktivierbar</span>
<button class="sg-mode-toggle sg-mode-toggle--local sg-activation-mode-toggle" type="button" data-active="absolute" aria-label="Aktivierung: aus" data-activation-target="component-checkbox-activatable">
<span class="sg-mode-toggle__switch" aria-hidden="true" data-component-part="toggle-track">
<span class="sg-activation-mode-toggle__switch-label sg-activation-mode-toggle__switch-label--left">aus</span>
<span class="sg-activation-mode-toggle__switch-label sg-activation-mode-toggle__switch-label--right">an</span>
<span class="sg-mode-toggle__handle" data-component-part="toggle-handle"></span>
</span>
</button>
<button class="sg-checkbox-field sg-checkbox-field--inactive-selectable" type="button" role="checkbox" aria-checked="false" aria-label="Option wählen">
<span class="sg-checkbox-field__mark" aria-hidden="true"></span>
</button>
<span>Option wählbar</span>
</div>
<label class="sg-checkbox-field-option sg-checkbox-field-option--disabled sg-body" data-component="checkbox-field" data-component-state="disabled">
<span class="sg-state-example__label sg-table-label">form-disabled</span>
<button class="sg-checkbox-field sg-checkbox-field--disabled" type="button" role="checkbox" aria-checked="false" aria-label="Option nicht verfügbar" disabled>
<span class="sg-checkbox-field__mark" aria-hidden="true"></span>
</button>
<span>Option nicht verfügbar</span>
</label>
</div>
</section>
<!-- Component: Radio Field -->
<section id="component-radio-field">
<p class="sg-preview-label">Component: Radio Button / Single Choice</p>
<!--
Radio examples are shown on the form-area preview background.
This wrapper is only the evaluation surface; it is not part of the radio component.
State meaning:
- form-inactive-selectable: not selected, but selectable.
- form-active / selected: selected radio option.
- form-disabled: technically unavailable and cannot be selected.
-->
<div class="sg-form-preview-area sg-checkbox-field-list">
<label class="sg-checkbox-field-option sg-body" data-component="radio-field" data-component-state="default">
<span class="sg-state-example__label sg-table-label">Komponente normal</span>
<span class="sg-radio-field-row">
<span class="sg-label">Label</span>
<span class="sg-radio-activatable-group__choices">
<span class="sg-radio-activatable-group__choice">
<button class="sg-radio-field" type="button" role="radio" aria-checked="false" aria-label="Radio 1 wählen">
<span class="sg-radio-field__mark" aria-hidden="true"></span>
</button>
<span>Radio 1</span>
</span>
<span class="sg-radio-activatable-group__choice">
<button class="sg-radio-field" type="button" role="radio" aria-checked="false" aria-label="Radio 2 wählen">
<span class="sg-radio-field__mark" aria-hidden="true"></span>
</button>
<span>Radio 2</span>
</span>
</span>
</span>
</label>
<div class="sg-checkbox-field-option sg-checkbox-field-option--inactive-selectable sg-body sg-radio-activatable-group" id="component-radio-activatable" data-component="radio-field" data-component-state="inactive-selectable" data-activatable="true" data-activatable-radio-group="true">
<span class="sg-state-example__label sg-table-label">Variante aktivierbar</span>
<span class="sg-radio-field-row">
<button class="sg-mode-toggle sg-mode-toggle--local sg-activation-mode-toggle" type="button" data-active="absolute" aria-label="Aktivierung: aus" data-activation-target="component-radio-activatable">
<span class="sg-mode-toggle__switch" aria-hidden="true" data-component-part="toggle-track">
<span class="sg-activation-mode-toggle__switch-label sg-activation-mode-toggle__switch-label--left">aus</span>
<span class="sg-activation-mode-toggle__switch-label sg-activation-mode-toggle__switch-label--right">an</span>
<span class="sg-mode-toggle__handle" data-component-part="toggle-handle"></span>
</span>
</button>
<span class="sg-label">Label</span>
<span class="sg-radio-activatable-group__choices">
<span class="sg-radio-activatable-group__choice">
<button class="sg-radio-field sg-radio-field--inactive-selectable" type="button" role="radio" aria-checked="false" aria-label="Option 1 wählen" disabled>
<span class="sg-radio-field__mark" aria-hidden="true"></span>
</button>
<span>Option 1</span>
</span>
<span class="sg-radio-activatable-group__choice">
<button class="sg-radio-field sg-radio-field--inactive-selectable" type="button" role="radio" aria-checked="false" aria-label="Option 2 wählen" disabled>
<span class="sg-radio-field__mark" aria-hidden="true"></span>
</button>
<span>Option 2</span>
</span>
</span>
</span>
</div>
<label class="sg-checkbox-field-option sg-checkbox-field-option--disabled sg-body" data-component="radio-field" data-component-state="disabled">
<span class="sg-state-example__label sg-table-label">form-disabled</span>
<span class="sg-radio-field-row">
<button class="sg-radio-field sg-radio-field--disabled" type="button" role="radio" aria-checked="false" aria-label="Option nicht verfügbar" disabled>
<span class="sg-radio-field__mark" aria-hidden="true"></span>
</button>
<span>Option nicht verfügbar</span>
</span>
</label>
<div class="sg-checkbox-field-option sg-body" data-component="radio-field" data-component-state="default">
<span class="sg-state-example__label sg-table-label">Variante ohne Gesamtlabel</span>
<span class="sg-radio-field-row sg-radio-field-row--without-label">
<span class="sg-radio-activatable-group__choices">
<span class="sg-radio-activatable-group__choice">
<button class="sg-radio-field" type="button" role="radio" aria-checked="false" aria-label="Radio 1 wählen">
<span class="sg-radio-field__mark" aria-hidden="true"></span>
</button>
<span>Radio 1</span>
</span>
<span class="sg-radio-activatable-group__choice">
<button class="sg-radio-field" type="button" role="radio" aria-checked="false" aria-label="Radio 2 wählen">
<span class="sg-radio-field__mark" aria-hidden="true"></span>
</button>
<span>Radio 2</span>
</span>
</span>
</span>
</div>
</div>
</section>
<!-- Component: Mode Toggle -->
<section id="component-mode-toggle">
<p class="sg-preview-label">Component: Modus Schieber global</p>
<button class="sg-mode-toggle" type="button" data-active="relative" aria-label="Modus Schieber global: relativ aktiv" data-component="mode-toggle" data-mode-label="Modus Schieber global">
<span class="sg-mode-toggle__label">absolut</span>
<span class="sg-mode-toggle__switch" aria-hidden="true" data-component-part="toggle-track">
<span class="sg-mode-toggle__handle" data-component-part="toggle-handle"></span>
</span>
<span class="sg-mode-toggle__label">relativ</span>
</button>
</section>
<!-- Component: Mode Toggle Local -->
<section id="component-mode-toggle-local">
<p class="sg-preview-label">Component: Modus Schieber lokal</p>
<button class="sg-mode-toggle sg-mode-toggle--local" type="button" data-active="relative" aria-label="Modus Schieber lokal: relativ aktiv" data-component="mode-toggle-local" data-mode-label="Modus Schieber lokal">
<span class="sg-mode-toggle__label">absolut</span>
<span class="sg-mode-toggle__switch" aria-hidden="true" data-component-part="toggle-track">
<span class="sg-mode-toggle__handle" data-component-part="toggle-handle"></span>
</span>
<span class="sg-mode-toggle__label">relativ</span>
</button>
</section>
<!-- Component: Aktivierungs-Schalter -->
<section id="component-activation-toggle">
<p class="sg-preview-label">Component: Aktivierungs-Schalter (an/aus)</p>
<div class="sg-activation-toggle-pattern">
<button class="sg-mode-toggle sg-mode-toggle--local sg-activation-mode-toggle" type="button" data-active="absolute" aria-label="Aktivierung: aus">
<span class="sg-mode-toggle__switch" aria-hidden="true" data-component-part="toggle-track">
<span class="sg-activation-mode-toggle__switch-label sg-activation-mode-toggle__switch-label--left">aus</span>
<span class="sg-activation-mode-toggle__switch-label sg-activation-mode-toggle__switch-label--right">an</span>
<span class="sg-mode-toggle__handle" data-component-part="toggle-handle"></span>
</span>
</button>
</div>
</section>
<!-- Component: Slider -->
<section id="component-slider">
<p class="sg-preview-label">Component: Slider</p>
<div class="sg-form-preview-area">
<div class="sg-state-example">
<p class="sg-state-example__label sg-table-label">Komponente normal</p>
<label class="sg-slider-row" data-component="slider" data-component-state="default">
<span class="sg-label">Wert</span>
<input
class="sg-interaction-element sg-slider"
type="range"
min="0"
max="10"
step="0.1"
value="6.5"
aria-label="Slider"
>
<output class="sg-slider-value" for="slider">6.5</output>
</label>
</div>
<div class="sg-state-example">
<p class="sg-state-example__label sg-table-label">Variante aktivierbar</p>
<div class="sg-activatable-row">
<span class="sg-slider-activatable-header">
<button class="sg-mode-toggle sg-mode-toggle--local sg-activation-mode-toggle" type="button" data-active="absolute" aria-label="Aktivierung: aus" data-activation-target="component-slider-activatable">
<span class="sg-mode-toggle__switch" aria-hidden="true" data-component-part="toggle-track">
<span class="sg-activation-mode-toggle__switch-label sg-activation-mode-toggle__switch-label--left">aus</span>
<span class="sg-activation-mode-toggle__switch-label sg-activation-mode-toggle__switch-label--right">an</span>
<span class="sg-mode-toggle__handle" data-component-part="toggle-handle"></span>
</span>
</button>
<span class="sg-label">Wert</span>
</span>
<label class="sg-slider-row sg-slider-row--inactive-selectable" id="component-slider-activatable" data-component="slider" data-component-state="inactive-selectable" data-activatable="true">
<input
class="sg-interaction-element sg-slider sg-form-inactive-selectable"
type="range"
min="0"
max="10"
step="0.1"
value="2.0"
aria-label="Slider inaktiv auswählbar"
disabled
>
<output class="sg-slider-value" for="slider">2.0</output>
</label>
</div>
</div>
</div>
</section>
<!-- Component: Sandwich Menu Button -->
<section id="component-sandwich-menu-button">
<p class="sg-preview-label">Component: Sandwich-Menü-Button Portal (groß)</p>
<div class="sg-component-row">
<div class="sg-sandwich-menu-wrap" data-open="false" data-component="sandwich-menu" data-component-size="default">
<button class="sg-interaction-element sg-sandwich-button" type="button" aria-expanded="false" aria-label="Portal-Menü öffnen" data-component-part="sandwich-trigger">
<span class="sg-sandwich-button__icon" aria-hidden="true">
<span class="sg-sandwich-button__line"></span>
<span class="sg-sandwich-button__line"></span>
<span class="sg-sandwich-button__line"></span>
</span>
</button>
<div class="sg-sandwich-menu-panel" aria-label="Ausgeklapptes Portal-Menü" data-component-part="sandwich-panel">
<a class="sg-sandwich-menu-link" href="#">Menüpunkt</a>
<a class="sg-sandwich-menu-link" href="#">Menüpunkt</a>
<a class="sg-sandwich-menu-link" href="#">Menüpunkt</a>
</div>
</div>
</div>
<p class="sg-preview-label">Component: Sandwich-Menü-Button Objekt (klein)</p>
<div class="sg-component-row">
<div class="sg-sandwich-menu-wrap" data-open="false" data-component="sandwich-menu" data-component-size="small">
<button class="sg-interaction-element sg-sandwich-button sg-sandwich-button--small" type="button" aria-expanded="false" aria-label="Objekt-Menü öffnen" data-component-part="sandwich-trigger">
<span class="sg-sandwich-button__icon" aria-hidden="true">
<span class="sg-sandwich-button__line"></span>
<span class="sg-sandwich-button__line"></span>
<span class="sg-sandwich-button__line"></span>
</span>
</button>
<div class="sg-sandwich-menu-panel" aria-label="Ausgeklapptes Objekt-Menü" data-component-part="sandwich-panel">
<a class="sg-sandwich-menu-link" href="#">Menüpunkt</a>
<a class="sg-sandwich-menu-link" href="#">Menüpunkt</a>
<a class="sg-sandwich-menu-link" href="#">Menüpunkt</a>
</div>
</div>
</div>
</section>
<!-- Component: Help Icon -->
<section id="component-help-icon">
<p class="sg-preview-label">Component: Fragezeichen-Icon</p>
<span class="sg-help-icon-wrap" data-open="false" data-align="left" data-component="help-icon">
<button class="sg-help-icon" type="button" aria-expanded="false" aria-label="Hilfetext anzeigen" data-component-part="help-trigger">?</button>
<span class="sg-help-icon-panel sg-table-label" role="tooltip" data-component-part="help-panel">
Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt.
</span>
</span>
</section>
<!-- Component: Hyperlink -->
<section id="component-hyperlink">
<p class="sg-preview-label">Component: Hyperlink</p>
<p class="sg-body">
Dies ist ein Text mit einem <a class="sg-hyperlink" href="#" data-component="hyperlink">Hyperlink</a>.
</p>
</section>
<script src="../scripts/help-icon-overlays.js"></script>
<script>
document.querySelectorAll('.sg-mode-toggle:not(.sg-activation-mode-toggle)').forEach((toggle) => {
toggle.addEventListener('click', () => {
const nextState = toggle.dataset.active === 'relative' ? 'absolute' : 'relative';
const modeLabel = toggle.dataset.modeLabel || 'Modus Schieber';
toggle.dataset.active = nextState;
toggle.setAttribute(
'aria-label',
`${modeLabel}: ${nextState === 'relative' ? 'relativ' : 'absolut'} aktiv`
);
});
});
const ensurePulldownDefaultSelection = (demo) => {
if (demo.dataset.defaultSelectionInitialized === 'true') {
return;
}
const options = demo.querySelectorAll('[data-pulldown-option]');
if (options.length === 0) {
return;
}
const hasSelectedOption = Array.from(options).some((option) => option.getAttribute('aria-checked') === 'true');
if (!hasSelectedOption) {
options[0].setAttribute('aria-checked', 'true');
}
demo.dataset.defaultSelectionInitialized = 'true';
};
const setActivatableComponentState = (target, isActive) => {
if (!target) {
return;
}
const componentType = target.dataset.component;
target.dataset.componentState = isActive ? 'active' : 'inactive-selectable';
if (componentType === 'pulldown') {
const trigger = target.querySelector('.sg-pulldown-demo__trigger');
const options = target.querySelectorAll('[data-pulldown-option]');
if (!trigger || options.length === 0) {
return;
}
if (isActive && target.dataset.activatable === 'true') {
ensurePulldownDefaultSelection(target);
}
target.dataset.open = 'false';
trigger.setAttribute('aria-expanded', 'false');
updatePulldownSelectionState(target);
return;
}
if (componentType === 'checkbox-field') {
const checkbox = target.querySelector('.sg-checkbox-field');
if (!checkbox) {
return;
}
if (!isActive) {
checkbox.setAttribute('aria-checked', 'false');
}
const isChecked = checkbox.getAttribute('aria-checked') === 'true';
checkbox.classList.toggle('sg-form-active', isChecked);
checkbox.classList.toggle('sg-checkbox-field--inactive-selectable', !isActive);
return;
}
if (componentType === 'radio-field') {
const radios = target.querySelectorAll('.sg-radio-field');
radios.forEach((radio) => {
radio.disabled = !isActive;
if (!isActive) {
radio.setAttribute('aria-checked', 'false');
}
const checked = radio.getAttribute('aria-checked') === 'true';
radio.setAttribute('aria-checked', String(checked));
radio.classList.toggle('sg-form-active', checked);
radio.classList.toggle('sg-radio-field--inactive-selectable', !isActive);
});
return;
}
if (componentType === 'slider') {
const slider = target.querySelector('.sg-slider');
if (!slider) {
return;
}
target.classList.toggle('sg-slider-row--inactive-selectable', !isActive);
slider.classList.toggle('sg-form-active', isActive);
slider.classList.toggle('sg-form-inactive-selectable', !isActive);
slider.disabled = !isActive;
}
};
document.querySelectorAll('.sg-activation-mode-toggle').forEach((toggle) => {
toggle.addEventListener('click', () => {
const nextState = toggle.dataset.active === 'absolute' ? 'relative' : 'absolute';
const isActive = nextState === 'relative';
toggle.dataset.active = nextState;
toggle.setAttribute('aria-label', `Aktivierung: ${isActive ? 'an' : 'aus'}`);
const targetId = toggle.dataset.activationTarget;
if (!targetId) {
return;
}
const target = document.getElementById(targetId);
setActivatableComponentState(target, isActive);
});
});
document.querySelectorAll('.sg-tab-button-group').forEach((group) => {
group.querySelectorAll('.sg-tab-button').forEach((button) => {
button.addEventListener('click', () => {
group.querySelectorAll('.sg-tab-button').forEach((otherButton) => {
otherButton.setAttribute('aria-selected', String(otherButton === button));
});
});
});
});
document.querySelectorAll('.sg-input-single-line-wrap').forEach((wrap) => {
const input = wrap.querySelector('.sg-input-single-line');
const clearButton = wrap.querySelector('.sg-input-clear-button');
const updateState = () => {
wrap.dataset.hasValue = String(input.value.length > 0);
};
input.addEventListener('input', updateState);
clearButton.addEventListener('click', () => {
if (input.disabled || clearButton.disabled) {
return;
}
input.value = '';
updateState();
input.focus();
});
updateState();
});
document.querySelectorAll('.sg-slider-row').forEach((row) => {
const slider = row.querySelector('.sg-slider');
const valueOutput = row.querySelector('.sg-slider-value');
if (!slider || !valueOutput) {
return;
}
const updateSliderState = () => {
const min = Number(slider.min || 0);
const max = Number(slider.max || 100);
const value = Number(slider.value || 0);
const denominator = max - min;
const progress = denominator > 0 ? ((value - min) / denominator) * 100 : 0;
slider.style.setProperty('--sg-slider-progress', `${progress}%`);
valueOutput.textContent = value.toFixed(1);
};
slider.addEventListener('input', () => {
if (row.dataset.activatable === 'true' && row.dataset.componentState !== 'active') {
return;
}
updateSliderState();
});
updateSliderState();
});
document.querySelectorAll('.sg-checkbox-field').forEach((checkbox) => {
checkbox.addEventListener('click', () => {
if (checkbox.disabled) {
return;
}
if (checkbox.matches('[data-pulldown-option]')) {
return;
}
const activatableOption = checkbox.closest('[data-component="checkbox-field"][data-activatable="true"]');
if (activatableOption) {
if (activatableOption.dataset.componentState !== 'active') {
return;
}
}
const nextState = checkbox.getAttribute('aria-checked') !== 'true';
checkbox.setAttribute('aria-checked', String(nextState));
const pulldownDemo = checkbox.closest('.sg-pulldown-demo');
if (pulldownDemo) {
updatePulldownSelectionState(pulldownDemo);
}
});
});
document.querySelectorAll('[data-pulldown-option]').forEach((option) => {
option.addEventListener('click', (event) => {
event.stopPropagation();
const pulldownDemo = option.closest('.sg-pulldown-demo');
if (!pulldownDemo) {
return;
}
if (pulldownDemo.dataset.activatable === 'true' && pulldownDemo.dataset.componentState !== 'active') {
return;
}
const selectionMode = pulldownDemo.dataset.selectionMode || 'single';
if (selectionMode === 'multiple') {
const nextState = option.getAttribute('aria-checked') !== 'true';
option.setAttribute('aria-checked', String(nextState));
} else {
pulldownDemo.querySelectorAll('[data-pulldown-option]').forEach((otherOption) => {
otherOption.setAttribute('aria-checked', String(otherOption === option));
});
}
if (pulldownDemo.dataset.activatable === 'true') {
pulldownDemo.dataset.defaultSelectionInitialized = 'true';
}
updatePulldownSelectionState(pulldownDemo);
if (selectionMode !== 'multiple') {
pulldownDemo.dataset.open = 'false';
const trigger = pulldownDemo.querySelector('.sg-pulldown-demo__trigger');
if (trigger) {
trigger.setAttribute('aria-expanded', 'false');
}
}
});
});
document.querySelectorAll('.sg-radio-field').forEach((radio) => {
radio.addEventListener('click', () => {
if (radio.disabled) {
return;
}
const activatableGroup = radio.closest('[data-activatable-radio-group="true"]');
if (activatableGroup) {
if (activatableGroup.dataset.componentState !== 'active') {
return;
}
const radios = activatableGroup.querySelectorAll('.sg-radio-field');
radios.forEach((otherRadio) => {
otherRadio.setAttribute('aria-checked', String(otherRadio === radio));
otherRadio.classList.remove('sg-radio-field--inactive-selectable');
otherRadio.classList.toggle('sg-form-active', otherRadio === radio);
});
return;
}
const group = radio.closest('.sg-form-preview-area');
if (!group) {
return;
}
group.querySelectorAll('.sg-radio-field').forEach((otherRadio) => {
otherRadio.setAttribute('aria-checked', String(otherRadio === radio));
});
});
});
const updatePulldownSelectionState = (demo) => {
const trigger = demo.querySelector('.sg-pulldown-demo__trigger');
const selectableOptions = demo.querySelectorAll('[data-pulldown-option]');
const selectionMode = demo.dataset.selectionMode || 'single';
const isActivatableInactive = demo.dataset.activatable === 'true' && demo.dataset.componentState !== 'active';
if (!trigger || selectableOptions.length === 0) {
return;
}
const selectedCount = Array.from(selectableOptions).filter((option) => {
return option.getAttribute('aria-checked') === 'true';
}).length;
const selectedOption = Array.from(selectableOptions).find((option) => {
return option.getAttribute('aria-checked') === 'true';
});
selectableOptions.forEach((option) => {
const isSelected = option.getAttribute('aria-checked') === 'true';
const optionRow = option.closest('.sg-pulldown-option');
if (!optionRow) {
if (option.classList.contains('sg-checkbox-field')) {
option.classList.toggle('sg-form-active', !isActivatableInactive && isSelected);
option.classList.toggle('sg-checkbox-field--inactive-selectable', isActivatableInactive || !isSelected);
}
return;
}
optionRow.classList.toggle(
'sg-pulldown-option--selected',
isSelected
);
if (option.classList.contains('sg-checkbox-field')) {
option.classList.toggle('sg-form-active', !isActivatableInactive && isSelected);
option.classList.toggle('sg-checkbox-field--inactive-selectable', isActivatableInactive || !isSelected);
}
});
const labelBase = trigger.dataset.labelBase || 'Auswahl';
if (selectionMode === 'multiple') {
trigger.textContent = selectedCount > 0 ? `${labelBase} (${selectedCount})` : labelBase;
} else if (selectedOption) {
const selectedText = selectedOption.closest('.sg-pulldown-option')?.querySelector('span')?.textContent?.trim()
|| selectedOption.closest('label')?.querySelector('span:last-child')?.textContent?.trim()
|| selectedOption.textContent?.trim();
trigger.textContent = selectedText || labelBase;
} else {
trigger.textContent = labelBase;
}
const isActivatableActive = demo.dataset.activatable === 'true' && demo.dataset.componentState === 'active';
const showActiveState = !isActivatableInactive && (selectedCount > 0 || isActivatableActive);
trigger.classList.toggle('sg-pulldown--selected', showActiveState);
trigger.classList.toggle('sg-form-active', showActiveState);
trigger.classList.toggle('sg-pulldown--inactive-selectable', !showActiveState);
trigger.setAttribute(
'aria-label',
showActiveState ? 'Pulldown mit aktiver Auswahl' : 'Pulldown ohne aktive Auswahl'
);
};
document.querySelectorAll('.sg-pulldown-demo').forEach(updatePulldownSelectionState);
// Sync activatable targets to the toggle's initial state on load.
document.querySelectorAll('.sg-activation-mode-toggle[data-activation-target]').forEach((toggle) => {
const target = document.getElementById(toggle.dataset.activationTarget);
if (!target) {
return;
}
setActivatableComponentState(target, toggle.dataset.active === 'relative');
});
// Pulldown behavior: pulldown demos open their panel below the trigger.
// Opening one closes all sandwich menus and any other open pulldown demo.
// If the panel is wider than the trigger or would overflow the viewport, it aligns from the opposite trigger edge.
document.querySelectorAll('.sg-pulldown-demo').forEach((demo) => {
const trigger = demo.querySelector('.sg-pulldown-demo__trigger');
if (!trigger) {
return;
}
trigger.addEventListener('click', (event) => {
event.stopPropagation();
if (demo.dataset.activatable === 'true' && demo.dataset.componentState !== 'active') {
return;
}
const nextState = demo.dataset.open !== 'true';
document.querySelectorAll('.sg-pulldown-demo').forEach((otherDemo) => {
const otherTrigger = otherDemo.querySelector('.sg-pulldown-demo__trigger');
otherDemo.dataset.open = 'false';
if (otherTrigger) {
otherTrigger.setAttribute('aria-expanded', 'false');
}
});
document.querySelectorAll('.sg-sandwich-menu-wrap').forEach((wrap) => {
const button = wrap.querySelector('.sg-sandwich-button');
wrap.dataset.open = 'false';
if (button) {
button.setAttribute('aria-expanded', 'false');
}
});
demo.dataset.align = 'left';
demo.dataset.open = String(nextState);
trigger.setAttribute('aria-expanded', String(nextState));
if (!nextState) {
return;
}
const panel = demo.querySelector('.sg-pulldown-panel');
if (!panel) {
return;
}
const triggerRect = trigger.getBoundingClientRect();
const panelRect = panel.getBoundingClientRect();
if (panelRect.width > triggerRect.width || panelRect.right > window.innerWidth) {
demo.dataset.align = 'right';
}
const alignedPanelRect = panel.getBoundingClientRect();
if (alignedPanelRect.left < 0) {
demo.dataset.align = 'left';
}
});
});
// Filter rows inside the opened pulldown start as inactive preselected rows.
// They are visually dimmed but remain operable; clicking or changing them activates the row.
document.querySelectorAll('[data-pulldown-filter-row]').forEach((row) => {
const select = row.querySelector('.sg-pulldown');
const removeButton = row.querySelector('.sg-pulldown-panel__remove');
const updateFilterRowState = () => {
const isActive = row.dataset.active === 'true';
row.classList.toggle('sg-pulldown-panel__row--disabled', !isActive);
select.classList.toggle('sg-pulldown--selected', isActive);
select.classList.toggle('sg-pulldown--inactive-selectable', !isActive);
removeButton.hidden = !isActive;
};
row.addEventListener('click', (event) => {
if (event.target === removeButton) {
return;
}
if (row.dataset.active !== 'true') {
row.dataset.active = 'true';
updateFilterRowState();
}
});
select.addEventListener('change', () => {
row.dataset.active = 'true';
updateFilterRowState();
});
removeButton.addEventListener('click', () => {
row.dataset.active = 'false';
updateFilterRowState();
});
updateFilterRowState();
});
document.querySelectorAll('.sg-sandwich-menu-wrap').forEach((wrap) => {
const button = wrap.querySelector('.sg-sandwich-button');
const panel = wrap.querySelector('.sg-sandwich-menu-panel');
button.addEventListener('click', (event) => {
event.stopPropagation();
const nextState = wrap.dataset.open !== 'true';
document.querySelectorAll('.sg-sandwich-menu-wrap').forEach((otherWrap) => {
const otherButton = otherWrap.querySelector('.sg-sandwich-button');
otherWrap.dataset.open = 'false';
if (otherButton) {
otherButton.setAttribute('aria-expanded', 'false');
}
});
document.querySelectorAll('.sg-pulldown-demo').forEach((demo) => {
const trigger = demo.querySelector('.sg-pulldown-demo__trigger');
demo.dataset.open = 'false';
if (trigger) {
trigger.setAttribute('aria-expanded', 'false');
}
});
wrap.dataset.open = String(nextState);
button.setAttribute('aria-expanded', String(nextState));
if (!nextState || !panel) {
return;
}
wrap.dataset.align = 'right';
const panelRect = panel.getBoundingClientRect();
if (panelRect.left < 0) {
wrap.dataset.align = 'left';
}
});
});
window.sgInitHelpIconOverlays({
closeOnOpenSelectors: ['.sg-pulldown-demo', '.sg-sandwich-menu-wrap'],
outsideClickIgnoreSelectors: ['.sg-pulldown-demo', '.sg-sandwich-menu-wrap'],
});
// Global close behavior for overlay-style controls.
// A click outside sandwich menus and pulldown demos closes both overlay types.
document.addEventListener('click', (event) => {
if (
event.target.closest('.sg-sandwich-menu-wrap')
|| event.target.closest('.sg-pulldown-demo')
) {
return;
}
document.querySelectorAll('.sg-sandwich-menu-wrap').forEach((wrap) => {
const button = wrap.querySelector('.sg-sandwich-button');
wrap.dataset.open = 'false';
if (button) {
button.setAttribute('aria-expanded', 'false');
}
});
document.querySelectorAll('.sg-pulldown-demo').forEach((demo) => {
const trigger = demo.querySelector('.sg-pulldown-demo__trigger');
demo.dataset.open = 'false';
if (trigger) {
trigger.setAttribute('aria-expanded', 'false');
}
});
});
</script>
</body>
</html>