@carbon/react
Version:
React components for the Carbon Design System
114 lines (112 loc) • 4.56 kB
JavaScript
/**
* Copyright IBM Corp. 2016, 2026
*
* 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 { usePrefix } from "../../internal/usePrefix.js";
import { Text } from "../Text/Text.js";
import { Enter, Space } from "../../internal/keyboard/keys.js";
import { matches } from "../../internal/keyboard/match.js";
import { useFallbackId } from "../../internal/useId.js";
import { noopFn } from "../../internal/noopFn.js";
import { deprecate } from "../../prop-types/deprecate.js";
import { isComponentElement } from "../../internal/utils.js";
import { useFeatureFlag } from "../FeatureFlags/index.js";
import { AILabel } from "../AILabel/index.js";
import classNames from "classnames";
import React, { cloneElement } from "react";
import PropTypes from "prop-types";
import { jsx, jsxs } from "react/jsx-runtime";
import { CheckmarkFilled, RadioButton, RadioButtonChecked } from "@carbon/icons-react";
//#region src/components/RadioTile/RadioTile.tsx
/**
* Copyright IBM Corp. 2016, 2025
*
* This source code is licensed under the Apache-2.0 license found in the
* LICENSE file in the root directory of this source tree.
*/
const RadioTile = React.forwardRef(({ children, className: customClassName, decorator, disabled, light, checked, name, value, id, onChange = noopFn, tabIndex = 0, hasRoundedCorners, slug, required, ...rest }, ref) => {
const prefix = usePrefix();
const inputId = useFallbackId(id);
const className = classNames(customClassName, `${prefix}--tile`, `${prefix}--tile--selectable`, `${prefix}--tile--radio`, {
[`${prefix}--tile--is-selected`]: checked,
[`${prefix}--tile--light`]: light,
[`${prefix}--tile--disabled`]: disabled,
[`${prefix}--tile--slug`]: slug,
[`${prefix}--tile--slug-rounded`]: slug && hasRoundedCorners,
[`${prefix}--tile--decorator`]: decorator,
[`${prefix}--tile--decorator-rounded`]: decorator && hasRoundedCorners
});
const { "aria-describedby": ariaDescribedBy, "aria-labelledby": ariaLabelledBy, ...labelProps } = rest;
const v12TileRadioIcons = useFeatureFlag("enable-v12-tile-radio-icons");
function icon() {
if (v12TileRadioIcons) if (checked) return /* @__PURE__ */ jsx(RadioButtonChecked, {});
else return /* @__PURE__ */ jsx(RadioButton, {});
else return /* @__PURE__ */ jsx(CheckmarkFilled, {});
}
function handleOnChange(evt) {
onChange(value, name, evt);
}
function handleOnKeyDown(evt) {
if (matches(evt, [Enter, Space])) {
evt.preventDefault();
onChange(value, name, evt);
}
}
const candidate = slug ?? decorator;
const normalizedDecorator = isComponentElement(candidate, AILabel) ? cloneElement(candidate, { size: "xs" }) : candidate;
return /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("input", {
checked,
className: `${prefix}--tile-input`,
disabled,
id: inputId,
name,
onChange: !disabled ? handleOnChange : void 0,
onKeyDown: !disabled ? handleOnKeyDown : void 0,
tabIndex: !disabled ? tabIndex : void 0,
type: "radio",
value,
...ariaDescribedBy && { "aria-describedby": ariaDescribedBy },
...ariaLabelledBy && { "aria-labelledby": ariaLabelledBy },
ref,
required
}), /* @__PURE__ */ jsxs("label", {
...labelProps,
htmlFor: inputId,
className,
children: [
/* @__PURE__ */ jsx("span", {
className: `${prefix}--tile__checkmark`,
children: icon()
}),
/* @__PURE__ */ jsx(Text, {
className: `${prefix}--tile-content`,
children
}),
slug ? normalizedDecorator : decorator ? /* @__PURE__ */ jsx("div", {
className: `${prefix}--tile--inner-decorator`,
children: normalizedDecorator
}) : ""
]
})] });
});
RadioTile.displayName = "RadioTile";
RadioTile.propTypes = {
checked: PropTypes.bool,
children: PropTypes.node,
className: PropTypes.string,
decorator: PropTypes.node,
disabled: PropTypes.bool,
hasRoundedCorners: PropTypes.bool,
id: PropTypes.string,
light: deprecate(PropTypes.bool, "The `light` prop for `RadioTile` is no longer needed and has been deprecated in v11 in favor of the new `Layer` component. It will be removed in the next major release."),
name: PropTypes.string,
onChange: PropTypes.func,
required: PropTypes.bool,
slug: deprecate(PropTypes.node, "The `slug` prop for `RadioTile` has been deprecated in favor of the new `decorator` prop. It will be removed in the next major release."),
tabIndex: PropTypes.number,
value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired
};
//#endregion
export { RadioTile as default };