This should get you headed in the right direction -- using mapped generics with React TSX definitions for various HTMLElements. Here is the Button being "unwrapped" -- all props become conditional and all are accessible
export type UnwrapButtonProps<
T extends keyof ButtonHTMLAttributes<HTMLButtonElement>
> = {
[P in T]?: ButtonHTMLAttributes<HTMLButtonElement>[P];
};
export const getColorPickerControl = ({
color,
style,
onChange,
...props
}: UnwrapButtonProps<
'color' | 'onSelect' | 'onSelectCapture' | 'onChange' | 'style'
>) => {
};
This logic is applicable to any Type that has children props (SVG, Anchor, Input, etc etc etc)
If it's icon color you're after, assuming they're svgs, then this will also be a useful helper function:
export type SVGAttribs<T extends keyof SVGAttributes<SVGSVGElement>> = {
[P in T]?: SVGAttributes<SVGSVGElement>[P];
};
Here's an example of the SVGAttribs type in action for an "X" icon for users to close given views
import { SVGAttribs } from '@/types/index';
const X = ({
...props
}: SVGAttribs<
'className' | 'width' | 'height' | 'onMouseOver' | 'aria-hidden'
>) => {
return (
<svg
width='24'
height='24'
viewBox='0 0 24 24'
fill='none'
xmlns='http://www.w3.org/2000/svg'
{...props}>
<path
d='M6 6L18 18M6 18L18 6L6 18Z'
stroke='rgb(29, 78, 216)'
strokeWidth='2'
className='ring-2 ring-blue-700'
strokeLinecap='round'
strokeLinejoin='round'
/>
</svg>
);
};
export default X;
Note how by only using ...props as the returned value all properties defined within the <"" | ""> of SVGAttribs are now conditionally available for consumption with this Component, anywhere in the project

Here is an example of the X component having those props called inline
<div className='relative z-10 flex items-center lg:hidden'>
{/* Mobile menu button */}
<Disclosure.Button
key={4 ** 5 / 2 ** 3 - 1}
className='rounded-md p-2 inline-flex items-center justify-center text-gray-400 hover:bg-gray-100 hover:text-gray-500 focus:outline-none focus:ring-2 focus:ring-inset focus:ring-blue-600'>
<span className='sr-only'>Open menu</span>
{open ? (
<X className='block h-6 w-6' height='24' width='24' onMouseOver={(e) => {
// additional logic for onMouseOverEvent, etc.
}} aria-hidden='true' />
) : (
<MenuStaggered
className='block h-6 w-6'
aria-hidden='true'
/>
)}
</Disclosure.Button>
</div>
as for conditionally changing color, you'll need to do that by mapping elements that the user will toggle to change to a given color. Something like this
{page?.afcSocial?.afcTemplate?.map((heroImg, i) => (
<div
key={i++}
className={cn(
'bg-white max-w-none bg-current',
i === 0
? 'bg-[#D2D2D2]'
: i === 1
? 'bg-[#0AA8C4]'
: i === 2
? 'bg-[#BFDAED]'
: ''
)}>
<div className='max-w-2xl mx-auto sm:px-6 lg:max-w-8xl'>
<div className='relative overflow-hidden h-[160px] lg:h-[210px] '>
<div className='absolute inset-0 max-w-[490px] mx-auto group'>
<Image
sizes={`${heroImg?.cta?.image?.sizes}`}
quality={85}
priority={true}
loader={ImageLoader}
placeholder='blur'
objectFit='cover'
layout='responsive'
blurDataURL={blurDataURLShimmer({
w: 203.38,
h: 479.97
})}
className=' h-full object-center max-w-[490px] group-hover:bg-opacity-75 duration-150 animated fadeIn'
src={`${heroImg?.cta?.image?.sourceUrl}`}
alt={`${heroImg?.cta?.image?.altText}`}
width={`${479.97}`}
height={`${203.38}`}
/>
</div>
<div
className={cn(
'relative max-w-[130px] lg:max-w-[190px] mx-auto flex flex-col left-[7rem] lg:left-[8rem] lg:px-0',
i === 0 ? 'text-[#00588F]' : 'text-white'
)}>
<div
className={cn(
' tracking-tight text-white lg:text-2xl absolute mt-5 md:mt-0 origin-right right-[0%]',
i === 0 ? 'text-[#00588F]' : 'text-white'
)}>
<div className='inline-flex flex-shrink font-medium align-middle text-[18px] w-[160px] sm:w-[190px] md:mt-2 '>
<p>{flow[i].icon}</p>
<p className='mt-2 my-auto align-middle'>
{' '}
<SocialChevron
className={cn(
i === 0 ? `fill-[#00588F]` : 'white',
''
)}
/>
</p>
<p
className={cn(
'sm:text-[20px] text-[18.6px] mt-1 mr-0.25 leading-[24px] ',
i === 1 ? 'max-w-[83px] sm:max-w-none' : ''
)}>
{heroImg?.cta?.caption}
</p>
</div>
<p
className={cn(
'lg:mt-4 mt-2.5 md:text-[16px] md:max-w-[275px] text-[12.25px] leading-[16px] md:leading-[20.26px] text-center font-normal',
i === 0
? 'w-[160px] md:max-w-[275px] text-[#00588F]'
: i === 1
? 'w-[200px] md:max-w-[380px] text-[#e5e5e5]'
: i === 2
? 'w-[200px] md:max-w-[340px] text-[#e5e5e5]'
: ''
)}>
{heroImg?.cta?.description}
</p>
</div>
</div>
</div>
</div>
</div>
))}
Note: The cn value is classnames, imported from the classnames package