take component as input in another component
Unanswered
shadow posted this in #help-forum
shadowOP
can i do something like this?
interface TooltipIconProps{
icon: React.ComponentType<any>;
text: string;
}
export function TooltipIcon({ icon: IconComponent, text }: TooltipIconProps) {
return (
<div className="group relative w-max">
<IconComponent className="text-blue-600" />
<span className="pointer-events-none absolute right-7 -top-3 w-max opacity-0 transition-opacity group-hover:opacity-100 bg-slate-600 p-2 py-1 rounded-md font-semibold">
{text}
</span>
</div>
);
}import { BiCategoryAlt } from "react-icons/bi";
<Tooltip icon={<BiCategoryAlt/>} text="test"/>30 Replies
@shadow can i do something like this?
js
interface TooltipIconProps{
icon: React.ComponentType<any>;
text: string;
}
export function TooltipIcon({ icon: IconComponent, text }: TooltipIconProps) {
return (
<div className="group relative w-max">
<IconComponent className="text-blue-600" />
<span className="pointer-events-none absolute right-7 -top-3 w-max opacity-0 transition-opacity group-hover:opacity-100 bg-slate-600 p-2 py-1 rounded-md font-semibold">
{text}
</span>
</div>
);
}
js
import { BiCategoryAlt } from "react-icons/bi";
<Tooltip icon={<BiCategoryAlt/>} text="test"/>
yes and
<Tooltip icon={BiCategoryAlt} text="test"/> should work (aside from the typing which i think you can fix yourself)Giant panda
My preference is
icon={<BiCategoryAlt/>} and typing icon as ReactNodeyeah but here they use
<IconComponent className="text-blue-600" /> so your approach doesn't work so easilyi use both, what to choose depends on the scenario
Giant panda
Oh I didn't notice the usage - I'd wager it's not necessarily inteded to begin with.
i actually have an
<Icon /> component where i add some default styling and variants so i can use something like <Icon icon={ArrowUp} variant="large" />like buttons
@Giant panda My preference is `icon={<BiCategoryAlt/>}` and typing `icon` as `ReactNode`
shadowOP
interface TooltipIconProps{
icon: ReactNode;
text: string;
}like this?
@shadow js
interface TooltipIconProps{
icon: ReactNode;
text: string;
}
like this?
<IconComponent className="text-blue-600" /> will no longer be possible if you pass a node. Good if it is what you want.@rphlmr 🫡 `<IconComponent className="text-blue-600" />` will no longer be possible if you pass a node. Good if it is what you want.
shadowOP
so needs to be
React.ComponentType<any>?@rphlmr 🫡 `<IconComponent className="text-blue-600" />` will no longer be possible if you pass a node. Good if it is what you want.
interface TooltipIconProps{
icon: ReactNode;
text: string;
}
export function TooltipIcon({ icon: IconComponent, text }: TooltipIconProps) {
return (
<div className="group relative w-max">
{cloneElement(icon, {
className: `text-blue-600 ${icon.props.className}`,
})}
<span className="pointer-events-none absolute right-7 -top-3 w-max opacity-0 transition-opacity group-hover:opacity-100 bg-slate-600 p-2 py-1 rounded-md font-semibold">
{text}
</span>
</div>
);
}Merging styles requires an other lib like
tailwind-merge if you don't want style merging issues@shadow so needs to be `React.ComponentType<any>`?
It depends your preference
what Near propose allows you to override default classnames of your component passed by props
example from your code: icon is default to text blue. At some point you can change the color:
<Tooltip icon={<BiCategoryAlt/>} text="test"/> //blue
<Tooltip icon={<BiCategoryAlt className="text-red-600" />} text="test"/> //red@rphlmr 🫡 tsx
interface TooltipIconProps{
icon: ReactNode;
text: string;
}
export function TooltipIcon({ icon: IconComponent, text }: TooltipIconProps) {
return (
<div className="group relative w-max">
{cloneElement(icon, {
className: `text-blue-600 ${icon.props.className}`,
})}
<span className="pointer-events-none absolute right-7 -top-3 w-max opacity-0 transition-opacity group-hover:opacity-100 bg-slate-600 p-2 py-1 rounded-md font-semibold">
{text}
</span>
</div>
);
}
Merging styles requires an other lib like `tailwind-merge` if you don't want style merging issues
shadowOP
what is
cloneElement?@shadow what is `cloneElement`?
It comes from React. It is to clone an element and manipulate its props
@rphlmr 🫡 It comes from React. It is to clone an element and manipulate its props
shadowOP
oh i have to import it got it
@rphlmr 🫡 tsx
interface TooltipIconProps{
icon: ReactNode;
text: string;
}
export function TooltipIcon({ icon: IconComponent, text }: TooltipIconProps) {
return (
<div className="group relative w-max">
{cloneElement(icon, {
className: `text-blue-600 ${icon.props.className}`,
})}
<span className="pointer-events-none absolute right-7 -top-3 w-max opacity-0 transition-opacity group-hover:opacity-100 bg-slate-600 p-2 py-1 rounded-md font-semibold">
{text}
</span>
</div>
);
}
Merging styles requires an other lib like `tailwind-merge` if you don't want style merging issues
shadowOP
its giving
but i think i have it defined
Cannot find name 'icon'but i think i have it defined
shadowOP
'IconComponent' is possibly 'null' or 'undefined'by convention :
icon => a nodeIcon => an Component@shadow `'IconComponent' is possibly 'null' or 'undefined'`
{icon ? cloneElement(icon, {
className: `text-blue-600 ${icon.props.className}`,
}) : null}make a ternary, but I don't know why it thinks it could be null
ah it's the wrong type
node can be nullish (undefined/null)
interface TooltipIconProps{
icon: React.ReactElement<{ className?: string }>;
text: string;
}is a better type
shadowOP
okay no errors, let me test it
its working thanks!!