From 9d011ff30591018a6e123181385e6b080ff89a5d Mon Sep 17 00:00:00 2001 From: "Janus C. H. Knudsen" Date: Sun, 7 Dec 2025 17:44:52 +0100 Subject: [PATCH] wip --- src/v2/V2CompositionRoot.ts | 2 + src/v2/core/HeaderDrawerManager.ts | 47 ++++++++++++++++++++++ src/v2/demo/DemoApp.ts | 14 ++++++- wwwroot/css/calendar-v2.css | 62 +++++++++++++++++++++++++++--- wwwroot/v2.html | 2 + 5 files changed, 121 insertions(+), 6 deletions(-) create mode 100644 src/v2/core/HeaderDrawerManager.ts diff --git a/src/v2/V2CompositionRoot.ts b/src/v2/V2CompositionRoot.ts index 24f2518..6c494d0 100644 --- a/src/v2/V2CompositionRoot.ts +++ b/src/v2/V2CompositionRoot.ts @@ -10,6 +10,7 @@ import { RendererRegistry } from './core/RendererRegistry'; import { CalendarOrchestrator } from './core/CalendarOrchestrator'; import { TimeAxisRenderer } from './features/timeaxis/TimeAxisRenderer'; import { ScrollManager } from './core/ScrollManager'; +import { HeaderDrawerManager } from './core/HeaderDrawerManager'; import { MockTeamStore, MockResourceStore } from './demo/MockStores'; import { DemoApp } from './demo/DemoApp'; @@ -47,6 +48,7 @@ export function createV2Container(): Container { builder.registerType(CalendarOrchestrator).as(); builder.registerType(TimeAxisRenderer).as(); builder.registerType(ScrollManager).as(); + builder.registerType(HeaderDrawerManager).as(); // Demo app builder.registerType(DemoApp).as(); diff --git a/src/v2/core/HeaderDrawerManager.ts b/src/v2/core/HeaderDrawerManager.ts new file mode 100644 index 0000000..ac2a838 --- /dev/null +++ b/src/v2/core/HeaderDrawerManager.ts @@ -0,0 +1,47 @@ +export class HeaderDrawerManager { + private drawer!: HTMLElement; + private spacer!: HTMLElement; + private expanded = false; + private readonly expandedHeight = 24; + private readonly duration = 200; + + init(container: HTMLElement): void { + this.drawer = container.querySelector('swp-header-drawer')!; + this.spacer = container.querySelector('swp-header-spacer')!; + } + + toggle(): void { + this.expanded ? this.collapse() : this.expand(); + } + + expand(): void { + if (this.expanded) return; + this.expanded = true; + this.animate(0, this.expandedHeight); + } + + collapse(): void { + if (!this.expanded) return; + this.expanded = false; + this.animate(this.expandedHeight, 0); + } + + private animate(from: number, to: number): void { + const keyframes = [ + { height: `${from}px` }, + { height: `${to}px` } + ]; + const options: KeyframeAnimationOptions = { + duration: this.duration, + easing: 'ease', + fill: 'forwards' + }; + + this.drawer.animate(keyframes, options); + this.spacer.animate(keyframes, options); + } + + isExpanded(): boolean { + return this.expanded; + } +} diff --git a/src/v2/demo/DemoApp.ts b/src/v2/demo/DemoApp.ts index 708e0d5..fbd64b4 100644 --- a/src/v2/demo/DemoApp.ts +++ b/src/v2/demo/DemoApp.ts @@ -3,6 +3,7 @@ import { TimeAxisRenderer } from '../features/timeaxis/TimeAxisRenderer'; import { NavigationAnimator } from '../core/NavigationAnimator'; import { DateService } from '../core/DateService'; import { ScrollManager } from '../core/ScrollManager'; +import { HeaderDrawerManager } from '../core/HeaderDrawerManager'; import { ViewConfig } from '../core/ViewConfig'; export class DemoApp { @@ -15,7 +16,8 @@ export class DemoApp { private orchestrator: CalendarOrchestrator, private timeAxisRenderer: TimeAxisRenderer, private dateService: DateService, - private scrollManager: ScrollManager + private scrollManager: ScrollManager, + private headerDrawerManager: HeaderDrawerManager ) {} init(): void { @@ -54,9 +56,13 @@ export class DemoApp { // Init scroll synkronisering this.scrollManager.init(this.container); + // Init header drawer + this.headerDrawerManager.init(this.container); + // Setup event handlers this.setupNavigation(); this.setupViewSwitchers(); + this.setupDrawerToggle(); // Initial render this.orchestrator.render(this.views.simple, this.container); @@ -86,4 +92,10 @@ export class DemoApp { document.getElementById('btn-team')!.onclick = () => this.animator.slide('left', () => this.orchestrator.render(this.views.team, this.container)); } + + private setupDrawerToggle(): void { + document.getElementById('btn-drawer')!.onclick = () => { + this.headerDrawerManager.toggle(); + }; + } } diff --git a/wwwroot/css/calendar-v2.css b/wwwroot/css/calendar-v2.css index 99aa182..e58bd70 100644 --- a/wwwroot/css/calendar-v2.css +++ b/wwwroot/css/calendar-v2.css @@ -1,5 +1,5 @@ :root { - --hour-height: 60px; + --hour-height: 64px; --time-axis-width: 60px; --grid-columns: 5; --day-start-hour: 0; @@ -8,6 +8,8 @@ --color-surface: #fff; --color-text-secondary: #666; --color-primary: #1976d2; + --color-hour-line: rgba(0, 0, 0, 0.2); + --color-grid-line-light: rgba(0, 0, 0, 0.05); } * { box-sizing: border-box; margin: 0; padding: 0; } @@ -85,6 +87,16 @@ swp-time-axis { } swp-header-spacer { + height: 0; + overflow: hidden; + border-bottom: 1px solid var(--color-border); +} + +swp-header-drawer { + display: block; + height: 0; + overflow: hidden; + background: #fafafa; border-bottom: 1px solid var(--color-border); } @@ -100,6 +112,17 @@ swp-hour-marker { font-size: 11px; color: var(--color-text-secondary); text-align: right; + position: relative; +} + +swp-hour-marker::after { + content: ''; + position: absolute; + top: -1px; + right: 0; + width: 5px; + height: 1px; + background: var(--color-hour-line); } /* Grid container */ @@ -211,15 +234,44 @@ swp-time-grid { min-height: calc((var(--day-end-hour) - var(--day-start-hour)) * var(--hour-height)); } -swp-grid-lines { +/* Timelinjer via ::after */ +swp-time-grid::after { + content: ''; position: absolute; inset: 0; - background: repeating-linear-gradient( + z-index: 2; + background-image: repeating-linear-gradient( to bottom, transparent, transparent calc(var(--hour-height) - 1px), - var(--color-border) calc(var(--hour-height) - 1px), - var(--color-border) var(--hour-height) + var(--color-hour-line) calc(var(--hour-height) - 1px), + var(--color-hour-line) var(--hour-height) + ); + pointer-events: none; +} + +/* Kvarterlinjer - 3 linjer per time (15, 30, 45 min), ikke ved timegrænsen */ +swp-grid-lines { + display: block; + position: absolute; + inset: 0; + z-index: 1; + background-image: repeating-linear-gradient( + to bottom, + transparent 0, + transparent calc(var(--hour-height) / 4 - 1px), + var(--color-grid-line-light) calc(var(--hour-height) / 4 - 1px), + var(--color-grid-line-light) calc(var(--hour-height) / 4), + transparent calc(var(--hour-height) / 4), + transparent calc(var(--hour-height) / 2 - 1px), + var(--color-grid-line-light) calc(var(--hour-height) / 2 - 1px), + var(--color-grid-line-light) calc(var(--hour-height) / 2), + transparent calc(var(--hour-height) / 2), + transparent calc(var(--hour-height) * 3 / 4 - 1px), + var(--color-grid-line-light) calc(var(--hour-height) * 3 / 4 - 1px), + var(--color-grid-line-light) calc(var(--hour-height) * 3 / 4), + transparent calc(var(--hour-height) * 3 / 4), + transparent var(--hour-height) ); } diff --git a/wwwroot/v2.html b/wwwroot/v2.html index 331334f..c4414ba 100644 --- a/wwwroot/v2.html +++ b/wwwroot/v2.html @@ -19,6 +19,7 @@ + Toggle @@ -31,6 +32,7 @@ +