这应该会让你朝着正确的方向前进——使用映射泛型和 React TSX 定义来处理各种 HTMLElement。这是“展开”的 Button——所有道具都成为有条件的,并且都可以访问
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'
>) => {
};
此逻辑适用于任何具有子属性(SVG、Anchor、Input 等)的类型
如果你想要的是图标颜色,假设它们是 svg,那么这也是一个有用的辅助函数:
export type SVGAttribs<T extends keyof SVGAttributes<SVGSVGElement>> = {
[P in T]?: SVGAttributes<SVGSVGElement>[P];
};
这里是一个 SVGAttribs 类型的示例,它用于用户关闭给定视图的“X”图标
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;
请注意,通过仅使用 ...props 作为返回值,在 SVGAttribs 的 <"" | ""> 中定义的所有属性现在都可以在项目中的任何位置有条件地用于此组件
这是一个 X 组件的示例,其中包含称为内联的这些道具
<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>
至于有条件地改变颜色,您需要通过映射用户将切换以更改为给定颜色的元素来做到这一点。像这样的
{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>
))}
注意:cn 的值是 classnames,从 classnames 包导入