320 lines
13 KiB
HTML
320 lines
13 KiB
HTML
<!doctype html>
|
||
<html lang="de">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<title>Styleguide – Pattern Options Row</title>
|
||
<link rel="stylesheet" href="../styleguide.css">
|
||
</head>
|
||
<body>
|
||
|
||
<h1 class="sg-main-heading">Pattern – Options Row</h1>
|
||
<section id="pattern-options-row">
|
||
<p class="sg-preview-label">Pattern: Options Row</p>
|
||
|
||
<p class="sg-table-label" style="color: var(--text-options-row-description);">
|
||
Desktop/Tablet: gleiche Breite wie das zugehörige Element; linke Optionen linksbündig, rechte Optionen rechtsbündig.
|
||
</p>
|
||
|
||
<p class="sg-table-label" style="color: var(--text-options-row-description);">
|
||
Mobile: rechte Optionen werden zum oberen Segment, linke Optionen zum unteren Segment; linke Optionen brechen innerhalb der verfügbaren Breite um.
|
||
</p>
|
||
|
||
<div class="sg-options-row" aria-label="Optionszeile" data-pattern="options-row">
|
||
|
||
<div class="sg-options-row__left" data-pattern-part="options-row-primary-actions">
|
||
<div class="sg-pulldown-demo" data-open="false" data-align="left" data-selection-mode="single" data-component="pulldown" data-component-context="options-row" data-component-state="inactive-selectable">
|
||
<button class="sg-interaction-element sg-pulldown sg-pulldown-demo__trigger" type="button" aria-expanded="false" aria-label="Pulldown Sortierung" data-component-part="pulldown-trigger" data-label-base="Sortierung">
|
||
Sortierung
|
||
</button>
|
||
|
||
<div class="sg-pulldown-panel" aria-label="Geöffnetes Pulldown Sortierung" data-component-part="pulldown-panel">
|
||
<ul class="sg-pulldown-option-list" aria-label="Sortierungsoptionen">
|
||
<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 class="sg-pulldown-demo" data-open="false" data-align="left" data-selection-mode="single" data-component="pulldown" data-component-context="options-row" data-component-state="inactive-selectable">
|
||
<button class="sg-interaction-element sg-pulldown sg-pulldown-demo__trigger" type="button" aria-expanded="false" aria-label="Pulldown Region" data-component-part="pulldown-trigger" data-label-base="Region">
|
||
Region
|
||
</button>
|
||
|
||
<div class="sg-pulldown-panel" aria-label="Geöffnetes Pulldown Region" data-component-part="pulldown-panel">
|
||
<ul class="sg-pulldown-option-list" aria-label="Regionsoptionen">
|
||
<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 class="sg-search-field-row">
|
||
<span class="sg-input-single-line-wrap sg-search-field-input" data-has-value="false" data-component="single-line-input" data-component-context="options-row" data-component-state="inactive-selectable">
|
||
<input
|
||
class="sg-interaction-element sg-input-single-line"
|
||
type="text"
|
||
placeholder="Suche"
|
||
aria-label="Suche"
|
||
>
|
||
<button class="sg-input-clear-button" type="button" aria-label="Eingabe löschen" data-component-part="input-clear-button">×</button>
|
||
</span>
|
||
<span class="sg-search-result-count sg-table-label" aria-live="polite" data-pattern-part="options-row-search-result-count">0 Treffer</span>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="sg-options-row__right" data-pattern-part="options-row-secondary-actions">
|
||
<button class="sg-mode-toggle" type="button" data-active="relative" aria-label="Modus Schieber global: relativ aktiv" data-component="mode-toggle" data-component-context="options-row">
|
||
<span class="sg-mode-toggle__label" data-component-part="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" data-component-part="toggle-label">relativ</span>
|
||
</button>
|
||
|
||
<span class="sg-help-icon-wrap" data-open="false" data-align="left" data-component="help-icon" data-component-context="options-row">
|
||
<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>
|
||
</div>
|
||
|
||
</div>
|
||
</section>
|
||
|
||
<script src="../scripts/help-icon-overlays.js"></script>
|
||
<script>
|
||
|
||
document.querySelectorAll('.sg-mode-toggle').forEach((toggle) => {
|
||
toggle.addEventListener('click', () => {
|
||
const nextState = toggle.dataset.active === 'relative' ? 'absolute' : 'relative';
|
||
toggle.dataset.active = nextState;
|
||
toggle.dataset.componentState = nextState;
|
||
toggle.setAttribute(
|
||
'aria-label',
|
||
`Modus Schieber global: ${nextState === 'relative' ? 'relativ' : 'absolut'} aktiv`
|
||
);
|
||
});
|
||
});
|
||
|
||
// Pulldown demo logic:
|
||
// Pulldowns with checkbox options stay open while options are toggled,
|
||
// because users may select or deselect several options in one opened panel.
|
||
const updatePulldownSelectionState = (demo) => {
|
||
const trigger = demo.querySelector('.sg-pulldown-demo__trigger');
|
||
const selectableOptions = demo.querySelectorAll('[data-pulldown-option]');
|
||
|
||
if (!trigger || selectableOptions.length === 0) {
|
||
return;
|
||
}
|
||
|
||
const selectedCount = Array.from(selectableOptions).filter((option) => {
|
||
return option.getAttribute('aria-checked') === 'true';
|
||
}).length;
|
||
|
||
selectableOptions.forEach((option) => {
|
||
const optionRow = option.closest('.sg-pulldown-option');
|
||
if (!optionRow) {
|
||
return;
|
||
}
|
||
|
||
optionRow.classList.toggle(
|
||
'sg-pulldown-option--selected',
|
||
option.getAttribute('aria-checked') === 'true'
|
||
);
|
||
});
|
||
|
||
const labelBase = trigger.dataset.labelBase || 'Auswahl';
|
||
|
||
trigger.textContent = selectedCount > 0 ? `${labelBase} (${selectedCount})` : labelBase;
|
||
trigger.classList.toggle('sg-pulldown--selected', selectedCount > 0);
|
||
trigger.classList.toggle('sg-form-active', selectedCount > 0);
|
||
trigger.dataset.componentState = selectedCount > 0 ? 'selected' : 'inactive-selectable';
|
||
demo.dataset.componentState = selectedCount > 0 ? 'selected' : 'inactive-selectable';
|
||
trigger.setAttribute(
|
||
'aria-label',
|
||
selectedCount > 0 ? `Pulldown ${labelBase} mit aktiver Auswahl` : `Pulldown ${labelBase} ohne aktive Auswahl`
|
||
);
|
||
};
|
||
|
||
document.querySelectorAll('.sg-pulldown-demo').forEach((demo) => {
|
||
const trigger = demo.querySelector('.sg-pulldown-demo__trigger');
|
||
|
||
if (!trigger) {
|
||
return;
|
||
}
|
||
|
||
trigger.addEventListener('click', (event) => {
|
||
event.stopPropagation();
|
||
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');
|
||
}
|
||
});
|
||
|
||
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 panelRect = panel.getBoundingClientRect();
|
||
if (panelRect.right > window.innerWidth) {
|
||
demo.dataset.align = 'right';
|
||
}
|
||
|
||
const alignedPanelRect = panel.getBoundingClientRect();
|
||
if (alignedPanelRect.left < 0) {
|
||
demo.dataset.align = 'left';
|
||
}
|
||
});
|
||
});
|
||
|
||
document.querySelectorAll('.sg-checkbox-field').forEach((checkbox) => {
|
||
checkbox.addEventListener('click', (event) => {
|
||
event.stopPropagation();
|
||
if (checkbox.disabled) {
|
||
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);
|
||
pulldownDemo.dataset.open = 'true';
|
||
const trigger = pulldownDemo.querySelector('.sg-pulldown-demo__trigger');
|
||
if (trigger) {
|
||
trigger.setAttribute('aria-expanded', 'true');
|
||
}
|
||
}
|
||
});
|
||
});
|
||
|
||
document.querySelectorAll('.sg-pulldown-option[data-pulldown-option]').forEach((option) => {
|
||
option.addEventListener('click', (event) => {
|
||
event.stopPropagation();
|
||
const pulldownDemo = option.closest('.sg-pulldown-demo');
|
||
if (pulldownDemo) {
|
||
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));
|
||
});
|
||
}
|
||
|
||
updatePulldownSelectionState(pulldownDemo);
|
||
const trigger = pulldownDemo.querySelector('.sg-pulldown-demo__trigger');
|
||
if (selectionMode === 'multiple') {
|
||
pulldownDemo.dataset.open = 'true';
|
||
if (trigger) {
|
||
trigger.setAttribute('aria-expanded', 'true');
|
||
}
|
||
} else {
|
||
pulldownDemo.dataset.open = 'false';
|
||
if (trigger) {
|
||
trigger.setAttribute('aria-expanded', 'false');
|
||
}
|
||
}
|
||
}
|
||
});
|
||
});
|
||
|
||
document.querySelectorAll('.sg-pulldown-demo').forEach(updatePulldownSelectionState);
|
||
|
||
window.sgInitHelpIconOverlays({
|
||
closeOnOpenSelectors: ['.sg-pulldown-demo'],
|
||
outsideClickIgnoreSelectors: ['.sg-pulldown-demo'],
|
||
});
|
||
|
||
document.addEventListener('click', (event) => {
|
||
if (event.target.closest('.sg-pulldown-demo')) {
|
||
return;
|
||
}
|
||
|
||
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');
|
||
}
|
||
});
|
||
});
|
||
|
||
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);
|
||
wrap.dataset.componentState = input.value.length > 0 ? 'active' : 'inactive-selectable';
|
||
};
|
||
|
||
input.addEventListener('input', updateState);
|
||
|
||
clearButton.addEventListener('click', () => {
|
||
input.value = '';
|
||
updateState();
|
||
input.focus();
|
||
});
|
||
|
||
updateState();
|
||
});
|
||
</script>
|
||
|
||
</body>
|
||
</html>
|