feat: style

This commit is contained in:
2026-04-20 22:00:06 +02:00
parent 0888795c09
commit 7a967e4d55
2 changed files with 37 additions and 23 deletions
+9 -10
View File
@@ -4,10 +4,10 @@
This repository is an Angular 21 SSR application. Main app code lives in `src/`, This repository is an Angular 21 SSR application. Main app code lives in `src/`,
with standalone components under `src/app/` such as `home/`, `footer/`, and with standalone components under `src/app/` such as `home/`, `footer/`, and
`imprint/`. Shared constants are kept in `src/global.ts`. Component tests `imprint/`. Shared constants are kept in `src/global.ts`. Component tests sit
sit next to their source files as `*.spec.ts`. Automation and project next to their source files as `*.spec.ts`. Automation and project maintenance
maintenance scripts live in `scripts/`. Generated build output goes to `dist/` scripts live in `scripts/`. Generated build output goes to `dist/` and should
and should not be edited manually. not be edited manually.
## Build, Test, and Development Commands ## Build, Test, and Development Commands
@@ -42,12 +42,11 @@ tests for changed behavior.
## Commit & Pull Request Guidelines ## Commit & Pull Request Guidelines
Recent history mixes short imperative messages (`Update src/global.ts`) Recent history mixes short imperative messages (`Update src/global.ts`) with
with lightweight conventional commits lightweight conventional commits (`feat: pre-render routes and restore scroll`).
(`feat: pre-render routes and restore scroll`). Prefer concise, imperative Prefer concise, imperative commit subjects and include a scope or prefix when it
commit subjects and include a scope or prefix when it adds clarity. PRs should adds clarity. PRs should summarize the user-visible change, mention any config
summarize the user-visible change, mention any config or script updates, link or script updates, link related issues, and include screenshots for UI changes.
related issues, and include screenshots for UI changes.
## Configuration Tips ## Configuration Tips
+23 -8
View File
@@ -155,11 +155,14 @@ export class HomeComponent implements OnInit, OnDestroy {
} }
const portraitImageUrls: Set<string> = new Set<string>( const portraitImageUrls: Set<string> = new Set<string>(
this.portraitHighlights.map((highlight: PortraitHighlight): string => new URL(highlight.image, window.location.href).href), this.portraitHighlights.map(
(highlight: PortraitHighlight): string =>
new URL(highlight.image, window.location.href).href,
),
); );
const portraitImages: HTMLImageElement[] = this.preloadedImages.filter((image: HTMLImageElement): boolean => const portraitImages: HTMLImageElement[] = this.preloadedImages.filter(
portraitImageUrls.has(image.src), (image: HTMLImageElement): boolean => portraitImageUrls.has(image.src),
); );
if (portraitImages.length === 0) { if (portraitImages.length === 0) {
@@ -167,14 +170,17 @@ export class HomeComponent implements OnInit, OnDestroy {
} }
const finalizeAspectRatio = (): void => { const finalizeAspectRatio = (): void => {
const minAspectRatio: number = portraitImages.reduce((minRatio: number, image: HTMLImageElement): number => { const minAspectRatio: number = portraitImages.reduce(
(minRatio: number, image: HTMLImageElement): number => {
if (image.naturalWidth === 0 || image.naturalHeight === 0) { if (image.naturalWidth === 0 || image.naturalHeight === 0) {
return minRatio; return minRatio;
} }
const currentRatio: number = image.naturalWidth / image.naturalHeight; const currentRatio: number = image.naturalWidth / image.naturalHeight;
return minRatio === 0 ? currentRatio : Math.min(minRatio, currentRatio); return minRatio === 0 ? currentRatio : Math.min(minRatio, currentRatio);
}, 0); },
0,
);
if (minAspectRatio > 0) { if (minAspectRatio > 0) {
this.tallestPortraitAspectRatio = minAspectRatio; this.tallestPortraitAspectRatio = minAspectRatio;
@@ -284,14 +290,23 @@ export class HomeComponent implements OnInit, OnDestroy {
const maxMediaHeight: number = buttonWidth / this.tallestPortraitAspectRatio; const maxMediaHeight: number = buttonWidth / this.tallestPortraitAspectRatio;
const currentButtonHeight: number = portraitButton.getBoundingClientRect().height; const currentButtonHeight: number = portraitButton.getBoundingClientRect().height;
const currentHighlightHeight: number = portraitHighlight.getBoundingClientRect().height; const currentHighlightHeight: number = portraitHighlight.getBoundingClientRect().height;
const staticHighlightOverhead: number = Math.max(currentHighlightHeight - currentButtonHeight, 0); const staticHighlightOverhead: number = Math.max(
currentHighlightHeight - currentButtonHeight,
0,
);
const requiredHighlightHeight: number = maxMediaHeight + staticHighlightOverhead; const requiredHighlightHeight: number = maxMediaHeight + staticHighlightOverhead;
const requiredContentHeight: number = Math.max(heroCopy.getBoundingClientRect().height, requiredHighlightHeight); const requiredContentHeight: number = Math.max(
heroCopy.getBoundingClientRect().height,
requiredHighlightHeight,
);
const heroSectionStyles: CSSStyleDeclaration = window.getComputedStyle(heroSection); const heroSectionStyles: CSSStyleDeclaration = window.getComputedStyle(heroSection);
const paddingTop: number = Number.parseFloat(heroSectionStyles.paddingTop) || 0; const paddingTop: number = Number.parseFloat(heroSectionStyles.paddingTop) || 0;
const paddingBottom: number = Number.parseFloat(heroSectionStyles.paddingBottom) || 0; const paddingBottom: number = Number.parseFloat(heroSectionStyles.paddingBottom) || 0;
const requiredSectionMinHeight: number = requiredContentHeight + paddingTop + paddingBottom; const requiredSectionMinHeight: number = requiredContentHeight + paddingTop + paddingBottom;
this.lockedHeroSectionMinHeight = Math.max(this.lockedHeroSectionMinHeight, requiredSectionMinHeight); this.lockedHeroSectionMinHeight = Math.max(
this.lockedHeroSectionMinHeight,
requiredSectionMinHeight,
);
document.documentElement.style.setProperty( document.documentElement.style.setProperty(
'--hero-section-min-height', '--hero-section-min-height',