Sync styleguide 2026.05.18.1

This commit is contained in:
2026-06-10 13:28:58 +02:00
parent 94b761a1b7
commit baf8b97938
6 changed files with 381 additions and 5 deletions
+1
View File
@@ -40,6 +40,7 @@
<ul class="sg-index-list"> <ul class="sg-index-list">
<li><a href="./patterns/portal-header.html">Portal Header</a></li> <li><a href="./patterns/portal-header.html">Portal Header</a></li>
<li><a href="./patterns/vsf-portal-header-public.html">VSF Portal Header Public</a></li>
<li><a href="./patterns/options-row.html">Options Row</a></li> <li><a href="./patterns/options-row.html">Options Row</a></li>
<li><a href="./patterns/object-card.html">Object Card</a></li> <li><a href="./patterns/object-card.html">Object Card</a></li>
<li><a href="./patterns/object-group-card.html">Object Group Card</a></li> <li><a href="./patterns/object-group-card.html">Object Group Card</a></li>
@@ -0,0 +1,300 @@
<!doctype html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Styleguide Pattern VSF Portal Header Public</title>
<link rel="stylesheet" href="../styleguide.css">
</head>
<body>
<h1 class="sg-main-heading">Pattern VSF Portal Header Public</h1>
<section id="pattern-portal-header">
<p class="sg-preview-label">Pattern: VSF Portal Header Public</p>
<p class="sg-table-label sg-text-on-dark">
Desktop/Tablet: Header skaliert über die verfügbare Breite.
</p>
<p class="sg-table-label sg-text-on-dark">
Mobile: Sandwich-Menü und Portaltitel in der ersten Zeile; Navigationstasten in einer eigenen Zeile darunter.
</p>
<article class="sg-portal-header-pattern-variant" aria-label="Portal Header ohne Options Row">
<p class="sg-table-label sg-portal-header-pattern-variant__label sg-text-on-dark">
Variante: Portal Header ohne Options Row
</p>
<header class="sg-portal-header" aria-label="Portal Header" data-pattern="portal-header">
<div class="sg-portal-header__main" data-pattern-part="portal-header-main">
<p class="sg-portal-header__brand sg-brand-title" data-pattern-part="portal-header-brand">ValueStockFinder</p>
<div class="sg-portal-header__menu-wrap sg-sandwich-menu-wrap" data-open="false" data-component="sandwich-menu" data-component-size="default" data-component-context="portal-header" data-pattern-part="portal-header-action">
<button class="sg-interaction-element sg-sandwich-button" 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-component-part="sandwich-menu-link">Admin</a>
<a class="sg-sandwich-menu-link" href="#" data-component-part="sandwich-menu-link">Logout</a>
</div>
</div>
<nav class="sg-portal-header__tabs sg-tab-button-group" aria-label="Hauptnavigation" data-component="tab-navigation" data-component-size="large" data-component-context="portal-header" data-pattern-part="portal-header-navigation">
<button class="sg-interaction-element sg-button sg-tab-button" type="button" aria-selected="false" data-component-part="tab-button" data-component-state="inactive">Updates</button>
<button class="sg-interaction-element sg-button sg-tab-button" type="button" aria-selected="true" data-component-part="tab-button" data-component-state="active">Titel</button>
<button class="sg-interaction-element sg-button sg-tab-button" type="button" aria-selected="false" data-component-part="tab-button" data-component-state="inactive">Gruppen</button>
<button class="sg-interaction-element sg-button sg-tab-button" type="button" aria-selected="false" data-component-part="tab-button" data-component-state="inactive">Listen</button>
</nav>
</div>
</header>
<p class="sg-table-label sg-portal-header-pattern-variant__next-element sg-text-on-dark">
Nächstes Element (Abstand nach unten: spacing-large)
</p>
</article>
</section>
<script src="../scripts/help-icon-overlays.js"></script>
<script>
document.querySelectorAll('.sg-portal-header__tabs').forEach((group) => {
group.querySelectorAll('.sg-tab-button').forEach((button) => {
button.addEventListener('click', () => {
group.querySelectorAll('.sg-tab-button').forEach((otherButton) => {
const isActive = otherButton === button;
otherButton.setAttribute('aria-selected', String(isActive));
otherButton.dataset.componentState = isActive ? 'active' : 'inactive';
});
});
});
});
document.querySelectorAll('.sg-sandwich-menu-wrap').forEach((wrap) => {
const button = wrap.querySelector('.sg-sandwich-button');
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));
});
});
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`
);
});
});
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', '.sg-sandwich-menu-wrap'],
outsideClickIgnoreSelectors: ['.sg-pulldown-demo', '.sg-sandwich-menu-wrap'],
});
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');
if (!input || !clearButton) {
return;
}
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();
});
document.addEventListener('click', (event) => {
if (!event.target.closest('.sg-sandwich-menu-wrap')) {
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');
}
});
}
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');
}
});
});
</script>
</body>
</html>
@@ -519,6 +519,29 @@
max-width: 100%; max-width: 100%;
} }
#component-pulldown .sg-labeled-input-row {
flex-direction: column;
align-items: flex-start;
gap: var(--spacing-small);
width: 100%;
max-width: 100%;
}
#component-pulldown .sg-labeled-input-row .sg-label {
min-width: 0;
flex: 0 0 auto;
margin-right: 0;
margin-bottom: 0;
line-height: 1;
}
#component-pulldown .sg-labeled-input-row .sg-pulldown-demo,
#component-pulldown .sg-labeled-input-row .sg-pulldown {
width: 100%;
min-width: 0;
max-width: 100%;
}
#component-pulldown .sg-activatable-row { #component-pulldown .sg-activatable-row {
grid-template-columns: 1fr; grid-template-columns: 1fr;
align-items: start; align-items: start;
@@ -530,6 +553,7 @@
.sg-labeled-input-row { .sg-labeled-input-row {
flex-direction: column; flex-direction: column;
align-items: flex-start; align-items: flex-start;
gap: var(--spacing-small);
width: 100%; width: 100%;
max-width: 100%; max-width: 100%;
} }
@@ -538,7 +562,8 @@
min-width: 0; min-width: 0;
flex: 0 0 auto; flex: 0 0 auto;
margin-right: 0; margin-right: 0;
margin-bottom: var(--spacing-large); margin-bottom: 0;
line-height: 1;
} }
.sg-labeled-input-row .sg-input-single-line, .sg-labeled-input-row .sg-input-single-line,
+26 -1
View File
@@ -1000,6 +1000,29 @@ section + section {
max-width: 100%; max-width: 100%;
} }
#component-pulldown .sg-labeled-input-row {
flex-direction: column;
align-items: flex-start;
gap: var(--spacing-small);
width: 100%;
max-width: 100%;
}
#component-pulldown .sg-labeled-input-row .sg-label {
min-width: 0;
flex: 0 0 auto;
margin-right: 0;
margin-bottom: 0;
line-height: 1;
}
#component-pulldown .sg-labeled-input-row .sg-pulldown-demo,
#component-pulldown .sg-labeled-input-row .sg-pulldown {
width: 100%;
min-width: 0;
max-width: 100%;
}
#component-pulldown .sg-activatable-row { #component-pulldown .sg-activatable-row {
grid-template-columns: 1fr; grid-template-columns: 1fr;
align-items: start; align-items: start;
@@ -1011,6 +1034,7 @@ section + section {
.sg-labeled-input-row { .sg-labeled-input-row {
flex-direction: column; flex-direction: column;
align-items: flex-start; align-items: flex-start;
gap: var(--spacing-small);
width: 100%; width: 100%;
max-width: 100%; max-width: 100%;
} }
@@ -1019,7 +1043,8 @@ section + section {
min-width: 0; min-width: 0;
flex: 0 0 auto; flex: 0 0 auto;
margin-right: 0; margin-right: 0;
margin-bottom: var(--spacing-large); margin-bottom: 0;
line-height: 1;
} }
.sg-labeled-input-row .sg-input-single-line, .sg-labeled-input-row .sg-input-single-line,
+2 -2
View File
@@ -1,7 +1,7 @@
{ {
"styleguideVersion": "2026.05.18.1", "styleguideVersion": "2026.05.18.1",
"styleguideCommit": "4a3c939", "styleguideCommit": "cc9103b",
"syncedAtUtc": "2026-06-09T08:51:49Z", "syncedAtUtc": "2026-06-10T11:28:58Z",
"sourceRepo": "/Users/mathias/Documents/Dokumente Chouchou/Codebases/Styleguide", "sourceRepo": "/Users/mathias/Documents/Dokumente Chouchou/Codebases/Styleguide",
"mirroredDocsPath": "docs/styleguide" "mirroredDocsPath": "docs/styleguide"
} }
+26 -1
View File
@@ -1000,6 +1000,29 @@ section + section {
max-width: 100%; max-width: 100%;
} }
#component-pulldown .sg-labeled-input-row {
flex-direction: column;
align-items: flex-start;
gap: var(--spacing-small);
width: 100%;
max-width: 100%;
}
#component-pulldown .sg-labeled-input-row .sg-label {
min-width: 0;
flex: 0 0 auto;
margin-right: 0;
margin-bottom: 0;
line-height: 1;
}
#component-pulldown .sg-labeled-input-row .sg-pulldown-demo,
#component-pulldown .sg-labeled-input-row .sg-pulldown {
width: 100%;
min-width: 0;
max-width: 100%;
}
#component-pulldown .sg-activatable-row { #component-pulldown .sg-activatable-row {
grid-template-columns: 1fr; grid-template-columns: 1fr;
align-items: start; align-items: start;
@@ -1011,6 +1034,7 @@ section + section {
.sg-labeled-input-row { .sg-labeled-input-row {
flex-direction: column; flex-direction: column;
align-items: flex-start; align-items: flex-start;
gap: var(--spacing-small);
width: 100%; width: 100%;
max-width: 100%; max-width: 100%;
} }
@@ -1019,7 +1043,8 @@ section + section {
min-width: 0; min-width: 0;
flex: 0 0 auto; flex: 0 0 auto;
margin-right: 0; margin-right: 0;
margin-bottom: var(--spacing-large); margin-bottom: 0;
line-height: 1;
} }
.sg-labeled-input-row .sg-input-single-line, .sg-labeled-input-row .sg-input-single-line,