Sync styleguide 2026.05.18.1
This commit is contained in:
@@ -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"
|
||||
Reference in New Issue
Block a user