UNPKG

@base-ui/react

Version:

Base UI is a library of headless ('unstyled') React components and low-level hooks. You gain complete control over your app's CSS and accessibility features.

64 lines (62 loc) 2.81 kB
'use client'; import * as React from 'react'; import { error } from '@base-ui/utils/error'; import { SafeReact } from '@base-ui/utils/safeReact'; import { useFieldRootContext } from "../../internals/field-root-context/FieldRootContext.js"; import { fieldValidityMapping } from "../../internals/field-constants/constants.js"; import { useRenderElement } from "../../internals/useRenderElement.js"; import { useLabelableContext } from "../../internals/labelable-provider/LabelableContext.js"; import { useLabel } from "../../internals/labelable-provider/useLabel.js"; /** * An accessible label that is automatically associated with the field control. * Renders a `<label>` element. * * Documentation: [Base UI Field](https://base-ui.com/react/components/field) */ export const FieldLabel = /*#__PURE__*/React.forwardRef(function FieldLabel(componentProps, forwardedRef) { const { render, className, style, id: idProp, nativeLabel = true, ...elementProps } = componentProps; const fieldRootContext = useFieldRootContext(false); const { labelId } = useLabelableContext(); const labelRef = React.useRef(null); const labelProps = useLabel({ id: labelId ?? idProp, native: nativeLabel }); if (process.env.NODE_ENV !== 'production') { // eslint-disable-next-line react-hooks/rules-of-hooks React.useEffect(() => { if (!labelRef.current) { return; } const isLabelTag = labelRef.current.tagName === 'LABEL'; if (nativeLabel) { if (!isLabelTag) { const ownerStackMessage = SafeReact.captureOwnerStack?.() || ''; const message = '<Field.Label> expected a <label> element because the `nativeLabel` prop is true. ' + 'Rendering a non-<label> disables native label association, so `htmlFor` will not ' + 'work. Use a real <label> in the `render` prop, or set `nativeLabel` to `false`.'; error(`${message}${ownerStackMessage}`); } } else if (isLabelTag) { const ownerStackMessage = SafeReact.captureOwnerStack?.() || ''; const message = '<Field.Label> expected a non-<label> element because the `nativeLabel` prop is false. ' + 'Rendering a <label> assumes native label behavior while Base UI treats it as ' + 'non-native, which can cause unexpected pointer behavior. Use a non-<label> in the ' + '`render` prop, or set `nativeLabel` to `true`.'; error(`${message}${ownerStackMessage}`); } }, [nativeLabel]); } const element = useRenderElement('label', componentProps, { ref: [forwardedRef, labelRef], state: fieldRootContext.state, props: [labelProps, elementProps], stateAttributesMapping: fieldValidityMapping }); return element; }); if (process.env.NODE_ENV !== "production") FieldLabel.displayName = "FieldLabel";