From 1c7c828267898a68e2c6d1a1a48330015dc5bd0d Mon Sep 17 00:00:00 2001 From: alexandru-morariu-lgp <84004128+alexandrumorariu@users.noreply.github.com> Date: Tue, 10 Feb 2026 11:16:28 +0200 Subject: [PATCH 1/2] Added selectOnFocus prop to enable selection on focus via pointer mode. --- CHANGELOG.md | 4 ++++ TabLayout/TabGroup.js | 12 ++++++++---- TabLayout/TabLayout.js | 12 +++++++++++- samples/sampler/stories/default/TabLayout.js | 2 ++ 4 files changed, 25 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0deaec7e7..ecff24755 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ The following is a curated list of changes in the Enact limestone module, newest ## [unreleased] +### Added + +- `limestone/TabLayout` `selectOnFocus` prop to enable selection when a tab is focused via pointer mode. + ### Fixed - `limestone/Card` press motion to work with key press diff --git a/TabLayout/TabGroup.js b/TabLayout/TabGroup.js index 0b56a7cbc..c42ae0156 100644 --- a/TabLayout/TabGroup.js +++ b/TabLayout/TabGroup.js @@ -35,6 +35,7 @@ const TabBase = kind({ onTabClick: PropTypes.func, orientation: PropTypes.string, selected: PropTypes.bool, + selectOnFocus: PropTypes.bool, sprite: PropTypes.object, stopped: PropTypes.bool }, @@ -58,7 +59,7 @@ const TabBase = kind({ onFocus: handle( forward('onFocus'), not(forProp('disabled', true)), - () => !Spotlight.getPointerMode(), + (ev, {selectOnFocus}) => (!Spotlight.getPointerMode() || selectOnFocus), forwardCustom('onFocusTab', (ev, {index}) => ({selected: index})) ) }, @@ -76,6 +77,7 @@ const TabBase = kind({ delete rest.noIcons; delete rest.onFocusTab; delete rest.onTabClick; + delete rest.selectOnFocus; delete rest.stopped; delete rest.sprite; @@ -173,6 +175,7 @@ const TabGroupBase = kind({ orientation: PropTypes.string, scrollPosition: PropTypes.object, selectedIndex: PropTypes.number, + selectOnFocus: PropTypes.bool, size: PropTypes.string, spotlightDisabled: PropTypes.bool, spotlightId: PropTypes.string @@ -192,7 +195,7 @@ const TabGroupBase = kind({ tabsSpotlightDisabled: ({spotlightDisabled, tabs}) => spotlightDisabled || tabs.find(tab => tab && !tab.spotlightDisabled) == null }, - render: ({css, collapsed, scrollable, id, noIcons, onBlur, onBlurList, onFocus, onFocusTab, onScrollStop, onSelect, orientation, primaryIndex, scrollPosition, selectedIndex, size, spotlightId, spotlightDisabled, tabs, tabsDisabled, tabsSpotlightDisabled, ...rest}) => { + render: ({css, collapsed, scrollable, id, noIcons, onBlur, onBlurList, onFocus, onFocusTab, onScrollStop, onSelect, orientation, primaryIndex, scrollPosition, selectedIndex, selectOnFocus, size, spotlightId, spotlightDisabled, tabs, tabsDisabled, tabsSpotlightDisabled, ...rest}) => { delete rest.children; const primaryTabSpotlightId = `${spotlightId}-primary-tab`; @@ -203,8 +206,9 @@ const TabGroupBase = kind({ collapsed, orientation, primaryIndex: collapsed ? null : primaryIndex, - primaryTabSpotlightId - }), [css, collapsed, orientation, primaryIndex, primaryTabSpotlightId, size]); + primaryTabSpotlightId, + selectOnFocus + }), [css, collapsed, orientation, primaryIndex, primaryTabSpotlightId, selectOnFocus, size]); // eslint-disable-next-line react-hooks/rules-of-hooks const children = useMemo(() => tabs.map(tab => { if (tab) { diff --git a/TabLayout/TabLayout.js b/TabLayout/TabLayout.js index 7930405b9..c1b012cc9 100644 --- a/TabLayout/TabLayout.js +++ b/TabLayout/TabLayout.js @@ -289,6 +289,14 @@ const TabLayoutBase = kind({ */ scrollPosition: PropTypes.object, + /** + * Indicates if tabs are to be selected via focus on pointer mode + * + * @type {Boolean} + * @public + */ + selectOnFocus: PropTypes.bool, + /** * The size of the horizontal tab. * @@ -340,6 +348,7 @@ const TabLayoutBase = kind({ primaryIndex: null, offset: 36, orientation: 'vertical', + selectOnFocus: false, scrollPosition: {x: 0, y: 0}, size: 'large', type: 'normal' @@ -510,7 +519,7 @@ const TabLayoutBase = kind({ } }, - render: ({children, collapsed, css, 'data-spotlight-id': spotlightId, primaryIndex, dimensions, handleClick, handleEnter, handleFlick, handleFocus, handleTabsTransitionEnd, index, onCollapse, onScrollStop, onSelect, orientation, scrollable, scrollPosition, size, tabOrientation, tabs, type, ...rest}) => { + render: ({children, collapsed, css, 'data-spotlight-id': spotlightId, primaryIndex, dimensions, handleClick, handleEnter, handleFlick, handleFocus, handleTabsTransitionEnd, index, onCollapse, onScrollStop, onSelect, orientation, selectOnFocus, scrollable, scrollPosition, size, tabOrientation, tabs, type, ...rest}) => { delete rest.anchorTo; delete rest.blockCollapseOnPortrait; delete rest.blockExpandOnLandscape; @@ -535,6 +544,7 @@ const TabLayoutBase = kind({ onSelect, orientation, selectedIndex: index, + selectOnFocus, tabs }; diff --git a/samples/sampler/stories/default/TabLayout.js b/samples/sampler/stories/default/TabLayout.js index cea130731..989024d69 100644 --- a/samples/sampler/stories/default/TabLayout.js +++ b/samples/sampler/stories/default/TabLayout.js @@ -64,6 +64,7 @@ export const _TabLayout = (args) => { onSelect={action('onSelect')} onTabAnimationEnd={action('onTabAnimationEnd')} orientation={args['orientation']} + selectOnFocus={args['selectOnFocus']} size={args['size']} tabSize={args['tabSize'] || null} > @@ -100,6 +101,7 @@ export const _TabLayout = (args) => { boolean('blockCollapseOnPortrait', _TabLayout, Config); boolean('blockExpandOnLandscape', _TabLayout, Config); select('tabs', _TabLayout, ['with icons', 'without icons'], Config, 'with icons'); +boolean('selectOnFocus', _TabLayout, Config); select('size', _TabLayout, ['small', 'large'], Config, 'large'); select('orientation', _TabLayout, ['vertical', 'horizontal'], Config); boolean('custom tabSize', _TabLayout, Config, false); From 74bfdf969c219eada6da05ea62f06e35d6bf89cc Mon Sep 17 00:00:00 2001 From: Daniel Stoian <63335068+daniel-stoian-lgp@users.noreply.github.com> Date: Wed, 11 Feb 2026 17:49:05 +0200 Subject: [PATCH 2/2] Apply suggestions from code review --- TabLayout/TabLayout.js | 1 + 1 file changed, 1 insertion(+) diff --git a/TabLayout/TabLayout.js b/TabLayout/TabLayout.js index c1b012cc9..f815e52c8 100644 --- a/TabLayout/TabLayout.js +++ b/TabLayout/TabLayout.js @@ -294,6 +294,7 @@ const TabLayoutBase = kind({ * * @type {Boolean} * @public + * @default false */ selectOnFocus: PropTypes.bool,