Sync styleguide 2026.05.18.1

This commit is contained in:
gitea_admin committed 2026-09-08 11:28:53 +02:00
1 parent 9d55a6d213
commit e47990dfe0
10 files changed
+514 -2

No files matched your search

@@ -847,7 +847,28 @@
</section>
<script src="../scripts/help-icon-overlays.js"></script>
<section id="component-file-input">
<p class="sg-preview-label">Component: File Input</p>
<div class="sg-form-preview-area">
<div class="sg-file-input" data-component="file-input">
<div class="sg-file-input__row sg-labeled-input-row">
<label class="sg-label" for="component-file-input-control">Datei auswählen</label>
<input class="sg-file-input__control" id="component-file-input-control" type="file" multiple>
<button class="sg-interaction-element sg-button sg-button--active sg-file-input__trigger" type="button">Dateien auswählen</button>
</div>
</div>
</div>
</section>
<script>
document.querySelectorAll('[data-component="file-input"]').forEach((fileInput) => {
const input = fileInput.querySelector('.sg-file-input__control');
const trigger = fileInput.querySelector('.sg-file-input__trigger');
if (input && trigger) {
trigger.addEventListener('click', () => input.click());
}
});
document.querySelectorAll('.sg-mode-toggle:not(.sg-activation-mode-toggle)').forEach((toggle) => {
toggle.addEventListener('click', () => {
const nextState = toggle.dataset.active === 'relative' ? 'absolute' : 'relative';
+1
View File
@@ -51,6 +51,7 @@
<li><a href="./patterns/content-cards-group.html">Content Cards Group</a></li>
<li><a href="./patterns/card-gruppe-mit-tastennavigation.html">Card Gruppe mit Tastennavigation</a></li>
<li><a href="./patterns/formular-mit-abschnitten.html">Formular mit Abschnitten</a></li>
<li><a href="./patterns/file-upload.html">Datei-Upload</a></li>
<li><a href="./patterns/multiselektions-pulldown.html">Multiselektions-Pulldown</a></li>
<li><a href="./patterns/text-layouts.html">Text Layouts</a></li>
<li><a href="./patterns/delete-confirmation-overlay.html">Overlay Card</a></li>
+71
View File
@@ -0,0 +1,71 @@
<!doctype html>
<html lang="de">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Styleguide – Pattern Datei-Upload</title>
<link rel="stylesheet" href="../styleguide.css">
</head>
<body>
<h1 class="sg-main-heading">Pattern – Datei-Upload</h1>
<section id="pattern-file-upload">
<p class="sg-preview-label">Pattern: Datei-Upload</p>
<form class="sg-file-upload" data-pattern="file-upload" action="#" method="post">
<div class="sg-file-upload__dropzone sg-labeled-input-row" data-drag-over="false">
<label class="sg-label" for="file-upload-input">Datei auswählen</label>
<input class="sg-file-input__control" id="file-upload-input" name="documents" type="file" multiple aria-describedby="file-upload-status">
<button class="sg-interaction-element sg-button sg-button--active sg-file-upload__trigger" type="button">Dateien auswählen</button>
</div>
<p class="sg-body sg-file-upload__status" id="file-upload-status" aria-live="polite">Noch keine Dateien ausgewählt.</p>
<ul class="sg-file-upload__files" aria-label="Ausgewählte Dateien"></ul>
<button class="sg-interaction-element sg-button sg-button--process sg-button--process-inactive" type="submit" disabled aria-disabled="true">Hochladen</button>
</form>
</section>
<script>
(() => {
const upload = document.querySelector('[data-pattern="file-upload"]');
if (!upload) return;
const input = upload.querySelector('#file-upload-input');
const dropzone = upload.querySelector('.sg-file-upload__dropzone');
const trigger = upload.querySelector('.sg-file-upload__trigger');
const filesList = upload.querySelector('.sg-file-upload__files');
const status = upload.querySelector('.sg-file-upload__status');
const submit = upload.querySelector('[type="submit"]');
let selectedFiles = [];
const formatSize = (bytes) => bytes < 1024 * 1024 ? `${Math.max(1, Math.round(bytes / 1024))} KB` : `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
const render = () => {
filesList.innerHTML = '';
selectedFiles.forEach((file, index) => {
const item = document.createElement('li');
item.className = 'sg-file-upload__file';
const name = document.createElement('span');
name.className = 'sg-file-upload__file-name';
name.textContent = file.name;
const meta = document.createElement('span');
meta.className = 'sg-file-upload__file-meta';
meta.textContent = ` · ${formatSize(file.size)}`;
name.append(meta);
const remove = document.createElement('button');
remove.className = 'sg-interaction-element sg-button sg-button--active sg-file-upload__remove';
remove.type = 'button';
remove.textContent = 'Entfernen';
remove.addEventListener('click', () => { selectedFiles.splice(index, 1); render(); });
item.append(name, remove);
filesList.append(item);
});
const count = selectedFiles.length;
status.textContent = count === 0 ? 'Noch keine Dateien ausgewählt.' : `${count} Datei${count === 1 ? '' : 'en'} ausgewählt.`;
submit.disabled = count === 0;
submit.setAttribute('aria-disabled', String(count === 0));
submit.classList.toggle('sg-button--process-inactive', count === 0);
};
trigger.addEventListener('click', () => input.click());
input.addEventListener('change', () => { selectedFiles = [...selectedFiles, ...Array.from(input.files)]; input.value = ''; render(); });
['dragenter', 'dragover'].forEach((eventName) => dropzone.addEventListener(eventName, (event) => { event.preventDefault(); dropzone.dataset.dragOver = 'true'; }));
['dragleave', 'drop'].forEach((eventName) => dropzone.addEventListener(eventName, (event) => { event.preventDefault(); dropzone.dataset.dragOver = 'false'; }));
dropzone.addEventListener('drop', (event) => { selectedFiles = [...selectedFiles, ...Array.from(event.dataTransfer.files)]; render(); });
render();
})();
</script>
</body>
</html>
@@ -148,6 +148,14 @@
<tr><td>layout-delete-confirmation-target-dim-opacity</td><td>opacity-delete-confirmation-target-dim</td><td>Deckkraft der grauen Überlagerung auf dem zu löschenden Objekt.</td></tr>
<tr><td>layer-delete-confirmation-overlay</td><td>dimension-layer-delete-confirmation-overlay</td><td>Z-Index-Layer des schwebenden Bestätigungsfensters.</td></tr>
</tbody></table>
<h3 class="sg-sub-heading sg-section-h3">Datei-Upload</h3>
<table class="sg-foundation-table sg-table-label"><thead><tr><th>Semantischer Token</th><th>Verwendeter Foundation-Token</th><th>Beschreibung Verwendungszweck im Pattern</th></tr></thead><tbody>
<tr><td>surface-file-upload-dropzone</td><td>surface-form-preview</td><td>Hintergrundfläche des auswählbaren Upload-Bereichs.</td></tr>
<tr><td>surface-file-upload-file-item</td><td>surface-control-default</td><td>Hintergrundfläche eines Eintrags in der Dateiliste.</td></tr>
<tr><td>text-file-upload-meta</td><td>text-control-disabled</td><td>Textfarbe für Dateigröße und ergänzende Dateimetadaten.</td></tr>
<tr><td>text-file-upload-error</td><td>color-signal-red</td><td>Textfarbe für Validierungs- und Upload-Fehlermeldungen.</td></tr>
</tbody></table>
</section>
</body>
+1
View File
@@ -2,6 +2,7 @@
@import "./styles/02-base.css";
@import "./styles/03-typography-helpers.css";
@import "./styles/10-components-interactive-elements.css";
@import "./styles/47-patterns-file-upload.css";
@import "./styles/20-patterns-portal-header.css";
@import "./styles/21-patterns-options-row.css";
@import "./styles/22-patterns-object-card.css";
@@ -1585,3 +1585,52 @@
color: var(--text-hyperlink);
text-decoration: none;
}
/* Component: File Input */
.sg-file-input {
width: 100%;
}
.sg-file-input__row {
display: flex;
align-items: center;
justify-content: space-between;
gap: var(--spacing-large);
width: 100%;
}
.sg-file-input__control {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border: 0;
}
.sg-file-input:focus-within .sg-file-input__trigger {
outline: 2px solid var(--text-hyperlink);
outline-offset: 2px;
}
.sg-file-input__trigger {
align-self: flex-start;
}
@media (max-width: 48rem) {
.sg-file-input__row {
align-items: flex-start;
flex-direction: column;
}
}
.sg-file-input--disabled {
opacity: var(--disabled-opacity);
}
.sg-file-input--disabled .sg-file-input__trigger {
cursor: not-allowed;
}
@@ -0,0 +1,87 @@
/* ========================================================= */
/* Patterns: Datei-Upload */
/* ========================================================= */
.sg-file-upload {
--surface-file-upload-dropzone: var(--surface-form-preview);
--surface-file-upload-file-item: var(--surface-control-default);
--text-file-upload-meta: var(--text-control-disabled);
--text-file-upload-error: var(--color-signal-red);
display: flex;
flex-direction: column;
gap: var(--spacing-large);
width: 100%;
max-width: var(--layout-input-field-max-width);
}
.sg-file-upload__status,
.sg-file-upload__file-meta {
margin: var(--spacing-small) 0 0;
}
.sg-file-upload__dropzone {
display: flex;
align-items: center;
justify-content: space-between;
gap: var(--spacing-large);
width: 100%;
padding: var(--spacing-large);
background: var(--surface-file-upload-dropzone);
border: 1px dashed var(--surface-button-active);
border-radius: var(--radius-interaction);
}
.sg-file-upload__dropzone[data-drag-over="true"] {
outline: 2px solid var(--text-hyperlink);
outline-offset: 2px;
}
.sg-file-upload__files {
display: flex;
flex-direction: column;
gap: var(--spacing-small);
margin: 0;
padding: 0;
list-style: none;
}
.sg-file-upload__file {
display: flex;
align-items: center;
justify-content: space-between;
gap: var(--spacing-large);
padding: var(--spacing-small) var(--spacing-large);
color: var(--text-control-default);
background: var(--surface-file-upload-file-item);
border-radius: var(--radius-interaction);
}
.sg-file-upload__file-name {
min-width: 0;
overflow-wrap: anywhere;
}
.sg-file-upload__file-meta {
color: var(--text-file-upload-meta);
}
.sg-file-upload__remove {
flex: 0 0 auto;
}
.sg-file-upload__error {
color: var(--text-file-upload-error);
}
@media (max-width: 48rem) {
.sg-file-upload__dropzone {
align-items: flex-start;
flex-direction: column;
}
.sg-file-upload__file {
align-items: flex-start;
flex-direction: column;
gap: var(--spacing-small);
}
}
+137
View File
@@ -2107,6 +2107,143 @@ section + section {
text-decoration: none;
}
/* Component: File Input */
.sg-file-input {
width: 100%;
}
.sg-file-input__row {
display: flex;
align-items: center;
justify-content: space-between;
gap: var(--spacing-large);
width: 100%;
}
.sg-file-input__control {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border: 0;
}
.sg-file-input:focus-within .sg-file-input__trigger {
outline: 2px solid var(--text-hyperlink);
outline-offset: 2px;
}
.sg-file-input__trigger {
align-self: flex-start;
}
@media (max-width: 48rem) {
.sg-file-input__row {
align-items: flex-start;
flex-direction: column;
}
}
.sg-file-input--disabled {
opacity: var(--disabled-opacity);
}
.sg-file-input--disabled .sg-file-input__trigger {
cursor: not-allowed;
}
/* ========================================================= */
/* Patterns: Datei-Upload */
/* ========================================================= */
.sg-file-upload {
--surface-file-upload-dropzone: var(--surface-form-preview);
--surface-file-upload-file-item: var(--surface-control-default);
--text-file-upload-meta: var(--text-control-disabled);
--text-file-upload-error: var(--color-signal-red);
display: flex;
flex-direction: column;
gap: var(--spacing-large);
width: 100%;
max-width: var(--layout-input-field-max-width);
}
.sg-file-upload__status,
.sg-file-upload__file-meta {
margin: var(--spacing-small) 0 0;
}
.sg-file-upload__dropzone {
display: flex;
align-items: center;
justify-content: space-between;
gap: var(--spacing-large);
width: 100%;
padding: var(--spacing-large);
background: var(--surface-file-upload-dropzone);
border: 1px dashed var(--surface-button-active);
border-radius: var(--radius-interaction);
}
.sg-file-upload__dropzone[data-drag-over="true"] {
outline: 2px solid var(--text-hyperlink);
outline-offset: 2px;
}
.sg-file-upload__files {
display: flex;
flex-direction: column;
gap: var(--spacing-small);
margin: 0;
padding: 0;
list-style: none;
}
.sg-file-upload__file {
display: flex;
align-items: center;
justify-content: space-between;
gap: var(--spacing-large);
padding: var(--spacing-small) var(--spacing-large);
color: var(--text-control-default);
background: var(--surface-file-upload-file-item);
border-radius: var(--radius-interaction);
}
.sg-file-upload__file-name {
min-width: 0;
overflow-wrap: anywhere;
}
.sg-file-upload__file-meta {
color: var(--text-file-upload-meta);
}
.sg-file-upload__remove {
flex: 0 0 auto;
}
.sg-file-upload__error {
color: var(--text-file-upload-error);
}
@media (max-width: 48rem) {
.sg-file-upload__dropzone {
align-items: flex-start;
flex-direction: column;
}
.sg-file-upload__file {
align-items: flex-start;
flex-direction: column;
gap: var(--spacing-small);
}
}
/* ========================================================= */
/* Patterns: Portal Header */
/* ========================================================= */
+2 -2
View File
@@ -1,7 +1,7 @@
{
"styleguideVersion": "2026.05.18.1",
"styleguideCommit": "7b733e5",
"syncedAtUtc": "2026-09-08T07:53:24Z",
"styleguideCommit": "5b2c75d",
"syncedAtUtc": "2026-09-08T09:28:53Z",
"sourceRepo": "/Users/mathias/Documents/Dokumente Chouchou/Codebases/Styleguide",
"mirroredDocsPath": "docs/styleguide"
}
+137
View File
@@ -2107,6 +2107,143 @@ section + section {
text-decoration: none;
}
/* Component: File Input */
.sg-file-input {
width: 100%;
}
.sg-file-input__row {
display: flex;
align-items: center;
justify-content: space-between;
gap: var(--spacing-large);
width: 100%;
}
.sg-file-input__control {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border: 0;
}
.sg-file-input:focus-within .sg-file-input__trigger {
outline: 2px solid var(--text-hyperlink);
outline-offset: 2px;
}
.sg-file-input__trigger {
align-self: flex-start;
}
@media (max-width: 48rem) {
.sg-file-input__row {
align-items: flex-start;
flex-direction: column;
}
}
.sg-file-input--disabled {
opacity: var(--disabled-opacity);
}
.sg-file-input--disabled .sg-file-input__trigger {
cursor: not-allowed;
}
/* ========================================================= */
/* Patterns: Datei-Upload */
/* ========================================================= */
.sg-file-upload {
--surface-file-upload-dropzone: var(--surface-form-preview);
--surface-file-upload-file-item: var(--surface-control-default);
--text-file-upload-meta: var(--text-control-disabled);
--text-file-upload-error: var(--color-signal-red);
display: flex;
flex-direction: column;
gap: var(--spacing-large);
width: 100%;
max-width: var(--layout-input-field-max-width);
}
.sg-file-upload__status,
.sg-file-upload__file-meta {
margin: var(--spacing-small) 0 0;
}
.sg-file-upload__dropzone {
display: flex;
align-items: center;
justify-content: space-between;
gap: var(--spacing-large);
width: 100%;
padding: var(--spacing-large);
background: var(--surface-file-upload-dropzone);
border: 1px dashed var(--surface-button-active);
border-radius: var(--radius-interaction);
}
.sg-file-upload__dropzone[data-drag-over="true"] {
outline: 2px solid var(--text-hyperlink);
outline-offset: 2px;
}
.sg-file-upload__files {
display: flex;
flex-direction: column;
gap: var(--spacing-small);
margin: 0;
padding: 0;
list-style: none;
}
.sg-file-upload__file {
display: flex;
align-items: center;
justify-content: space-between;
gap: var(--spacing-large);
padding: var(--spacing-small) var(--spacing-large);
color: var(--text-control-default);
background: var(--surface-file-upload-file-item);
border-radius: var(--radius-interaction);
}
.sg-file-upload__file-name {
min-width: 0;
overflow-wrap: anywhere;
}
.sg-file-upload__file-meta {
color: var(--text-file-upload-meta);
}
.sg-file-upload__remove {
flex: 0 0 auto;
}
.sg-file-upload__error {
color: var(--text-file-upload-error);
}
@media (max-width: 48rem) {
.sg-file-upload__dropzone {
align-items: flex-start;
flex-direction: column;
}
.sg-file-upload__file {
align-items: flex-start;
flex-direction: column;
gap: var(--spacing-small);
}
}
/* ========================================================= */
/* Patterns: Portal Header */
/* ========================================================= */