From 52eda97e91316274e6d6f0204dda23f2f2b3e03d Mon Sep 17 00:00:00 2001 From: Kerrie Wu Date: Sat, 14 Sep 2024 15:54:24 +0800 Subject: [PATCH] add props in BPK tabs --- .../examples.tsx | 40 ++++++++----- .../src/BpkNavigationTabGroup-test.tsx | 59 +++++++++++++++++-- .../src/BpkNavigationTabGroup.tsx | 35 +++++++---- .../src/accessibility-test.tsx | 14 +++-- 4 files changed, 111 insertions(+), 37 deletions(-) diff --git a/examples/bpk-component-navigation-tab-group/examples.tsx b/examples/bpk-component-navigation-tab-group/examples.tsx index eb4ddf7355..5a7b4f49f9 100644 --- a/examples/bpk-component-navigation-tab-group/examples.tsx +++ b/examples/bpk-component-navigation-tab-group/examples.tsx @@ -40,37 +40,38 @@ const carIcons = withRtlSupport(Car); const flightIcons = withRtlSupport(Flight); const tabs: BpkNavigationTabGroupProps['tabs'] = [ - { text: 'Flights', href: '/' }, - { text: 'Hotels', href: '/hotel' }, - { text: 'Car hire', href: '/carhire' }, - { text: 'Explore', href: '/Explore' }, + { id: 'air', text: 'Flights', href: '/' }, + { id: 'hotel', text: 'Hotels', href: '/hotel' }, + { id: 'car', text: 'Car hire', href: '/carhire' }, + { id: 'explore', text: 'Explore', href: '/Explore' }, ]; const tabsWithIcon: BpkNavigationTabGroupProps['tabs'] = [ - { text: 'Flights', href: '/', icon: flightIcons }, - { text: 'Hotels', href: '/hotel', icon: hotelIcons }, - { text: 'Car hire', href: '/carhire', icon: carIcons }, - { text: 'Explore', href: '/Explore', icon: exploreIcons }, + { id: 'air', text: 'Flights', href: '/', icon: flightIcons, dataCy:'flight-feature', dataAnalyticsName:'flights' }, + { id: 'hotel', text: 'Hotels', href: '/hotel', icon: hotelIcons, dataCy:'hotel-feature', dataAnalyticsName:'hotels' }, + { id: 'car', text: 'Car hire', href: '/carhire', icon: carIcons, dataCy:'carhire-feature', dataAnalyticsName:'car hire' }, + { id: 'explore', text: 'Explore', href: '/Explore', icon: exploreIcons, dataCy:'explore-feature', dataAnalyticsName:'explore' }, ]; const tabsNoHref: BpkNavigationTabGroupProps['tabs'] = [ - { text: 'Flights', icon: flightIcons }, - { text: 'Hotels', icon: hotelIcons }, - { text: 'Car hire', icon: carIcons }, - { text: 'Explore', icon: exploreIcons }, + { id: 'air', text: 'Flights', icon: flightIcons }, + { id: 'hotel', text: 'Hotels', icon: hotelIcons }, + { id: 'carhire', text: 'Car hire', icon: carIcons }, + { id: 'explore', text: 'Explore', icon: exploreIcons }, ]; const tabsOnlyText: BpkNavigationTabGroupProps['tabs'] = [ - { text: 'Flights'}, - { text: 'Hotels' }, - { text: 'Car hire'}, - { text: 'Explore'}, + { id: 'air', text: 'Flights'}, + { id: 'hotel', text: 'Hotels' }, + { id: 'carhire', text: 'Car hire'}, + { id: 'explore', text: 'Explore'}, ]; // Simple Navigation Tab Group const SimpleSurfaceContrast = () => (
{}} selectedIndex={2} @@ -86,6 +87,7 @@ const SimpleCanvasDefault = () => ( className={getClassNames('bpk-navigation-tab-group-story__canvas-default')} > {}} selectedIndex={0} @@ -98,6 +100,7 @@ const SimpleCanvasDefault = () => ( const WithIconSurfaceContrastForExample = () => (
{}} selectedIndex={0} @@ -111,6 +114,7 @@ const WithIconSurfaceContrastForExample = () => ( const WithIconCanvasDefaultForExample = () => (
{}} selectedIndex={0} @@ -124,6 +128,7 @@ const WithIconCanvasDefaultForExample = () => ( const TabsNoHrefSurfaceContrastForExample = () => (
{}} selectedIndex={0} @@ -137,6 +142,7 @@ const TabsNoHrefSurfaceContrastForExample = () => ( const TabsNoHrefCanvasDefaultForExample = () => (
{}} selectedIndex={0} @@ -150,6 +156,7 @@ const TabsNoHrefCanvasDefaultForExample = () => ( const TabsOnlyTextSurfaceContrastForExample = () => (
{}} selectedIndex={0} @@ -163,6 +170,7 @@ const TabsOnlyTextSurfaceContrastForExample = () => ( const TabsOnlyTextCanvasDefaultForExample = () => (
{}} selectedIndex={0} diff --git a/packages/bpk-component-navigation-tab-group/src/BpkNavigationTabGroup-test.tsx b/packages/bpk-component-navigation-tab-group/src/BpkNavigationTabGroup-test.tsx index 85536adb96..3413ec1d17 100644 --- a/packages/bpk-component-navigation-tab-group/src/BpkNavigationTabGroup-test.tsx +++ b/packages/bpk-component-navigation-tab-group/src/BpkNavigationTabGroup-test.tsx @@ -24,9 +24,15 @@ import BpkNavigationTabGroup, { NAVIGATION_TAB_GROUP_TYPES } from './BpkNavigati import type { Props } from './BpkNavigationTabGroup'; const tabs: Props['tabs'] = [ - { text: 'Flights', href: '/' }, - { text: 'Hotels', href: '/hotel' }, - { text: 'Car hire', href: '/carhire' }, + { id: 'air', text: 'Flights', href: '/' }, + { id: 'hotel', text: 'Hotels', href: '/hotel' }, + { id: 'car', text: 'Car hire', href: '/carhire' }, +]; + +const tabsWithAnalytics: Props['tabs'] = [ + { id: 'air', text: 'Flights', href: '/', dataCy:'flight-feature', dataAnalyticsName:'flights' }, + { id: 'hotel', text: 'Hotels', href: '/hotel', dataCy:'hotel-feature', dataAnalyticsName:'hotels' }, + { id: 'car', text: 'Car hire', href: '/carhire', dataCy:'carhire-feature', dataAnalyticsName:'car hire' }, ]; describe('BpkNavigationTabGroup', () => { @@ -41,6 +47,7 @@ describe('BpkNavigationTabGroup', () => { it('should render correctly', () => { render( {}} selectedIndex={0} @@ -57,6 +64,7 @@ describe('BpkNavigationTabGroup', () => { it('should render selected link', () => { render( {}} selectedIndex={0} @@ -79,6 +87,7 @@ describe('BpkNavigationTabGroup', () => { render( { expect(onItemClick).toHaveBeenCalledTimes(1); expect(onItemClick).toHaveBeenCalledWith( - { text: 'Hotels', href: '/hotel' }, + expect.any(Object), + { id:'hotel', text: 'Hotels', href: '/hotel' }, 1, ); }); @@ -98,6 +108,7 @@ describe('BpkNavigationTabGroup', () => { it('should render correctly when type is CanvasDefault', () => { render( {}} selectedIndex={0} @@ -111,4 +122,44 @@ describe('BpkNavigationTabGroup', () => { expect(flightLink).toHaveClass('bpk-navigation-tab-wrap--canvas-default'); }); + + it('should render correctly props when tab props with data analytics', () => { + render( + {}} + selectedIndex={0} + type={NAVIGATION_TAB_GROUP_TYPES.CanvasDefault} + ariaLabel="Navigation tabs" + />, + ); + + const flightTextElement = screen.getByText('Flights'); + const flightLink = flightTextElement.closest('a'); + + expect(flightLink).toHaveAttribute('id', 'air'); + expect(flightLink).toHaveAttribute('data-cy', 'flight-feature'); + expect(flightLink).toHaveAttribute('data-analytics-name', 'flights'); + }); + + it('should render correctly props when tab props without data analytics', () => { + render( + {}} + selectedIndex={0} + type={NAVIGATION_TAB_GROUP_TYPES.CanvasDefault} + ariaLabel="Navigation tabs" + />, + ); + + const flightTextElement = screen.getByText('Flights'); + const flightLink = flightTextElement.closest('a'); + + expect(flightLink).toHaveAttribute('id', 'air'); + expect(flightLink).not.toHaveAttribute('data-cy'); + expect(flightLink).not.toHaveAttribute('data-analytics-name'); + }); }); diff --git a/packages/bpk-component-navigation-tab-group/src/BpkNavigationTabGroup.tsx b/packages/bpk-component-navigation-tab-group/src/BpkNavigationTabGroup.tsx index e3973e645c..0f388a5d25 100644 --- a/packages/bpk-component-navigation-tab-group/src/BpkNavigationTabGroup.tsx +++ b/packages/bpk-component-navigation-tab-group/src/BpkNavigationTabGroup.tsx @@ -16,7 +16,7 @@ * limitations under the License. */ -import type { FunctionComponent, ReactElement } from 'react'; +import type { MouseEvent, FunctionComponent, ReactElement } from 'react'; import { useState } from 'react'; import BpkText, { TEXT_STYLES } from '../../bpk-component-text'; @@ -34,17 +34,21 @@ export type NavigationTabGroupTypes = (typeof NAVIGATION_TAB_GROUP_TYPES)[keyof typeof NAVIGATION_TAB_GROUP_TYPES]; type TabItem = { + id: string; text: string; icon?: FunctionComponent | null; href?: string; + dataCy?: string; + dataAnalyticsName?: string; }; export type Props = { + id: string; tabs: TabItem[]; type?: NavigationTabGroupTypes; /* * Index parameter to track which is clicked */ - onItemClick: (tab: TabItem, index: number) => void; + onItemClick: (e: MouseEvent,tab: TabItem, index: number) => void; selectedIndex: number; ariaLabel: string; }; @@ -54,7 +58,7 @@ type TabWrapProps = { type: NavigationTabGroupTypes; selected: boolean; children: ReactElement; - onClick: () => void; + onClick: (e: MouseEvent) => void; }; const TabWrap = ({ children, onClick, selected, tab, type }: TabWrapProps) => { @@ -64,22 +68,29 @@ const TabWrap = ({ children, onClick, selected, tab, type }: TabWrapProps) => { selected && `bpk-navigation-tab-wrap--${type}-selected`, ); + const tabProps = { + ...(tab.dataCy && { 'data-cy': tab.dataCy }), + ...(tab.dataAnalyticsName && { 'data-analytics-name': tab.dataAnalyticsName }), + id: tab.id, + className: tabStyling, + }; + return tab.href ? ( ) => onClick(e)} aria-current={selected ? 'page' : false} > {children} ) : ( @@ -88,23 +99,25 @@ const TabWrap = ({ children, onClick, selected, tab, type }: TabWrapProps) => { const BpkNavigationTabGroup = ({ ariaLabel, + id, onItemClick, selectedIndex, tabs, type = NAVIGATION_TAB_GROUP_TYPES.SurfaceContrast, }: Props) => { const [selectedTab, setSelectedTab] = useState(selectedIndex); - const handleButtonClick = (tab: TabItem, index: number) => { + const handleButtonClick = (e: MouseEvent, tab: TabItem, index: number) => { if (index !== selectedTab) { setSelectedTab(index); } - onItemClick(tab, index); + onItemClick(e, tab, index); }; const containerStyling = getClassName('bpk-navigation-tab-group'); return (