diff --git a/packages/web-react/src/components/Dropdown/DropdownTrigger.tsx b/packages/web-react/src/components/Dropdown/DropdownTrigger.tsx index a4407de03e..7b9019dbe2 100644 --- a/packages/web-react/src/components/Dropdown/DropdownTrigger.tsx +++ b/packages/web-react/src/components/Dropdown/DropdownTrigger.tsx @@ -1,6 +1,5 @@ 'use client'; -import classNames from 'classnames'; import React, { ElementType } from 'react'; import { useStyleProps } from '../../hooks'; import { DropdownTriggerProps } from '../../types'; @@ -14,25 +13,23 @@ const defaultProps = { const DropdownTrigger = (props: DropdownTriggerProps) => { const propsWithDefaults = { ...defaultProps, ...props }; - const { elementType = 'button', children, ...rest } = propsWithDefaults; + const { elementType: ElementTag = 'button', children, ...rest } = propsWithDefaults; const { id, isOpen, onToggle, fullWidthMode, triggerRef } = useDropdownContext(); - const Component = elementType; const { classProps, props: modifiedProps } = useDropdownStyleProps({ isOpen, ...rest }); - const { styleProps, props: otherProps } = useStyleProps(modifiedProps); + const { styleProps: triggerStyleProps, props: transferProps } = useStyleProps({ + ElementTag, + customClassName: classProps.trigger, + ...modifiedProps, + }); const { triggerProps } = useDropdownAriaProps({ id, isOpen, toggleHandler: onToggle, fullWidthMode }); return ( - + {typeof children === 'function' ? children({ isOpen }) : children} - + ); }; +DropdownTrigger.spiritComponent = 'DropdownTrigger'; + export default DropdownTrigger; diff --git a/packages/web-react/src/components/Dropdown/__tests__/DropdownTrigger.test.tsx b/packages/web-react/src/components/Dropdown/__tests__/DropdownTrigger.test.tsx index ab4212cbbb..9527f40fd3 100644 --- a/packages/web-react/src/components/Dropdown/__tests__/DropdownTrigger.test.tsx +++ b/packages/web-react/src/components/Dropdown/__tests__/DropdownTrigger.test.tsx @@ -8,8 +8,16 @@ import DropdownTrigger from '../DropdownTrigger'; jest.mock('../../../hooks/useIcon'); describe('DropdownTrigger', () => { + // pass style props to the default trigger + stylePropsTest((props) => ); + + // pass style props to the custom trigger stylePropsTest((props) => ); + // pass rest props to the default trigger + restPropsTest((props) => , 'button'); + + // pass rest props to the custom trigger restPropsTest((props) => , 'button'); it('should have Button elementType', () => { diff --git a/packages/web-react/src/hooks/__tests__/styleProps.test.ts b/packages/web-react/src/hooks/__tests__/styleProps.test.ts index bc5e28190e..2a527ff47b 100644 --- a/packages/web-react/src/hooks/__tests__/styleProps.test.ts +++ b/packages/web-react/src/hooks/__tests__/styleProps.test.ts @@ -1,4 +1,5 @@ import { renderHook } from '@testing-library/react'; +import { Button } from '../../components/Button'; import { StyleProps } from '../../types'; import { useStyleProps } from '../styleProps'; @@ -15,6 +16,10 @@ describe('styleProps', () => { { className: undefined, style: { 'vertical-align': 'center' } }, ], [{ role: 'button' }, { className: undefined, style: undefined }], + [ + { ElementTag: Button, UNSAFE_className: 'test-class' }, + { UNSAFE_className: 'test-class', style: undefined }, + ], ])('should use UNSAFE_style and UNSAFE_className props', (input, expected) => { const { result } = renderHook(() => useStyleProps(input as StyleProps)); @@ -125,6 +130,10 @@ describe('styleProps', () => { { margin: 'space-100', UNSAFE_className: 'm-500' }, { className: 'm-500 m-100', style: undefined }, ], + [ + { ElementTag: Button, margin: 'space-100', UNSAFE_className: 'm-500' }, + { UNSAFE_className: 'm-500 m-100', style: undefined }, + ], ])('should return correct combination of class and style', (input, expected) => { const { result } = renderHook(() => useStyleProps(input as StyleProps)); diff --git a/packages/web-react/src/hooks/styleProps.ts b/packages/web-react/src/hooks/styleProps.ts index c6a0aa3782..a0b8b95909 100644 --- a/packages/web-react/src/hooks/styleProps.ts +++ b/packages/web-react/src/hooks/styleProps.ts @@ -22,7 +22,7 @@ export function useStyleProps( additionalUtilities?: Record, ): StylePropsResult { const classNamePrefix = useContext(ClassNamePrefixContext); - const { UNSAFE_className, UNSAFE_style, ElementTag, ...otherProps } = props; + const { UNSAFE_className, UNSAFE_style, ElementTag, customClassName, ...otherProps } = props; const { styleUtilities, props: modifiedProps } = useStyleUtilities(otherProps, classNamePrefix, additionalUtilities); const style: CSSProperties = { ...UNSAFE_style }; @@ -58,7 +58,7 @@ export function useStyleProps( const styleProps = { style: Object.keys(style).length > 0 ? style : undefined, - className: classNames(UNSAFE_className, ...styleUtilities) || undefined, + className: classNames(UNSAFE_className, ...styleUtilities, customClassName) || undefined, }; return { @@ -70,7 +70,9 @@ export function useStyleProps( return { styleProps: { ...(UNSAFE_style !== undefined && { UNSAFE_style }), - ...(UNSAFE_className !== undefined && { UNSAFE_className }), + ...((UNSAFE_className !== undefined || styleUtilities !== undefined) && { + UNSAFE_className: classNames(UNSAFE_className, ...styleUtilities, customClassName), + }), }, props: modifiedProps as HTMLAttributes, }; diff --git a/packages/web-react/src/types/shared/style.ts b/packages/web-react/src/types/shared/style.ts index 96151d2ccc..9c8bef256a 100644 --- a/packages/web-react/src/types/shared/style.ts +++ b/packages/web-react/src/types/shared/style.ts @@ -23,6 +23,7 @@ export interface SpacingCSSProperties extends CSSProperties { type ElementTagType = string | ElementType; export interface StyleProps extends SpacingProps { + customClassName?: string; ElementTag?: ElementTagType; // For backward compatibility! /** Sets the CSS [className](https://developer.mozilla.org/en-US/docs/Web/API/Element/className) for the element. Only use as a **last resort**. Use style props instead. */