From 2e50679602531fd5705d38a554c66769be7857cc Mon Sep 17 00:00:00 2001 From: Janus Knudsen Date: Tue, 29 Jul 2025 23:01:00 +0200 Subject: [PATCH] Refactors grid layout for scrollbar implementation Updates the grid structure to correctly position the scrollbars. Replaces fixed scrollbars with a grid-based layout using spacers and a right column for a more integrated and maintainable solution. This change addresses layout issues related to scrollbar positioning and ensures better alignment across different browsers. --- src/managers/GridManager.ts | 45 +++++++++++------- src/managers/ScrollManager.ts | 18 ++++---- wwwroot/css/calendar-layout-css.css | 71 ++++++++++++++--------------- 3 files changed, 72 insertions(+), 62 deletions(-) diff --git a/src/managers/GridManager.ts b/src/managers/GridManager.ts index 70ce268..b331375 100644 --- a/src/managers/GridManager.ts +++ b/src/managers/GridManager.ts @@ -117,12 +117,13 @@ export class GridManager { // Clear existing grid and rebuild POC structure this.grid.innerHTML = ''; - // Create POC structure: header-spacer + time-axis + week-container + fixed scrollbars + // Create POC structure: header-spacer + time-axis + week-container + right-column + bottom spacers this.createHeaderSpacer(); + this.createRightHeaderSpacer(); this.createTimeAxis(); this.createWeekContainer(); + this.createRightColumn(); this.createBottomRow(); - this.createFixedScrollbars(); console.log('GridManager: Grid rendered successfully with POC structure'); } @@ -138,24 +139,26 @@ export class GridManager { } /** - * Create fixed scrollbars at browser edges + * Create right header spacer for scrollbar alignment */ - private createFixedScrollbars(): void { - if (!document.body) return; + private createRightHeaderSpacer(): void { + if (!this.grid) return; - // Create right scrollbar at browser edge - const rightScrollbar = document.createElement('swp-right-scrollbar'); - const rightColumn = document.createElement('swp-right-column'); - rightScrollbar.appendChild(rightColumn); - document.body.appendChild(rightScrollbar); - - // Create bottom scrollbar at browser edge - const bottomScrollbar = document.createElement('swp-bottom-scrollbar'); - const bottomColumn = document.createElement('swp-bottom-column'); - bottomScrollbar.appendChild(bottomColumn); - document.body.appendChild(bottomScrollbar); + const rightHeaderSpacer = document.createElement('swp-right-header-spacer'); + this.grid.appendChild(rightHeaderSpacer); } + /** + * Create right column for scrollbar area + */ + private createRightColumn(): void { + if (!this.grid) return; + + const rightColumn = document.createElement('swp-right-column'); + this.grid.appendChild(rightColumn); + } + + /** * Create time axis (positioned beside week container) like in POC */ @@ -210,7 +213,7 @@ export class GridManager { } /** - * Create bottom row with spacer + * Create bottom row with spacers */ private createBottomRow(): void { if (!this.grid) return; @@ -218,6 +221,14 @@ export class GridManager { // Bottom spacer (left) const bottomSpacer = document.createElement('swp-bottom-spacer'); this.grid.appendChild(bottomSpacer); + + // Bottom middle spacer + const bottomMiddleSpacer = document.createElement('swp-bottom-middle-spacer'); + this.grid.appendChild(bottomMiddleSpacer); + + // Right bottom spacer + const rightBottomSpacer = document.createElement('swp-right-bottom-spacer'); + this.grid.appendChild(rightBottomSpacer); } /** diff --git a/src/managers/ScrollManager.ts b/src/managers/ScrollManager.ts index ceea69f..229e079 100644 --- a/src/managers/ScrollManager.ts +++ b/src/managers/ScrollManager.ts @@ -22,7 +22,7 @@ export class ScrollManager { private handleHeight: number = 40; // Horizontal scrolling - private bottomColumn: HTMLElement | null = null; + private bottomMiddleSpacer: HTMLElement | null = null; private horizontalScrollHandle: HTMLElement | null = null; private weekHeader: HTMLElement | null = null; private isHorizontalDragging: boolean = false; @@ -73,7 +73,7 @@ export class ScrollManager { } // Setup horizontal scrolling - if (this.bottomColumn && this.scrollableContent && this.weekHeader) { + if (this.bottomMiddleSpacer && this.scrollableContent && this.weekHeader) { this.createHorizontalScrollHandle(); this.setupHorizontalScrollSynchronization(); this.calculateHorizontalScrollBounds(); @@ -91,12 +91,12 @@ export class ScrollManager { this.timeAxis = document.querySelector('swp-time-axis'); // Horizontal scrolling elements - this.bottomColumn = document.querySelector('swp-bottom-column'); + this.bottomMiddleSpacer = document.querySelector('swp-bottom-middle-spacer'); this.weekHeader = document.querySelector('swp-week-header'); console.log('ScrollManager: Found elements:', { rightColumn: !!this.rightColumn, - bottomColumn: !!this.bottomColumn, + bottomMiddleSpacer: !!this.bottomMiddleSpacer, scrollableContent: !!this.scrollableContent, weekHeader: !!this.weekHeader }); @@ -399,13 +399,13 @@ export class ScrollManager { } /** - * Create and add horizontal scroll handle to bottom column + * Create and add horizontal scroll handle to bottom middle spacer */ private createHorizontalScrollHandle(): void { - if (!this.bottomColumn) return; + if (!this.bottomMiddleSpacer) return; // Remove existing handle if any - const existingHandle = this.bottomColumn.querySelector('swp-horizontal-scroll-handle'); + const existingHandle = this.bottomMiddleSpacer.querySelector('swp-horizontal-scroll-handle'); if (existingHandle) { existingHandle.remove(); } @@ -414,14 +414,14 @@ export class ScrollManager { this.horizontalScrollHandle = document.createElement('swp-horizontal-scroll-handle'); this.horizontalScrollHandle.addEventListener('mousedown', this.handleHorizontalMouseDown.bind(this)); - this.bottomColumn.appendChild(this.horizontalScrollHandle); + this.bottomMiddleSpacer.appendChild(this.horizontalScrollHandle); } /** * Calculate horizontal scroll bounds based on content and container widths */ private calculateHorizontalScrollBounds(): void { - if (!this.scrollableContent || !this.bottomColumn) return; + if (!this.scrollableContent || !this.bottomMiddleSpacer) return; const contentWidth = this.scrollableContent.scrollWidth; const containerWidth = this.scrollableContent.clientWidth; diff --git a/wwwroot/css/calendar-layout-css.css b/wwwroot/css/calendar-layout-css.css index 088febb..c9e362a 100644 --- a/wwwroot/css/calendar-layout-css.css +++ b/wwwroot/css/calendar-layout-css.css @@ -39,7 +39,7 @@ swp-calendar-nav { swp-calendar-container { flex: 1; display: grid; - grid-template-columns: 60px 1fr; + grid-template-columns: 60px 1fr 20px; grid-template-rows: auto 1fr 20px; overflow: hidden; position: relative; @@ -58,22 +58,22 @@ swp-header-spacer { position: relative; } -/* Right scrollbar - positioned at browser edge */ -swp-right-scrollbar { - position: fixed; - top: 0; - right: 0; - width: 20px; - height: 100vh; - background: #f0f0f0; - border-left: 2px solid #333; - z-index: 1000; - overflow: hidden; + +/* Right header spacer for scrollbar alignment */ +swp-right-header-spacer { + grid-column: 3; + grid-row: 1; + height: 80px; /* Same as week header height */ + background: var(--color-surface); + border-left: 1px solid var(--color-border); + border-bottom: 1px solid var(--color-border); + z-index: 5; /* Higher than time-axis to cover it when scrolling */ + position: relative; } /* Week container for sliding */ swp-week-container { - grid-column: 2; + grid-column: 2 / 4; /* Span across columns 2-3 to include right spacer area */ grid-row: 1 / 3; display: grid; grid-template-rows: auto 1fr; @@ -82,6 +82,16 @@ swp-week-container { transition: transform 400ms cubic-bezier(0.4, 0, 0.2, 1); } +/* Right column for scrollbar */ +swp-right-column { + grid-column: 3; + grid-row: 2; + background: #f0f0f0; + border-left: 2px solid #333; + position: relative; + overflow: hidden; +} + /* Time axis */ swp-time-axis { grid-column: 1; @@ -96,14 +106,14 @@ swp-time-axis { flex-direction: column; } -/* Right column - now part of fixed scrollbar */ -swp-right-column { - position: absolute; - top: 80px; /* Below navigation */ - left: 0; - right: 0; - bottom: 20px; /* Above horizontal scrollbar */ - background: transparent; +/* Right bottom spacer */ +swp-right-bottom-spacer { + grid-column: 3; + grid-row: 3; + height: 20px; + background: var(--color-surface); + border-left: 1px solid var(--color-border); + border-top: 1px solid var(--color-border); } /* Scroll handle */ @@ -138,27 +148,16 @@ swp-bottom-spacer { border-top: 1px solid var(--color-border); } -/* Bottom scrollbar - positioned at browser edge */ -swp-bottom-scrollbar { - position: fixed; - bottom: 0; - left: 0; - right: 20px; /* Leave space for vertical scrollbar */ +/* Bottom middle spacer */ +swp-bottom-middle-spacer { + grid-column: 2; + grid-row: 3; height: 20px; background: #f0f0f0; border-top: 2px solid #333; - z-index: 1000; overflow: hidden; } -swp-bottom-column { - position: absolute; - top: 0; - left: 60px; /* Start after time-axis */ - right: 0; - bottom: 0; - background: transparent; -} /* Horizontal scroll handle */ swp-horizontal-scroll-handle {