diff --git a/examples/button/button.polymorph.tsx b/examples/button/button.polymorph.tsx
index ea99ef348..3609ffff8 100644
--- a/examples/button/button.polymorph.tsx
+++ b/examples/button/button.polymorph.tsx
@@ -46,6 +46,7 @@ function Component() {
+ {/* @ts-expect-error TODO: fix `as` inference */}
diff --git a/examples/dropdown/dropdown.customItem.tsx b/examples/dropdown/dropdown.customItem.tsx
index d6fbc7aa0..96509097b 100644
--- a/examples/dropdown/dropdown.customItem.tsx
+++ b/examples/dropdown/dropdown.customItem.tsx
@@ -41,6 +41,7 @@ function Component() {
function Component() {
return (
+ {/* @ts-expect-error TODO: fix `as` inference */}
Home
diff --git a/src/components/Button/Button.tsx b/src/components/Button/Button.tsx
index 53c672d12..1df740f29 100644
--- a/src/components/Button/Button.tsx
+++ b/src/components/Button/Button.tsx
@@ -1,6 +1,7 @@
-import type { ElementType } from 'react';
-import { forwardRef, type ReactNode } from 'react';
+import type { ComponentPropsWithoutRef, ElementType, ForwardedRef } from 'react';
+import { type ReactNode } from 'react';
import { twMerge } from 'tailwind-merge';
+import genericForwardRef from '../../helpers/generic-forward-ref';
import { mergeDeep } from '../../helpers/merge-deep';
import { getTheme } from '../../theme-store';
import type { DeepPartial } from '../../types';
@@ -15,7 +16,6 @@ import { Spinner } from '../Spinner';
import { ButtonBase, type ButtonBaseProps } from './ButtonBase';
import type { PositionInButtonGroup } from './ButtonGroup';
import { ButtonGroup } from './ButtonGroup';
-import type { PolymorphicComponentPropWithRef, PolymorphicRef } from '../../helpers/generic-as-prop';
export interface FlowbiteButtonTheme {
base: string;
@@ -67,110 +67,105 @@ export interface ButtonSizes extends Pick = PolymorphicComponentPropWithRef<
- T,
- {
- href?: string;
- color?: keyof FlowbiteColors;
- fullSized?: boolean;
- gradientDuoTone?: keyof ButtonGradientDuoToneColors;
- gradientMonochrome?: keyof ButtonGradientColors;
- target?: string;
- isProcessing?: boolean;
- processingLabel?: string;
- processingSpinner?: ReactNode;
- label?: ReactNode;
- outline?: boolean;
- pill?: boolean;
- positionInGroup?: keyof PositionInButtonGroup;
- size?: keyof ButtonSizes;
- theme?: DeepPartial;
- }
->;
-
-type ButtonComponentType = ((
- props: ButtonProps,
-) => React.ReactNode | null) & { displayName?: string };
+export type ButtonProps = {
+ as?: T | null;
+ href?: string;
+ color?: keyof FlowbiteColors;
+ fullSized?: boolean;
+ gradientDuoTone?: keyof ButtonGradientDuoToneColors;
+ gradientMonochrome?: keyof ButtonGradientColors;
+ target?: string;
+ isProcessing?: boolean;
+ processingLabel?: string;
+ processingSpinner?: ReactNode;
+ label?: ReactNode;
+ outline?: boolean;
+ pill?: boolean;
+ positionInGroup?: keyof PositionInButtonGroup;
+ size?: keyof ButtonSizes;
+ theme?: DeepPartial;
+} & ComponentPropsWithoutRef;
-const ButtonComponentFn: ButtonComponentType = forwardRef(
- (
- {
- children,
- className,
- color = 'info',
- disabled,
- fullSized,
- isProcessing = false,
- processingLabel = 'Loading...',
- processingSpinner,
- gradientDuoTone,
- gradientMonochrome,
- label,
- outline = false,
- pill = false,
- positionInGroup = 'none',
- size = 'md',
- theme: customTheme = {},
- ...props
- }: ButtonProps,
- ref: PolymorphicRef,
- ) => {
- const { buttonGroup: groupTheme, button: buttonTheme } = getTheme();
- const theme = mergeDeep(buttonTheme, customTheme);
+const ButtonComponentFn = (
+ {
+ children,
+ className,
+ color = 'info',
+ disabled,
+ fullSized,
+ isProcessing = false,
+ processingLabel = 'Loading...',
+ processingSpinner,
+ gradientDuoTone,
+ gradientMonochrome,
+ label,
+ outline = false,
+ pill = false,
+ positionInGroup = 'none',
+ size = 'md',
+ theme: customTheme = {},
+ ...props
+ }: ButtonProps,
+ ref: ForwardedRef,
+) => {
+ const { buttonGroup: groupTheme, button: buttonTheme } = getTheme();
+ const theme = mergeDeep(buttonTheme, customTheme);
- const theirProps = props as ButtonBaseProps;
+ const theirProps = props as ButtonBaseProps;
- return (
-
+
-
+ {isProcessing && (
+
+ {processingSpinner || }
+
)}
- >
- <>
- {isProcessing && (
-
- {processingSpinner || }
-
- )}
- {typeof children !== 'undefined' ? (
- children
- ) : (
-
- {isProcessing ? processingLabel : label}
-
- )}
- >
-
-
- );
- },
-);
+ {typeof children !== 'undefined' ? (
+ children
+ ) : (
+
+ {isProcessing ? processingLabel : label}
+
+ )}
+ >
+
+
+ );
+};
ButtonComponentFn.displayName = 'Button';
-export const Button = Object.assign(ButtonComponentFn, {
+
+const ButtonComponent = genericForwardRef(ButtonComponentFn);
+
+export const Button = Object.assign(ButtonComponent, {
Group: ButtonGroup,
});
diff --git a/src/components/Button/ButtonBase.tsx b/src/components/Button/ButtonBase.tsx
index 6bb5a97c1..42bd13799 100644
--- a/src/components/Button/ButtonBase.tsx
+++ b/src/components/Button/ButtonBase.tsx
@@ -1,19 +1,18 @@
-import { createElement, type ComponentPropsWithoutRef, type ElementType, type ForwardedRef, forwardRef } from 'react';
+import { createElement, type ComponentPropsWithoutRef, type ElementType, type ForwardedRef } from 'react';
+import genericForwardRef from '../../helpers/generic-forward-ref';
export type ButtonBaseProps = {
as?: T;
href?: string;
} & ComponentPropsWithoutRef;
-export const ButtonBase = forwardRef(
- (
- { children, as: Component, href, type = 'button', ...props }: ButtonBaseProps,
- ref: ForwardedRef,
- ) => {
- const BaseComponent = Component || (href ? 'a' : 'button');
+const ButtonBaseComponent = (
+ { children, as: Component, href, type = 'button', ...props }: ButtonBaseProps,
+ ref: ForwardedRef,
+) => {
+ const BaseComponent = Component || (href ? 'a' : 'button');
- return createElement(BaseComponent, { ref, href, type, ...props }, children);
- },
-);
+ return createElement(BaseComponent, { ref, href, type, ...props }, children);
+};
-ButtonBase.displayName = 'ButtonBaseComponent';
+export const ButtonBase = genericForwardRef(ButtonBaseComponent);
diff --git a/src/components/Dropdown/Dropdown.spec.tsx b/src/components/Dropdown/Dropdown.spec.tsx
index fec8846ae..c5f1895c8 100644
--- a/src/components/Dropdown/Dropdown.spec.tsx
+++ b/src/components/Dropdown/Dropdown.spec.tsx
@@ -167,7 +167,7 @@ describe('Components / Dropdown', () => {
});
describe('Dropdown item render', async () => {
- it('should override Dropdown.Item base component when using `as` prop', async () => {
+ it('should override Dropdownn.Item base component when using `as` prop', async () => {
const user = userEvent.setup();
const CustomBaseItem = ({ children }: PropsWithChildren) => {
diff --git a/src/components/Dropdown/Dropdown.tsx b/src/components/Dropdown/Dropdown.tsx
index 3b34ac8f1..8398785b1 100644
--- a/src/components/Dropdown/Dropdown.tsx
+++ b/src/components/Dropdown/Dropdown.tsx
@@ -10,6 +10,7 @@ import type {
MutableRefObject,
ReactElement,
ReactNode,
+ RefCallback,
SetStateAction,
} from 'react';
import { cloneElement, useCallback, useEffect, useMemo, useRef, useState } from 'react';
@@ -97,7 +98,13 @@ const Trigger = ({
{children}
) : (
-