diff --git a/apps/desktop/src/components/ConversationHeader.tsx b/apps/desktop/src/components/ConversationHeader.tsx index 4fa1de2..92d3d80 100644 --- a/apps/desktop/src/components/ConversationHeader.tsx +++ b/apps/desktop/src/components/ConversationHeader.tsx @@ -197,7 +197,7 @@ function HeaderBar({ interface HeaderActionButtonProps { label: string; - icon: (props: React.SVGProps) => React.JSX.Element; + icon: React.ComponentType>; onClick?: () => void; disabled?: boolean; tone?: 'default' | 'accent'; diff --git a/apps/desktop/src/components/Sidebar.tsx b/apps/desktop/src/components/Sidebar.tsx index aa12d22..47c436a 100644 --- a/apps/desktop/src/components/Sidebar.tsx +++ b/apps/desktop/src/components/Sidebar.tsx @@ -17,7 +17,7 @@ import { interface NavItem { to: string; labelKey: string; - icon: (props: React.SVGProps) => React.JSX.Element; + icon: React.ComponentType>; badge?: 'friends' | 'chats'; } @@ -95,7 +95,7 @@ export function Sidebar() { interface RailNavLinkProps { to: string; label: string; - icon: (props: React.SVGProps) => React.JSX.Element; + icon: React.ComponentType>; badge?: number; } @@ -135,7 +135,7 @@ function RailNavLink({ to, label, icon: Icon, badge = 0 }: RailNavLinkProps) { interface RailIconButtonProps { label: string; onClick: () => void; - icon: (props: React.SVGProps) => React.JSX.Element; + icon: React.ComponentType>; tone?: 'default' | 'danger'; } diff --git a/apps/desktop/src/components/icons.tsx b/apps/desktop/src/components/icons.tsx index a5ba632..2ffae37 100644 --- a/apps/desktop/src/components/icons.tsx +++ b/apps/desktop/src/components/icons.tsx @@ -1,6 +1,7 @@ // Inline SVG icons — no icon library dependency. Lucide-style stroke=1.75. +import { memo } from 'react'; -type IconProps = React.SVGProps; +type IconProps = React.ComponentPropsWithoutRef<'svg'>; function Base({ children, ...props }: IconProps & { children: React.ReactNode }) { return ( @@ -20,7 +21,7 @@ function Base({ children, ...props }: IconProps & { children: React.ReactNode }) ); } -export function MailIcon(props: IconProps) { +function MailIconInner(props: IconProps) { return ( @@ -28,8 +29,9 @@ export function MailIcon(props: IconProps) { ); } +export const MailIcon = memo(MailIconInner); -export function AtIcon(props: IconProps) { +function AtIconInner(props: IconProps) { return ( @@ -37,8 +39,9 @@ export function AtIcon(props: IconProps) { ); } +export const AtIcon = memo(AtIconInner); -export function TicketIcon(props: IconProps) { +function TicketIconInner(props: IconProps) { return ( @@ -46,8 +49,9 @@ export function TicketIcon(props: IconProps) { ); } +export const TicketIcon = memo(TicketIconInner); -export function ArrowRightIcon(props: IconProps) { +function ArrowRightIconInner(props: IconProps) { return ( @@ -55,8 +59,9 @@ export function ArrowRightIcon(props: IconProps) { ); } +export const ArrowRightIcon = memo(ArrowRightIconInner); -export function CheckCircleIcon(props: IconProps) { +function CheckCircleIconInner(props: IconProps) { return ( @@ -64,8 +69,9 @@ export function CheckCircleIcon(props: IconProps) { ); } +export const CheckCircleIcon = memo(CheckCircleIconInner); -export function AlertIcon(props: IconProps) { +function AlertIconInner(props: IconProps) { return ( @@ -74,8 +80,9 @@ export function AlertIcon(props: IconProps) { ); } +export const AlertIcon = memo(AlertIconInner); -export function ShieldIcon(props: IconProps) { +function ShieldIconInner(props: IconProps) { return ( @@ -83,8 +90,9 @@ export function ShieldIcon(props: IconProps) { ); } +export const ShieldIcon = memo(ShieldIconInner); -export function LockIcon(props: IconProps) { +function LockIconInner(props: IconProps) { return ( @@ -92,8 +100,9 @@ export function LockIcon(props: IconProps) { ); } +export const LockIcon = memo(LockIconInner); -export function WifiLowIcon(props: IconProps) { +function WifiLowIconInner(props: IconProps) { return ( @@ -102,8 +111,9 @@ export function WifiLowIcon(props: IconProps) { ); } +export const WifiLowIcon = memo(WifiLowIconInner); -export function WifiOffIcon(props: IconProps) { +function WifiOffIconInner(props: IconProps) { return ( @@ -116,8 +126,9 @@ export function WifiOffIcon(props: IconProps) { ); } +export const WifiOffIcon = memo(WifiOffIconInner); -export function PinIcon(props: IconProps) { +function PinIconInner(props: IconProps) { return ( @@ -125,8 +136,9 @@ export function PinIcon(props: IconProps) { ); } +export const PinIcon = memo(PinIconInner); -export function EyeOffIcon(props: IconProps) { +function EyeOffIconInner(props: IconProps) { return ( @@ -136,8 +148,9 @@ export function EyeOffIcon(props: IconProps) { ); } +export const EyeOffIcon = memo(EyeOffIconInner); -export function CaptionsIcon(props: IconProps) { +function CaptionsIconInner(props: IconProps) { return ( @@ -146,8 +159,9 @@ export function CaptionsIcon(props: IconProps) { ); } +export const CaptionsIcon = memo(CaptionsIconInner); -export function PinOffIcon(props: IconProps) { +function PinOffIconInner(props: IconProps) { return ( @@ -157,8 +171,9 @@ export function PinOffIcon(props: IconProps) { ); } +export const PinOffIcon = memo(PinOffIconInner); -export function SparklesIcon(props: IconProps) { +function SparklesIconInner(props: IconProps) { return ( @@ -172,8 +187,9 @@ export function SparklesIcon(props: IconProps) { ); } +export const SparklesIcon = memo(SparklesIconInner); -export function SpinnerIcon(props: IconProps) { +function SpinnerIconInner(props: IconProps) { return ( ); } +export const SpinnerIcon = memo(SpinnerIconInner); -export function ChatBubbleIcon(props: IconProps) { +function ChatBubbleIconInner(props: IconProps) { return ( ); } +export const ChatBubbleIcon = memo(ChatBubbleIconInner); -export function UsersIcon(props: IconProps) { +function UsersIconInner(props: IconProps) { return ( @@ -227,8 +245,9 @@ export function UsersIcon(props: IconProps) { ); } +export const UsersIcon = memo(UsersIconInner); -export function GearIcon(props: IconProps) { +function GearIconInner(props: IconProps) { return ( @@ -236,8 +255,9 @@ export function GearIcon(props: IconProps) { ); } +export const GearIcon = memo(GearIconInner); -export function SearchIcon(props: IconProps) { +function SearchIconInner(props: IconProps) { return ( @@ -245,16 +265,18 @@ export function SearchIcon(props: IconProps) { ); } +export const SearchIcon = memo(SearchIconInner); -export function PlusIcon(props: IconProps) { +function PlusIconInner(props: IconProps) { return ( ); } +export const PlusIcon = memo(PlusIconInner); -export function SignOutIcon(props: IconProps) { +function SignOutIconInner(props: IconProps) { return ( @@ -263,32 +285,36 @@ export function SignOutIcon(props: IconProps) { ); } +export const SignOutIcon = memo(SignOutIconInner); -export function MenuIcon(props: IconProps) { +function MenuIconInner(props: IconProps) { return ( ); } +export const MenuIcon = memo(MenuIconInner); -export function ChevronDownIcon(props: IconProps) { +function ChevronDownIconInner(props: IconProps) { return ( ); } +export const ChevronDownIcon = memo(ChevronDownIconInner); -export function PencilIcon(props: IconProps) { +function PencilIconInner(props: IconProps) { return ( ); } +export const PencilIcon = memo(PencilIconInner); -export function TrashIcon(props: IconProps) { +function TrashIconInner(props: IconProps) { return ( @@ -299,8 +325,9 @@ export function TrashIcon(props: IconProps) { ); } +export const TrashIcon = memo(TrashIconInner); -export function SmileIcon(props: IconProps) { +function SmileIconInner(props: IconProps) { return ( @@ -310,8 +337,9 @@ export function SmileIcon(props: IconProps) { ); } +export const SmileIcon = memo(SmileIconInner); -export function CopyIcon(props: IconProps) { +function CopyIconInner(props: IconProps) { return ( @@ -319,16 +347,18 @@ export function CopyIcon(props: IconProps) { ); } +export const CopyIcon = memo(CopyIconInner); -export function PhoneIcon(props: IconProps) { +function PhoneIconInner(props: IconProps) { return ( ); } +export const PhoneIcon = memo(PhoneIconInner); -export function PhoneOffIcon(props: IconProps) { +function PhoneOffIconInner(props: IconProps) { return ( @@ -337,8 +367,9 @@ export function PhoneOffIcon(props: IconProps) { ); } +export const PhoneOffIcon = memo(PhoneOffIconInner); -export function MicIcon(props: IconProps) { +function MicIconInner(props: IconProps) { return ( @@ -348,8 +379,9 @@ export function MicIcon(props: IconProps) { ); } +export const MicIcon = memo(MicIconInner); -export function MicOffIcon(props: IconProps) { +function MicOffIconInner(props: IconProps) { return ( @@ -362,8 +394,9 @@ export function MicOffIcon(props: IconProps) { ); } +export const MicOffIcon = memo(MicOffIconInner); -export function InfoIcon(props: IconProps) { +function InfoIconInner(props: IconProps) { return ( @@ -372,16 +405,18 @@ export function InfoIcon(props: IconProps) { ); } +export const InfoIcon = memo(InfoIconInner); -export function XIcon(props: IconProps) { +function XIconInner(props: IconProps) { return ( ); } +export const XIcon = memo(XIconInner); -export function MonitorShareIcon(props: IconProps) { +function MonitorShareIconInner(props: IconProps) { return ( @@ -390,8 +425,9 @@ export function MonitorShareIcon(props: IconProps) { ); } +export const MonitorShareIcon = memo(MonitorShareIconInner); -export function MonitorStopIcon(props: IconProps) { +function MonitorStopIconInner(props: IconProps) { return ( @@ -400,8 +436,9 @@ export function MonitorStopIcon(props: IconProps) { ); } +export const MonitorStopIcon = memo(MonitorStopIconInner); -export function SunIcon(props: IconProps) { +function SunIconInner(props: IconProps) { return ( @@ -409,16 +446,18 @@ export function SunIcon(props: IconProps) { ); } +export const SunIcon = memo(SunIconInner); -export function MoonIcon(props: IconProps) { +function MoonIconInner(props: IconProps) { return ( ); } +export const MoonIcon = memo(MoonIconInner); -export function GridIcon(props: IconProps) { +function GridIconInner(props: IconProps) { return ( @@ -428,8 +467,9 @@ export function GridIcon(props: IconProps) { ); } +export const GridIcon = memo(GridIconInner); -export function ImageIcon(props: IconProps) { +function ImageIconInner(props: IconProps) { return ( @@ -438,8 +478,9 @@ export function ImageIcon(props: IconProps) { ); } +export const ImageIcon = memo(ImageIconInner); -export function FileIcon(props: IconProps) { +function FileIconInner(props: IconProps) { return ( @@ -447,8 +488,9 @@ export function FileIcon(props: IconProps) { ); } +export const FileIcon = memo(FileIconInner); -export function PollIcon(props: IconProps) { +function PollIconInner(props: IconProps) { return ( @@ -458,8 +500,9 @@ export function PollIcon(props: IconProps) { ); } +export const PollIcon = memo(PollIconInner); -export function FocusIcon(props: IconProps) { +function FocusIconInner(props: IconProps) { return ( @@ -467,8 +510,9 @@ export function FocusIcon(props: IconProps) { ); } +export const FocusIcon = memo(FocusIconInner); -export function MaximizeIcon(props: IconProps) { +function MaximizeIconInner(props: IconProps) { return ( @@ -478,8 +522,9 @@ export function MaximizeIcon(props: IconProps) { ); } +export const MaximizeIcon = memo(MaximizeIconInner); -export function VideoIcon(props: IconProps) { +function VideoIconInner(props: IconProps) { return ( @@ -487,16 +532,18 @@ export function VideoIcon(props: IconProps) { ); } +export const VideoIcon = memo(VideoIconInner); -export function CrownIcon(props: IconProps) { +function CrownIconInner(props: IconProps) { return ( ); } +export const CrownIcon = memo(CrownIconInner); -export function MusicIcon(props: IconProps) { +function MusicIconInner(props: IconProps) { return ( @@ -505,16 +552,18 @@ export function MusicIcon(props: IconProps) { ); } +export const MusicIcon = memo(MusicIconInner); -export function SendIcon(props: IconProps) { +function SendIconInner(props: IconProps) { return ( ); } +export const SendIcon = memo(SendIconInner); -export function ArchiveIcon(props: IconProps) { +function ArchiveIconInner(props: IconProps) { return ( @@ -523,8 +572,9 @@ export function ArchiveIcon(props: IconProps) { ); } +export const ArchiveIcon = memo(ArchiveIconInner); -export function BellIcon(props: IconProps) { +function BellIconInner(props: IconProps) { return ( @@ -532,8 +582,9 @@ export function BellIcon(props: IconProps) { ); } +export const BellIcon = memo(BellIconInner); -export function BellOffIcon(props: IconProps) { +function BellOffIconInner(props: IconProps) { return ( @@ -545,8 +596,9 @@ export function BellOffIcon(props: IconProps) { ); } +export const BellOffIcon = memo(BellOffIconInner); -export function MoreVerticalIcon(props: IconProps) { +function MoreVerticalIconInner(props: IconProps) { return ( @@ -555,8 +607,9 @@ export function MoreVerticalIcon(props: IconProps) { ); } +export const MoreVerticalIcon = memo(MoreVerticalIconInner); -export function HeadphonesIcon(props: IconProps) { +function HeadphonesIconInner(props: IconProps) { return ( @@ -565,8 +618,9 @@ export function HeadphonesIcon(props: IconProps) { ); } +export const HeadphonesIcon = memo(HeadphonesIconInner); -export function HeadphonesOffIcon(props: IconProps) { +function HeadphonesOffIconInner(props: IconProps) { return ( @@ -577,8 +631,9 @@ export function HeadphonesOffIcon(props: IconProps) { ); } +export const HeadphonesOffIcon = memo(HeadphonesOffIconInner); -export function ReplyIcon(props: IconProps) { +function ReplyIconInner(props: IconProps) { return ( @@ -586,8 +641,9 @@ export function ReplyIcon(props: IconProps) { ); } +export const ReplyIcon = memo(ReplyIconInner); -export function ForwardIcon(props: IconProps) { +function ForwardIconInner(props: IconProps) { return ( @@ -595,16 +651,18 @@ export function ForwardIcon(props: IconProps) { ); } +export const ForwardIcon = memo(ForwardIconInner); -export function ChevronUpIcon(props: IconProps) { +function ChevronUpIconInner(props: IconProps) { return ( ); } +export const ChevronUpIcon = memo(ChevronUpIconInner); -export function AddUserIcon(props: IconProps) { +function AddUserIconInner(props: IconProps) { return ( @@ -613,12 +671,13 @@ export function AddUserIcon(props: IconProps) { ); } +export const AddUserIcon = memo(AddUserIconInner); // Soft-N mark: rounded-square violet tile with a stylised "N" glyph. Used // wherever the app needs a standalone icon (sidebar rail, auth screen, // favicon). Colour decisions sit inside the SVG so consumers just size the // element via `className`. -export function LogoMark(props: IconProps) { +function LogoMarkInner(props: IconProps) { return ( ); } +export const LogoMark = memo(LogoMarkInner); // Full lockup: soft-N mark + "Netralax" wordmark. `tone` decides text colour: // "dark" = white text (use on dark background), "light" = near-black. -export function LogoLockup({ +function LogoLockupInner({ tone = 'dark', ...props }: IconProps & { tone?: 'dark' | 'light' }) { @@ -676,3 +736,4 @@ export function LogoLockup({ ); } +export const LogoLockup = memo(LogoLockupInner);