From 1a3f136d5c910a049f872af664ddada1548b41d2 Mon Sep 17 00:00:00 2001 From: Jialecl Date: Mon, 7 Jul 2025 11:56:08 +0200 Subject: [PATCH 01/11] Old props removed and adding scroll to active tab in responsive mode --- packages/lib/src/tabs/Tabs.stories.tsx | 2 +- packages/lib/src/tabs/Tabs.tsx | 19 +++---- packages/lib/src/tabs/types.ts | 74 +------------------------- 3 files changed, 10 insertions(+), 85 deletions(-) diff --git a/packages/lib/src/tabs/Tabs.stories.tsx b/packages/lib/src/tabs/Tabs.stories.tsx index 31c4522a2..a99f69a74 100644 --- a/packages/lib/src/tabs/Tabs.stories.tsx +++ b/packages/lib/src/tabs/Tabs.stories.tsx @@ -36,7 +36,7 @@ const tabs = (margin?: Space | Margin) => ( <> - + <> diff --git a/packages/lib/src/tabs/Tabs.tsx b/packages/lib/src/tabs/Tabs.tsx index 556f3df9f..524dcf76c 100644 --- a/packages/lib/src/tabs/Tabs.tsx +++ b/packages/lib/src/tabs/Tabs.tsx @@ -90,17 +90,7 @@ const ScrollableTabsList = styled.div<{ height: ${({ iconPosition }) => (iconPosition === "top" ? "72px" : "var(--height-xxl)")}; `; -const DxcTabs = ({ - activeTabIndex, - children, - defaultActiveTabIndex, - iconPosition = "left", - margin, - onTabClick, - onTabHover, - tabIndex = 0, - tabs, -}: TabsPropsType) => { +const DxcTabs = ({ children, iconPosition = "left", margin, tabIndex = 0 }: TabsPropsType) => { const childrenArray: ReactElement[] = useMemo( () => Children.toArray(children) as ReactElement[], [children] @@ -199,7 +189,12 @@ const DxcTabs = ({ if (refTabList.current) setTotalTabsWidth(() => { let total = 0; - refTabList.current?.querySelectorAll('[role="tab"]').forEach((tab) => { + refTabList.current?.querySelectorAll('[role="tab"]').forEach((tab, index) => { + if (tab.ariaSelected === "true") { + console.log(-total); + setTranslateScroll(-total); + if (index) setScrollLeftEnabled(true); + } total += (tab as HTMLElement).offsetWidth; }); return total; diff --git a/packages/lib/src/tabs/types.ts b/packages/lib/src/tabs/types.ts index e940f2b70..b3d4578de 100644 --- a/packages/lib/src/tabs/types.ts +++ b/packages/lib/src/tabs/types.ts @@ -2,21 +2,6 @@ import { ReactNode } from "react"; import type { Space, Margin, SVG } from "../common/utils"; -type TabCommonProps = { - /** - * Whether the tab is disabled or not. - */ - isDisabled?: boolean; - /** - * If the value is 'true', an empty badge will appear. - * If it is 'false', no badge will appear. - * If a number is put it will be shown as the label of the notification - * in the tab, taking into account that if that number is greater than 99, - * it will appear as '+99' in the badge. - */ - notificationNumber?: boolean | number; -}; - export type TabsContextProps = { activeTabId?: string; focusedTabId?: string; @@ -48,17 +33,6 @@ export type TabIconProps = { icon: string | SVG; }; -export type TabPropsLegacy = { - tab: TabCommonProps & (TabLabelProps | TabIconProps); - active: boolean; - tabIndex: number; - hasLabelAndIcon: boolean; - iconPosition: "top" | "left"; - onClick: () => void; - onMouseEnter: () => void; - onMouseLeave: () => void; -}; - export type TabProps = { defaultActive?: boolean; active?: boolean; @@ -71,51 +45,7 @@ export type TabProps = { onHover?: () => void; } & (TabLabelProps | TabIconProps); -type LegacyProps = { - /** - * @deprecated This prop is deprecated and will be removed in future versions. Use the children prop instead. - * The index of the active tab. If undefined, the component will be - * uncontrolled and the active tab will be managed internally by the component. - */ - activeTabIndex?: number; - /** - * @deprecated This prop is deprecated and will be removed in future versions. - * Initially active tab, only when it is uncontrolled. - */ - defaultActiveTabIndex?: number; - /** - * Whether the icon should appear above or to the left of the label. - */ - iconPosition?: "top" | "left"; - /** - * Size of the margin to be applied to the component ('xxsmall' | 'xsmall' | 'small' | 'medium' | 'large' | 'xlarge' | 'xxlarge'). - * You can pass an object with 'top', 'bottom', 'left' and 'right' properties in order to specify different margin sizes. - */ - margin?: Space | Margin; - /** - * @deprecated This prop is deprecated and will be removed in future versions. - * This function will be called when the user clicks on a tab. The index of the - * clicked tab will be passed as a parameter. - */ - onTabClick?: (index: number) => void; - /** - * @deprecated This prop is deprecated and will be removed in future versions. - * This function will be called when the user hovers a tab.The index of the - * hovered tab will be passed as a parameter. - */ - onTabHover?: (index: number | null) => void; - /** - * Value of the tabindex attribute applied to each tab. - */ - tabIndex?: number; - /** - * @deprecated This prop is deprecated and will be removed in future versions. - * An array of objects representing the tabs. - */ - tabs?: (TabCommonProps & (TabLabelProps | TabIconProps))[]; -}; - -type NewProps = { +type TabsProps = { /** * Whether the icon should appear above or to the left of the label. */ @@ -135,6 +65,6 @@ type NewProps = { children?: ReactNode; }; -type Props = LegacyProps & NewProps; +type Props = TabsProps; export default Props; From 63e8569e71d1bbc6c31dc593b4d638917836deb8 Mon Sep 17 00:00:00 2001 From: Jialecl Date: Mon, 7 Jul 2025 12:30:56 +0200 Subject: [PATCH 02/11] debug message removed --- packages/lib/src/tabs/Tabs.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/lib/src/tabs/Tabs.tsx b/packages/lib/src/tabs/Tabs.tsx index 524dcf76c..c3f226426 100644 --- a/packages/lib/src/tabs/Tabs.tsx +++ b/packages/lib/src/tabs/Tabs.tsx @@ -191,7 +191,6 @@ const DxcTabs = ({ children, iconPosition = "left", margin, tabIndex = 0 }: Tabs let total = 0; refTabList.current?.querySelectorAll('[role="tab"]').forEach((tab, index) => { if (tab.ariaSelected === "true") { - console.log(-total); setTranslateScroll(-total); if (index) setScrollLeftEnabled(true); } From 16a11c3220c69a7e2d38e35d2fb097df7869150f Mon Sep 17 00:00:00 2001 From: Jialecl Date: Tue, 8 Jul 2025 11:34:22 +0200 Subject: [PATCH 03/11] Fixed scroll when active is changed --- packages/lib/src/tabs/Tabs.stories.tsx | 6 +++--- packages/lib/src/tabs/Tabs.tsx | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/lib/src/tabs/Tabs.stories.tsx b/packages/lib/src/tabs/Tabs.stories.tsx index a99f69a74..83422c53d 100644 --- a/packages/lib/src/tabs/Tabs.stories.tsx +++ b/packages/lib/src/tabs/Tabs.stories.tsx @@ -36,7 +36,7 @@ const tabs = (margin?: Space | Margin) => ( <> - + <> @@ -266,7 +266,7 @@ const Scroll = () => ( {tabs()} </ExampleContainer> - <ExampleContainer pseudoState="pseudo-hover"> + {/* <ExampleContainer pseudoState="pseudo-hover"> <Title title="Hovered tabs" theme="light" level={4} /> {tabs()} </ExampleContainer> @@ -277,7 +277,7 @@ const Scroll = () => ( <ExampleContainer pseudoState="pseudo-active"> <Title title="Actived tabs" theme="light" level={4} /> {tabs()} - </ExampleContainer> + </ExampleContainer> */} </> ); diff --git a/packages/lib/src/tabs/Tabs.tsx b/packages/lib/src/tabs/Tabs.tsx index c3f226426..2421f7d53 100644 --- a/packages/lib/src/tabs/Tabs.tsx +++ b/packages/lib/src/tabs/Tabs.tsx @@ -191,7 +191,7 @@ const DxcTabs = ({ children, iconPosition = "left", margin, tabIndex = 0 }: Tabs let total = 0; refTabList.current?.querySelectorAll('[role="tab"]').forEach((tab, index) => { if (tab.ariaSelected === "true") { - setTranslateScroll(-total); + setInnerFocusIndex(index); if (index) setScrollLeftEnabled(true); } total += (tab as HTMLElement).offsetWidth; From 624fcec1ce1fca3f40f7d3a11eb000513ac6212d Mon Sep 17 00:00:00 2001 From: Jialecl <jialestrabajos@gmail.com> Date: Tue, 8 Jul 2025 12:08:45 +0200 Subject: [PATCH 04/11] added back tests --- packages/lib/src/tabs/Tabs.stories.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/lib/src/tabs/Tabs.stories.tsx b/packages/lib/src/tabs/Tabs.stories.tsx index 83422c53d..6f168c701 100644 --- a/packages/lib/src/tabs/Tabs.stories.tsx +++ b/packages/lib/src/tabs/Tabs.stories.tsx @@ -266,7 +266,7 @@ const Scroll = () => ( <Title title="Only label" theme="light" level={4} /> {tabs()} </ExampleContainer> - {/* <ExampleContainer pseudoState="pseudo-hover"> + <ExampleContainer pseudoState="pseudo-hover"> <Title title="Hovered tabs" theme="light" level={4} /> {tabs()} </ExampleContainer> @@ -277,7 +277,7 @@ const Scroll = () => ( <ExampleContainer pseudoState="pseudo-active"> <Title title="Actived tabs" theme="light" level={4} /> {tabs()} - </ExampleContainer> */} + </ExampleContainer> </> ); From e436616c1c194802b2359c33476d0668692357ba Mon Sep 17 00:00:00 2001 From: Jialecl <jialestrabajos@gmail.com> Date: Tue, 8 Jul 2025 14:12:11 +0200 Subject: [PATCH 05/11] changed button behaviour --- packages/lib/src/tabs/Tabs.tsx | 55 +++++++++++++++------------------- 1 file changed, 24 insertions(+), 31 deletions(-) diff --git a/packages/lib/src/tabs/Tabs.tsx b/packages/lib/src/tabs/Tabs.tsx index 2421f7d53..7512d1c78 100644 --- a/packages/lib/src/tabs/Tabs.tsx +++ b/packages/lib/src/tabs/Tabs.tsx @@ -81,11 +81,8 @@ const TabsContent = styled.div` const ScrollableTabsList = styled.div<{ enabled: boolean; iconPosition: TabsPropsType["iconPosition"]; - translateScroll: number; }>` display: flex; - ${({ enabled, translateScroll }) => - enabled ? `transform: translateX(${translateScroll}px)` : "transform: translateX(0px)"}; transition: all 300ms cubic-bezier(0.4, 0, 0.2, 1) 0ms; height: ${({ iconPosition }) => (iconPosition === "top" ? "72px" : "var(--height-xxl)")}; `; @@ -107,12 +104,11 @@ const DxcTabs = ({ children, iconPosition = "left", margin, tabIndex = 0 }: Tabs return isValidElement(initialActiveTab) ? (initialActiveTab.props.label ?? initialActiveTab.props.tabId) : ""; }); - const [countClick, setCountClick] = useState(0); const [innerFocusIndex, setInnerFocusIndex] = useState<number | null>(null); const [scrollLeftEnabled, setScrollLeftEnabled] = useState(false); const [scrollRightEnabled, setScrollRightEnabled] = useState(true); - const [translateScroll, setTranslateScroll] = useState(0); const [totalTabsWidth, setTotalTabsWidth] = useState(0); + const refTabListContainer = useRef<HTMLDivElement | null>(null); const refTabList = useRef<HTMLDivElement | null>(null); const translatedLabels = useContext(HalstackLanguageContext); const viewWidth = useWidth(refTabList.current); @@ -128,36 +124,32 @@ const DxcTabs = ({ children, iconPosition = "left", margin, tabIndex = 0 }: Tabs }; }, [activeTabId, childrenArray, iconPosition, innerFocusIndex, tabIndex]); + const scrollLimitCheck = () => { + if (refTabListContainer.current) { + refTabListContainer.current.scrollLeft -= 100; + if (refTabListContainer.current.scrollLeft <= 0) setScrollLeftEnabled(false); + else setScrollLeftEnabled(true); + } + if (refTabListContainer.current) { + refTabListContainer.current.scrollLeft += 100; + if (refTabListContainer.current.scrollLeft >= refTabListContainer.current.offsetWidth) + setScrollRightEnabled(false); + else setScrollRightEnabled(true); + } + }; + const scrollLeft = () => { - const offsetHeight = refTabList?.current?.offsetHeight ?? 0; - let moveX = 0; - if (countClick <= offsetHeight) { - moveX = 0; - setScrollLeftEnabled(false); - setScrollRightEnabled(true); - } else { - moveX = countClick - offsetHeight * 2; - setScrollRightEnabled(true); - setScrollLeftEnabled(true); + if (refTabListContainer.current) { + refTabListContainer.current.scrollLeft -= 100; + scrollLimitCheck(); } - setTranslateScroll(-moveX); - setCountClick(moveX); }; const scrollRight = () => { - const offsetHeight = refTabList?.current?.offsetHeight ?? 0; - let moveX = 0; - if (countClick + offsetHeight >= totalTabsWidth) { - moveX = totalTabsWidth - offsetHeight; - setScrollRightEnabled(false); - setScrollLeftEnabled(true); - } else { - moveX = countClick + offsetHeight * 2; - setScrollLeftEnabled(true); - setScrollRightEnabled(true); + if (refTabListContainer.current) { + refTabListContainer.current.scrollLeft += 100; + scrollLimitCheck(); } - setTranslateScroll(-moveX); - setCountClick(moveX); }; const handleOnKeyDown = (event: KeyboardEvent<HTMLDivElement>) => { @@ -169,11 +161,13 @@ const DxcTabs = ({ children, iconPosition = "left", margin, tabIndex = 0 }: Tabs case "ArrowLeft": event.preventDefault(); setInnerFocusIndex(getPreviousTabIndex(childrenArray, innerFocusIndex === null ? activeTab : innerFocusIndex)); + scrollLimitCheck(); break; case "Right": case "ArrowRight": event.preventDefault(); setInnerFocusIndex(getNextTabIndex(childrenArray, innerFocusIndex === null ? activeTab : innerFocusIndex)); + scrollLimitCheck(); break; case "Tab": if (activeTab !== innerFocusIndex) { @@ -215,14 +209,13 @@ const DxcTabs = ({ children, iconPosition = "left", margin, tabIndex = 0 }: Tabs <DxcIcon icon="keyboard_arrow_left" /> </ScrollIndicatorButton> )} - <TabsContent> + <TabsContent ref={refTabListContainer}> <ScrollableTabsList enabled={viewWidth < totalTabsWidth} iconPosition={iconPosition} onKeyDown={handleOnKeyDown} ref={refTabList} role="tablist" - translateScroll={translateScroll} > <TabsContext.Provider value={contextValue}>{children}</TabsContext.Provider> </ScrollableTabsList> From ba0aafec8ede00ac06eb7dd3fdc44df99905acba Mon Sep 17 00:00:00 2001 From: Jialecl <jialestrabajos@gmail.com> Date: Wed, 9 Jul 2025 08:34:35 +0200 Subject: [PATCH 06/11] fixed timing issue due to child component focus --- packages/lib/src/tabs/Tabs.tsx | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/packages/lib/src/tabs/Tabs.tsx b/packages/lib/src/tabs/Tabs.tsx index 7512d1c78..64d297959 100644 --- a/packages/lib/src/tabs/Tabs.tsx +++ b/packages/lib/src/tabs/Tabs.tsx @@ -125,16 +125,15 @@ const DxcTabs = ({ children, iconPosition = "left", margin, tabIndex = 0 }: Tabs }, [activeTabId, childrenArray, iconPosition, innerFocusIndex, tabIndex]); const scrollLimitCheck = () => { - if (refTabListContainer.current) { - refTabListContainer.current.scrollLeft -= 100; - if (refTabListContainer.current.scrollLeft <= 0) setScrollLeftEnabled(false); - else setScrollLeftEnabled(true); - } - if (refTabListContainer.current) { - refTabListContainer.current.scrollLeft += 100; - if (refTabListContainer.current.scrollLeft >= refTabListContainer.current.offsetWidth) - setScrollRightEnabled(false); - else setScrollRightEnabled(true); + const container = refTabListContainer.current; + if (container) { + const currentScroll = container.scrollLeft; + const scrollingLength = container.scrollWidth - container.offsetWidth; + const startingScroll = currentScroll <= 1; + const endScroll = currentScroll >= scrollingLength - 1; + + setScrollLeftEnabled(!startingScroll); + setScrollRightEnabled(!endScroll); } }; @@ -156,18 +155,20 @@ const DxcTabs = ({ children, iconPosition = "left", margin, tabIndex = 0 }: Tabs const activeTab = childrenArray.findIndex( (child: ReactElement) => (child.props.label ?? child.props.tabId) === activeTabId ); + let index; switch (event.key) { case "Left": case "ArrowLeft": event.preventDefault(); - setInnerFocusIndex(getPreviousTabIndex(childrenArray, innerFocusIndex === null ? activeTab : innerFocusIndex)); - scrollLimitCheck(); + index = getPreviousTabIndex(childrenArray, innerFocusIndex === null ? activeTab : innerFocusIndex); + setInnerFocusIndex(index); + break; case "Right": case "ArrowRight": event.preventDefault(); - setInnerFocusIndex(getNextTabIndex(childrenArray, innerFocusIndex === null ? activeTab : innerFocusIndex)); - scrollLimitCheck(); + index = getNextTabIndex(childrenArray, innerFocusIndex === null ? activeTab : innerFocusIndex); + setInnerFocusIndex(index); break; case "Tab": if (activeTab !== innerFocusIndex) { @@ -177,6 +178,9 @@ const DxcTabs = ({ children, iconPosition = "left", margin, tabIndex = 0 }: Tabs default: break; } + setTimeout(() => { + scrollLimitCheck(); + }, 0); }; useLayoutEffect(() => { From 6ddfa623ec428fb97898d048c915190c36aa7904 Mon Sep 17 00:00:00 2001 From: Jialecl <jialestrabajos@gmail.com> Date: Wed, 9 Jul 2025 13:03:30 +0200 Subject: [PATCH 07/11] new visual test --- packages/lib/src/tabs/Tabs.stories.tsx | 42 +++++++++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-) diff --git a/packages/lib/src/tabs/Tabs.stories.tsx b/packages/lib/src/tabs/Tabs.stories.tsx index 6f168c701..a27c8ca70 100644 --- a/packages/lib/src/tabs/Tabs.stories.tsx +++ b/packages/lib/src/tabs/Tabs.stories.tsx @@ -36,7 +36,7 @@ const tabs = (margin?: Space | Margin) => ( <DxcTabs.Tab label="Tab 4"> <></> </DxcTabs.Tab> - <DxcTabs.Tab label="Tab 5" defaultActive title="test tooltip 5"> + <DxcTabs.Tab label="Tab 5" title="test tooltip 5"> <></> </DxcTabs.Tab> <DxcTabs.Tab label="Tab 6"> @@ -281,6 +281,36 @@ const Scroll = () => ( </> ); +const ResponsiveFocused = () => ( + <> + <ExampleContainer> + <DxcTabs> + <DxcTabs.Tab label="Tab 1" title="test tooltip"> + <></> + </DxcTabs.Tab> + <DxcTabs.Tab label="Tab 2"> + <></> + </DxcTabs.Tab> + <DxcTabs.Tab label="Tab 3" disabled> + <></> + </DxcTabs.Tab> + <DxcTabs.Tab label="Tab 4"> + <></> + </DxcTabs.Tab> + <DxcTabs.Tab label="Tab 5" title="test tooltip 5"> + <></> + </DxcTabs.Tab> + <DxcTabs.Tab label="Tab 6"> + <></> + </DxcTabs.Tab> + <DxcTabs.Tab label="Tab 7" defaultActive> + <></> + </DxcTabs.Tab> + </DxcTabs> + </ExampleContainer> + </> +); + type Story = StoryObj<typeof DxcTabs>; export const Chromatic: Story = { @@ -301,3 +331,13 @@ export const ScrollableTabs: Story = { chromatic: { viewports: [375], delay: 5000 }, }, }; + +export const ResponsiveFocusedTabs: Story = { + render: ResponsiveFocused, + parameters: { + viewport: { + defaultViewport: "iphonex", + }, + chromatic: { viewports: [375], delay: 5000 }, + }, +}; From 01752c84aca93ff32181179631733c00afec471f Mon Sep 17 00:00:00 2001 From: Jialecl <jialestrabajos@gmail.com> Date: Wed, 9 Jul 2025 13:03:39 +0200 Subject: [PATCH 08/11] bug fixed --- packages/lib/src/tabs/Tabs.tsx | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/lib/src/tabs/Tabs.tsx b/packages/lib/src/tabs/Tabs.tsx index 64d297959..4e99f2a8d 100644 --- a/packages/lib/src/tabs/Tabs.tsx +++ b/packages/lib/src/tabs/Tabs.tsx @@ -4,6 +4,7 @@ import { KeyboardEvent, ReactElement, useContext, + useEffect, useLayoutEffect, useMemo, useRef, @@ -183,20 +184,20 @@ const DxcTabs = ({ children, iconPosition = "left", margin, tabIndex = 0 }: Tabs }, 0); }; - useLayoutEffect(() => { + useEffect(() => { if (refTabList.current) setTotalTabsWidth(() => { let total = 0; refTabList.current?.querySelectorAll('[role="tab"]').forEach((tab, index) => { if (tab.ariaSelected === "true") { setInnerFocusIndex(index); - if (index) setScrollLeftEnabled(true); } total += (tab as HTMLElement).offsetWidth; }); return total; }); - }, []); + scrollLimitCheck(); + }, [viewWidth]); return ( <> From 86c3f1ac3896f84d2151992728618cb8938045ce Mon Sep 17 00:00:00 2001 From: Jialecl <jialestrabajos@gmail.com> Date: Wed, 9 Jul 2025 13:20:40 +0200 Subject: [PATCH 09/11] adding width check to avoid focus whenever it is unresponsive --- packages/lib/src/tabs/Tabs.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/lib/src/tabs/Tabs.tsx b/packages/lib/src/tabs/Tabs.tsx index 4e99f2a8d..76845c4c6 100644 --- a/packages/lib/src/tabs/Tabs.tsx +++ b/packages/lib/src/tabs/Tabs.tsx @@ -189,7 +189,7 @@ const DxcTabs = ({ children, iconPosition = "left", margin, tabIndex = 0 }: Tabs setTotalTabsWidth(() => { let total = 0; refTabList.current?.querySelectorAll('[role="tab"]').forEach((tab, index) => { - if (tab.ariaSelected === "true") { + if (tab.ariaSelected === "true" && viewWidth < totalTabsWidth) { setInnerFocusIndex(index); } total += (tab as HTMLElement).offsetWidth; @@ -197,7 +197,7 @@ const DxcTabs = ({ children, iconPosition = "left", margin, tabIndex = 0 }: Tabs return total; }); scrollLimitCheck(); - }, [viewWidth]); + }, [viewWidth, totalTabsWidth]); return ( <> From c41ab2f632be1d66d2d5687b5b6ab52d8ac7b31c Mon Sep 17 00:00:00 2001 From: Jialecl <jialestrabajos@gmail.com> Date: Wed, 9 Jul 2025 13:58:22 +0200 Subject: [PATCH 10/11] additional width checks --- packages/lib/src/tabs/Tabs.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/lib/src/tabs/Tabs.tsx b/packages/lib/src/tabs/Tabs.tsx index 76845c4c6..3d6d3dce1 100644 --- a/packages/lib/src/tabs/Tabs.tsx +++ b/packages/lib/src/tabs/Tabs.tsx @@ -189,7 +189,7 @@ const DxcTabs = ({ children, iconPosition = "left", margin, tabIndex = 0 }: Tabs setTotalTabsWidth(() => { let total = 0; refTabList.current?.querySelectorAll('[role="tab"]').forEach((tab, index) => { - if (tab.ariaSelected === "true" && viewWidth < totalTabsWidth) { + if (tab.ariaSelected === "true" && viewWidth && viewWidth < totalTabsWidth) { setInnerFocusIndex(index); } total += (tab as HTMLElement).offsetWidth; From c8c3967e2391b4aa319b791858dd32fa88f11a48 Mon Sep 17 00:00:00 2001 From: Enrique Moreno <enrique.moreno@dxc.com> Date: Mon, 14 Jul 2025 08:50:12 +0200 Subject: [PATCH 11/11] Added fix for ResizeObserver mock --- packages/lib/src/tabs/Tabs.accessibility.test.tsx | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/packages/lib/src/tabs/Tabs.accessibility.test.tsx b/packages/lib/src/tabs/Tabs.accessibility.test.tsx index 33f6d052c..27a8f562e 100644 --- a/packages/lib/src/tabs/Tabs.accessibility.test.tsx +++ b/packages/lib/src/tabs/Tabs.accessibility.test.tsx @@ -2,6 +2,12 @@ import { render } from "@testing-library/react"; import { axe } from "../../test/accessibility/axe-helper"; import DxcTabs from "./Tabs"; +(global as any).ResizeObserver = class ResizeObserver { + observe() {} + unobserve() {} + disconnect() {} +}; + const iconSVG = ( <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" height="20" width="20" fill="currentColor"> <path d="m10 17-1.042-.938q-2.083-1.854-3.437-3.177-1.354-1.323-2.136-2.354Q2.604 9.5 2.302 8.646 2 7.792 2 6.896q0-1.854 1.271-3.125T6.396 2.5q1.021 0 1.979.438.958.437 1.625 1.229.667-.792 1.625-1.229.958-.438 1.979-.438 1.854 0 3.125 1.271T18 6.896q0 .896-.292 1.729-.291.833-1.073 1.854-.781 1.021-2.145 2.365-1.365 1.344-3.49 3.26Zm0-2.021q1.938-1.729 3.188-2.948 1.25-1.219 1.989-2.125.74-.906 1.031-1.614.292-.709.292-1.396 0-1.229-.833-2.063Q14.833 4 13.604 4q-.729 0-1.364.302-.636.302-1.094.844L10.417 6h-.834l-.729-.854q-.458-.542-1.114-.844Q7.083 4 6.396 4q-1.229 0-2.063.833-.833.834-.833 2.063 0 .687.271 1.364.271.678.989 1.573.719.896 1.98 2.125Q8 13.188 10 14.979Zm0-5.5Z" />