From b6a33e04210de2d0eb972755dbce804d479e14a9 Mon Sep 17 00:00:00 2001 From: GerganaKremenska Date: Mon, 8 Apr 2024 11:24:58 +0300 Subject: [PATCH] feat(focus): new focus handling (#8590) * feat(focus): new focus handling * feat(focus): new focus handling * chore: fix card header focuse in ff --- packages/fiori/src/SideNavigationItemBase.ts | 9 +++++++++ .../fiori/src/themes/NotificationListItemBase.css | 1 + packages/fiori/src/themes/SideNavigationItemBase.css | 3 ++- packages/main/src/Badge.ts | 9 +++++++++ packages/main/src/BusyIndicator.ts | 6 ++++++ packages/main/src/CardHeader.ts | 11 ++++++++++- packages/main/src/Carousel.ts | 3 +++ packages/main/src/Popup.ts | 5 ++++- packages/main/src/RadioButton.ts | 6 ++++++ packages/main/src/TabContainer.ts | 6 ++++++ packages/main/src/themes/Badge.css | 3 ++- packages/main/src/themes/BusyIndicator.css | 5 +++-- packages/main/src/themes/CardHeader.css | 6 ++++-- packages/main/src/themes/Carousel.css | 3 ++- packages/main/src/themes/Dialog.css | 3 ++- packages/main/src/themes/RadioButton.css | 11 ++++------- packages/main/src/themes/TabContainer.css | 1 + packages/main/src/themes/TabInOverflow.css | 1 + packages/main/src/themes/TabInStrip.css | 12 ++++++++---- .../main/src/themes/base/RadioButton-parameters.css | 1 - 20 files changed, 83 insertions(+), 22 deletions(-) diff --git a/packages/fiori/src/SideNavigationItemBase.ts b/packages/fiori/src/SideNavigationItemBase.ts index df868622b26b..39a99e9e60ac 100644 --- a/packages/fiori/src/SideNavigationItemBase.ts +++ b/packages/fiori/src/SideNavigationItemBase.ts @@ -1,5 +1,8 @@ import UI5Element from "@ui5/webcomponents-base/dist/UI5Element.js"; import property from "@ui5/webcomponents-base/dist/decorators/property.js"; +import { + isDesktop, +} from "@ui5/webcomponents-base/dist/Device.js"; import type { ITabbable } from "@ui5/webcomponents-base/dist/delegate/ItemNavigation.js"; import type SideNavigation from "./SideNavigation.js"; @@ -55,6 +58,12 @@ class SideNavigationItemBase extends UI5Element implements ITabbable { _sideNavigation!: SideNavigation; + onEnterDOM() { + if (isDesktop()) { + this.setAttribute("desktop", ""); + } + } + get _tooltip() { return this.title || undefined; } diff --git a/packages/fiori/src/themes/NotificationListItemBase.css b/packages/fiori/src/themes/NotificationListItemBase.css index df866e67711b..aea63adf9319 100644 --- a/packages/fiori/src/themes/NotificationListItemBase.css +++ b/packages/fiori/src/themes/NotificationListItemBase.css @@ -12,6 +12,7 @@ border-bottom: var(--ui5-listitem-border-bottom); } +/*TODO after li is implemented*/ :host([focused]) .ui5-nli-focusable { outline: none; } diff --git a/packages/fiori/src/themes/SideNavigationItemBase.css b/packages/fiori/src/themes/SideNavigationItemBase.css index 2a7f99bd845e..3acf7252e442 100644 --- a/packages/fiori/src/themes/SideNavigationItemBase.css +++ b/packages/fiori/src/themes/SideNavigationItemBase.css @@ -32,7 +32,8 @@ outline: none; } -.ui5-sn-item:focus::after { +:host([desktop]) .ui5-sn-item:focus::after, +.ui5-sn-item:focus-visible::after { border: var(--sapContent_FocusWidth) var(--sapContent_FocusStyle) var(--sapContent_FocusColor); position: absolute; content: ""; diff --git a/packages/main/src/Badge.ts b/packages/main/src/Badge.ts index bc2aac57a4dd..5795d045a082 100644 --- a/packages/main/src/Badge.ts +++ b/packages/main/src/Badge.ts @@ -7,6 +7,9 @@ import litRender from "@ui5/webcomponents-base/dist/renderer/LitRenderer.js"; import { getI18nBundle } from "@ui5/webcomponents-base/dist/i18nBundle.js"; import type I18nBundle from "@ui5/webcomponents-base/dist/i18nBundle.js"; import willShowContent from "@ui5/webcomponents-base/dist/util/willShowContent.js"; +import { + isDesktop, +} from "@ui5/webcomponents-base/dist/Device.js"; import type { IIcon } from "./Icon.js"; import Icon from "./Icon.js"; import "@ui5/webcomponents-icons/dist/sys-help-2.js"; @@ -171,6 +174,12 @@ class Badge extends UI5Element { Badge.i18nBundle = await getI18nBundle("@ui5/webcomponents"); } + onEnterDOM() { + if (isDesktop()) { + this.setAttribute("desktop", ""); + } + } + onBeforeRendering() { this._hasIcon = this.hasIcon || !!this._semanticIconName; this._iconOnly = this.iconOnly; diff --git a/packages/main/src/BusyIndicator.ts b/packages/main/src/BusyIndicator.ts index a89cc0eb80a1..c6612bdd4f3b 100644 --- a/packages/main/src/BusyIndicator.ts +++ b/packages/main/src/BusyIndicator.ts @@ -7,6 +7,9 @@ import type I18nBundle from "@ui5/webcomponents-base/dist/i18nBundle.js"; import { isTabNext } from "@ui5/webcomponents-base/dist/Keys.js"; import Integer from "@ui5/webcomponents-base/dist/types/Integer.js"; import type { Timeout } from "@ui5/webcomponents-base/dist/types.js"; +import { + isDesktop, +} from "@ui5/webcomponents-base/dist/Device.js"; import BusyIndicatorSize from "./types/BusyIndicatorSize.js"; import BusyIndicatorTextPlacement from "./types/BusyIndicatorTextPlacement.js"; import Label from "./Label.js"; @@ -135,6 +138,9 @@ class BusyIndicator extends UI5Element { this.addEventListener("keyup", this._preventEventHandler, { capture: true, }); + if (isDesktop()) { + this.setAttribute("desktop", ""); + } } onExitDOM() { diff --git a/packages/main/src/CardHeader.ts b/packages/main/src/CardHeader.ts index 13e874fde91c..ba90daba309a 100644 --- a/packages/main/src/CardHeader.ts +++ b/packages/main/src/CardHeader.ts @@ -7,7 +7,10 @@ import litRender from "@ui5/webcomponents-base/dist/renderer/LitRenderer.js"; import type I18nBundle from "@ui5/webcomponents-base/dist/i18nBundle.js"; import { getI18nBundle } from "@ui5/webcomponents-base/dist/i18nBundle.js"; import { isSpace, isEnter } from "@ui5/webcomponents-base/dist/Keys.js"; -import { isFirefox } from "@ui5/webcomponents-base/dist/Device.js"; +import { + isFirefox, + isDesktop, +} from "@ui5/webcomponents-base/dist/Device.js"; import Integer from "@ui5/webcomponents-base/dist/types/Integer.js"; import CardHeaderTemplate from "./generated/templates/CardHeaderTemplate.lit.js"; @@ -120,6 +123,12 @@ class CardHeader extends UI5Element { static i18nBundle: I18nBundle; + onEnterDOM() { + if (isDesktop()) { + this.setAttribute("desktop", ""); + } + } + get classes() { return { root: { diff --git a/packages/main/src/Carousel.ts b/packages/main/src/Carousel.ts index 1d50db6737f1..ecd6f9c84e1a 100644 --- a/packages/main/src/Carousel.ts +++ b/packages/main/src/Carousel.ts @@ -329,6 +329,9 @@ class Carousel extends UI5Element { onEnterDOM() { ResizeHandler.register(this, this._onResizeBound); + if (isDesktop()) { + this.setAttribute("desktop", ""); + } } onExitDOM() { diff --git a/packages/main/src/Popup.ts b/packages/main/src/Popup.ts index bd8b369c6c8a..7f54d9d289b4 100644 --- a/packages/main/src/Popup.ts +++ b/packages/main/src/Popup.ts @@ -6,7 +6,7 @@ import property from "@ui5/webcomponents-base/dist/decorators/property.js"; import type { ClassMap } from "@ui5/webcomponents-base/dist/types.js"; import litRender from "@ui5/webcomponents-base/dist/renderer/LitRenderer.js"; import UI5Element from "@ui5/webcomponents-base/dist/UI5Element.js"; -import { isChrome, isSafari } from "@ui5/webcomponents-base/dist/Device.js"; +import { isChrome, isSafari, isDesktop } from "@ui5/webcomponents-base/dist/Device.js"; import { getFirstFocusableElement, getLastFocusableElement } from "@ui5/webcomponents-base/dist/util/FocusableElements.js"; import { getEffectiveAriaLabelText } from "@ui5/webcomponents-base/dist/util/AriaLabelHelper.js"; import getEffectiveScrollbarStyle from "@ui5/webcomponents-base/dist/util/getEffectiveScrollbarStyle.js"; @@ -251,6 +251,9 @@ abstract class Popup extends UI5Element { onEnterDOM() { this.setAttribute("popover", "manual"); ResizeHandler.register(this, this._resizeHandler); + if (isDesktop()) { + this.setAttribute("desktop", ""); + } } onExitDOM() { diff --git a/packages/main/src/RadioButton.ts b/packages/main/src/RadioButton.ts index e09e3283d137..2ef3f110e66a 100644 --- a/packages/main/src/RadioButton.ts +++ b/packages/main/src/RadioButton.ts @@ -270,6 +270,12 @@ class RadioButton extends UI5Element implements IFormElement { this._enableFormSupport(); } + onEnterDOM() { + if (isDesktop()) { + this.setAttribute("desktop", ""); + } + } + onExitDOM() { this.syncGroup(true); } diff --git a/packages/main/src/TabContainer.ts b/packages/main/src/TabContainer.ts index d1b523147f5f..48315a5df39c 100644 --- a/packages/main/src/TabContainer.ts +++ b/packages/main/src/TabContainer.ts @@ -13,6 +13,9 @@ import Integer from "@ui5/webcomponents-base/dist/types/Integer.js"; import AnimationMode from "@ui5/webcomponents-base/dist/types/AnimationMode.js"; import { getAnimationMode } from "@ui5/webcomponents-base/dist/config/AnimationMode.js"; import ItemNavigation from "@ui5/webcomponents-base/dist/delegate/ItemNavigation.js"; +import { + isDesktop, +} from "@ui5/webcomponents-base/dist/Device.js"; import { isSpace, isEnter, @@ -397,6 +400,9 @@ class TabContainer extends UI5Element { ResizeHandler.register(this._getHeader(), this._handleResizeBound); DragRegistry.subscribe(this); this._setDraggedElement = DragRegistry.addSelfManagedArea(this); + if (isDesktop()) { + this.setAttribute("desktop", ""); + } } onExitDOM() { diff --git a/packages/main/src/themes/Badge.css b/packages/main/src/themes/Badge.css index 3a88e6809a52..58fffe1ad57b 100644 --- a/packages/main/src/themes/Badge.css +++ b/packages/main/src/themes/Badge.css @@ -51,7 +51,8 @@ cursor: pointer; } -:host([interactive]) .ui5-badge-root:focus { +:host([desktop][interactive]) .ui5-badge-root:focus, +:host([interactive]) .ui5-badge-root:focus-visible { outline: var(--sapContent_FocusWidth) var(--sapContent_FocusStyle) var(--sapContent_FocusColor); outline-offset: 1px; } diff --git a/packages/main/src/themes/BusyIndicator.css b/packages/main/src/themes/BusyIndicator.css index 1cd35294ae85..fde41996a666 100644 --- a/packages/main/src/themes/BusyIndicator.css +++ b/packages/main/src/themes/BusyIndicator.css @@ -89,10 +89,11 @@ flex-direction: column; } -.ui5-busy-indicator-busy-area:focus { +:host([desktop]) .ui5-busy-indicator-busy-area:focus, +.ui5-busy-indicator-busy-area:focus-visible { outline: var(--_ui5_busy_indicator_focus_outline); outline-offset: -2px; - border-radius: var(--_ui5_busy_indicator_focus_border_radius); + border-radius: var(--_ui5_busy_indicator_focus_border_radius); } .ui5-busy-indicator-circles-wrapper { diff --git a/packages/main/src/themes/CardHeader.css b/packages/main/src/themes/CardHeader.css index 063fee5b58dd..3a326ade2469 100644 --- a/packages/main/src/themes/CardHeader.css +++ b/packages/main/src/themes/CardHeader.css @@ -12,7 +12,8 @@ align-items: flex-start; } -.ui5-card-header.ui5-card-header-ff:not(.ui5-card-header-hide-focus):focus-within:before { +:host([desktop]) .ui5-card-header.ui5-card-header-ff:not(.ui5-card-header-hide-focus):focus-within:before, +.ui5-card-header.ui5-card-header-ff:not(.ui5-card-header-hide-focus):focus-visible:before { outline: none; content: ""; position: absolute; @@ -29,7 +30,8 @@ } /* cannot be combined with the above style, because :has selector breaks the whole style if FF */ -.ui5-card-header:not(.ui5-card-header-ff):not(.ui5-card-header-hide-focus):has(.ui5-card-header-focusable-element:focus):before { +:host([desktop]) .ui5-card-header:not(.ui5-card-header-ff):not(.ui5-card-header-hide-focus):has(.ui5-card-header-focusable-element:focus):before, +.ui5-card-header:not(.ui5-card-header-ff):not(.ui5-card-header-hide-focus):has(.ui5-card-header-focusable-element:focus-visible):before { outline: none; content: ""; position: absolute; diff --git a/packages/main/src/themes/Carousel.css b/packages/main/src/themes/Carousel.css index 2c2be0c114c6..2f387cde5999 100644 --- a/packages/main/src/themes/Carousel.css +++ b/packages/main/src/themes/Carousel.css @@ -8,7 +8,8 @@ height: 100%; } -.ui5-carousel-root:focus { +:host([desktop]) .ui5-carousel-root:focus, +.ui5-carousel-root:focus-visible { outline: var(--sapContent_FocusWidth) var(--sapContent_FocusStyle) var(--sapContent_FocusColor); } diff --git a/packages/main/src/themes/Dialog.css b/packages/main/src/themes/Dialog.css index 64c92939a998..9a0e83118e88 100644 --- a/packages/main/src/themes/Dialog.css +++ b/packages/main/src/themes/Dialog.css @@ -96,7 +96,8 @@ outline: none; } -.ui5-popup-header-root:focus:after { +:host([desktop]) .ui5-popup-header-root:focus:after, +.ui5-popup-header-root:focus-visible:after { content: ''; position: absolute; left: var(--_ui5_dialog_header_focus_left_offset); diff --git a/packages/main/src/themes/RadioButton.css b/packages/main/src/themes/RadioButton.css index 644d1e4f988c..30b4ea03bf56 100644 --- a/packages/main/src/themes/RadioButton.css +++ b/packages/main/src/themes/RadioButton.css @@ -41,7 +41,8 @@ } /* focused */ -:host(:not([disabled])) .ui5-radio-root:focus::before { +:host(:not([disabled])[desktop]) .ui5-radio-root:focus::before, +:host(:not([disabled])) .ui5-radio-root:focus-visible::before { content: ""; display: var(--_ui5_radio_button_focus_outline); position: absolute; @@ -51,11 +52,6 @@ border-radius: var(--_ui5_radio_button_border_radius); } -:host(:not([disabled])) .ui5-radio-root:focus { - border-radius: var(--_ui5_radio_button_border_radius); - border: var(--_ui5_radio_button_focus_border); -} - /* hovered and value-state */ :host(:not([value-state="Error"]):not([value-state="Warning"]):not([value-state="Success"]):not([value-state="Information"])) .ui5-radio-root:hover .ui5-radio-inner--hoverable .ui5-radio-svg-outer { stroke: var(--_ui5_radio_button_outer_ring_hover_color); @@ -85,7 +81,8 @@ padding-inline-end: var(--_ui5_radio_button_border_width); } -:host([text]) .ui5-radio-root:focus::before { +:host([text][desktop]) .ui5-radio-root:focus::before, +:host([text]) .ui5-radio-root:focus-visible::before { inset-inline-end: 0px; } diff --git a/packages/main/src/themes/TabContainer.css b/packages/main/src/themes/TabContainer.css index f6dc6ba5399d..f7e28a03e9bc 100644 --- a/packages/main/src/themes/TabContainer.css +++ b/packages/main/src/themes/TabContainer.css @@ -93,6 +93,7 @@ color: var(--_ui5_tc_overflow_text_color); } +/*TODO checkout out how button is implemented */ .ui5-tc__overflow > [ui5-button][focused] { outline-offset: 0.125rem; --_ui5_button_focused_border: none; diff --git a/packages/main/src/themes/TabInOverflow.css b/packages/main/src/themes/TabInOverflow.css index f0fcd04218b2..f7b06802f651 100644 --- a/packages/main/src/themes/TabInOverflow.css +++ b/packages/main/src/themes/TabInOverflow.css @@ -59,6 +59,7 @@ color: var(--_ui5_tc_overflowItem_current_color); } +/*TODO checkout out how li is implemented */ .ui5-tab-container-responsive-popover [ui5-li-custom][focused]::part(native-li)::after { inset: var(--_ui5_tc_overflowItem_focus_offset); } diff --git a/packages/main/src/themes/TabInStrip.css b/packages/main/src/themes/TabInStrip.css index 8bb18c70e2ea..759f0ca1b2df 100644 --- a/packages/main/src/themes/TabInStrip.css +++ b/packages/main/src/themes/TabInStrip.css @@ -166,8 +166,10 @@ outline: none; } -.ui5-tab-strip-item--textOnly:focus:not([data-moving]) .ui5-tab-strip-itemText::before, -.ui5-tab-strip-item--inline.ui5-tab-strip-item--textOnly:focus:not([data-moving]) .ui5-tab-strip-itemText::before { +:host([desktop]) .ui5-tab-strip-item--textOnly:focus:not([data-moving]) .ui5-tab-strip-itemText::before, +.ui5-tab-strip-item--textOnly:focus-visible:not([data-moving]) .ui5-tab-strip-itemText::before, +:host([desktop]) .ui5-tab-strip-item--inline.ui5-tab-strip-item--textOnly:focus:not([data-moving]) .ui5-tab-strip-itemText::before, +.ui5-tab-strip-item--inline.ui5-tab-strip-item--textOnly:focus-visible:not([data-moving]) .ui5-tab-strip-itemText::before { border-radius: var(--_ui5_tc_headerItem_focus_border_radius); content: ""; pointer-events: none; @@ -179,7 +181,8 @@ bottom: var(--_ui5_tc_headerItem_text_focus_border_offset_bottom); } -.ui5-tab-strip-item--mixedMode:focus:not([data-moving]) .ui5-tab-strip-itemContent::before { +:host([desktop]) .ui5-tab-strip-item--mixedMode:focus:not([data-moving]) .ui5-tab-strip-itemContent::before, +.ui5-tab-strip-item--mixedMode:focus-visible:not([data-moving]) .ui5-tab-strip-itemContent::before { border-radius: var(--_ui5_tc_headerItem_focus_border_radius); content: ""; pointer-events: none; @@ -191,7 +194,8 @@ bottom: var(--_ui5_tc_headerItem_mixed_mode_focus_border_offset_bottom); } -.ui5-tab-strip-item--withIcon:focus:not([data-moving]) .ui5-tab-strip-item-icon-outer::before { +:host([desktop]) .ui5-tab-strip-item--withIcon:focus:not([data-moving]) .ui5-tab-strip-item-icon-outer::before, +.ui5-tab-strip-item--withIcon:focus-visible:not([data-moving]) .ui5-tab-strip-item-icon-outer::before { content: ""; pointer-events: none; position: absolute; diff --git a/packages/main/src/themes/base/RadioButton-parameters.css b/packages/main/src/themes/base/RadioButton-parameters.css index b63e6d9be418..5bab240bcee2 100644 --- a/packages/main/src/themes/base/RadioButton-parameters.css +++ b/packages/main/src/themes/base/RadioButton-parameters.css @@ -22,7 +22,6 @@ --_ui5_radio_button_outer_ring_padding_with_label: 0 0.6875rem; --_ui5_radio_button_border_radius: 0; --_ui5_radio_button_border: none; - --_ui5_radio_button_focus_border: none; --_ui5_radio_button_focus_outline: block; --_ui5_radio_button_focus_dist: 0.5rem; --_ui5_radio_button_color: var(--sapField_BorderColor);