Files
Styleguide/patterns/multiselektions-pulldown.html
T

566 lines
26 KiB
HTML
Raw 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 Pattern Multiselektions-Pulldown</title>
<link rel="stylesheet" href="../styleguide.css">
</head>
<body>
<h1 class="sg-main-heading">Pattern Multiselektions-Pulldown</h1>
<section id="pattern-multiselektions-pulldown">
<p class="sg-preview-label">Pattern: Multiselektions-Pulldown</p>
<div class="sg-options-row" aria-label="Multiselektions-Pulldown Wrapper" data-pattern="multiselektions-pulldown">
<div class="sg-options-row__left" data-pattern-part="multiselektions-pulldown-trigger-area">
<div class="sg-pulldown-demo" data-open="false" data-align="left" data-selection-mode="multiple" data-component="pulldown" data-component-state="active" data-force-active="true">
<span class="sg-activatable-control">
<button class="sg-interaction-element sg-pulldown sg-pulldown--selected sg-form-active sg-pulldown-demo__trigger" type="button" aria-expanded="false" aria-label="Multiselektions-Pulldown mit aktiver Auswahl" data-label-base="Multiselektions-Pulldown" data-component-part="pulldown-trigger">
Multiselektions-Pulldown
</button>
</span>
<div class="sg-pulldown-panel" aria-label="Geöffnetes Multiselektions-Pulldown" data-component-part="pulldown-panel">
<div class="sg-form-sections-card-wrapper" data-pattern="form-sections" aria-label="Multiselektions-Inhalt">
<form class="sg-form-sections-card" action="#" method="post">
<div class="sg-form-sections-card__body" data-pattern-part="form-body">
<section class="sg-form-sections-card__chapter" aria-labelledby="multiselect-block-1">
<h2 id="multiselect-block-1" class="sg-strong sg-form-sections-card__chapter-title">Block 1</h2>
<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--inactive-selectable" type="button" role="checkbox" aria-checked="false" aria-label="Checkbox 1 wählen" data-pulldown-option>
<span class="sg-checkbox-field__mark" aria-hidden="true"></span>
</button>
<span>Checkbox 1</span>
</label>
<label class="sg-slider-row sg-slider-row--inactive-selectable" data-component="slider" data-component-state="inactive-selectable" data-activatable="true">
<span class="sg-label">Slider 1</span>
<input
class="sg-interaction-element sg-slider sg-form-inactive-selectable"
type="range"
min="1"
max="10"
step="0.1"
value="6.5"
aria-label="Slider 1 von 1 bis 10"
>
<output class="sg-slider-value sg-body" for="slider">6.5</output>
<button class="sg-activatable-remove" type="button" aria-label="Slider 1 entfernen" data-slider-activate-remove hidden>×</button>
</label>
<label class="sg-slider-row sg-slider-row--inactive-selectable" data-component="slider" data-component-state="inactive-selectable" data-activatable="true">
<span class="sg-label">Slider 2</span>
<input
class="sg-interaction-element sg-slider sg-form-inactive-selectable"
type="range"
min="1"
max="10"
step="0.1"
value="9.5"
aria-label="Slider 2 von 1 bis 10"
>
<output class="sg-slider-value sg-body" for="slider">9.5</output>
<button class="sg-activatable-remove" type="button" aria-label="Slider 2 entfernen" data-slider-activate-remove hidden>×</button>
</label>
<label class="sg-slider-row sg-slider-row--inactive-selectable" data-component="slider" data-component-state="inactive-selectable" data-activatable="true">
<span class="sg-label">Slider 3</span>
<input
class="sg-interaction-element sg-slider sg-form-inactive-selectable"
type="range"
min="1"
max="10"
step="0.1"
value="5.0"
aria-label="Slider 3 von 1 bis 10"
>
<output class="sg-slider-value sg-body" for="slider">5.0</output>
<button class="sg-activatable-remove" type="button" aria-label="Slider 3 entfernen" data-slider-activate-remove hidden>×</button>
</label>
<label class="sg-slider-row sg-slider-row--inactive-selectable" data-component="slider" data-component-state="inactive-selectable" data-activatable="true">
<span class="sg-label">Slider 4</span>
<input
class="sg-interaction-element sg-slider sg-form-inactive-selectable"
type="range"
min="1"
max="10"
step="0.1"
value="6.5"
aria-label="Slider 4 von 1 bis 10"
>
<output class="sg-slider-value sg-body" for="slider">6.5</output>
<button class="sg-activatable-remove" type="button" aria-label="Slider 4 entfernen" data-slider-activate-remove hidden>×</button>
</label>
</section>
<section class="sg-form-sections-card__chapter" aria-labelledby="multiselect-block-2">
<h2 id="multiselect-block-2" class="sg-strong sg-form-sections-card__chapter-title">Block 2</h2>
<label class="sg-slider-row sg-slider-row--inactive-selectable" data-component="slider" data-component-state="inactive-selectable" data-activatable="true">
<span class="sg-label">Slider 5</span>
<input
class="sg-interaction-element sg-slider sg-form-inactive-selectable"
type="range"
min="1"
max="10"
step="0.1"
value="3.0"
aria-label="Slider 5 von 1 bis 10"
>
<output class="sg-slider-value sg-body" for="slider">3.0</output>
<button class="sg-activatable-remove" type="button" aria-label="Slider 5 entfernen" data-slider-activate-remove hidden>×</button>
</label>
<label class="sg-slider-row sg-slider-row--inactive-selectable" data-component="slider" data-component-state="inactive-selectable" data-activatable="true">
<span class="sg-label">Slider 6</span>
<input
class="sg-interaction-element sg-slider sg-form-inactive-selectable"
type="range"
min="1"
max="10"
step="0.1"
value="2.5"
aria-label="Slider 6 von 1 bis 10"
>
<output class="sg-slider-value sg-body" for="slider">2.5</output>
<button class="sg-activatable-remove" type="button" aria-label="Slider 6 entfernen" data-slider-activate-remove hidden>×</button>
</label>
<label class="sg-slider-row sg-slider-row--inactive-selectable" data-component="slider" data-component-state="inactive-selectable" data-activatable="true">
<span class="sg-label">Slider 7</span>
<input
class="sg-interaction-element sg-slider sg-form-inactive-selectable"
type="range"
min="1"
max="10"
step="0.1"
value="1.6"
aria-label="Slider 7 von 1 bis 10"
>
<output class="sg-slider-value sg-body" for="slider">1.6</output>
<button class="sg-activatable-remove" type="button" aria-label="Slider 7 entfernen" data-slider-activate-remove hidden>×</button>
</label>
</section>
<section class="sg-form-sections-card__chapter" aria-labelledby="multiselect-block-3">
<h2 id="multiselect-block-3" class="sg-strong sg-form-sections-card__chapter-title">Block 3</h2>
<label class="sg-checkbox-field-option sg-checkbox-field-option--inactive-selectable sg-body sg-radio-activatable-group" data-component="radio-field" data-component-state="inactive-selectable" data-activatable="true" data-activatable-radio-group="true">
<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="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 sg-radio-field--inactive-selectable" 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>
<button class="sg-activatable-remove" type="button" aria-label="Radio-Auswahl entfernen" data-radio-activate-remove hidden>×</button>
</label>
<div class="sg-pulldown-panel__row sg-pulldown-panel__row--disabled" data-pulldown-filter-row data-active="false" data-component-part="pulldown-filter-row">
<p class="sg-pulldown-panel__label sg-body">Pulldown 1</p>
<select class="sg-interaction-element sg-pulldown" aria-label="Pulldown 1 Auswahl">
<option selected>Option 1</option>
<option>Option 2</option>
<option>Option 3</option>
</select>
<button class="sg-pulldown-panel__remove" type="button" aria-label="Pulldown 1 entfernen" hidden>×</button>
</div>
</section>
<section class="sg-form-sections-card__chapter" aria-labelledby="multiselect-block-4">
<h2 id="multiselect-block-4" class="sg-strong sg-form-sections-card__chapter-title">Block 4</h2>
<div class="sg-pulldown-panel__row sg-pulldown-panel__row--disabled" data-pulldown-filter-row data-active="false" data-component-part="pulldown-filter-row">
<p class="sg-pulldown-panel__label sg-body">Pulldown 2</p>
<select class="sg-interaction-element sg-pulldown" aria-label="Pulldown 2 Auswahl">
<option selected>Option 1</option>
<option>Option 2</option>
<option>Option 3</option>
</select>
<button class="sg-pulldown-panel__remove" type="button" aria-label="Pulldown 2 entfernen" hidden>×</button>
</div>
<div class="sg-pulldown-panel__row sg-pulldown-panel__row--disabled" data-pulldown-filter-row data-active="false" data-component-part="pulldown-filter-row">
<p class="sg-pulldown-panel__label sg-body">Pulldown 3</p>
<select class="sg-interaction-element sg-pulldown" aria-label="Pulldown 3 Auswahl">
<option selected>Option 1</option>
<option>Option 2</option>
<option>Option 3</option>
</select>
<button class="sg-pulldown-panel__remove" type="button" aria-label="Pulldown 3 entfernen" hidden>×</button>
</div>
<div class="sg-pulldown-panel__row sg-pulldown-panel__row--disabled" data-pulldown-filter-row data-active="false" data-component-part="pulldown-filter-row">
<p class="sg-pulldown-panel__label sg-body">Pulldown 4</p>
<select class="sg-interaction-element sg-pulldown" aria-label="Pulldown 4 Auswahl">
<option selected>Option 1</option>
<option>Option 2</option>
<option>Option 3</option>
</select>
<button class="sg-pulldown-panel__remove" type="button" aria-label="Pulldown 4 entfernen" hidden>×</button>
</div>
</section>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
</section>
<script>
(() => {
const updatePulldownSelectionState = (demo) => {
const trigger = demo.querySelector('.sg-pulldown-demo__trigger');
const selectableOptions = demo.querySelectorAll('[data-pulldown-option]');
const activatableRemove = demo.querySelector('[data-pulldown-activate-remove]');
const forceActive = demo.dataset.forceActive === 'true';
if (!trigger || selectableOptions.length === 0) {
return;
}
const selectedCount = Array.from(selectableOptions).filter((option) => {
return option.getAttribute('aria-checked') === 'true';
}).length;
const labelBase = trigger.dataset.labelBase || 'Auswahl';
trigger.textContent = forceActive
? labelBase
: (selectedCount > 0 ? `${labelBase} (${selectedCount})` : labelBase);
trigger.classList.toggle('sg-pulldown--selected', forceActive || selectedCount > 0);
trigger.classList.toggle('sg-form-active', forceActive || selectedCount > 0);
trigger.classList.toggle('sg-pulldown--inactive-selectable', !forceActive && selectedCount === 0);
if (activatableRemove) {
activatableRemove.hidden = forceActive || selectedCount === 0;
}
trigger.setAttribute(
'aria-label',
forceActive || selectedCount > 0 ? `${labelBase} mit aktiver Auswahl` : `${labelBase} ohne aktive Auswahl`
);
};
document.querySelectorAll('.sg-slider-row').forEach((row) => {
const slider = row.querySelector('.sg-slider');
const valueOutput = row.querySelector('.sg-slider-value');
const removeButton = row.querySelector('[data-slider-activate-remove]');
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);
};
const activateSliderRow = () => {
if (row.dataset.activatable === 'true' && row.dataset.componentState === 'inactive-selectable') {
row.dataset.componentState = 'active';
row.classList.remove('sg-slider-row--inactive-selectable');
slider.classList.remove('sg-form-inactive-selectable');
slider.classList.add('sg-form-active');
if (removeButton) {
removeButton.hidden = false;
}
}
};
slider.addEventListener('input', () => {
activateSliderRow();
updateSliderState();
});
slider.addEventListener('pointerdown', activateSliderRow);
slider.addEventListener('click', activateSliderRow);
updateSliderState();
});
document.querySelectorAll('.sg-checkbox-field').forEach((checkbox) => {
checkbox.addEventListener('click', (event) => {
event.stopPropagation();
if (checkbox.disabled) {
return;
}
const activatableOption = checkbox.closest('[data-component="checkbox-field"][data-activatable="true"]');
if (activatableOption) {
checkbox.setAttribute('aria-checked', 'true');
checkbox.classList.add('sg-form-active');
checkbox.classList.remove('sg-checkbox-field--inactive-selectable');
activatableOption.dataset.componentState = 'active';
const removeButton = activatableOption.querySelector('[data-checkbox-activate-remove]');
if (removeButton) {
removeButton.hidden = false;
}
}
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-radio-field').forEach((radio) => {
radio.addEventListener('click', (event) => {
event.stopPropagation();
if (radio.disabled) {
return;
}
const activatableGroup = radio.closest('[data-activatable-radio-group="true"]');
if (!activatableGroup) {
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);
});
activatableGroup.dataset.componentState = 'active';
const removeButton = activatableGroup.querySelector('[data-radio-activate-remove]');
if (removeButton) {
removeButton.hidden = false;
}
});
});
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';
if (demo.dataset.activatable === 'true') {
const activatableRemove = demo.querySelector('[data-pulldown-activate-remove]');
trigger.classList.add('sg-pulldown--selected', 'sg-form-active');
trigger.classList.remove('sg-pulldown--inactive-selectable');
if (activatableRemove) {
activatableRemove.hidden = false;
}
}
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 viewportInset = 16;
demo.dataset.align = 'left';
panel.style.left = '0px';
panel.style.right = 'auto';
const initialRect = panel.getBoundingClientRect();
let offsetX = 0;
if (initialRect.right > window.innerWidth - viewportInset) {
offsetX -= initialRect.right - (window.innerWidth - viewportInset);
}
if (initialRect.left + offsetX < viewportInset) {
offsetX += viewportInset - (initialRect.left + offsetX);
}
panel.style.left = `${offsetX}px`;
});
});
document.querySelectorAll('[data-pulldown-activate-remove]').forEach((removeButton) => {
removeButton.addEventListener('click', (event) => {
event.stopPropagation();
const demo = removeButton.closest('.sg-pulldown-demo');
const trigger = demo ? demo.querySelector('.sg-pulldown-demo__trigger') : null;
if (!demo || !trigger) {
return;
}
demo.querySelectorAll('[data-pulldown-option]').forEach((option) => {
option.setAttribute('aria-checked', 'false');
});
demo.dataset.componentState = 'inactive-selectable';
demo.dataset.open = 'false';
trigger.setAttribute('aria-expanded', 'false');
updatePulldownSelectionState(demo);
});
});
document.querySelectorAll('[data-checkbox-activate-remove]').forEach((removeButton) => {
removeButton.addEventListener('click', (event) => {
event.stopPropagation();
const option = removeButton.closest('[data-component="checkbox-field"][data-activatable="true"]');
const checkbox = option ? option.querySelector('.sg-checkbox-field') : null;
if (!option || !checkbox) {
return;
}
option.dataset.componentState = 'inactive-selectable';
checkbox.setAttribute('aria-checked', 'false');
checkbox.classList.remove('sg-form-active');
checkbox.classList.add('sg-checkbox-field--inactive-selectable');
removeButton.hidden = true;
const pulldownDemo = option.closest('.sg-pulldown-demo');
if (pulldownDemo) {
updatePulldownSelectionState(pulldownDemo);
}
});
});
document.querySelectorAll('[data-radio-activate-remove]').forEach((removeButton) => {
removeButton.addEventListener('click', (event) => {
event.stopPropagation();
const option = removeButton.closest('[data-activatable-radio-group="true"]');
const radios = option ? option.querySelectorAll('.sg-radio-field') : null;
if (!option || !radios || radios.length === 0) {
return;
}
option.dataset.componentState = 'inactive-selectable';
radios.forEach((radio) => {
radio.setAttribute('aria-checked', 'false');
radio.classList.remove('sg-form-active');
radio.classList.add('sg-radio-field--inactive-selectable');
});
removeButton.hidden = true;
});
});
document.querySelectorAll('[data-slider-activate-remove]').forEach((removeButton) => {
removeButton.addEventListener('click', (event) => {
event.stopPropagation();
const row = removeButton.closest('.sg-slider-row[data-activatable="true"]');
const slider = row ? row.querySelector('.sg-slider') : null;
if (!row || !slider) {
return;
}
row.dataset.componentState = 'inactive-selectable';
row.classList.add('sg-slider-row--inactive-selectable');
slider.classList.remove('sg-form-active');
slider.classList.add('sg-form-inactive-selectable');
removeButton.hidden = true;
});
});
document.querySelectorAll('[data-pulldown-filter-row]').forEach((row) => {
const select = row.querySelector('.sg-pulldown');
const removeButton = row.querySelector('.sg-pulldown-panel__remove');
if (!select || !removeButton) {
return;
}
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;
};
select.addEventListener('click', (event) => {
event.stopPropagation();
if (row.dataset.active !== 'true') {
row.dataset.active = 'true';
updateFilterRowState();
}
});
select.addEventListener('change', () => {
row.dataset.active = 'true';
updateFilterRowState();
});
removeButton.addEventListener('click', (event) => {
event.stopPropagation();
row.dataset.active = 'false';
updateFilterRowState();
});
updateFilterRowState();
});
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-pulldown-demo').forEach(updatePulldownSelectionState);
})();
</script>
</body>
</html>