diff --git a/packages/react/src/components/Checkbox/Checkbox.tsx b/packages/react/src/components/Checkbox/Checkbox.tsx index 97d3002b7b7f..5b88fe3135a0 100644 --- a/packages/react/src/components/Checkbox/Checkbox.tsx +++ b/packages/react/src/components/Checkbox/Checkbox.tsx @@ -11,11 +11,9 @@ import classNames from 'classnames'; import { Text } from '../Text'; import { usePrefix } from '../../internal/usePrefix'; import { WarningFilled, WarningAltFilled } from '@carbon/icons-react'; -import setupGetInstanceId from '../../tools/setupGetInstanceId'; +import { useId } from '../../internal/useId'; import { noopFn } from '../../internal/noopFn'; -const getInstanceId = setupGetInstanceId(); - type ExcludedAttributes = 'id' | 'onChange' | 'onClick' | 'type'; export interface CheckboxProps @@ -127,7 +125,7 @@ const Checkbox = React.forwardRef( const showWarning = !readOnly && !invalid && warn; const showHelper = !invalid && !warn; - const checkboxGroupInstanceId = getInstanceId(); + const checkboxGroupInstanceId = useId(); const helperId = !helperText ? undefined diff --git a/packages/react/src/components/CheckboxGroup/CheckboxGroup.tsx b/packages/react/src/components/CheckboxGroup/CheckboxGroup.tsx index 4b08089326af..d7cfc299cfba 100644 --- a/packages/react/src/components/CheckboxGroup/CheckboxGroup.tsx +++ b/packages/react/src/components/CheckboxGroup/CheckboxGroup.tsx @@ -10,9 +10,7 @@ import React, { ReactNode } from 'react'; import cx from 'classnames'; import { usePrefix } from '../../internal/usePrefix'; import { WarningFilled, WarningAltFilled } from '@carbon/icons-react'; -import setupGetInstanceId from '../../tools/setupGetInstanceId'; - -const getInstanceId = setupGetInstanceId(); +import { useId } from '../../internal/useId'; export interface CheckboxGroupProps { children?: ReactNode; @@ -54,7 +52,7 @@ const CheckboxGroup: React.FC = ({ const showWarning = !readOnly && !invalid && warn; const showHelper = !invalid && !warn; - const checkboxGroupInstanceId = getInstanceId(); + const checkboxGroupInstanceId = useId(); const helperId = !helperText ? undefined diff --git a/packages/react/src/components/ComboBox/ComboBox.tsx b/packages/react/src/components/ComboBox/ComboBox.tsx index 45fd997b40cb..ebcf086faeff 100644 --- a/packages/react/src/components/ComboBox/ComboBox.tsx +++ b/packages/react/src/components/ComboBox/ComboBox.tsx @@ -39,7 +39,7 @@ import ListBox, { } from '../ListBox'; import { ListBoxTrigger, ListBoxSelection } from '../ListBox/next'; import { match, keys } from '../../internal/keyboard'; -import setupGetInstanceId from '../../tools/setupGetInstanceId'; +import { useId } from '../../internal/useId'; import mergeRefs from '../../tools/mergeRefs'; import deprecate from '../../prop-types/deprecate'; import { usePrefix } from '../../internal/usePrefix'; @@ -122,8 +122,6 @@ const findHighlightedIndex = ( return -1; }; -const getInstanceId = setupGetInstanceId(); - type ExcludedAttributes = 'id' | 'onChange' | 'onClick' | 'type' | 'size'; interface OnChangeData { @@ -379,7 +377,7 @@ const ComboBox = forwardRef( const prefix = usePrefix(); const { isFluid } = useContext(FormContext); const textInput = useRef(null); - const comboBoxInstanceId = getInstanceId(); + const comboBoxInstanceId = useId(); const [inputValue, setInputValue] = useState( getInputValue({ initialSelectedItem, diff --git a/packages/react/src/components/DataTable/TableToolbarSearch.tsx b/packages/react/src/components/DataTable/TableToolbarSearch.tsx index 4bfc1c99a91e..de2429bb783d 100644 --- a/packages/react/src/components/DataTable/TableToolbarSearch.tsx +++ b/packages/react/src/components/DataTable/TableToolbarSearch.tsx @@ -18,13 +18,11 @@ import React, { RefObject, } from 'react'; import Search, { SearchProps } from '../Search'; -import setupGetInstanceId from './tools/instanceId'; +import { useId } from '../../internal/useId'; import { usePrefix } from '../../internal/usePrefix'; import { noopFn } from '../../internal/noopFn'; import { InternationalProps } from '../../types/common'; -const getInstanceId = setupGetInstanceId(); - export type TableToolbarTranslationKey = | 'carbon.table.toolbar.search.label' | 'carbon.table.toolbar.search.placeholder'; @@ -150,7 +148,7 @@ const TableToolbarSearch = ({ const expanded = controlled ? expandedProp : expandedState; const [value, setValue] = useState(defaultValue || ''); - const uniqueId = useMemo(getInstanceId, []); + const uniqueId = useId(); const [focusTarget, setFocusTarget] = useState | null>( null ); diff --git a/packages/react/src/components/DataTable/__tests__/__snapshots__/DataTable-test.js.snap b/packages/react/src/components/DataTable/__tests__/__snapshots__/DataTable-test.js.snap index 68b8c440b08e..609e44a2565f 100644 --- a/packages/react/src/components/DataTable/__tests__/__snapshots__/DataTable-test.js.snap +++ b/packages/react/src/components/DataTable/__tests__/__snapshots__/DataTable-test.js.snap @@ -10,20 +10,20 @@ exports[`DataTable behaves as expected selection -- radio buttons should not hav >

DataTable with selection

@@ -182,20 +182,20 @@ exports[`DataTable behaves as expected selection -- radio buttons should render >

DataTable with selection

@@ -354,13 +354,13 @@ exports[`DataTable behaves as expected selection should render and match snapsho >

DataTable with selection

@@ -797,13 +797,13 @@ exports[`DataTable renders as expected - Component API should render and match s >

DataTable with toolbar

diff --git a/packages/react/src/components/DatePickerInput/DatePickerInput.tsx b/packages/react/src/components/DatePickerInput/DatePickerInput.tsx index 4575042fcb6b..60db66408a76 100644 --- a/packages/react/src/components/DatePickerInput/DatePickerInput.tsx +++ b/packages/react/src/components/DatePickerInput/DatePickerInput.tsx @@ -11,11 +11,10 @@ import PropTypes, { ReactElementLike, ReactNodeArray } from 'prop-types'; import React, { ForwardedRef, useContext } from 'react'; import { usePrefix } from '../../internal/usePrefix'; import { FormContext } from '../FluidForm'; -import setupGetInstanceId from '../../tools/setupGetInstanceId'; +import { useId } from '../../internal/useId'; import { ReactAttr } from '../../types/common'; import { Text } from '../Text'; -const getInstanceId = setupGetInstanceId(); type ExcludedAttributes = 'value' | 'onChange' | 'locale' | 'children'; export type ReactNodeLike = | ReactElementLike @@ -158,7 +157,7 @@ const DatePickerInput = React.forwardRef(function DatePickerInput( } = props; const prefix = usePrefix(); const { isFluid } = useContext(FormContext); - const datePickerInputInstanceId = getInstanceId(); + const datePickerInputInstanceId = useId(); const datePickerInputProps = { id, onChange: (event) => { diff --git a/packages/react/src/components/Dropdown/Dropdown.tsx b/packages/react/src/components/Dropdown/Dropdown.tsx index 172db2034886..2c548a86fa29 100644 --- a/packages/react/src/components/Dropdown/Dropdown.tsx +++ b/packages/react/src/components/Dropdown/Dropdown.tsx @@ -40,7 +40,7 @@ import deprecate from '../../prop-types/deprecate'; import { usePrefix } from '../../internal/usePrefix'; import { FormContext } from '../FluidForm'; import { ReactAttr } from '../../types/common'; -import setupGetInstanceId from '../../tools/setupGetInstanceId'; +import { useId } from '../../internal/useId'; import { useFloating, flip, @@ -48,8 +48,6 @@ import { size as floatingSize, } from '@floating-ui/react'; -const getInstanceId = setupGetInstanceId(); - const { ToggleButtonKeyDownArrowDown, ToggleButtonKeyDownArrowUp, @@ -335,7 +333,7 @@ const Dropdown = React.forwardRef( return isObject && 'disabled' in item && item.disabled === true; }, }; - const { current: dropdownInstanceId } = useRef(getInstanceId()); + const dropdownInstanceId = useId(); function stateReducer(state, actionAndChanges) { const { changes, props, type } = actionAndChanges; diff --git a/packages/react/src/components/Modal/Modal.tsx b/packages/react/src/components/Modal/Modal.tsx index f635a7993570..4dcdbfad26b1 100644 --- a/packages/react/src/components/Modal/Modal.tsx +++ b/packages/react/src/components/Modal/Modal.tsx @@ -21,7 +21,7 @@ import wrapFocus, { } from '../../internal/wrapFocus'; import debounce from 'lodash.debounce'; import useIsomorphicEffect from '../../internal/useIsomorphicEffect'; -import setupGetInstanceId from '../../tools/setupGetInstanceId'; +import { useId } from '../../internal/useId'; import { usePrefix } from '../../internal/usePrefix'; import { keys, match } from '../../internal/keyboard'; import { IconButton } from '../IconButton'; @@ -32,8 +32,6 @@ import { InlineLoadingStatus } from '../InlineLoading/InlineLoading'; import { useFeatureFlag } from '../FeatureFlags'; import { composeEventHandlers } from '../../tools/events'; -const getInstanceId = setupGetInstanceId(); - export const ModalSizes = ['xs', 'sm', 'md', 'lg'] as const; export type ModalSize = (typeof ModalSizes)[number]; @@ -264,7 +262,7 @@ const Modal = React.forwardRef(function Modal( const startTrap = useRef(null); const endTrap = useRef(null); const [isScrollable, setIsScrollable] = useState(false); - const modalInstanceId = `modal-${getInstanceId()}`; + const modalInstanceId = `modal-${useId()}`; const modalLabelId = `${prefix}--modal-header__label--${modalInstanceId}`; const modalHeadingId = `${prefix}--modal-header__heading--${modalInstanceId}`; const modalBodyId = `${prefix}--modal-body--${modalInstanceId}`; diff --git a/packages/react/src/components/MultiSelect/MultiSelect.tsx b/packages/react/src/components/MultiSelect/MultiSelect.tsx index 2a87e50eb2eb..53423e09e8b5 100644 --- a/packages/react/src/components/MultiSelect/MultiSelect.tsx +++ b/packages/react/src/components/MultiSelect/MultiSelect.tsx @@ -36,7 +36,7 @@ import { } from './MultiSelectPropTypes'; import { defaultSortItems, defaultCompareItems } from './tools/sorting'; import { useSelection } from '../../internal/Selection'; -import setupGetInstanceId from '../../tools/setupGetInstanceId'; +import { useId } from '../../internal/useId'; import mergeRefs from '../../tools/mergeRefs'; import deprecate from '../../prop-types/deprecate'; import { keys, match } from '../../internal/keyboard'; @@ -52,7 +52,6 @@ import { autoUpdate, } from '@floating-ui/react'; -const getInstanceId = setupGetInstanceId(); const { ItemClick, ToggleButtonBlur, @@ -328,7 +327,7 @@ const MultiSelect = React.forwardRef( ) => { const prefix = usePrefix(); const { isFluid } = useContext(FormContext); - const { current: multiSelectInstanceId } = useRef(getInstanceId()); + const multiSelectInstanceId = useId(); const [isFocused, setIsFocused] = useState(false); const [inputFocused, setInputFocused] = useState(false); const [isOpen, setIsOpen] = useState(open || false); diff --git a/packages/react/src/components/Pagination/experimental/PageSelector.js b/packages/react/src/components/Pagination/experimental/PageSelector.js index 0ba404724570..5335bba5b4cd 100644 --- a/packages/react/src/components/Pagination/experimental/PageSelector.js +++ b/packages/react/src/components/Pagination/experimental/PageSelector.js @@ -8,12 +8,11 @@ import React from 'react'; import PropTypes from 'prop-types'; import classnames from 'classnames'; -import setupGetInstanceId from '../../../tools/setupGetInstanceId'; +import { useId } from '../../../internal/useId'; import Select from '../../Select'; import SelectItem from '../../SelectItem'; import { usePrefix } from '../../../internal/usePrefix'; -const getInstanceId = setupGetInstanceId(); function PageSelector({ className = null, currentPage, @@ -24,7 +23,7 @@ function PageSelector({ }) { const prefix = usePrefix(); const namespace = `${prefix}--unstable-pagination__page-selector`; - const instanceId = `${namespace}__select-${getInstanceId()}`; + const instanceId = `${namespace}__select-${useId()}`; const renderPages = (total) => { const pages = []; diff --git a/packages/react/src/components/RadioButtonGroup/RadioButtonGroup.tsx b/packages/react/src/components/RadioButtonGroup/RadioButtonGroup.tsx index 12028b795c5c..d9f4f030997a 100644 --- a/packages/react/src/components/RadioButtonGroup/RadioButtonGroup.tsx +++ b/packages/react/src/components/RadioButtonGroup/RadioButtonGroup.tsx @@ -19,9 +19,7 @@ import { Legend } from '../Text'; import { usePrefix } from '../../internal/usePrefix'; import { WarningFilled, WarningAltFilled } from '@carbon/icons-react'; import mergeRefs from '../../tools/mergeRefs'; -import setupGetInstanceId from '../../tools/setupGetInstanceId'; - -const getInstanceId = setupGetInstanceId(); +import { useId } from '../../internal/useId'; export const RadioButtonGroupContext = createContext(null); @@ -157,7 +155,7 @@ const RadioButtonGroup = React.forwardRef( const [selected, setSelected] = useState(valueSelected ?? defaultSelected); const [prevValueSelected, setPrevValueSelected] = useState(valueSelected); - const { current: radioButtonGroupInstanceId } = useRef(getInstanceId()); + const radioButtonGroupInstanceId = useId(); /** * prop + state alignment - getDerivedStateFromProps diff --git a/packages/react/src/components/Select/Select.tsx b/packages/react/src/components/Select/Select.tsx index fd9991aadd9e..93cdd92d1f1d 100644 --- a/packages/react/src/components/Select/Select.tsx +++ b/packages/react/src/components/Select/Select.tsx @@ -24,12 +24,10 @@ import { import deprecate from '../../prop-types/deprecate'; import { usePrefix } from '../../internal/usePrefix'; import { FormContext } from '../FluidForm'; -import setupGetInstanceId from '../../tools/setupGetInstanceId'; +import { useId } from '../../internal/useId'; import { composeEventHandlers } from '../../tools/events'; import { Text } from '../Text'; -const getInstanceId = setupGetInstanceId(); - type ExcludedAttributes = 'size'; interface SelectProps @@ -165,7 +163,7 @@ const Select = React.forwardRef(function Select( const { isFluid } = useContext(FormContext); const [isFocused, setIsFocused] = useState(false); const [title, setTitle] = useState(''); - const { current: selectInstanceId } = useRef(getInstanceId()); + const selectInstanceId = useId(); const selectClasses = classNames({ [`${prefix}--select`]: true, diff --git a/packages/react/src/components/Tag/DismissibleTag.tsx b/packages/react/src/components/Tag/DismissibleTag.tsx index 541602ea35ce..7b385c3fce84 100644 --- a/packages/react/src/components/Tag/DismissibleTag.tsx +++ b/packages/react/src/components/Tag/DismissibleTag.tsx @@ -8,7 +8,7 @@ import PropTypes from 'prop-types'; import React, { useLayoutEffect, useState, ReactNode, useRef } from 'react'; import classNames from 'classnames'; -import setupGetInstanceId from '../../tools/setupGetInstanceId'; +import { useId } from '../../internal/useId'; import { usePrefix } from '../../internal/usePrefix'; import { PolymorphicProps } from '../../types/common'; import Tag, { SIZES, TYPES } from './Tag'; @@ -17,8 +17,6 @@ import { Tooltip } from '../Tooltip'; import { Text } from '../Text'; import { isEllipsisActive } from './isEllipsisActive'; -const getInstanceId = setupGetInstanceId(); - export interface DismissibleTagBaseProps { /** * Provide a custom className that is applied to the containing @@ -93,7 +91,7 @@ const DismissibleTag = ({ }: DismissibleTagProps) => { const prefix = usePrefix(); const tagLabelRef = useRef(); - const tagId = id || `tag-${getInstanceId()}`; + const tagId = id || `tag-${useId()}`; const tagClasses = classNames(`${prefix}--tag--filter`, className); const [isEllipsisApplied, setIsEllipsisApplied] = useState(false); diff --git a/packages/react/src/components/Tag/OperationalTag.tsx b/packages/react/src/components/Tag/OperationalTag.tsx index b0f6eaa9fb26..77b29e78525b 100644 --- a/packages/react/src/components/Tag/OperationalTag.tsx +++ b/packages/react/src/components/Tag/OperationalTag.tsx @@ -14,7 +14,7 @@ import React, { useRef, } from 'react'; import classNames from 'classnames'; -import setupGetInstanceId from '../../tools/setupGetInstanceId'; +import { useId } from '../../internal/useId'; import { usePrefix } from '../../internal/usePrefix'; import { PolymorphicProps } from '../../types/common'; import Tag, { SIZES } from './Tag'; @@ -22,8 +22,6 @@ import { Tooltip } from '../Tooltip'; import { Text } from '../Text'; import { isEllipsisActive } from './isEllipsisActive'; -const getInstanceId = setupGetInstanceId(); - const TYPES = { red: 'Red', magenta: 'Magenta', @@ -100,7 +98,7 @@ const OperationalTag = ({ }: OperationalTagProps) => { const prefix = usePrefix(); const tagRef = useRef(); - const tagId = id || `tag-${getInstanceId()}`; + const tagId = id || `tag-${useId()}`; const tagClasses = classNames(`${prefix}--tag--operational`, className); const [isEllipsisApplied, setIsEllipsisApplied] = useState(false); diff --git a/packages/react/src/components/Tag/SelectableTag.tsx b/packages/react/src/components/Tag/SelectableTag.tsx index d4d87e3c5344..1f69e1cdfad9 100644 --- a/packages/react/src/components/Tag/SelectableTag.tsx +++ b/packages/react/src/components/Tag/SelectableTag.tsx @@ -8,7 +8,7 @@ import PropTypes from 'prop-types'; import React, { useLayoutEffect, useState, ReactNode, useRef } from 'react'; import classNames from 'classnames'; -import setupGetInstanceId from '../../tools/setupGetInstanceId'; +import { useId } from '../../internal/useId'; import { usePrefix } from '../../internal/usePrefix'; import { PolymorphicProps } from '../../types/common'; import Tag, { SIZES } from './Tag'; @@ -16,8 +16,6 @@ import { Tooltip } from '../Tooltip'; import { Text } from '../Text'; import { isEllipsisActive } from './isEllipsisActive'; -const getInstanceId = setupGetInstanceId(); - export interface SelectableTagBaseProps { /** * Provide a custom className that is applied to the containing @@ -80,7 +78,7 @@ const SelectableTag = ({ }: SelectableTagProps) => { const prefix = usePrefix(); const tagRef = useRef(); - const tagId = id || `tag-${getInstanceId()}`; + const tagId = id || `tag-${useId()}`; const [selectedTag, setSelectedTag] = useState(selected); const tagClasses = classNames(`${prefix}--tag--selectable`, className, { [`${prefix}--tag--selectable-selected`]: selectedTag, diff --git a/packages/react/src/components/Tag/Tag.tsx b/packages/react/src/components/Tag/Tag.tsx index 6c7e212aa24d..144ea9295f92 100644 --- a/packages/react/src/components/Tag/Tag.tsx +++ b/packages/react/src/components/Tag/Tag.tsx @@ -15,7 +15,7 @@ import React, { } from 'react'; import classNames from 'classnames'; import { Close } from '@carbon/icons-react'; -import setupGetInstanceId from '../../tools/setupGetInstanceId'; +import { useId } from '../../internal/useId'; import { usePrefix } from '../../internal/usePrefix'; import { PolymorphicProps } from '../../types/common'; import { Text } from '../Text'; @@ -24,7 +24,6 @@ import { DefinitionTooltip } from '../Tooltip'; import { isEllipsisActive } from './isEllipsisActive'; import { useMergeRefs } from '@floating-ui/react'; -const getInstanceId = setupGetInstanceId(); export const TYPES = { red: 'Red', magenta: 'Magenta', @@ -131,7 +130,7 @@ const Tag = React.forwardRef(function Tag( const prefix = usePrefix(); const tagRef = useRef(); const ref = useMergeRefs([forwardRef, tagRef]); - const tagId = id || `tag-${getInstanceId()}`; + const tagId = id || `tag-${useId()}`; const [isEllipsisApplied, setIsEllipsisApplied] = useState(false); useLayoutEffect(() => { diff --git a/packages/react/src/components/TextArea/TextArea.tsx b/packages/react/src/components/TextArea/TextArea.tsx index 6785ad74d60f..8ffe932bf48f 100644 --- a/packages/react/src/components/TextArea/TextArea.tsx +++ b/packages/react/src/components/TextArea/TextArea.tsx @@ -21,12 +21,10 @@ import { FormContext } from '../FluidForm'; import { useAnnouncer } from '../../internal/useAnnouncer'; import useIsomorphicEffect from '../../internal/useIsomorphicEffect'; import { useMergedRefs } from '../../internal/useMergedRefs'; -import setupGetInstanceId from '../../tools/setupGetInstanceId'; +import { useId } from '../../internal/useId'; import { noopFn } from '../../internal/noopFn'; import { Text } from '../Text'; -const getInstanceId = setupGetInstanceId(); - export interface TextAreaProps extends React.InputHTMLAttributes { /** @@ -185,7 +183,7 @@ const TextArea = React.forwardRef((props: TextAreaProps, forwardRef) => { const { isFluid } = useContext(FormContext); const { defaultValue, value } = other; - const { current: textAreaInstanceId } = useRef(getInstanceId()); + const textAreaInstanceId = useId(); const textareaRef = useRef(null); const ref = useMergedRefs([forwardRef, textareaRef]) as diff --git a/packages/react/src/components/TextInput/ControlledPasswordInput.tsx b/packages/react/src/components/TextInput/ControlledPasswordInput.tsx index 24d7858d4801..583b5caa8b56 100644 --- a/packages/react/src/components/TextInput/ControlledPasswordInput.tsx +++ b/packages/react/src/components/TextInput/ControlledPasswordInput.tsx @@ -6,12 +6,10 @@ import { textInputProps } from './util'; import { warning } from '../../internal/warning'; import deprecate from '../../prop-types/deprecate'; import { usePrefix } from '../../internal/usePrefix'; -import setupGetInstanceId from '../../tools/setupGetInstanceId'; +import { useId } from '../../internal/useId'; import { ReactAttr } from '../../types/common'; import { noopFn } from '../../internal/noopFn'; -const getInstanceId = setupGetInstanceId(); - let didWarnAboutDeprecation = false; export interface ControlledPasswordInputProps @@ -149,7 +147,7 @@ const ControlledPasswordInput = React.forwardRef( ref ) { const prefix = usePrefix(); - const { current: controlledPasswordInstanceId } = useRef(getInstanceId()); + const controlledPasswordInstanceId = useId(); if (__DEV__) { warning(