Files
erp_naurua/docs/styleguide/patterns/delete-confirmation-overlay.html
T

514 lines
24 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 Overlay Card</title>
<link rel="stylesheet" href="../styleguide.css">
</head>
<body>
<h1 class="sg-main-heading">Pattern - Overlay Card</h1>
<section id="pattern-overlay-card" class="sg-delete-confirmation-pattern">
<p class="sg-preview-label">Pattern: Overlay Card</p>
<div class="sg-delete-confirmation-pattern__stage sg-delete-confirmation-pattern__host sg-object-card" data-pattern="overlay-card" data-dialog-open="false" data-overlay-confirmation-value="DELETE">
<article class="sg-card sg-object-card sg-delete-confirmation-pattern__target" aria-label="Zu löschendes Objekt">
<header class="sg-card-segment sg-card-segment--header sg-card-segment--darkblue sg-object-card__header">
<div class="sg-strong">Alcon Inc.</div>
<div class="sg-sandwich-menu-wrap" data-open="false" data-align="right" 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="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 Menü" data-component-part="sandwich-panel">
<a class="sg-sandwich-menu-link" href="#!" data-overlay-open-dialog="delete">Objekt löschen</a>
</div>
</div>
</header>
<div class="sg-card-segment sg-card-segment--body sg-object-card__content">
<p class="sg-body">Objekt-Inhalt der Card. Während das Löschfenster sichtbar ist, wird dieses Objekt um 50% ausgegraut.</p>
</div>
<footer class="sg-card-segment sg-card-segment--body sg-object-card__actions-segment">
<div class="sg-object-card__actions">
<button class="sg-interaction-element sg-button sg-button--active sg-object-card__action" type="button">Peer-Group</button>
<button class="sg-interaction-element sg-button sg-button--active sg-object-card__action" type="button">Fundamentalanalyse</button>
</div>
</footer>
</article>
<article class="sg-card sg-card--overlay-host sg-delete-confirmation-pattern__floating-card" aria-label="Löschbestätigung" role="dialog" aria-modal="true" aria-labelledby="delete-confirmation-title" data-overlay-dialog="delete" hidden>
<div class="sg-card-segment sg-card-segment--body sg-delete-confirmation-pattern__body">
<p class="sg-body sg-delete-confirmation-pattern__text" id="delete-confirmation-title"><strong>Möchtest du Alcon Inc. wirklich löschen?</strong></p>
<p class="sg-body sg-delete-confirmation-pattern__text">Du kannst das nicht rückgängig machen. Bestätige durch Eingabe von <span class="sg-delete-confirmation-pattern__code">DELETE</span>.</p>
<label class="sg-labeled-input-row sg-delete-confirmation-pattern__input-row">
<span class="sg-label">Bestätigung</span>
<input
class="sg-interaction-element sg-input-single-line sg-input-single-line--inactive-selectable sg-form-inactive-selectable"
type="text"
placeholder="DELETE"
aria-label="Löschbestätigung durch DELETE"
data-overlay-confirmation-input
>
</label>
<div class="sg-delete-confirmation-pattern__actions">
<button class="sg-interaction-element sg-button sg-button--active" type="button" data-overlay-dialog-close>Abbrechen</button>
<button
class="sg-interaction-element sg-button sg-button--process sg-button--process-inactive"
type="button"
disabled
aria-disabled="true"
data-overlay-confirmation-submit
data-overlay-dialog-close
>
Löschen
</button>
</div>
</div>
</article>
</div>
</section>
<section id="pattern-add-to-list-overlay" class="sg-delete-confirmation-pattern">
<p class="sg-preview-label">Pattern: Add to List Overlay</p>
<div class="sg-delete-confirmation-pattern__stage sg-delete-confirmation-pattern__host sg-object-card" data-pattern="add-to-list-overlay" data-dialog-open="false" data-overlay-selected-lists="1,2">
<article class="sg-card sg-object-card sg-delete-confirmation-pattern__target" aria-label="Zu einer Liste hinzuzufügendes Objekt">
<header class="sg-card-segment sg-card-segment--header sg-card-segment--darkblue sg-object-card__header">
<div class="sg-strong">Alcon Inc.</div>
<div class="sg-sandwich-menu-wrap" data-open="false" data-align="right" 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="Zur Liste hinzufügen" data-component-part="sandwich-trigger" data-overlay-open-dialog="add-to-list">
<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>
</header>
<div class="sg-card-segment sg-card-segment--body sg-object-card__content">
<p class="sg-body">Objekt-Inhalt der Card. Während das Overlay sichtbar ist, wird dieses Objekt um 50% ausgegraut.</p>
</div>
<footer class="sg-card-segment sg-card-segment--body sg-object-card__actions-segment">
<div class="sg-object-card__actions">
<button class="sg-interaction-element sg-button sg-button--active sg-object-card__action" type="button">Peer-Group</button>
<button class="sg-interaction-element sg-button sg-button--active sg-object-card__action" type="button">Fundamentalanalyse</button>
</div>
</footer>
</article>
<article class="sg-card sg-card--overlay-host sg-object-card sg-object-card--variable-height sg-delete-confirmation-pattern__floating-card" aria-label="Zur Liste hinzufügen" role="dialog" aria-modal="true" aria-labelledby="add-to-list-title" data-overlay-dialog="add-to-list" hidden>
<header class="sg-card-segment sg-card-segment--header sg-card-segment--darkblue sg-object-card__header">
<p class="sg-body sg-strong" id="add-to-list-title">Füge das Unternehmen einer Liste hinzu</p>
</header>
<div class="sg-card-segment sg-card-segment--body sg-delete-confirmation-pattern__body">
<ul class="sg-delete-confirmation-pattern__list" aria-label="Listen">
<li class="sg-delete-confirmation-pattern__list-item">
<button class="sg-interaction-element sg-button sg-delete-confirmation-pattern__list-button" type="button" data-overlay-list-toggle data-overlay-list-id="1" aria-pressed="true">
<span class="sg-delete-confirmation-pattern__list-icon" aria-hidden="true"></span>
<span class="sg-delete-confirmation-pattern__list-label">Liste 1</span>
</button>
</li>
<li class="sg-delete-confirmation-pattern__list-item">
<button class="sg-interaction-element sg-button sg-delete-confirmation-pattern__list-button" type="button" data-overlay-list-toggle data-overlay-list-id="2" aria-pressed="true">
<span class="sg-delete-confirmation-pattern__list-icon" aria-hidden="true"></span>
<span class="sg-delete-confirmation-pattern__list-label">Liste 2</span>
</button>
</li>
<li class="sg-delete-confirmation-pattern__list-item">
<button class="sg-interaction-element sg-button sg-delete-confirmation-pattern__list-button" type="button" data-overlay-list-toggle data-overlay-list-id="3" aria-pressed="false">
<span class="sg-delete-confirmation-pattern__list-icon" aria-hidden="true"></span>
<span class="sg-delete-confirmation-pattern__list-label">Liste 3</span>
</button>
</li>
<li class="sg-delete-confirmation-pattern__list-item">
<button class="sg-interaction-element sg-button sg-delete-confirmation-pattern__list-button" type="button" data-overlay-list-toggle data-overlay-list-id="4" aria-pressed="false">
<span class="sg-delete-confirmation-pattern__list-icon" aria-hidden="true"></span>
<span class="sg-delete-confirmation-pattern__list-label">Liste 4</span>
</button>
</li>
<li class="sg-delete-confirmation-pattern__list-item">
<button class="sg-interaction-element sg-button sg-delete-confirmation-pattern__list-button" type="button" data-overlay-list-toggle data-overlay-list-id="5" aria-pressed="false">
<span class="sg-delete-confirmation-pattern__list-icon" aria-hidden="true"></span>
<span class="sg-delete-confirmation-pattern__list-label">Liste 5</span>
</button>
</li>
</ul>
<div class="sg-delete-confirmation-pattern__actions">
<button class="sg-interaction-element sg-button sg-button--active sg-delete-confirmation-pattern__create-list-toggle" type="button" data-create-list-form-toggle aria-expanded="false">Neue Liste anlegen</button>
</div>
</div>
<div class="sg-card-segment sg-card-segment--body sg-delete-confirmation-pattern__body sg-delete-confirmation-pattern__create-list-segment" data-create-list-form hidden>
<p class="sg-body sg-delete-confirmation-pattern__text sg-delete-confirmation-pattern__create-list-title" data-create-list-title>Füge das Unternehmen einer neuen Liste hinzu</p>
<div class="sg-form-sections-card-wrapper sg-delete-confirmation-pattern__create-list-form" aria-label="Formular mit Abschnitten">
<form class="sg-form-sections-card" action="#" method="post" aria-label="Neue Liste anlegen Formular">
<div class="sg-form-sections-card__body" data-pattern-part="form-body">
<section class="sg-form-sections-card__chapter" aria-label="Neue Liste">
<div class="sg-form-sections-card__field-group">
<label class="sg-labeled-input-row">
<span class="sg-label">Name</span>
<span class="sg-input-validation-stack">
<input
class="sg-interaction-element sg-input-single-line sg-input-single-line--inactive-selectable sg-form-inactive-selectable"
type="text"
placeholder="Name eingeben"
aria-label="Name"
maxlength="80"
aria-describedby="create-list-name-error"
>
<span class="sg-form-validation-text" id="create-list-name-error" hidden>Eine Liste mit diesem Namen existiert bereits.</span>
</span>
</label>
<label class="sg-labeled-input-row">
<span class="sg-label">Beschreibung</span>
<textarea
class="sg-input-multi-line sg-form-inactive-selectable"
rows="4"
placeholder="Beschreibung eingeben"
aria-label="Beschreibung"
maxlength="350"
></textarea>
</label>
</div>
</section>
</div>
</form>
</div>
</div>
<footer class="sg-card-segment sg-card-segment--body sg-delete-confirmation-pattern__actions-segment">
<div class="sg-delete-confirmation-pattern__actions sg-delete-confirmation-pattern__actions--footer">
<button class="sg-interaction-element sg-button sg-button--active" type="button" data-overlay-dialog-cancel>Abbrechen</button>
<button class="sg-interaction-element sg-button sg-button--process" type="button" data-overlay-dialog-save>Speichern</button>
</div>
</footer>
</article>
</div>
</section>
<script>
const setupOverlayStage = (stage) => {
const confirmationInput = stage.querySelector('[data-overlay-confirmation-input]');
const confirmationSubmitButton = stage.querySelector('[data-overlay-confirmation-submit]');
const expectedConfirmationValue = stage.dataset.overlayConfirmationValue ?? '';
const overlayListButtons = Array.from(stage.querySelectorAll('[data-overlay-list-toggle]'));
const overlayList = stage.querySelector('.sg-delete-confirmation-pattern__list');
const createListForm = stage.querySelector('[data-create-list-form]');
const createListFormToggle = stage.querySelector('[data-create-list-form-toggle]');
const createListTitle = stage.querySelector('[data-create-list-title]');
const createListSegment = stage.querySelector('[data-create-list-form]');
const createListNameInput = stage.querySelector('[data-create-list-form] input[aria-label="Name"]');
const createListNameError = stage.querySelector('#create-list-name-error');
const createListDescriptionInput = stage.querySelector('[data-create-list-form] textarea[aria-label="Beschreibung"]');
const isAddToListOverlay = stage.dataset.pattern === 'add-to-list-overlay';
const committedListIds = new Set(
(stage.dataset.overlaySelectedLists ?? '')
.split(',')
.map((value) => value.trim())
.filter(Boolean)
);
let draftListIds = new Set(committedListIds);
let resetAddToListDraftState = () => {};
const closeStageDialogs = ({ resetAddToListDraft = false } = {}) => {
stage.querySelectorAll('[data-overlay-dialog]').forEach((dialog) => {
dialog.hidden = true;
});
if (isAddToListOverlay && resetAddToListDraft) {
resetAddToListDraftState();
}
stage.dataset.dialogOpen = 'false';
};
const syncOverlayListState = () => {
overlayListButtons.forEach((button) => {
const listId = button.dataset.overlayListId;
const isSelected = Boolean(listId && draftListIds.has(listId));
button.dataset.selected = String(isSelected);
button.setAttribute('aria-pressed', String(isSelected));
});
};
const bindOverlayListButton = (button) => {
button.addEventListener('click', (event) => {
event.preventDefault();
const listId = button.dataset.overlayListId;
if (!listId) {
return;
}
if (draftListIds.has(listId)) {
draftListIds.delete(listId);
} else {
draftListIds.add(listId);
}
syncOverlayListState();
});
};
const appendCreatedListButton = (title) => {
if (!overlayList) {
return null;
}
const listId = `created-${Date.now()}`;
const listItem = document.createElement('li');
listItem.className = 'sg-delete-confirmation-pattern__list-item';
const button = document.createElement('button');
button.type = 'button';
button.className = 'sg-interaction-element sg-button sg-delete-confirmation-pattern__list-button';
button.dataset.overlayListToggle = '';
button.dataset.overlayListId = listId;
button.dataset.selected = 'true';
button.setAttribute('aria-pressed', 'true');
const icon = document.createElement('span');
icon.className = 'sg-delete-confirmation-pattern__list-icon';
icon.setAttribute('aria-hidden', 'true');
const label = document.createElement('span');
label.className = 'sg-delete-confirmation-pattern__list-label';
label.textContent = title;
button.append(icon, label);
listItem.appendChild(button);
overlayList.appendChild(listItem);
overlayListButtons.push(button);
bindOverlayListButton(button);
return listId;
};
const setCreateListNameErrorState = (isInvalid) => {
if (!createListNameInput || !createListNameError) {
return;
}
createListNameInput.setAttribute('aria-invalid', String(isInvalid));
createListNameError.hidden = !isInvalid;
if (!isInvalid) {
createListNameInput.removeAttribute('aria-describedby');
} else {
createListNameInput.setAttribute('aria-describedby', 'create-list-name-error');
}
};
if (confirmationInput && confirmationSubmitButton) {
const updateConfirmationState = () => {
const isValid = confirmationInput.value === expectedConfirmationValue;
confirmationSubmitButton.disabled = !isValid;
confirmationSubmitButton.setAttribute('aria-disabled', String(!isValid));
confirmationSubmitButton.classList.toggle('sg-button--process-inactive', !isValid);
};
confirmationInput.addEventListener('input', updateConfirmationState);
updateConfirmationState();
}
if (overlayListButtons.length > 0) {
syncOverlayListState();
}
if (createListForm && createListFormToggle) {
resetAddToListDraftState = () => {
draftListIds = new Set(committedListIds);
syncOverlayListState();
setCreateListNameErrorState(false);
if (createListSegment) {
createListSegment.hidden = true;
}
if (createListFormToggle) {
createListFormToggle.disabled = false;
createListFormToggle.setAttribute('aria-disabled', 'false');
createListFormToggle.setAttribute('aria-expanded', 'false');
createListFormToggle.classList.remove('sg-button--inactive');
createListFormToggle.classList.add('sg-button--active');
}
if (createListNameInput) {
createListNameInput.value = '';
}
if (createListDescriptionInput) {
createListDescriptionInput.value = '';
}
};
createListFormToggle.addEventListener('click', (event) => {
event.preventDefault();
setCreateListNameErrorState(false);
if (createListSegment) {
createListSegment.hidden = false;
}
createListFormToggle.setAttribute('aria-expanded', 'true');
createListFormToggle.classList.remove('sg-button--active');
createListFormToggle.classList.add('sg-button--inactive');
createListFormToggle.disabled = true;
createListFormToggle.setAttribute('aria-disabled', 'true');
});
}
if (isAddToListOverlay) {
resetAddToListDraftState();
}
closeStageDialogs({ resetAddToListDraft: false });
stage.querySelectorAll('[data-overlay-open-dialog]').forEach((link) => {
link.addEventListener('click', (event) => {
event.preventDefault();
event.stopPropagation();
const target = link.getAttribute('data-overlay-open-dialog');
const dialog = stage.querySelector(`[data-overlay-dialog="${target}"]`);
if (!dialog) {
return;
}
closeStageDialogs({ resetAddToListDraft: target === 'add-to-list' });
dialog.hidden = false;
stage.dataset.dialogOpen = 'true';
const menuWrap = link.closest('.sg-sandwich-menu-wrap');
const menuButton = menuWrap?.querySelector('.sg-sandwich-button');
if (menuWrap) {
menuWrap.dataset.open = 'false';
}
if (menuButton) {
menuButton.setAttribute('aria-expanded', 'false');
}
});
});
stage.querySelectorAll('[data-overlay-dialog-close]').forEach((button) => {
button.addEventListener('click', (event) => {
event.preventDefault();
closeStageDialogs();
});
});
stage.querySelectorAll('[data-overlay-dialog-cancel]').forEach((button) => {
button.addEventListener('click', (event) => {
event.preventDefault();
closeStageDialogs({ resetAddToListDraft: true });
});
});
stage.querySelectorAll('[data-overlay-dialog-save]').forEach((button) => {
button.addEventListener('click', (event) => {
event.preventDefault();
if (isAddToListOverlay) {
const createdListTitle = createListNameInput?.value.trim() ?? '';
const existingListNames = new Set(
Array.from(stage.querySelectorAll('.sg-delete-confirmation-pattern__list-label'))
.map((label) => label.textContent?.trim().toLowerCase())
.filter(Boolean)
);
if (!createdListTitle) {
setCreateListNameErrorState(true);
return;
}
if (existingListNames.has(createdListTitle.toLowerCase())) {
setCreateListNameErrorState(true);
return;
}
setCreateListNameErrorState(false);
if (createdListTitle) {
const createdListId = appendCreatedListButton(createdListTitle);
if (createdListId) {
draftListIds.add(createdListId);
committedListIds.add(createdListId);
}
}
committedListIds.clear();
draftListIds.forEach((value) => committedListIds.add(value));
stage.dataset.overlaySelectedLists = Array.from(committedListIds).join(',');
}
closeStageDialogs({ resetAddToListDraft: true });
});
});
stage.querySelectorAll('.sg-sandwich-menu-wrap').forEach((wrap) => {
const button = wrap.querySelector('.sg-sandwich-button');
const panel = wrap.querySelector('.sg-sandwich-menu-panel');
if (!button) {
return;
}
if (button.hasAttribute('data-overlay-open-dialog')) {
return;
}
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');
}
});
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';
}
});
});
return closeStageDialogs;
};
const overlayStages = Array.from(document.querySelectorAll('.sg-delete-confirmation-pattern__stage'));
overlayStages.forEach((stage) => {
setupOverlayStage(stage);
});
document.addEventListener('click', (event) => {
if (event.target.closest('.sg-sandwich-menu-wrap')) {
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');
}
});
});
</script>
</body>
</html>