From c68186f95a7577c5f315b2ffc63f80c7ebcc7e3d Mon Sep 17 00:00:00 2001 From: Boyan Rakilovski Date: Sat, 18 Oct 2025 01:03:33 +0300 Subject: [PATCH 1/2] fix(ui5-color-palette): improve HOME/END key navigation for any row position - HOME key from first swatch in any row navigates to Default Color button - END key from last swatch in any row navigates to More Colors button - Add fallback navigation to first/last swatches when buttons unavailable --- packages/main/src/ColorPalette.ts | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/packages/main/src/ColorPalette.ts b/packages/main/src/ColorPalette.ts index 29e3e601707c..c6f00de5955a 100644 --- a/packages/main/src/ColorPalette.ts +++ b/packages/main/src/ColorPalette.ts @@ -494,17 +494,19 @@ class ColorPalette extends UI5Element { () => this._focusDefaultColor(), () => this._focusFirstDisplayedColor(), ); - } else if (isHome(e) && this._isFirstSwatch(target, this.displayedColors)) { + } else if (isHome(e) && this._isFirstSwatchInRow(target)) { e.stopPropagation(); this._focusFirstAvailable( () => this._focusDefaultColor(), () => this._focusMoreColors(), + () => this._focusFirstDisplayedColor(), ); - } else if (isEnd(e) && this._isLastSwatch(target, this.displayedColors)) { + } else if (isEnd(e) && this._isLastSwatchInRow(target)) { e.stopPropagation(); this._focusFirstAvailable( () => this._focusMoreColors(), () => this._focusDefaultColor(), + () => this._focusLastDisplayedColor(), ); } else if (isEnd(e) && this._isSwatchInLastRow(target)) { e.stopPropagation(); @@ -569,6 +571,24 @@ class ColorPalette extends UI5Element { return swatches && Boolean(swatches.length) && swatches[swatches.length - 1] === target; } + /** + * Checks if the target swatch is the first swatch in its row. + * @private + */ + _isFirstSwatchInRow(target: ColorPaletteItem): boolean { + const index = this.displayedColors.indexOf(target); + return index >= 0 ? index % this.rowSize === 0 : false; + } + + /** + * Checks if the target swatch is the last swatch in its row. + * @private + */ + _isLastSwatchInRow(target: ColorPaletteItem): boolean { + const index = this.displayedColors.indexOf(target); + return index >= 0 ? (index + 1) % this.rowSize === 0 || index === this.displayedColors.length - 1 : false; + } + /** * Checks if the given color swatch is the last swatch of the last full row. * From f9c7880159d34597c625717e03ddd9c46bfddab8 Mon Sep 17 00:00:00 2001 From: Boyan Rakilovski Date: Fri, 24 Oct 2025 13:06:01 +0300 Subject: [PATCH 2/2] fix: adjust Home/End interactions - Prevent page scrolling in popover mode - Prevent End key navigation in inline mode --- packages/main/src/ColorPalette.ts | 69 ++++++++++++++++++++++++++++--- 1 file changed, 63 insertions(+), 6 deletions(-) diff --git a/packages/main/src/ColorPalette.ts b/packages/main/src/ColorPalette.ts index c6f00de5955a..3e6bed653a41 100644 --- a/packages/main/src/ColorPalette.ts +++ b/packages/main/src/ColorPalette.ts @@ -353,12 +353,6 @@ class ColorPalette extends UI5Element { if (isSpace(e)) { e.preventDefault(); } - - // Prevent Home/End keys from working in embedded mode - they only work in popup mode as per design - if (!this.popupMode && (isHome(e) || isEnd(e))) { - e.preventDefault(); - e.stopPropagation(); - } } handleSelection(target: ColorPaletteItem) { @@ -410,9 +404,11 @@ class ColorPalette extends UI5Element { } if (this._isNext(e)) { + e.preventDefault(); e.stopPropagation(); this._focusFirstDisplayedColor(); } else if (isLeft(e)) { + e.preventDefault(); e.stopPropagation(); this._focusFirstAvailable( () => this._focusLastRecentColor(), @@ -420,6 +416,7 @@ class ColorPalette extends UI5Element { () => this._focusLastDisplayedColor(), ); } else if (isUp(e)) { + e.preventDefault(); e.stopPropagation(); this._focusFirstAvailable( () => this._focusLastRecentColor(), @@ -428,6 +425,13 @@ class ColorPalette extends UI5Element { () => this._focusLastDisplayedColor(), ); } else if (isEnd(e)) { + // Prevent Home/End keys from working in embedded mode - they only work in popup mode as per design + if (this._shouldPreventHomeEnd(e)) { + e.preventDefault(); + e.stopPropagation(); + return; + } + e.preventDefault(); e.stopPropagation(); this._focusFirstAvailable( () => this._focusMoreColors(), @@ -438,15 +442,18 @@ class ColorPalette extends UI5Element { _onMoreColorsKeyDown(e: KeyboardEvent) { if (isLeft(e)) { + e.preventDefault(); e.stopPropagation(); this._focusLastDisplayedColor(); } else if (isUp(e)) { + e.preventDefault(); e.stopPropagation(); this._focusFirstAvailable( () => this._focusLastSwatchOfLastFullRow(), () => this._focusLastDisplayedColor(), ); } else if (this._isNext(e)) { + e.preventDefault(); e.stopPropagation(); this._focusFirstAvailable( () => this._focusFirstRecentColor(), @@ -454,11 +461,28 @@ class ColorPalette extends UI5Element { () => this._focusFirstDisplayedColor(), ); } else if (isHome(e)) { + // Prevent Home/End keys from working in embedded mode - they only work in popup mode as per design + if (this._shouldPreventHomeEnd(e)) { + e.preventDefault(); + e.stopPropagation(); + return; + } + e.preventDefault(); e.stopPropagation(); this._focusFirstAvailable( () => this._focusDefaultColor(), () => this._focusFirstDisplayedColor(), ); + } else if (isEnd(e)) { + // Prevent Home/End keys from working in embedded mode - they only work in popup mode as per design + if (this._shouldPreventHomeEnd(e)) { + e.preventDefault(); + e.stopPropagation(); + return; + } + // More Colors button is typically the last element, so END key stays here + e.preventDefault(); + e.stopPropagation(); } } @@ -466,6 +490,13 @@ class ColorPalette extends UI5Element { const target = e.target as ColorPaletteItem; const isLastSwatchInSingleRow = this._isSingleRow() && this._isLastSwatch(target, this.displayedColors); + // Prevent Home/End keys from working in embedded mode - they only work in popup mode as per design + if (this._shouldPreventHomeEnd(e)) { + e.preventDefault(); + e.stopPropagation(); + return; + } + if (this._isUpOrDownNavigatableColorPaletteItem(e)) { this._currentlySelected = undefined; } @@ -476,6 +507,7 @@ class ColorPalette extends UI5Element { } if (this._isPrevious(e) && this._isFirstSwatch(target, this.displayedColors)) { + e.preventDefault(); e.stopPropagation(); this._focusFirstAvailable( () => this._focusDefaultColor(), @@ -487,6 +519,7 @@ class ColorPalette extends UI5Element { } else if ((isRight(e) && this._isLastSwatch(target, this.displayedColors)) || (isDown(e) && (this._isLastSwatchOfLastFullRow(target) || isLastSwatchInSingleRow)) ) { + e.preventDefault(); e.stopPropagation(); this._focusFirstAvailable( () => this._focusMoreColors(), @@ -495,6 +528,7 @@ class ColorPalette extends UI5Element { () => this._focusFirstDisplayedColor(), ); } else if (isHome(e) && this._isFirstSwatchInRow(target)) { + e.preventDefault(); e.stopPropagation(); this._focusFirstAvailable( () => this._focusDefaultColor(), @@ -502,6 +536,7 @@ class ColorPalette extends UI5Element { () => this._focusFirstDisplayedColor(), ); } else if (isEnd(e) && this._isLastSwatchInRow(target)) { + e.preventDefault(); e.stopPropagation(); this._focusFirstAvailable( () => this._focusMoreColors(), @@ -509,6 +544,7 @@ class ColorPalette extends UI5Element { () => this._focusLastDisplayedColor(), ); } else if (isEnd(e) && this._isSwatchInLastRow(target)) { + e.preventDefault(); e.stopPropagation(); this._focusLastDisplayedColor(); } @@ -517,11 +553,19 @@ class ColorPalette extends UI5Element { _onRecentColorsContainerKeyDown(e: KeyboardEvent) { const target = e.target as ColorPaletteItem; + // Prevent Home/End keys from working in embedded mode - they only work in popup mode as per design + if (this._shouldPreventHomeEnd(e)) { + e.preventDefault(); + e.stopPropagation(); + return; + } + if (this._isUpOrDownNavigatableColorPaletteItem(e)) { this._currentlySelected = undefined; } if (this._isNext(e) && this._isLastSwatch(target, this.recentColorsElements)) { + e.preventDefault(); e.stopPropagation(); this._focusFirstAvailable( () => this._focusDefaultColor(), @@ -529,6 +573,7 @@ class ColorPalette extends UI5Element { () => this._focusFirstDisplayedColor(), ); } else if (this._isPrevious(e) && this._isFirstSwatch(target, this.recentColorsElements)) { + e.preventDefault(); e.stopPropagation(); this._focusFirstAvailable( () => this._focusMoreColors(), @@ -537,6 +582,7 @@ class ColorPalette extends UI5Element { () => this._focusDefaultColor(), ); } else if (isEnd(e)) { + e.preventDefault(); e.stopPropagation(); this._focusLastRecentColor(); } @@ -614,6 +660,17 @@ class ColorPalette extends UI5Element { return index >= 0 && index >= this.displayedColors.length - lastRowSwatchesCount; } + /** + * Checks if HOME/END navigation should be prevented in embedded mode. + * In embedded mode, HOME/END keys are blocked as they only work in popup mode per design. + * @private + * @param e The keyboard event to check + * @returns True if the event should be prevented, false otherwise + */ + _shouldPreventHomeEnd(e: KeyboardEvent): boolean { + return !this.popupMode && (isHome(e) || isEnd(e)); + } + /** * Helper to check if all displayed colors fit in a single row * @private