Skip to content

Commit 9f8d565

Browse files
authored
fix(ui5-color-palette): enhance HOME/END navigation from any row position (#12504)
What Changed: - Enhanced keyboard navigation in ui5-color-palette to support HOME/END keys from any row position, not just absolute first/last items. Key Improvements: - HOME key: Works from any first swatch in any row → navigates to Default Color button - END key: Works from any last swatch in any row → navigates to More Colors button - Fallback logic: When buttons are unavailable, falls back to first/last swatches - HOME/END: Prevent page scrolling in popover mode - END key: Prevent navigation from the recent colors section in inline palette mode
1 parent 8b6b947 commit 9f8d565

File tree

1 file changed

+85
-8
lines changed

1 file changed

+85
-8
lines changed

packages/main/src/ColorPalette.ts

Lines changed: 85 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -353,12 +353,6 @@ class ColorPalette extends UI5Element {
353353
if (isSpace(e)) {
354354
e.preventDefault();
355355
}
356-
357-
// Prevent Home/End keys from working in embedded mode - they only work in popup mode as per design
358-
if (!this.popupMode && (isHome(e) || isEnd(e))) {
359-
e.preventDefault();
360-
e.stopPropagation();
361-
}
362356
}
363357

364358
handleSelection(target: ColorPaletteItem) {
@@ -410,16 +404,19 @@ class ColorPalette extends UI5Element {
410404
}
411405

412406
if (this._isNext(e)) {
407+
e.preventDefault();
413408
e.stopPropagation();
414409
this._focusFirstDisplayedColor();
415410
} else if (isLeft(e)) {
411+
e.preventDefault();
416412
e.stopPropagation();
417413
this._focusFirstAvailable(
418414
() => this._focusLastRecentColor(),
419415
() => this._focusMoreColors(),
420416
() => this._focusLastDisplayedColor(),
421417
);
422418
} else if (isUp(e)) {
419+
e.preventDefault();
423420
e.stopPropagation();
424421
this._focusFirstAvailable(
425422
() => this._focusLastRecentColor(),
@@ -428,6 +425,13 @@ class ColorPalette extends UI5Element {
428425
() => this._focusLastDisplayedColor(),
429426
);
430427
} else if (isEnd(e)) {
428+
// Prevent Home/End keys from working in embedded mode - they only work in popup mode as per design
429+
if (this._shouldPreventHomeEnd(e)) {
430+
e.preventDefault();
431+
e.stopPropagation();
432+
return;
433+
}
434+
e.preventDefault();
431435
e.stopPropagation();
432436
this._focusFirstAvailable(
433437
() => this._focusMoreColors(),
@@ -438,34 +442,61 @@ class ColorPalette extends UI5Element {
438442

439443
_onMoreColorsKeyDown(e: KeyboardEvent) {
440444
if (isLeft(e)) {
445+
e.preventDefault();
441446
e.stopPropagation();
442447
this._focusLastDisplayedColor();
443448
} else if (isUp(e)) {
449+
e.preventDefault();
444450
e.stopPropagation();
445451
this._focusFirstAvailable(
446452
() => this._focusLastSwatchOfLastFullRow(),
447453
() => this._focusLastDisplayedColor(),
448454
);
449455
} else if (this._isNext(e)) {
456+
e.preventDefault();
450457
e.stopPropagation();
451458
this._focusFirstAvailable(
452459
() => this._focusFirstRecentColor(),
453460
() => this._focusDefaultColor(),
454461
() => this._focusFirstDisplayedColor(),
455462
);
456463
} else if (isHome(e)) {
464+
// Prevent Home/End keys from working in embedded mode - they only work in popup mode as per design
465+
if (this._shouldPreventHomeEnd(e)) {
466+
e.preventDefault();
467+
e.stopPropagation();
468+
return;
469+
}
470+
e.preventDefault();
457471
e.stopPropagation();
458472
this._focusFirstAvailable(
459473
() => this._focusDefaultColor(),
460474
() => this._focusFirstDisplayedColor(),
461475
);
476+
} else if (isEnd(e)) {
477+
// Prevent Home/End keys from working in embedded mode - they only work in popup mode as per design
478+
if (this._shouldPreventHomeEnd(e)) {
479+
e.preventDefault();
480+
e.stopPropagation();
481+
return;
482+
}
483+
// More Colors button is typically the last element, so END key stays here
484+
e.preventDefault();
485+
e.stopPropagation();
462486
}
463487
}
464488

465489
_onColorContainerKeyDown(e: KeyboardEvent) {
466490
const target = e.target as ColorPaletteItem;
467491
const isLastSwatchInSingleRow = this._isSingleRow() && this._isLastSwatch(target, this.displayedColors);
468492

493+
// Prevent Home/End keys from working in embedded mode - they only work in popup mode as per design
494+
if (this._shouldPreventHomeEnd(e)) {
495+
e.preventDefault();
496+
e.stopPropagation();
497+
return;
498+
}
499+
469500
if (this._isUpOrDownNavigatableColorPaletteItem(e)) {
470501
this._currentlySelected = undefined;
471502
}
@@ -476,6 +507,7 @@ class ColorPalette extends UI5Element {
476507
}
477508

478509
if (this._isPrevious(e) && this._isFirstSwatch(target, this.displayedColors)) {
510+
e.preventDefault();
479511
e.stopPropagation();
480512
this._focusFirstAvailable(
481513
() => this._focusDefaultColor(),
@@ -487,26 +519,32 @@ class ColorPalette extends UI5Element {
487519
} else if ((isRight(e) && this._isLastSwatch(target, this.displayedColors))
488520
|| (isDown(e) && (this._isLastSwatchOfLastFullRow(target) || isLastSwatchInSingleRow))
489521
) {
522+
e.preventDefault();
490523
e.stopPropagation();
491524
this._focusFirstAvailable(
492525
() => this._focusMoreColors(),
493526
() => this._focusFirstRecentColor(),
494527
() => this._focusDefaultColor(),
495528
() => this._focusFirstDisplayedColor(),
496529
);
497-
} else if (isHome(e) && this._isFirstSwatch(target, this.displayedColors)) {
530+
} else if (isHome(e) && this._isFirstSwatchInRow(target)) {
531+
e.preventDefault();
498532
e.stopPropagation();
499533
this._focusFirstAvailable(
500534
() => this._focusDefaultColor(),
501535
() => this._focusMoreColors(),
536+
() => this._focusFirstDisplayedColor(),
502537
);
503-
} else if (isEnd(e) && this._isLastSwatch(target, this.displayedColors)) {
538+
} else if (isEnd(e) && this._isLastSwatchInRow(target)) {
539+
e.preventDefault();
504540
e.stopPropagation();
505541
this._focusFirstAvailable(
506542
() => this._focusMoreColors(),
507543
() => this._focusDefaultColor(),
544+
() => this._focusLastDisplayedColor(),
508545
);
509546
} else if (isEnd(e) && this._isSwatchInLastRow(target)) {
547+
e.preventDefault();
510548
e.stopPropagation();
511549
this._focusLastDisplayedColor();
512550
}
@@ -515,18 +553,27 @@ class ColorPalette extends UI5Element {
515553
_onRecentColorsContainerKeyDown(e: KeyboardEvent) {
516554
const target = e.target as ColorPaletteItem;
517555

556+
// Prevent Home/End keys from working in embedded mode - they only work in popup mode as per design
557+
if (this._shouldPreventHomeEnd(e)) {
558+
e.preventDefault();
559+
e.stopPropagation();
560+
return;
561+
}
562+
518563
if (this._isUpOrDownNavigatableColorPaletteItem(e)) {
519564
this._currentlySelected = undefined;
520565
}
521566

522567
if (this._isNext(e) && this._isLastSwatch(target, this.recentColorsElements)) {
568+
e.preventDefault();
523569
e.stopPropagation();
524570
this._focusFirstAvailable(
525571
() => this._focusDefaultColor(),
526572
() => this._focusMoreColors(),
527573
() => this._focusFirstDisplayedColor(),
528574
);
529575
} else if (this._isPrevious(e) && this._isFirstSwatch(target, this.recentColorsElements)) {
576+
e.preventDefault();
530577
e.stopPropagation();
531578
this._focusFirstAvailable(
532579
() => this._focusMoreColors(),
@@ -535,6 +582,7 @@ class ColorPalette extends UI5Element {
535582
() => this._focusDefaultColor(),
536583
);
537584
} else if (isEnd(e)) {
585+
e.preventDefault();
538586
e.stopPropagation();
539587
this._focusLastRecentColor();
540588
}
@@ -569,6 +617,24 @@ class ColorPalette extends UI5Element {
569617
return swatches && Boolean(swatches.length) && swatches[swatches.length - 1] === target;
570618
}
571619

620+
/**
621+
* Checks if the target swatch is the first swatch in its row.
622+
* @private
623+
*/
624+
_isFirstSwatchInRow(target: ColorPaletteItem): boolean {
625+
const index = this.displayedColors.indexOf(target);
626+
return index >= 0 ? index % this.rowSize === 0 : false;
627+
}
628+
629+
/**
630+
* Checks if the target swatch is the last swatch in its row.
631+
* @private
632+
*/
633+
_isLastSwatchInRow(target: ColorPaletteItem): boolean {
634+
const index = this.displayedColors.indexOf(target);
635+
return index >= 0 ? (index + 1) % this.rowSize === 0 || index === this.displayedColors.length - 1 : false;
636+
}
637+
572638
/**
573639
* Checks if the given color swatch is the last swatch of the last full row.
574640
*
@@ -594,6 +660,17 @@ class ColorPalette extends UI5Element {
594660
return index >= 0 && index >= this.displayedColors.length - lastRowSwatchesCount;
595661
}
596662

663+
/**
664+
* Checks if HOME/END navigation should be prevented in embedded mode.
665+
* In embedded mode, HOME/END keys are blocked as they only work in popup mode per design.
666+
* @private
667+
* @param e The keyboard event to check
668+
* @returns True if the event should be prevented, false otherwise
669+
*/
670+
_shouldPreventHomeEnd(e: KeyboardEvent): boolean {
671+
return !this.popupMode && (isHome(e) || isEnd(e));
672+
}
673+
597674
/**
598675
* Helper to check if all displayed colors fit in a single row
599676
* @private

0 commit comments

Comments
 (0)