diff --git a/packages/react/src/components/ComboButton/index.js b/packages/react/src/components/ComboButton/index.js
deleted file mode 100644
index d6b2577bfcff..000000000000
--- a/packages/react/src/components/ComboButton/index.js
+++ /dev/null
@@ -1,216 +0,0 @@
-/**
- * Copyright IBM Corp. 2023
- *
- * This source code is licensed under the Apache-2.0 license found in the
- * LICENSE file in the root directory of this source tree.
- */
-
-import React, { useRef, useState } from 'react';
-import PropTypes from 'prop-types';
-import classNames from 'classnames';
-
-import { ChevronDown } from '@carbon/icons-react';
-import { IconButton } from '../IconButton';
-import Button from '../Button';
-import { Menu } from '../Menu';
-
-import { useAttachedMenu } from '../../internal/useAttachedMenu';
-import { useId } from '../../internal/useId';
-import { useMergedRefs } from '../../internal/useMergedRefs';
-import { usePrefix } from '../../internal/usePrefix';
-
-const spacing = 0; // top and bottom spacing between the button and the menu. in px
-const defaultTranslations = {
- 'carbon.combo-button.additional-actions': 'Additional actions',
-};
-
-function defaultTranslateWithId(messageId) {
- return defaultTranslations[messageId];
-}
-
-const ComboButton = React.forwardRef(function ComboButton(
- {
- children,
- className,
- disabled,
- label,
- onClick,
- size = 'lg',
- menuAlignment = 'bottom',
- tooltipAlignment,
- translateWithId: t = defaultTranslateWithId,
- ...rest
- },
- forwardRef
-) {
- const id = useId('combobutton');
- const prefix = usePrefix();
- const containerRef = useRef(null);
- const menuRef = useRef(null);
- const ref = useMergedRefs([forwardRef, containerRef]);
- const [width, setWidth] = useState(0);
- const {
- open,
- x,
- y,
- handleClick: hookOnClick,
- handleMousedown: handleTriggerMousedown,
- handleClose,
- } = useAttachedMenu(containerRef);
-
- function handleTriggerClick() {
- if (containerRef.current) {
- const { width: w } = containerRef.current.getBoundingClientRect();
- setWidth(w);
- hookOnClick();
- }
- }
-
- function handlePrimaryActionClick(e) {
- if (onClick) {
- onClick(e);
- }
- }
-
- function handleOpen() {
- menuRef.current.style.inlineSize = `${width}px`;
- menuRef.current.style.minInlineSize = `${width}px`;
-
- if (menuAlignment !== 'bottom' && menuAlignment !== 'top') {
- menuRef.current.style.inlineSize = `fit-content`;
- }
- }
-
- const containerClasses = classNames(
- `${prefix}--combo-button__container`,
- `${prefix}--combo-button__container--${size}`,
- {
- [`${prefix}--combo-button__container--open`]: open,
- },
- className
- );
-
- const menuClasses = classNames(`${prefix}--combo-button__${menuAlignment}`);
-
- const primaryActionClasses = classNames(
- `${prefix}--combo-button__primary-action`
- );
- const triggerClasses = classNames(`${prefix}--combo-button__trigger`);
-
- return (
-
-
-
-
-
-
-
-
-
- );
-});
-
-ComboButton.propTypes = {
- /**
- * A collection of MenuItems to be rendered as additional actions for this ComboButton.
- */
- children: PropTypes.node.isRequired,
-
- /**
- * Additional CSS class names.
- */
- className: PropTypes.string,
-
- /**
- * Specify whether the ComboButton should be disabled, or not.
- */
- disabled: PropTypes.bool,
-
- /**
- * Provide the label to be renderd on the primary action button.
- */
- label: PropTypes.string.isRequired,
-
- /**
- * Experimental property. Specify how the menu should align with the button element
- */
- menuAlignment: PropTypes.oneOf([
- 'top',
- 'top-start',
- 'top-end',
- 'bottom',
- 'bottom-start',
- 'bottom-end',
- ]),
-
- /**
- * Provide an optional function to be called when the primary action element is clicked.
- */
- onClick: PropTypes.func,
-
- /**
- * Specify the size of the buttons and menu.
- */
- size: PropTypes.oneOf(['sm', 'md', 'lg']),
-
- /**
- * Specify how the trigger tooltip should be aligned.
- */
- tooltipAlignment: PropTypes.oneOf([
- 'top',
- 'top-left',
- 'top-start',
- 'top-right',
- 'top-end',
- 'bottom',
- 'bottom-left',
- 'bottom-start',
- 'bottom-right',
- 'bottom-end',
- 'left',
- 'right',
- ]),
-
- /**
- * Optional method that takes in a message id and returns an
- * internationalized string.
- */
- translateWithId: PropTypes.func,
-};
-
-export { ComboButton };
diff --git a/packages/react/src/components/ComboButton/index.tsx b/packages/react/src/components/ComboButton/index.tsx
new file mode 100644
index 000000000000..a2123440fa9e
--- /dev/null
+++ b/packages/react/src/components/ComboButton/index.tsx
@@ -0,0 +1,268 @@
+/**
+ * Copyright IBM Corp. 2023
+ *
+ * This source code is licensed under the Apache-2.0 license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+import React, { useRef, useState } from 'react';
+import PropTypes from 'prop-types';
+import classNames from 'classnames';
+
+import { ChevronDown } from '@carbon/icons-react';
+import { IconButton } from '../IconButton';
+import Button from '../Button';
+import { Menu } from '../Menu';
+
+import { useAttachedMenu } from '../../internal/useAttachedMenu';
+import { useId } from '../../internal/useId';
+import { useMergedRefs } from '../../internal/useMergedRefs';
+import { usePrefix } from '../../internal/usePrefix';
+
+const spacing = 0; // top and bottom spacing between the button and the menu. in px
+const defaultTranslations = {
+ 'carbon.combo-button.additional-actions': 'Additional actions',
+};
+
+function defaultTranslateWithId(messageId: string) {
+ return defaultTranslations[messageId];
+}
+
+interface ComboButtonProps {
+ /**
+ * A collection of `MenuItems` to be rendered as additional actions for this `ComboButton`.
+ */
+ children: React.ComponentProps['children'];
+
+ /**
+ * Additional CSS class names.
+ */
+ className?: string;
+
+ /**
+ * Specify whether the `ComboButton` should be disabled, or not.
+ */
+ disabled?: boolean;
+
+ /**
+ * Provide the label to be rendered on the primary action button.
+ */
+ label: React.ComponentProps['title'];
+
+ /**
+ * Experimental property. Specify how the menu should align with the button element
+ */
+ menuAlignment?: React.ComponentProps['menuAlignment'];
+
+ /**
+ * Provide an optional function to be called when the primary action element is clicked.
+ */
+ onClick?: React.ComponentProps['onClick'];
+
+ /**
+ * Specify the size of the buttons and menu.
+ */
+ size?: 'sm' | 'md' | 'lg';
+
+ /**
+ * Specify how the trigger tooltip should be aligned.
+ */
+ tooltipAlignment?: React.ComponentProps['align'];
+
+ /**
+ * Optional method that takes in a message `id` and returns an
+ * internationalized string.
+ */
+ translateWithId?: (id: string) => string;
+}
+
+const ComboButton = React.forwardRef(
+ function ComboButton(
+ {
+ children,
+ className,
+ disabled,
+ label,
+ onClick,
+ size = 'lg',
+ menuAlignment = 'bottom',
+ tooltipAlignment,
+ translateWithId: t = defaultTranslateWithId,
+ ...rest
+ },
+ forwardRef
+ ) {
+ const id = useId('combobutton');
+ const prefix = usePrefix();
+ const containerRef = useRef(null);
+ const menuRef = useRef>(null);
+ const ref = useMergedRefs([forwardRef, containerRef]);
+ const [width, setWidth] = useState(0);
+ const {
+ open,
+ x,
+ y,
+ handleClick: hookOnClick,
+ handleMousedown: handleTriggerMousedown,
+ handleClose,
+ } = useAttachedMenu(containerRef);
+
+ function handleTriggerClick() {
+ if (containerRef.current) {
+ const { width: w } = containerRef.current.getBoundingClientRect();
+ setWidth(w);
+ hookOnClick();
+ }
+ }
+
+ function handlePrimaryActionClick(e: React.MouseEvent) {
+ if (onClick) {
+ onClick(e);
+ }
+ }
+
+ function handleOpen() {
+ if (menuRef.current) {
+ menuRef.current.style.inlineSize = `${width}px`;
+ menuRef.current.style.minInlineSize = `${width}px`;
+
+ if (menuAlignment !== 'bottom' && menuAlignment !== 'top') {
+ menuRef.current.style.inlineSize = `fit-content`;
+ }
+ }
+ }
+
+ const containerClasses = classNames(
+ `${prefix}--combo-button__container`,
+ `${prefix}--combo-button__container--${size}`,
+ {
+ [`${prefix}--combo-button__container--open`]: open,
+ },
+ className
+ );
+
+ const menuClasses = classNames(`${prefix}--combo-button__${menuAlignment}`);
+
+ const primaryActionClasses = classNames(
+ `${prefix}--combo-button__primary-action`
+ );
+ const triggerClasses = classNames(`${prefix}--combo-button__trigger`);
+
+ return (
+
+
+
+
+
+
+
+
+
+ );
+ }
+);
+
+ComboButton.propTypes = {
+ /**
+ * A collection of MenuItems to be rendered as additional actions for this ComboButton.
+ */
+ children: PropTypes.node.isRequired,
+
+ /**
+ * Additional CSS class names.
+ */
+ className: PropTypes.string,
+
+ /**
+ * Specify whether the ComboButton should be disabled, or not.
+ */
+ disabled: PropTypes.bool,
+
+ /**
+ * Provide the label to be rendered on the primary action button.
+ */
+ label: PropTypes.string.isRequired,
+
+ /**
+ * Experimental property. Specify how the menu should align with the button element
+ */
+ menuAlignment: PropTypes.oneOf([
+ 'top',
+ 'top-start',
+ 'top-end',
+ 'bottom',
+ 'bottom-start',
+ 'bottom-end',
+ ]),
+
+ /**
+ * Provide an optional function to be called when the primary action element is clicked.
+ */
+ onClick: PropTypes.func,
+
+ /**
+ * Specify the size of the buttons and menu.
+ */
+ size: PropTypes.oneOf(['sm', 'md', 'lg']),
+
+ /**
+ * Specify how the trigger tooltip should be aligned.
+ */
+ tooltipAlignment: PropTypes.oneOf([
+ 'top',
+ 'top-left',
+ 'top-start',
+ 'top-right',
+ 'top-end',
+ 'bottom',
+ 'bottom-left',
+ 'bottom-start',
+ 'bottom-right',
+ 'bottom-end',
+ 'left',
+ 'right',
+ ]),
+
+ /**
+ * Optional method that takes in a message id and returns an
+ * internationalized string.
+ */
+ translateWithId: PropTypes.func,
+};
+
+export { ComboButton, type ComboButtonProps };