383 lines
21 KiB
HTML
383 lines
21 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 – Layout VSF List Card</title>
|
||
<link rel="stylesheet" href="../styleguide.css">
|
||
</head>
|
||
<body>
|
||
|
||
<h1 class="sg-main-heading">Layout – VSF List Card</h1>
|
||
|
||
<section id="layout-vsf-list-card">
|
||
<p class="sg-preview-label">Layout: VSF List Card</p>
|
||
<p class="sg-body">Diese Layout-Seite zeigt VSF-spezifische List-Card-Layouts als Grundlage fuer weitere Ausdifferenzierungen.</p>
|
||
|
||
<h2 class="sg-sub-heading sg-section-h2">Layout 1: Neue Liste anlegen Karte</h2>
|
||
<div class="sg-object-card-grid" aria-label="VSF List Card Layout Neue Liste anlegen">
|
||
<article class="sg-card sg-object-card" data-pattern="object-group-card" aria-label="Neue Liste anlegen Karte">
|
||
<header class="sg-card-segment sg-card-segment--header sg-card-segment--darkblue sg-object-card__header" data-pattern-part="object-group-card-header">
|
||
<div class="sg-strong">Neue Liste anlegen</div>
|
||
</header>
|
||
<div class="sg-card-segment sg-card-segment--gray sg-object-card__content" data-pattern-part="object-group-card-content">
|
||
<div class="sg-form-sections-card-wrapper" data-pattern="form-sections" 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">Listentyp</span>
|
||
<div class="sg-pulldown-demo" data-open="false" data-align="left" data-selection-mode="single" data-component="pulldown" data-component-context="form" data-component-state="inactive-selectable">
|
||
<button class="sg-interaction-element sg-pulldown sg-pulldown--inactive-selectable sg-form-inactive-selectable sg-pulldown-demo__trigger" type="button" aria-expanded="false" aria-label="Pulldown ohne aktive Auswahl" data-component-part="pulldown-trigger" data-label-base="Listentyp">
|
||
Listentyp
|
||
</button>
|
||
<div class="sg-pulldown-panel" aria-label="Geoeffnetes Pulldown Listentyp" data-component-part="pulldown-panel">
|
||
<ul class="sg-pulldown-option-list" aria-label="Listentyp Optionen">
|
||
<li class="sg-pulldown-option" role="checkbox" aria-checked="false" data-pulldown-option><span>Watchlist</span></li>
|
||
<li class="sg-pulldown-option" role="checkbox" aria-checked="false" data-pulldown-option><span>Portfolio</span></li>
|
||
<li class="sg-pulldown-option" role="checkbox" aria-checked="false" data-pulldown-option><span>Screening</span></li>
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
</label>
|
||
|
||
<label class="sg-labeled-input-row">
|
||
<span class="sg-label">Name</span>
|
||
<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"
|
||
>
|
||
</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>
|
||
|
||
<footer class="sg-form-sections-card__actions-segment" data-pattern-part="form-actions-segment">
|
||
<div class="sg-form-sections-card__actions" data-pattern-part="form-actions">
|
||
<button class="sg-interaction-element sg-button sg-button--active sg-form-sections-card__action" type="button">Zuruecksetzen</button>
|
||
<button class="sg-interaction-element sg-button sg-button--process sg-button--process-inactive sg-form-sections-card__action" type="submit" disabled aria-disabled="true">Liste anlegen</button>
|
||
</div>
|
||
</footer>
|
||
</form>
|
||
</div>
|
||
</div>
|
||
</article>
|
||
</div>
|
||
|
||
<h2 class="sg-sub-heading sg-section-h2">Layout 2: Maximale Listenzahl erreicht</h2>
|
||
<div class="sg-object-card-grid" aria-label="VSF List Card Layout maximale Listenzahl erreicht">
|
||
<article class="sg-card sg-object-card" data-pattern="object-group-card" aria-label="Maximale Listenzahl erreicht Karte">
|
||
<header class="sg-card-segment sg-card-segment--header sg-card-segment--darkblue sg-object-card__header" data-pattern-part="object-group-card-header">
|
||
<div class="sg-strong">Neue Liste anlegen</div>
|
||
</header>
|
||
<div class="sg-card-segment sg-card-segment--gray sg-object-card__content" data-pattern-part="object-group-card-content">
|
||
<div class="sg-form-sections-card-wrapper" data-pattern="form-sections" aria-label="Formular mit Abschnitten">
|
||
<form class="sg-form-sections-card" action="#" method="post" aria-label="Neue Liste anlegen Formular deaktiviert">
|
||
<p class="sg-vsf-list-card-limit-note">Maximale Listenanzahl erreicht. Du musst eine Liste loeschen oder dein Abonnement upgraden, um mehr Listen anzulegen.</p>
|
||
<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">Listentyp</span>
|
||
<div class="sg-pulldown-demo" data-open="false" data-align="left" data-selection-mode="single" data-component="pulldown" data-component-context="form" data-component-state="inactive-selectable">
|
||
<button class="sg-interaction-element sg-pulldown sg-pulldown--disabled sg-form-disabled sg-pulldown-demo__trigger" type="button" aria-expanded="false" aria-label="Pulldown ohne aktive Auswahl" data-component-part="pulldown-trigger" data-label-base="Listentyp" disabled aria-disabled="true">
|
||
Listentyp
|
||
</button>
|
||
<div class="sg-pulldown-panel" aria-label="Geoeffnetes Pulldown Listentyp" data-component-part="pulldown-panel">
|
||
<ul class="sg-pulldown-option-list" aria-label="Listentyp Optionen">
|
||
<li class="sg-pulldown-option" role="checkbox" aria-checked="false" data-pulldown-option><span>Watchlist</span></li>
|
||
<li class="sg-pulldown-option" role="checkbox" aria-checked="false" data-pulldown-option><span>Portfolio</span></li>
|
||
<li class="sg-pulldown-option" role="checkbox" aria-checked="false" data-pulldown-option><span>Screening</span></li>
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
</label>
|
||
|
||
<label class="sg-labeled-input-row">
|
||
<span class="sg-label">Name</span>
|
||
<input
|
||
class="sg-interaction-element sg-input-single-line sg-input-single-line--disabled sg-form-disabled"
|
||
type="text"
|
||
placeholder="Name eingeben"
|
||
aria-label="Name"
|
||
maxlength="80"
|
||
disabled
|
||
>
|
||
</label>
|
||
|
||
<label class="sg-labeled-input-row">
|
||
<span class="sg-label">Beschreibung</span>
|
||
<textarea
|
||
class="sg-input-multi-line sg-form-disabled"
|
||
rows="4"
|
||
placeholder="Beschreibung eingeben"
|
||
aria-label="Beschreibung"
|
||
maxlength="350"
|
||
disabled
|
||
></textarea>
|
||
</label>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
|
||
<footer class="sg-form-sections-card__actions-segment" data-pattern-part="form-actions-segment">
|
||
<div class="sg-form-sections-card__actions" data-pattern-part="form-actions">
|
||
<button class="sg-interaction-element sg-button sg-button--inactive sg-button--disabled sg-form-sections-card__action" type="button" disabled aria-disabled="true">Zuruecksetzen</button>
|
||
<button class="sg-interaction-element sg-button sg-button--process sg-button--process-inactive sg-button--disabled sg-form-sections-card__action" type="submit" disabled aria-disabled="true">Liste anlegen</button>
|
||
</div>
|
||
</footer>
|
||
</form>
|
||
</div>
|
||
</div>
|
||
</article>
|
||
</div>
|
||
|
||
<h2 class="sg-sub-heading sg-section-h2">Layout 3: List Card</h2>
|
||
<div class="sg-object-card-grid" aria-label="VSF List Card Layout List Card">
|
||
<article class="sg-card sg-object-card" data-pattern="object-group-card" aria-label="List Card">
|
||
<header class="sg-card-segment sg-card-segment--header sg-card-segment--darkblue sg-object-card__header" data-pattern-part="object-group-card-header">
|
||
<div class="sg-strong">NAME DER LISTE</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="#">Editieren</a>
|
||
<a class="sg-sandwich-menu-link" href="#">Liste loeschen</a>
|
||
</div>
|
||
</div>
|
||
</header>
|
||
<div class="sg-card-segment sg-card-segment--body sg-card-segment--gray" data-pattern-part="list-card-placeholder-top">
|
||
<div class="sg-score-bar-list sg-score-bar-list--single-score" aria-label="Gesamtscore-Balken" data-component="score-bar-list">
|
||
<div class="sg-score-bar-item" data-component="score-bar">
|
||
<p class="sg-score-bar-label sg-bar-label" data-component-part="score-label">Medianscore:</p>
|
||
<div class="sg-score-bar sg-score-bar--marker-mid" role="img" aria-label="Gesamtscore 96 Prozent mit Median-Marker bei 50 Prozent" data-component-part="score-track">
|
||
<div class="sg-score-bar__value sg-score-bar__value--positive sg-score-bar__value--w96" data-component-part="score-value" data-component-state="positive"></div>
|
||
</div>
|
||
<p class="sg-bar-label sg-score-state--positive" data-component-part="score-state">attraktiv</p>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="sg-card-segment sg-card-segment--body sg-card-segment--gray" data-pattern-part="list-card-placeholder-bottom">
|
||
<div class="sg-text-layout-pattern__sample sg-text-layout-pattern__three-column-distributed" aria-label="Company Kennzahlen dreispaltig verteilt" data-pattern-part="company-card-metrics-three-column">
|
||
<p class="sg-body sg-text-layout-pattern__column sg-text-layout-pattern__column--align-left">
|
||
PE: <span class="sg-data-table__value">28.8</span>
|
||
</p>
|
||
<p class="sg-body sg-text-layout-pattern__column sg-text-layout-pattern__column--align-center">
|
||
PE forw.: <span class="sg-data-table__value sg-company-card__metric-negative" data-component-state="negative">23.3</span>
|
||
</p>
|
||
<p class="sg-body sg-text-layout-pattern__column sg-text-layout-pattern__column--align-right">
|
||
PEG: <span class="sg-data-table__value sg-company-card__metric-negative" data-component-state="negative">3.54</span>
|
||
</p>
|
||
</div>
|
||
</div>
|
||
<div class="sg-card-segment sg-card-segment--body sg-card-segment--white sg-vsf-list-card__content-grow" data-pattern-part="company-card-content">
|
||
<p class="sg-table-label sg-company-card__analysis-title">Median-Subscores:</p>
|
||
<div class="sg-score-bar-list sg-company-card__analysis-bars" aria-label="Fundamentalanalyse Score-Balken" data-component="score-bar-list">
|
||
<div class="sg-score-bar-item" data-component="score-bar">
|
||
<p class="sg-score-bar-label sg-bar-label" data-component-part="score-label">Marktbewertung:</p>
|
||
<div class="sg-score-bar sg-score-bar--marker-mid" data-component-part="score-track">
|
||
<div class="sg-score-bar__value sg-score-bar__value--positive sg-score-bar__value--w96" data-component-part="score-value" data-component-state="positive"></div>
|
||
</div>
|
||
</div>
|
||
<div class="sg-score-bar-item" data-component="score-bar">
|
||
<p class="sg-score-bar-label sg-bar-label" data-component-part="score-label">Wachstum:</p>
|
||
<div class="sg-score-bar sg-score-bar--marker-mid" data-component-part="score-track">
|
||
<div class="sg-score-bar__value sg-score-bar__value--neutral sg-score-bar__value--w64" data-component-part="score-value" data-component-state="neutral"></div>
|
||
</div>
|
||
</div>
|
||
<div class="sg-score-bar-item" data-component="score-bar">
|
||
<p class="sg-score-bar-label sg-bar-label" data-component-part="score-label">Profitabilität:</p>
|
||
<div class="sg-score-bar sg-score-bar--marker-mid" data-component-part="score-track">
|
||
<div class="sg-score-bar__value sg-score-bar__value--negative sg-score-bar__value--w35" data-component-part="score-value" data-component-state="negative"></div>
|
||
</div>
|
||
</div>
|
||
<div class="sg-score-bar-item" data-component="score-bar">
|
||
<p class="sg-score-bar-label sg-bar-label" data-component-part="score-label">Stabilität:</p>
|
||
<div class="sg-score-bar sg-score-bar--marker-mid" data-component-part="score-track">
|
||
<div class="sg-score-bar__value sg-score-bar__value--neutral sg-score-bar__value--w64" data-component-part="score-value" data-component-state="neutral"></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<p class="sg-body sg-company-card__summary sg-vsf-list-card__summary">BESCHREIBUNG LISTE</p>
|
||
</div>
|
||
<footer class="sg-card-segment sg-card-segment--body sg-card-segment--white" data-pattern-part="list-card-actions">
|
||
<div class="sg-object-card__actions">
|
||
<button class="sg-interaction-element sg-button sg-button--active sg-object-card__action" type="button">Unternehmen ansehen</button>
|
||
</div>
|
||
</footer>
|
||
</article>
|
||
</div>
|
||
</section>
|
||
|
||
<script>
|
||
const formCard = document.querySelector('#layout-vsf-list-card .sg-object-card-grid:first-of-type .sg-form-sections-card');
|
||
const processButton = formCard?.querySelector('.sg-button--process');
|
||
|
||
const updateProcessButtonState = () => {
|
||
if (!formCard || !processButton) {
|
||
return;
|
||
}
|
||
|
||
const hasPulldownSelection = Array.from(formCard.querySelectorAll('[data-pulldown-option]'))
|
||
.some((option) => option.getAttribute('aria-checked') === 'true');
|
||
const hasTextInput = Array.from(formCard.querySelectorAll('input[type="text"], textarea'))
|
||
.some((field) => field.value.trim().length > 0);
|
||
const isActive = hasPulldownSelection || hasTextInput;
|
||
|
||
processButton.disabled = !isActive;
|
||
processButton.setAttribute('aria-disabled', String(!isActive));
|
||
processButton.classList.toggle('sg-button--process-inactive', !isActive);
|
||
};
|
||
|
||
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;
|
||
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';
|
||
updateProcessButtonState();
|
||
};
|
||
|
||
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.open = String(nextState);
|
||
trigger.setAttribute('aria-expanded', String(nextState));
|
||
});
|
||
});
|
||
|
||
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) {
|
||
return;
|
||
}
|
||
|
||
pulldownDemo.querySelectorAll('[data-pulldown-option]').forEach((otherOption) => {
|
||
otherOption.setAttribute('aria-checked', String(otherOption === option));
|
||
});
|
||
|
||
updatePulldownSelectionState(pulldownDemo);
|
||
const trigger = pulldownDemo.querySelector('.sg-pulldown-demo__trigger');
|
||
pulldownDemo.dataset.open = 'false';
|
||
if (trigger) {
|
||
trigger.setAttribute('aria-expanded', 'false');
|
||
}
|
||
});
|
||
});
|
||
|
||
document.querySelectorAll('.sg-pulldown-demo').forEach(updatePulldownSelectionState);
|
||
formCard?.querySelectorAll('input[type="text"], textarea').forEach((field) => {
|
||
field.addEventListener('input', updateProcessButtonState);
|
||
});
|
||
updateProcessButtonState();
|
||
|
||
document.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;
|
||
}
|
||
|
||
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';
|
||
}
|
||
});
|
||
});
|
||
|
||
document.addEventListener('click', (event) => {
|
||
if (event.target.closest('.sg-pulldown-demo') || event.target.closest('.sg-sandwich-menu-wrap')) {
|
||
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-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>
|