diff --git a/packages/main/cypress/specs/ColorPalettePopover.cy.tsx b/packages/main/cypress/specs/ColorPalettePopover.cy.tsx
index bad0c933f675..6c93e2d1b8b7 100644
--- a/packages/main/cypress/specs/ColorPalettePopover.cy.tsx
+++ b/packages/main/cypress/specs/ColorPalettePopover.cy.tsx
@@ -543,7 +543,7 @@ describe("Color Popover Palette arrow keys navigation", () => {
});
describe("Color Popover Palette Home and End keyboard navigation", () => {
- it.skip("should navigate with Home/End when showDefaultColor is set", () => {
+ it("should navigate with Home/End when showDefaultColor is set", () => {
cy.mount(
);
@@ -640,7 +640,7 @@ describe("Color Popover Palette Home and End keyboard navigation", () => {
.should("have.attr", "aria-label", "More Colors...");
});
- it.skip("should navigate with Home/End when showDefaultColor & showMoreColors are set", () => {
+ it("should navigate with Home/End when showDefaultColor & showMoreColors are set", () => {
cy.mount(
);
diff --git a/packages/main/src/ColorPalette.ts b/packages/main/src/ColorPalette.ts
index 474a9607f710..a6e2254d26b9 100644
--- a/packages/main/src/ColorPalette.ts
+++ b/packages/main/src/ColorPalette.ts
@@ -507,8 +507,8 @@ class ColorPalette extends UI5Element {
}
_onColorContainerKeyDown(e: KeyboardEvent) {
- const target = e.target as ColorPaletteItem;
- const isLastSwatchInSingleRow = this._isSingleRow() && this._isLastSwatch(target, this.displayedColors);
+ const eventTarget = e.target as ColorPaletteItem;
+ const swatchTarget = this._getColorPaletteItemFromEvent(e, this.displayedColors);
// Prevent Home/End keys from working in embedded mode - they only work in popup mode as per design
if (this._shouldPreventHomeEnd(e)) {
@@ -523,10 +523,16 @@ class ColorPalette extends UI5Element {
if (isTabNext(e) && this.popupMode) {
e.preventDefault();
- this.selectColor(target);
+ this.selectColor(swatchTarget || eventTarget);
+ }
+
+ if (!swatchTarget) {
+ return;
}
- if (this._isPrevious(e) && this._isFirstSwatch(target, this.displayedColors)) {
+ const isLastSwatchInSingleRow = this._isSingleRow() && this._isLastSwatch(swatchTarget, this.displayedColors);
+
+ if (this._isPrevious(e) && this._isFirstSwatch(swatchTarget, this.displayedColors)) {
e.preventDefault();
e.stopPropagation();
this._focusFirstAvailable(
@@ -536,8 +542,8 @@ class ColorPalette extends UI5Element {
() => this._focusLastSwatchOfLastFullRow(),
() => this._focusLastDisplayedColor(),
);
- } else if ((isRight(e) && this._isLastSwatch(target, this.displayedColors))
- || (isDown(e) && (this._isLastSwatchOfLastFullRow(target) || isLastSwatchInSingleRow))
+ } else if ((isRight(e) && this._isLastSwatch(swatchTarget, this.displayedColors))
+ || (isDown(e) && (this._isLastSwatchOfLastFullRow(swatchTarget) || isLastSwatchInSingleRow))
) {
e.preventDefault();
e.stopPropagation();
@@ -547,7 +553,7 @@ class ColorPalette extends UI5Element {
() => this._focusDefaultColor(),
() => this._focusFirstDisplayedColor(),
);
- } else if (isHome(e) && this._isFirstSwatchInRow(target)) {
+ } else if (isHome(e) && this._isFirstSwatchInRow(swatchTarget)) {
e.preventDefault();
e.stopPropagation();
this._focusFirstAvailable(
@@ -555,7 +561,7 @@ class ColorPalette extends UI5Element {
() => this._focusMoreColors(),
() => this._focusFirstDisplayedColor(),
);
- } else if (isEnd(e) && this._isLastSwatchInRow(target)) {
+ } else if (isEnd(e) && this._isLastSwatchInRow(swatchTarget)) {
e.preventDefault();
e.stopPropagation();
this._focusFirstAvailable(
@@ -563,7 +569,7 @@ class ColorPalette extends UI5Element {
() => this._focusDefaultColor(),
() => this._focusLastDisplayedColor(),
);
- } else if (isEnd(e) && this._isSwatchInLastRow(target)) {
+ } else if (isEnd(e) && this._isSwatchInLastRow(swatchTarget)) {
e.preventDefault();
e.stopPropagation();
this._focusLastDisplayedColor();
@@ -571,7 +577,7 @@ class ColorPalette extends UI5Element {
}
_onRecentColorsContainerKeyDown(e: KeyboardEvent) {
- const target = e.target as ColorPaletteItem;
+ const swatchTarget = this._getColorPaletteItemFromEvent(e, this.recentColorsElements);
// Prevent Home/End keys from working in embedded mode - they only work in popup mode as per design
if (this._shouldPreventHomeEnd(e)) {
@@ -584,7 +590,11 @@ class ColorPalette extends UI5Element {
this._currentlySelected = undefined;
}
- if (this._isNext(e) && this._isLastSwatch(target, this.recentColorsElements)) {
+ if (!swatchTarget) {
+ return;
+ }
+
+ if (this._isNext(e) && this._isLastSwatch(swatchTarget, this.recentColorsElements)) {
e.preventDefault();
e.stopPropagation();
this._focusFirstAvailable(
@@ -592,7 +602,7 @@ class ColorPalette extends UI5Element {
() => this._focusMoreColors(),
() => this._focusFirstDisplayedColor(),
);
- } else if (this._isPrevious(e) && this._isFirstSwatch(target, this.recentColorsElements)) {
+ } else if (this._isPrevious(e) && this._isFirstSwatch(swatchTarget, this.recentColorsElements)) {
e.preventDefault();
e.stopPropagation();
this._focusFirstAvailable(
@@ -633,6 +643,11 @@ class ColorPalette extends UI5Element {
return swatches && Boolean(swatches.length) && swatches[0] === (target);
}
+ _getColorPaletteItemFromEvent(e: KeyboardEvent, swatches: Array): ColorPaletteItem | undefined {
+ const path = e.composedPath();
+ return swatches.find(swatch => path.includes(swatch));
+ }
+
_isLastSwatch(target: ColorPaletteItem, swatches: Array): boolean {
return swatches && Boolean(swatches.length) && swatches[swatches.length - 1] === (target);
}
diff --git a/packages/main/src/ColorPalettePopover.ts b/packages/main/src/ColorPalettePopover.ts
index 212e4fcefd74..0b4d18ceee75 100644
--- a/packages/main/src/ColorPalettePopover.ts
+++ b/packages/main/src/ColorPalettePopover.ts
@@ -195,12 +195,15 @@ class ColorPalettePopover extends UI5Element {
onAfterOpen() {
const colorPalette = this._colorPalette;
+
+ // Focus the last selected color (or first recent color) on reopen. The default color button
+ // and the first swatch are intentionally left to the popover's built-in initial focus: it
+ // already lands on them, and re-focusing those here fires on the "open" event a frame later,
+ // stealing focus back after the user has already started navigating with the keyboard.
if (colorPalette._currentlySelected) {
- colorPalette._currentlySelected?.focus();
+ colorPalette._currentlySelected.getFocusDomRef()?.focus();
} else if (colorPalette.showRecentColors && colorPalette.recentColorsElements.length) {
- colorPalette.recentColorsElements[0].focus();
- } else if (colorPalette.showDefaultColor) {
- colorPalette._defaultColorButton?.focus();
+ colorPalette.recentColorsElements[0].getFocusDomRef()?.focus();
}
// since height is dynamically determined by padding-block-start