Sync styleguide 2026.05.18.1

This commit is contained in:
2026-06-03 16:25:03 +02:00
parent 70272e81d6
commit 543d3e5af5
66 changed files with 22706 additions and 0 deletions
+33
View File
@@ -0,0 +1,33 @@
#!/usr/bin/env bash
set -euo pipefail
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
CSS_FILE="$ROOT_DIR/styleguide.css"
selectors=(
"sg-portal-header"
"sg-options-row"
"sg-card-list-page-drawer__header"
"sg-card-list-page-drawer__content"
)
for selector in "${selectors[@]}"; do
block="$(awk -v selector=".$selector" '
$0 ~ selector"[[:space:]]*\\{" {in_block=1}
in_block {print}
in_block && /}/ {exit}
' "$CSS_FILE")"
if [[ -z "$block" ]]; then
echo "ERROR: selector .$selector not found in styleguide.css"
exit 1
fi
if echo "$block" | rg -n "(padding|padding-inline|padding-left|padding-right|inset|inset-inline)([^\n;]*)([0-9]+px)" >/dev/null; then
echo "ERROR: hardcoded px inset/padding value found in .$selector"
echo "$block"
exit 1
fi
done
echo "OK: no hardcoded px inset values in guarded pattern selectors"
@@ -0,0 +1,129 @@
(function initHelpIconOverlayModule() {
const CLOSE_HANDLERS = {
'.sg-pulldown-demo': (root) => {
root.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');
}
});
},
'.sg-sandwich-menu-wrap': (root) => {
root.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');
}
});
},
};
const getViewportWidth = () => {
if (window.visualViewport && typeof window.visualViewport.width === 'number') {
return window.visualViewport.width;
}
return window.innerWidth;
};
const getSafeInsetPx = () => {
const rootStyles = getComputedStyle(document.documentElement);
const spacingSmallRaw = rootStyles.getPropertyValue('--spacing-small').trim();
const rootFontSize = parseFloat(rootStyles.fontSize) || 16;
const spacingSmallValue = parseFloat(spacingSmallRaw);
if (Number.isNaN(spacingSmallValue)) {
return 0;
}
if (spacingSmallRaw.endsWith('rem')) {
return spacingSmallValue * rootFontSize;
}
return spacingSmallValue;
};
const closeAllHelpIcons = (root) => {
root.querySelectorAll('.sg-help-icon-wrap').forEach((wrap) => {
const button = wrap.querySelector('.sg-help-icon');
const panel = wrap.querySelector('.sg-help-icon-panel');
wrap.dataset.open = 'false';
if (panel) {
panel.style.removeProperty('transform');
}
if (button) {
button.setAttribute('aria-expanded', 'false');
}
});
};
window.sgInitHelpIconOverlays = (options = {}) => {
const root = options.root || document;
const closeOnOpenSelectors = options.closeOnOpenSelectors || [];
const outsideClickIgnoreSelectors = options.outsideClickIgnoreSelectors || [];
root.querySelectorAll('.sg-help-icon-wrap').forEach((wrap) => {
if (wrap.dataset.helpIconInit === 'true') {
return;
}
wrap.dataset.helpIconInit = 'true';
const button = wrap.querySelector('.sg-help-icon');
const panel = wrap.querySelector('.sg-help-icon-panel');
if (!button || !panel) {
return;
}
button.addEventListener('click', (event) => {
event.stopPropagation();
const nextState = wrap.dataset.open !== 'true';
closeAllHelpIcons(root);
closeOnOpenSelectors.forEach((selector) => {
const handler = CLOSE_HANDLERS[selector];
if (handler) {
handler(root);
}
});
if (!nextState) {
return;
}
wrap.dataset.align = 'left';
wrap.dataset.open = 'true';
button.setAttribute('aria-expanded', 'true');
const viewportWidth = getViewportWidth();
const panelRect = panel.getBoundingClientRect();
if (panelRect.right > viewportWidth) {
wrap.dataset.align = 'right';
}
const alignedPanelRect = panel.getBoundingClientRect();
if (alignedPanelRect.left < 0) {
wrap.dataset.align = 'left';
}
const clampedRect = panel.getBoundingClientRect();
const safeInset = getSafeInsetPx();
let shiftX = 0;
if (clampedRect.right > (viewportWidth - safeInset)) {
shiftX -= clampedRect.right - (viewportWidth - safeInset);
}
if ((clampedRect.left + shiftX) < safeInset) {
shiftX += safeInset - (clampedRect.left + shiftX);
}
if (shiftX !== 0) {
panel.style.transform = `translateX(${shiftX}px)`;
}
});
});
document.addEventListener('click', (event) => {
const isInsideIgnoredZone = ['.sg-help-icon-wrap', ...outsideClickIgnoreSelectors]
.some((selector) => event.target.closest(selector));
if (isInsideIgnoredZone) {
return;
}
closeAllHelpIcons(root);
});
};
})();
@@ -0,0 +1,235 @@
#!/usr/bin/env bash
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
STYLEGUIDE_REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
SOURCE_CSS="$STYLEGUIDE_REPO_ROOT/styleguide.css"
VERSION_FILE="$STYLEGUIDE_REPO_ROOT/VERSION"
PORTAL_KEY="vsf"
PORTAL_REPO_PATH=""
PORTAL_CSS_REL="public/assets/styleguide.upstream.css"
PORTAL_BUILT_CSS_REL="public/assets/styles.css"
PORTAL_META_REL="public/assets/styleguide.upstream.meta.json"
PORTAL_STYLEGUIDE_DOCS_REL="docs/styleguide"
PORTAL_BUILD_SCRIPT_REL="scripts/styleguide/build_styles.sh"
COMMIT_IN_PORTAL="false"
usage() {
cat <<USAGE
Usage:
$(basename "$0") [--portal <vsf|naurua>] [--portal-repo <path>] [--commit-portal]
Options:
--portal <name> Portal target. Defaults to vsf.
--portal-repo <path> Optional override for portal repository root.
--commit-portal Create commit in portal repo after sync.
-h, --help Show this help.
USAGE
}
while [[ $# -gt 0 ]]; do
case "$1" in
--portal)
PORTAL_KEY="${2:-}"
shift 2
;;
--portal-repo)
PORTAL_REPO_PATH="${2:-}"
shift 2
;;
--commit-portal)
COMMIT_IN_PORTAL="true"
shift
;;
-h|--help)
usage
exit 0
;;
*)
echo "Unknown argument: $1" >&2
usage
exit 1
;;
esac
done
case "$PORTAL_KEY" in
vsf)
if [[ -z "$PORTAL_REPO_PATH" ]]; then
PORTAL_REPO_PATH="/Users/mathias/Documents/Dokumente Chouchou/Codebases/WebApp_Aktienberater"
fi
;;
naurua)
if [[ -z "$PORTAL_REPO_PATH" ]]; then
PORTAL_REPO_PATH="/Users/mathias/Documents/Dokumente Chouchou/Codebases/erp_naurua"
fi
;;
*)
echo "Unknown portal: $PORTAL_KEY" >&2
usage
exit 1
;;
esac
if [[ ! -f "$SOURCE_CSS" ]]; then
echo "Source CSS not found: $SOURCE_CSS" >&2
exit 1
fi
if [[ ! -f "$VERSION_FILE" ]]; then
echo "Version file not found: $VERSION_FILE" >&2
exit 1
fi
if [[ ! -d "$PORTAL_REPO_PATH/.git" ]]; then
echo "Portal repo is not a git repository: $PORTAL_REPO_PATH" >&2
exit 1
fi
PORTAL_CSS_PATH="$PORTAL_REPO_PATH/$PORTAL_CSS_REL"
PORTAL_BUILT_CSS_PATH="$PORTAL_REPO_PATH/$PORTAL_BUILT_CSS_REL"
PORTAL_META_PATH="$PORTAL_REPO_PATH/$PORTAL_META_REL"
PORTAL_STYLEGUIDE_DOCS_PATH="$PORTAL_REPO_PATH/$PORTAL_STYLEGUIDE_DOCS_REL"
PORTAL_BUILD_SCRIPT_PATH="$PORTAL_REPO_PATH/$PORTAL_BUILD_SCRIPT_REL"
mkdir -p "$(dirname "$PORTAL_CSS_PATH")"
mkdir -p "$PORTAL_STYLEGUIDE_DOCS_PATH"
flatten_css() {
local source_file="$1"
local source_root="$2"
local output_file="$3"
: > "$output_file"
while IFS= read -r line; do
if [[ "$line" =~ ^[[:space:]]*@import[[:space:]]+\"([^\"]+)\"[[:space:]]*\;[[:space:]]*$ ]]; then
local import_path="${BASH_REMATCH[1]}"
local import_abs="$source_root/$import_path"
if [[ ! -f "$import_abs" ]]; then
echo "Imported CSS not found: $import_abs" >&2
exit 1
fi
cat "$import_abs" >> "$output_file"
printf "\n" >> "$output_file"
else
printf "%s\n" "$line" >> "$output_file"
fi
done < "$source_file"
}
transform_portal_css() {
local source_file="$1"
local output_file="$2"
case "$PORTAL_KEY" in
vsf)
awk '
BEGIN { skip=0 }
/^:root\[data-portal="naurua"\] \{/ { skip=1; next }
skip && /^}/ { skip=0; next }
skip { next }
{ print }
' "$source_file" > "$output_file"
;;
naurua)
awk '
BEGIN { in_override=0 }
/^:root\[data-portal="naurua"\] \{/ { print ":root {"; in_override=1; next }
in_override && /^}/ { print "}"; in_override=0; next }
{ print }
' "$source_file" > "$output_file"
;;
esac
}
assert_no_unimported_styles() {
local source_file="$1"
local source_root="$2"
local styles_dir="$source_root/styles"
local missing_imports=()
if [[ ! -d "$styles_dir" ]]; then
return 0
fi
while IFS= read -r css_file; do
local rel_path="./styles/$(basename "$css_file")"
if ! grep -Eq "^[[:space:]]*@import[[:space:]]+\"$rel_path\"[[:space:]]*;" "$source_file"; then
missing_imports+=("$rel_path")
fi
done < <(find "$styles_dir" -maxdepth 1 -type f -name '*.css' | sort)
if [[ ${#missing_imports[@]} -gt 0 ]]; then
echo "Unimported CSS module files detected in styles/:" >&2
for file in "${missing_imports[@]}"; do
echo " - $file" >&2
done
echo "Add missing @import lines in $source_file before syncing." >&2
exit 1
fi
}
TMP_UPSTREAM_CSS="$(mktemp)"
trap 'rm -f "$TMP_UPSTREAM_CSS"' EXIT
assert_no_unimported_styles "$SOURCE_CSS" "$STYLEGUIDE_REPO_ROOT"
flatten_css "$SOURCE_CSS" "$STYLEGUIDE_REPO_ROOT" "$TMP_UPSTREAM_CSS"
transform_portal_css "$TMP_UPSTREAM_CSS" "$PORTAL_CSS_PATH"
rsync -a --delete \
--exclude ".git/" \
--exclude ".codex/" \
--exclude ".DS_Store" \
--exclude "AGENTS.md" \
"$STYLEGUIDE_REPO_ROOT/" \
"$PORTAL_STYLEGUIDE_DOCS_PATH/"
STYLEGUIDE_VERSION="$(tr -d '[:space:]' < "$VERSION_FILE")"
STYLEGUIDE_COMMIT="$(git -C "$STYLEGUIDE_REPO_ROOT" rev-parse --short HEAD)"
SYNCED_AT="$(date -u +"%Y-%m-%dT%H:%M:%SZ")"
cat > "$PORTAL_META_PATH" <<META
{
"styleguideVersion": "$STYLEGUIDE_VERSION",
"styleguideCommit": "$STYLEGUIDE_COMMIT",
"syncedAtUtc": "$SYNCED_AT",
"sourceRepo": "$STYLEGUIDE_REPO_ROOT",
"mirroredDocsPath": "$PORTAL_STYLEGUIDE_DOCS_REL"
}
META
case "$PORTAL_KEY" in
vsf)
PORTAL_BUILD_SCRIPT_PATH="$PORTAL_REPO_PATH/$PORTAL_BUILD_SCRIPT_REL"
if [[ ! -f "$PORTAL_BUILD_SCRIPT_PATH" ]]; then
echo "Portal build script not found: $PORTAL_BUILD_SCRIPT_PATH" >&2
exit 1
fi
bash "$PORTAL_BUILD_SCRIPT_PATH"
;;
naurua)
cp "$PORTAL_CSS_PATH" "$PORTAL_BUILT_CSS_PATH"
;;
esac
if [[ "$COMMIT_IN_PORTAL" == "true" ]]; then
git -C "$PORTAL_REPO_PATH" add -A \
"$PORTAL_CSS_REL" \
"$PORTAL_BUILT_CSS_REL" \
"$PORTAL_META_REL" \
"$PORTAL_STYLEGUIDE_DOCS_REL"
if ! git -C "$PORTAL_REPO_PATH" diff --cached --quiet; then
git -C "$PORTAL_REPO_PATH" commit -m "Sync styleguide $STYLEGUIDE_VERSION"
git -C "$PORTAL_REPO_PATH" push
echo "Portal repo synced and pushed."
else
echo "No changes to commit in portal repo."
fi
else
echo "Portal files updated locally (no commit requested)."
fi
echo "Synced $SOURCE_CSS -> $PORTAL_CSS_PATH"
echo "Built portal stylesheet: $PORTAL_BUILT_CSS_PATH"
echo "Metadata written: $PORTAL_META_PATH"
echo "Mirrored styleguide docs: $PORTAL_STYLEGUIDE_DOCS_PATH"