diff --git a/src/ElementChildren.tsx b/src/ElementChildren.tsx
index 72079467fb..db3ce7520a 100644
--- a/src/ElementChildren.tsx
+++ b/src/ElementChildren.tsx
@@ -1,4 +1,5 @@
import * as React from 'react';
+import { BsComponent } from './helpers';
/**
* Iterates through children that are typically specified as `props.children`,
@@ -35,4 +36,22 @@ function forEach
(
});
}
-export { map, forEach };
+/**
+ * Checks that at least one child is of the specified type (either a string for
+ * an HTML element or a component for a React element).
+ */
+function includesType(
+ children: React.ReactNode,
+ type: string | BsComponent,
+) {
+ const childrenList = React.Children.toArray(children);
+ return childrenList.some(
+ (child) =>
+ React.isValidElement(child) &&
+ (child.type === type ||
+ (child.type as BsComponent)?.typeName ===
+ (type as BsComponent).typeName),
+ );
+}
+
+export { map, forEach, includesType };
diff --git a/src/FormCheck.tsx b/src/FormCheck.tsx
index 4f70d96779..d608323e9c 100644
--- a/src/FormCheck.tsx
+++ b/src/FormCheck.tsx
@@ -8,6 +8,7 @@ import FormCheckLabel from './FormCheckLabel';
import FormContext from './FormContext';
import { useBootstrapPrefix } from './ThemeProvider';
import { BsPrefixProps, BsPrefixRefForwardingComponent } from './helpers';
+import { includesType } from './ElementChildren';
export type FormCheckType = 'checkbox' | 'radio' | 'switch';
@@ -150,7 +151,9 @@ const FormCheck: BsPrefixRefForwardingComponent<'input', FormCheckProps> =
[controlId, id],
);
- const hasLabel = label != null && label !== false && !children;
+ const hasLabel =
+ (label != null && label !== false) ||
+ (children && includesType(children, FormCheckLabel));
const input = (
=
style={style}
className={classNames(
className,
- label && bsPrefix,
+ hasLabel && bsPrefix,
inline && `${bsPrefix}-inline`,
type === 'switch' && bsSwitchPrefix,
)}
diff --git a/src/FormCheckLabel.tsx b/src/FormCheckLabel.tsx
index cd061fd88c..2c8da953ba 100644
--- a/src/FormCheckLabel.tsx
+++ b/src/FormCheckLabel.tsx
@@ -5,7 +5,7 @@ import { useContext } from 'react';
import FormContext from './FormContext';
import { useBootstrapPrefix } from './ThemeProvider';
-import { BsPrefixProps } from './helpers';
+import { BsPrefixProps, BsPrefixRefForwardingComponent } from './helpers';
export interface FormCheckLabelProps
extends React.LabelHTMLAttributes,
@@ -21,7 +21,10 @@ const propTypes = {
htmlFor: PropTypes.string,
};
-const FormCheckLabel = React.forwardRef(
+const FormCheckLabel: BsPrefixRefForwardingComponent<
+ 'label',
+ FormCheckLabelProps
+> = React.forwardRef(
({ bsPrefix, className, htmlFor, ...props }, ref) => {
const { controlId } = useContext(FormContext);
@@ -39,6 +42,7 @@ const FormCheckLabel = React.forwardRef(
);
FormCheckLabel.displayName = 'FormCheckLabel';
+FormCheckLabel.typeName = 'FormCheckLabel';
FormCheckLabel.propTypes = propTypes;
export default FormCheckLabel;
diff --git a/src/helpers.ts b/src/helpers.ts
index d514b24abd..c8c83917b4 100644
--- a/src/helpers.ts
+++ b/src/helpers.ts
@@ -33,18 +33,28 @@ export interface BsPrefixRefForwardingComponent<
contextTypes?: any;
defaultProps?: Partial;
displayName?: string;
+ typeName?: string;
}
export class BsPrefixComponent<
As extends React.ElementType,
P = unknown,
-> extends React.Component & P>> {}
+> extends React.Component & P>> {
+ typeName?: string;
+}
// Need to use this instead of typeof Component to get proper type checking.
export type BsPrefixComponentClass<
As extends React.ElementType,
P = unknown,
-> = React.ComponentClass & P>>;
+> = React.ComponentClass & P>> & {
+ typeName?: string;
+};
+
+export type BsComponent =
+ | BsPrefixRefForwardingComponent
+ | BsPrefixComponentClass
+ | BsPrefixComponentClass;
export type TransitionType = boolean | TransitionComponent;