Files
ChatApp/apps/desktop/src/components/icons.tsx
T
byGalax 1303c8e26f feat: backup/restore, user profile popover, image compress, video blur, wake lock
- backup/restore dialog + user profile popover components
- image compression, video blur, wake lock utilities
- message cache + conversation messages hook refinements
- call context, active speakers, screen share dialog tweaks
- audio + screen share settings persistence
- refreshed app icons (smaller sizes) across all platforms
2026-04-21 12:11:09 +02:00

584 lines
14 KiB
TypeScript

// Inline SVG icons — no icon library dependency. Lucide-style stroke=1.75.
type IconProps = React.SVGProps<SVGSVGElement>;
function Base({ children, ...props }: IconProps & { children: React.ReactNode }) {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
strokeWidth="1.75"
strokeLinecap="round"
strokeLinejoin="round"
aria-hidden="true"
{...props}
>
{children}
</svg>
);
}
export function MailIcon(props: IconProps) {
return (
<Base {...props}>
<rect x="3" y="5" width="18" height="14" rx="2" />
<path d="m3 7 9 6 9-6" />
</Base>
);
}
export function AtIcon(props: IconProps) {
return (
<Base {...props}>
<circle cx="12" cy="12" r="4" />
<path d="M16 8v5a3 3 0 0 0 6 0v-1a10 10 0 1 0-4 8" />
</Base>
);
}
export function TicketIcon(props: IconProps) {
return (
<Base {...props}>
<path d="M3 8a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2v2a2 2 0 1 0 0 4v2a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-2a2 2 0 1 0 0-4V8Z" />
<path d="M9 6v12" strokeDasharray="2 3" />
</Base>
);
}
export function ArrowRightIcon(props: IconProps) {
return (
<Base {...props}>
<path d="M5 12h14" />
<path d="m13 6 6 6-6 6" />
</Base>
);
}
export function CheckCircleIcon(props: IconProps) {
return (
<Base {...props}>
<circle cx="12" cy="12" r="9" />
<path d="m8.5 12.5 2.5 2.5 4.5-5" />
</Base>
);
}
export function AlertIcon(props: IconProps) {
return (
<Base {...props}>
<path d="M12 9v4" />
<path d="M12 17h.01" />
<path d="M10.3 3.86 1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0Z" />
</Base>
);
}
export function ShieldIcon(props: IconProps) {
return (
<Base {...props}>
<path d="M12 3 4 6v6c0 5 3.5 8.5 8 9 4.5-.5 8-4 8-9V6l-8-3Z" />
<path d="m9.5 12.5 2 2 3.5-4" />
</Base>
);
}
export function LockIcon(props: IconProps) {
return (
<Base {...props}>
<rect x="4" y="11" width="16" height="10" rx="2" />
<path d="M8 11V8a4 4 0 1 1 8 0v3" />
</Base>
);
}
export function SparklesIcon(props: IconProps) {
return (
<Base {...props}>
<path d="M12 3v4" />
<path d="M12 17v4" />
<path d="M3 12h4" />
<path d="M17 12h4" />
<path d="m6 6 2 2" />
<path d="m16 16 2 2" />
<path d="m6 18 2-2" />
<path d="m16 8 2-2" />
</Base>
);
}
export function SpinnerIcon(props: IconProps) {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="none"
aria-hidden="true"
{...props}
>
<circle
cx="12"
cy="12"
r="9"
stroke="currentColor"
strokeOpacity="0.25"
strokeWidth="2.5"
/>
<path
d="M21 12a9 9 0 0 0-9-9"
stroke="currentColor"
strokeWidth="2.5"
strokeLinecap="round"
>
<animateTransform
attributeName="transform"
type="rotate"
from="0 12 12"
to="360 12 12"
dur="0.8s"
repeatCount="indefinite"
/>
</path>
</svg>
);
}
export function ChatBubbleIcon(props: IconProps) {
return (
<Base {...props}>
<path d="M21 15a2 2 0 0 1-2 2H8l-5 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2Z" />
</Base>
);
}
export function UsersIcon(props: IconProps) {
return (
<Base {...props}>
<path d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2" />
<circle cx="9" cy="7" r="4" />
<path d="M22 21v-2a4 4 0 0 0-3-3.87" />
<path d="M16 3.13a4 4 0 0 1 0 7.75" />
</Base>
);
}
export function GearIcon(props: IconProps) {
return (
<Base {...props}>
<circle cx="12" cy="12" r="3" />
<path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 1 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 1 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 1 1-2.83-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 1 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 1 1 2.83-2.83l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 1 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 1 1 2.83 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 1 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1Z" />
</Base>
);
}
export function SearchIcon(props: IconProps) {
return (
<Base {...props}>
<circle cx="11" cy="11" r="7" />
<path d="m21 21-4.3-4.3" />
</Base>
);
}
export function PlusIcon(props: IconProps) {
return (
<Base {...props}>
<path d="M12 5v14M5 12h14" />
</Base>
);
}
export function SignOutIcon(props: IconProps) {
return (
<Base {...props}>
<path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4" />
<path d="m16 17 5-5-5-5" />
<path d="M21 12H9" />
</Base>
);
}
export function MenuIcon(props: IconProps) {
return (
<Base {...props}>
<path d="M3 6h18M3 12h18M3 18h18" />
</Base>
);
}
export function ChevronDownIcon(props: IconProps) {
return (
<Base {...props}>
<path d="m6 9 6 6 6-6" />
</Base>
);
}
export function PencilIcon(props: IconProps) {
return (
<Base {...props}>
<path d="M17 3a2.85 2.83 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5Z" />
</Base>
);
}
export function TrashIcon(props: IconProps) {
return (
<Base {...props}>
<path d="M3 6h18" />
<path d="m19 6-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6" />
<path d="M10 11v6" />
<path d="M14 11v6" />
<path d="M9 6V4a1 1 0 0 1 1-1h4a1 1 0 0 1 1 1v2" />
</Base>
);
}
export function SmileIcon(props: IconProps) {
return (
<Base {...props}>
<circle cx="12" cy="12" r="9" />
<path d="M8 14s1.5 2 4 2 4-2 4-2" />
<path d="M9 9h.01" />
<path d="M15 9h.01" />
</Base>
);
}
export function CopyIcon(props: IconProps) {
return (
<Base {...props}>
<rect x="9" y="9" width="13" height="13" rx="2" />
<path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1" />
</Base>
);
}
export function PhoneIcon(props: IconProps) {
return (
<Base {...props}>
<path d="M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6A19.79 19.79 0 0 1 2.12 4.18 2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72c.127.96.361 1.903.7 2.81a2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45c.907.339 1.85.573 2.81.7A2 2 0 0 1 22 16.92Z" />
</Base>
);
}
export function PhoneOffIcon(props: IconProps) {
return (
<Base {...props}>
<path d="M10.68 13.31a16 16 0 0 0 3.41 2.6l1.27-1.27a2 2 0 0 1 2.11-.45c.907.339 1.85.573 2.81.7A2 2 0 0 1 22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-3.48-3.05" />
<path d="M22 2 2 22" />
<path d="M6.12 2H4.11A2 2 0 0 0 2.12 4.18c.17 1.39.5 2.72 1 3.97" />
</Base>
);
}
export function MicIcon(props: IconProps) {
return (
<Base {...props}>
<rect x="9" y="2" width="6" height="12" rx="3" />
<path d="M19 10v2a7 7 0 0 1-14 0v-2" />
<path d="M12 19v4" />
<path d="M8 23h8" />
</Base>
);
}
export function MicOffIcon(props: IconProps) {
return (
<Base {...props}>
<path d="M1 1l22 22" />
<path d="M9 9v3a3 3 0 0 0 5.12 2.12" />
<path d="M15 9.34V4a3 3 0 0 0-5.94-.6" />
<path d="M17 16.95A7 7 0 0 1 5 12v-2" />
<path d="M19 10v2a7 7 0 0 1-.11 1.23" />
<path d="M12 19v4" />
<path d="M8 23h8" />
</Base>
);
}
export function InfoIcon(props: IconProps) {
return (
<Base {...props}>
<circle cx="12" cy="12" r="9" />
<path d="M12 16v-4" />
<path d="M12 8h.01" />
</Base>
);
}
export function XIcon(props: IconProps) {
return (
<Base {...props}>
<path d="M18 6 6 18M6 6l12 12" />
</Base>
);
}
export function MonitorShareIcon(props: IconProps) {
return (
<Base {...props}>
<rect x="3" y="4" width="18" height="12" rx="2" />
<path d="M8 20h8M12 16v4" />
<path d="M12 12V7M9.5 9.5L12 7l2.5 2.5" />
</Base>
);
}
export function MonitorStopIcon(props: IconProps) {
return (
<Base {...props}>
<rect x="3" y="4" width="18" height="12" rx="2" />
<path d="M8 20h8M12 16v4" />
<path d="M9 9h6v3H9z" fill="currentColor" />
</Base>
);
}
export function SunIcon(props: IconProps) {
return (
<Base {...props}>
<circle cx="12" cy="12" r="4" />
<path d="M12 2v2M12 20v2M4.93 4.93l1.41 1.41M17.66 17.66l1.41 1.41M2 12h2M20 12h2M4.93 19.07l1.41-1.41M17.66 6.34l1.41-1.41" />
</Base>
);
}
export function MoonIcon(props: IconProps) {
return (
<Base {...props}>
<path d="M21 12.79A9 9 0 1 1 11.21 3a7 7 0 0 0 9.79 9.79Z" />
</Base>
);
}
export function GridIcon(props: IconProps) {
return (
<Base {...props}>
<rect x="3" y="3" width="7" height="7" rx="1.5" />
<rect x="14" y="3" width="7" height="7" rx="1.5" />
<rect x="3" y="14" width="7" height="7" rx="1.5" />
<rect x="14" y="14" width="7" height="7" rx="1.5" />
</Base>
);
}
export function FocusIcon(props: IconProps) {
return (
<Base {...props}>
<rect x="3" y="3" width="18" height="18" rx="2" />
<rect x="8" y="8" width="8" height="8" rx="1" />
</Base>
);
}
export function MaximizeIcon(props: IconProps) {
return (
<Base {...props}>
<path d="M4 9V5a1 1 0 0 1 1-1h4" />
<path d="M20 9V5a1 1 0 0 0-1-1h-4" />
<path d="M4 15v4a1 1 0 0 0 1 1h4" />
<path d="M20 15v4a1 1 0 0 1-1 1h-4" />
</Base>
);
}
export function VideoIcon(props: IconProps) {
return (
<Base {...props}>
<rect x="2" y="6" width="15" height="12" rx="2" />
<path d="m22 8-5 4 5 4V8Z" />
</Base>
);
}
export function CrownIcon(props: IconProps) {
return (
<Base {...props}>
<path d="m3 7 4 4 5-6 5 6 4-4v10a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V7Z" />
</Base>
);
}
export function MusicIcon(props: IconProps) {
return (
<Base {...props}>
<path d="M9 18V5l12-2v13" />
<circle cx="6" cy="18" r="3" />
<circle cx="18" cy="16" r="3" />
</Base>
);
}
export function SendIcon(props: IconProps) {
return (
<Base {...props}>
<path d="m3 11 18-8-8 18-2-8-8-2Z" />
</Base>
);
}
export function ArchiveIcon(props: IconProps) {
return (
<Base {...props}>
<rect x="3" y="4" width="18" height="5" rx="1" />
<path d="M5 9v10a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1V9" />
<path d="M10 13h4" />
</Base>
);
}
export function BellIcon(props: IconProps) {
return (
<Base {...props}>
<path d="M6 8a6 6 0 1 1 12 0c0 4 1.5 5 2 6H4c.5-1 2-2 2-6Z" />
<path d="M9.5 18a2.5 2.5 0 0 0 5 0" />
</Base>
);
}
export function BellOffIcon(props: IconProps) {
return (
<Base {...props}>
<path d="M9.5 18a2.5 2.5 0 0 0 5 0" />
<path d="M13.73 4A2 2 0 0 0 10 4" />
<path d="M18 8c0 1-.1 1.9-.2 2.7" />
<path d="M4 4 20 20" />
<path d="M6 8a6 6 0 0 1 .2-1.7" />
<path d="M4 18h13.5L18 17.4c.5-1 2-2 2-6" />
</Base>
);
}
export function MoreVerticalIcon(props: IconProps) {
return (
<Base {...props}>
<circle cx="12" cy="5" r="1.5" />
<circle cx="12" cy="12" r="1.5" />
<circle cx="12" cy="19" r="1.5" />
</Base>
);
}
export function HeadphonesIcon(props: IconProps) {
return (
<Base {...props}>
<path d="M3 14v-2a9 9 0 0 1 18 0v2" />
<path d="M3 14h4v7H5a2 2 0 0 1-2-2Z" />
<path d="M21 14h-4v7h2a2 2 0 0 0 2-2Z" />
</Base>
);
}
export function HeadphonesOffIcon(props: IconProps) {
return (
<Base {...props}>
<path d="M3 14v-2a9 9 0 0 1 11.3-8.7" />
<path d="M21 14v-2a9 9 0 0 0-1.5-5" />
<path d="M3 14h4v7H5a2 2 0 0 1-2-2Z" />
<path d="M21 14h-4v7h2a2 2 0 0 0 2-2Z" />
<path d="M3 3 21 21" />
</Base>
);
}
export function ReplyIcon(props: IconProps) {
return (
<Base {...props}>
<polyline points="9 17 4 12 9 7" />
<path d="M20 18v-2a4 4 0 0 0-4-4H4" />
</Base>
);
}
export function ForwardIcon(props: IconProps) {
return (
<Base {...props}>
<polyline points="15 17 20 12 15 7" />
<path d="M4 18v-2a4 4 0 0 1 4-4h12" />
</Base>
);
}
export function ChevronUpIcon(props: IconProps) {
return (
<Base {...props}>
<polyline points="18 15 12 9 6 15" />
</Base>
);
}
export function AddUserIcon(props: IconProps) {
return (
<Base {...props}>
<path d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2" />
<circle cx="9" cy="7" r="4" />
<path d="M19 8v6M22 11h-6" />
</Base>
);
}
// 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) {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 64 64"
aria-hidden="true"
{...props}
>
<rect x="4" y="4" width="56" height="56" rx="20" fill="#a78bfa" />
<path
d="M20 46 V22 a3 3 0 0 1 5.5 -1.8 L 40 43 a2 2 0 0 0 4 -1.2 V22 a3 3 0 0 0 -6 0"
fill="none"
stroke="#fff"
strokeWidth="5"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
);
}
// Full lockup: soft-N mark + "Netralax" wordmark. `tone` decides text colour:
// "dark" = white text (use on dark background), "light" = near-black.
export function LogoLockup({
tone = 'dark',
...props
}: IconProps & { tone?: 'dark' | 'light' }) {
const textFill = tone === 'dark' ? '#ffffff' : '#14121c';
return (
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 260 64"
aria-hidden="true"
{...props}
>
<rect x="4" y="4" width="56" height="56" rx="20" fill="#a78bfa" />
<path
d="M20 46 V22 a3 3 0 0 1 5.5 -1.8 L 40 43 a2 2 0 0 0 4 -1.2 V22 a3 3 0 0 0 -6 0"
fill="none"
stroke="#fff"
strokeWidth="5"
strokeLinecap="round"
strokeLinejoin="round"
/>
<text
x="78"
y="42"
fontFamily="'Space Grotesk', system-ui, sans-serif"
fontSize="30"
fontWeight="600"
letterSpacing="-0.6"
fill={textFill}
>
Netralax
</text>
</svg>
);
}