Created
September 25, 2026 10:39
-
-
Save YuraSab/033444cc231a23c7d6d4a126fea32ef2 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // src/components/ui/Icon/Icon.tsx | |
| import * as LucideIcons from "lucide-react"; | |
| import { tv, type VariantProps } from "tailwind-variants"; | |
| export const iconVariants = tv({ | |
| base: "shrink-0 transition-colors", | |
| variants: { | |
| size: { | |
| xs: "size-3.5", // 14px | |
| sm: "size-4", // 16px | |
| md: "size-5", // 20px | |
| lg: "size-6", // 24px | |
| xl: "size-8", // 32px | |
| }, | |
| color: { | |
| primary: "text-blue-600", | |
| error: "text-red-600", | |
| success: "text-green-600", | |
| muted: "text-gray-400", | |
| current: "text-current", | |
| }, | |
| }, | |
| defaultVariants: { | |
| size: "sm", | |
| color: "current", | |
| }, | |
| }); | |
| export type IconName = keyof typeof LucideIcons; | |
| export interface IconProps extends VariantProps<typeof iconVariants> { | |
| name: IconName; | |
| className?: string; | |
| strokeWidth?: number; | |
| customSize?: number; | |
| } | |
| export const Icon = ({ | |
| name, | |
| size, | |
| color, | |
| className, | |
| strokeWidth = 2, | |
| customSize, | |
| }: IconProps) => { | |
| // Lucide types their exports as LucideIcon | |
| const IconComponent = LucideIcons[name] as LucideIcons.LucideIcon; | |
| // динамічний клас для кастомного розміру | |
| const customSizeClass = customSize ? `size-[${customSize}px]` : undefined; | |
| // об'єднюю класи, фільтруючи потенційний undefined | |
| const combinedClasses = [className, customSizeClass] | |
| .filter(Boolean) | |
| .join(" "); | |
| return ( | |
| <IconComponent | |
| // передаю customSize, щоб синхронізувати width/height із значенням в класі (не обов'язково, оскільки пріоритет в класу, проте є хорошою практикою) | |
| size={customSize} | |
| className={iconVariants({ | |
| // виключаю дефолтний розмір, якщо передано customSize | |
| size: customSize ? undefined : size, | |
| color, | |
| className: combinedClasses, | |
| })} | |
| strokeWidth={strokeWidth} | |
| /> | |
| ); | |
| }; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment