diff --git a/packages/react/__tests__/__snapshots__/PublicAPI-test.js.snap b/packages/react/__tests__/__snapshots__/PublicAPI-test.js.snap index 580ba15890c8..4dbda9318f52 100644 --- a/packages/react/__tests__/__snapshots__/PublicAPI-test.js.snap +++ b/packages/react/__tests__/__snapshots__/PublicAPI-test.js.snap @@ -2645,6 +2645,9 @@ Map { "onChange": Object { "type": "func", }, + "renderSelectedItem": Object { + "type": "func", + }, "selectedItem": Object { "args": Array [ Array [ diff --git a/packages/react/src/components/Dropdown/Dropdown-story.js b/packages/react/src/components/Dropdown/Dropdown-story.js index 2da0b3ec8b55..17f28e5b0418 100644 --- a/packages/react/src/components/Dropdown/Dropdown-story.js +++ b/packages/react/src/components/Dropdown/Dropdown-story.js @@ -17,6 +17,11 @@ import { import Dropdown from '../Dropdown'; import DropdownSkeleton from './Dropdown.Skeleton'; import mdx from './Dropdown.mdx'; +import { + ChartBubble16, + ChartColumnFloating16, + ChartVennDiagram16, +} from '@carbon/icons-react'; const items = [ { @@ -122,6 +127,51 @@ export const Default = () => ( /> ); +export const RenderSelectedItem = () => ( +
+ (item ? item.text : '')} + itemToElement={(item) => ( + <> + {React.createElement(item.icon)} + + {item.text} + + + )} + renderSelectedItem={(item) => ( + <> + {React.createElement(item.icon)} + + {item.text} + + + )} + onChange={action('onChange')} + /> +
+); export const Inline = () => (
diff --git a/packages/react/src/components/Dropdown/Dropdown-test.js b/packages/react/src/components/Dropdown/Dropdown-test.js index 903f92b5c52d..3b5ed0807f71 100644 --- a/packages/react/src/components/Dropdown/Dropdown-test.js +++ b/packages/react/src/components/Dropdown/Dropdown-test.js @@ -65,6 +65,31 @@ describe('Dropdown', () => { expect(wrapper).toMatchSnapshot(); }); + it('should render selectedItem as an element', () => { + const wrapper = mount( + ( +
+ {selectedItem.label} +
+ )} + /> + ); + // custom element should be rendered for the selected item + expect(wrapper.find('#a-custom-element-for-selected-item')).toHaveLength(1); + // the title should use the normal itemToString method + expect(wrapper.find('button').instance()).toHaveAttribute( + 'title', + 'Item 1' + ); + }); + describe('title', () => { let wrapper; let renderedLabel; diff --git a/packages/react/src/components/Dropdown/Dropdown.js b/packages/react/src/components/Dropdown/Dropdown.js index 789e4857ee12..b4c18490afb6 100644 --- a/packages/react/src/components/Dropdown/Dropdown.js +++ b/packages/react/src/components/Dropdown/Dropdown.js @@ -39,6 +39,7 @@ const Dropdown = React.forwardRef(function Dropdown( ariaLabel, itemToString, itemToElement, + renderSelectedItem, type, size, onChange, @@ -174,7 +175,11 @@ const Dropdown = React.forwardRef(function Dropdown( {...toggleButtonProps} ref={mergeRefs(toggleButtonProps.ref, ref)}> - {selectedItem ? itemToString(selectedItem) : label} + {selectedItem + ? renderSelectedItem + ? renderSelectedItem(selectedItem) + : itemToString(selectedItem) + : label} @@ -329,6 +334,12 @@ Dropdown.propTypes = { */ onChange: PropTypes.func, + /** + * An optional callback to render the currently selected item as a react element instead of only + * as a string. + */ + renderSelectedItem: PropTypes.func, + /** * In the case you want to control the dropdown selection entirely. */