402 lines
11 KiB
TypeScript
402 lines
11 KiB
TypeScript
import type { ReactElement, ReactNode } from 'react';
|
|
|
|
// Inline stroke icons so glyphs render identically on every OS/browser (no
|
|
// emoji font variance). `currentColor` lets callers theme them via CSS.
|
|
interface IconProps {
|
|
size?: number;
|
|
className?: string;
|
|
}
|
|
|
|
const base = (
|
|
size: number,
|
|
className: string | undefined,
|
|
children: ReactNode,
|
|
strokeWidth = 2,
|
|
): ReactElement => (
|
|
<svg
|
|
width={size}
|
|
height={size}
|
|
viewBox="0 0 24 24"
|
|
fill="none"
|
|
stroke="currentColor"
|
|
strokeWidth={strokeWidth}
|
|
strokeLinecap="round"
|
|
strokeLinejoin="round"
|
|
aria-hidden="true"
|
|
className={className}
|
|
>
|
|
{children}
|
|
</svg>
|
|
);
|
|
|
|
// Solid-fill variant helper (play triangle, filled dots, etc.).
|
|
const solid = (size: number, className: string | undefined, children: ReactNode): ReactElement => (
|
|
<svg
|
|
width={size}
|
|
height={size}
|
|
viewBox="0 0 24 24"
|
|
fill="currentColor"
|
|
aria-hidden="true"
|
|
className={className}
|
|
>
|
|
{children}
|
|
</svg>
|
|
);
|
|
|
|
export const PaperclipIcon = ({ size = 20, className }: IconProps): ReactElement =>
|
|
base(
|
|
size,
|
|
className,
|
|
<path d="M21.44 11.05l-9.19 9.19a6 6 0 0 1-8.49-8.49l9.19-9.19a4 4 0 0 1 5.66 5.66l-9.2 9.19a2 2 0 0 1-2.83-2.83l8.49-8.48" />,
|
|
);
|
|
|
|
export const MicIcon = ({ size = 20, className }: IconProps): ReactElement =>
|
|
base(
|
|
size,
|
|
className,
|
|
<>
|
|
<rect x="9" y="2" width="6" height="12" rx="3" />
|
|
<path d="M5 10a7 7 0 0 0 14 0" />
|
|
<line x1="12" y1="17" x2="12" y2="22" />
|
|
<line x1="8" y1="22" x2="16" y2="22" />
|
|
</>,
|
|
);
|
|
|
|
export const VideoIcon = ({ size = 20, className }: IconProps): ReactElement =>
|
|
base(
|
|
size,
|
|
className,
|
|
<>
|
|
<rect x="2" y="6" width="14" height="12" rx="2" />
|
|
<path d="M22 8l-6 4 6 4V8z" />
|
|
</>,
|
|
);
|
|
|
|
export const StopIcon = ({ size = 20, className }: IconProps): ReactElement =>
|
|
solid(size, className, <rect x="6" y="6" width="12" height="12" rx="2" />);
|
|
|
|
export const SendIcon = ({ size = 20, className }: IconProps): ReactElement =>
|
|
solid(size, className, <path d="M3.4 20.4l17.45-8.3a1 1 0 0 0 0-1.8L3.4 2A.7.7 0 0 0 2.4 2.7L4.5 11 2.4 21.3a.7.7 0 0 0 1 .1z" />);
|
|
|
|
export const CloseIcon = ({ size = 20, className }: IconProps): ReactElement =>
|
|
base(
|
|
size,
|
|
className,
|
|
<>
|
|
<line x1="18" y1="6" x2="6" y2="18" />
|
|
<line x1="6" y1="6" x2="18" y2="18" />
|
|
</>,
|
|
);
|
|
|
|
export const FileIcon = ({ size = 20, className }: IconProps): ReactElement =>
|
|
base(
|
|
size,
|
|
className,
|
|
<>
|
|
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" />
|
|
<polyline points="14 2 14 8 20 8" />
|
|
</>,
|
|
);
|
|
|
|
export const SearchIcon = ({ size = 20, className }: IconProps): ReactElement =>
|
|
base(
|
|
size,
|
|
className,
|
|
<>
|
|
<circle cx="11" cy="11" r="8" />
|
|
<line x1="21" y1="21" x2="16.65" y2="16.65" />
|
|
</>,
|
|
);
|
|
|
|
export const PlayIcon = ({ size = 20, className }: IconProps): ReactElement =>
|
|
solid(size, className, <path d="M7 4.5v15a1 1 0 0 0 1.53.85l12-7.5a1 1 0 0 0 0-1.7l-12-7.5A1 1 0 0 0 7 4.5z" />);
|
|
|
|
export const PauseIcon = ({ size = 20, className }: IconProps): ReactElement =>
|
|
solid(
|
|
size,
|
|
className,
|
|
<>
|
|
<rect x="6" y="4.5" width="4" height="15" rx="1.2" />
|
|
<rect x="14" y="4.5" width="4" height="15" rx="1.2" />
|
|
</>,
|
|
);
|
|
|
|
export const RefreshIcon = ({ size = 20, className }: IconProps): ReactElement =>
|
|
base(
|
|
size,
|
|
className,
|
|
<>
|
|
<polyline points="23 4 23 10 17 10" />
|
|
<path d="M20.49 15a9 9 0 1 1-2.12-9.36L23 10" />
|
|
</>,
|
|
);
|
|
|
|
export const DownloadIcon = ({ size = 20, className }: IconProps): ReactElement =>
|
|
base(
|
|
size,
|
|
className,
|
|
<>
|
|
<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" />
|
|
<polyline points="7 10 12 15 17 10" />
|
|
<line x1="12" y1="15" x2="12" y2="3" />
|
|
</>,
|
|
);
|
|
|
|
export const ImageIcon = ({ size = 20, className }: IconProps): ReactElement =>
|
|
base(
|
|
size,
|
|
className,
|
|
<>
|
|
<rect x="3" y="3" width="18" height="18" rx="2" />
|
|
<circle cx="8.5" cy="8.5" r="1.5" />
|
|
<path d="M21 15l-5-5L5 21" />
|
|
</>,
|
|
);
|
|
|
|
export const CheckIcon = ({ size = 20, className }: IconProps): ReactElement =>
|
|
base(size, className, <polyline points="20 6 9 17 4 12" />, 2.4);
|
|
|
|
export const DoubleCheckIcon = ({ size = 20, className }: IconProps): ReactElement =>
|
|
base(
|
|
size,
|
|
className,
|
|
<>
|
|
<path d="M2 12.5l4.5 4.5L16 7" />
|
|
<path d="M11 16.5l1 1L22 7" />
|
|
</>,
|
|
2.4,
|
|
);
|
|
|
|
export const PlusIcon = ({ size = 20, className }: IconProps): ReactElement =>
|
|
base(
|
|
size,
|
|
className,
|
|
<>
|
|
<line x1="12" y1="5" x2="12" y2="19" />
|
|
<line x1="5" y1="12" x2="19" y2="12" />
|
|
</>,
|
|
);
|
|
|
|
export const ChevronLeftIcon = ({ size = 20, className }: IconProps): ReactElement =>
|
|
base(size, className, <polyline points="15 18 9 12 15 6" />);
|
|
|
|
export const SunIcon = ({ size = 20, className }: IconProps): ReactElement =>
|
|
base(
|
|
size,
|
|
className,
|
|
<>
|
|
<circle cx="12" cy="12" r="4" />
|
|
<path d="M12 2v2M12 20v2M4.9 4.9l1.4 1.4M17.7 17.7l1.4 1.4M2 12h2M20 12h2M4.9 19.1l1.4-1.4M17.7 6.3l1.4-1.4" />
|
|
</>,
|
|
);
|
|
|
|
export const MoonIcon = ({ size = 20, className }: IconProps): ReactElement =>
|
|
base(size, className, <path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z" />);
|
|
|
|
export const MonitorIcon = ({ size = 20, className }: IconProps): ReactElement =>
|
|
base(
|
|
size,
|
|
className,
|
|
<>
|
|
<rect x="2" y="3" width="20" height="14" rx="2" />
|
|
<line x1="8" y1="21" x2="16" y2="21" />
|
|
<line x1="12" y1="17" x2="12" y2="21" />
|
|
</>,
|
|
);
|
|
|
|
export const LogOutIcon = ({ size = 20, className }: IconProps): ReactElement =>
|
|
base(
|
|
size,
|
|
className,
|
|
<>
|
|
<path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4" />
|
|
<polyline points="16 17 21 12 16 7" />
|
|
<line x1="21" y1="12" x2="9" y2="12" />
|
|
</>,
|
|
);
|
|
|
|
export const TrashIcon = ({ size = 20, className }: IconProps): ReactElement =>
|
|
base(
|
|
size,
|
|
className,
|
|
<>
|
|
<polyline points="3 6 5 6 21 6" />
|
|
<path d="M19 6l-1 14a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2L5 6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2" />
|
|
</>,
|
|
);
|
|
|
|
export const EditIcon = ({ size = 20, className }: IconProps): ReactElement =>
|
|
base(
|
|
size,
|
|
className,
|
|
<>
|
|
<path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7" />
|
|
<path d="M18.5 2.5a2.12 2.12 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z" />
|
|
</>,
|
|
);
|
|
|
|
export const SmileIcon = ({ size = 20, className }: IconProps): ReactElement =>
|
|
base(
|
|
size,
|
|
className,
|
|
<>
|
|
<circle cx="12" cy="12" r="10" />
|
|
<path d="M8 14s1.5 2 4 2 4-2 4-2" />
|
|
<line x1="9" y1="9" x2="9.01" y2="9" />
|
|
<line x1="15" y1="9" x2="15.01" y2="9" />
|
|
</>,
|
|
);
|
|
|
|
export const UsersIcon = ({ size = 20, className }: IconProps): ReactElement =>
|
|
base(
|
|
size,
|
|
className,
|
|
<>
|
|
<path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2" />
|
|
<circle cx="9" cy="7" r="4" />
|
|
<path d="M23 21v-2a4 4 0 0 0-3-3.87M16 3.13a4 4 0 0 1 0 7.75" />
|
|
</>,
|
|
);
|
|
|
|
export const PinIcon = ({ size = 20, className }: IconProps): ReactElement =>
|
|
base(
|
|
size,
|
|
className,
|
|
<>
|
|
<path d="M12 17v5" />
|
|
<path d="M9 3h6l-1 7 3 2v3H7v-3l3-2-1-7z" />
|
|
</>,
|
|
);
|
|
|
|
export const PinOffIcon = ({ size = 20, className }: IconProps): ReactElement =>
|
|
base(
|
|
size,
|
|
className,
|
|
<>
|
|
<path d="M12 17v5" />
|
|
<path d="M9 3h6l-1 7 3 2v3H7v-3l3-2-1-7z" />
|
|
<line x1="3" y1="3" x2="21" y2="21" />
|
|
</>,
|
|
);
|
|
|
|
export const FolderIcon = ({ size = 20, className }: IconProps): ReactElement =>
|
|
base(
|
|
size,
|
|
className,
|
|
<path d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z" />,
|
|
);
|
|
|
|
export const CopyIcon = ({ size = 20, className }: IconProps): ReactElement =>
|
|
base(
|
|
size,
|
|
className,
|
|
<>
|
|
<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" />
|
|
</>,
|
|
);
|
|
|
|
export const EraserIcon = ({ size = 20, className }: IconProps): ReactElement =>
|
|
base(
|
|
size,
|
|
className,
|
|
<>
|
|
<path d="M20 20H7L3 16a1.9 1.9 0 0 1 0-2.7L13.3 3a1.9 1.9 0 0 1 2.7 0l5 5a1.9 1.9 0 0 1 0 2.7L13 19" />
|
|
<line x1="9" y1="8" x2="16" y2="15" />
|
|
</>,
|
|
);
|
|
|
|
export const SettingsIcon = ({ size = 20, className }: IconProps): ReactElement =>
|
|
base(
|
|
size,
|
|
className,
|
|
<>
|
|
<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-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.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 1 1 0-4h.09a1.65 1.65 0 0 0 1.51-1 1.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.33h.01a1.65 1.65 0 0 0 1-1.51V3a2 2 0 1 1 4 0v.09a1.65 1.65 0 0 0 1 1.51h.01a1.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.82v.01a1.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" />
|
|
</>,
|
|
);
|
|
|
|
export const ChatsIcon = ({ size = 20, className }: IconProps): ReactElement =>
|
|
base(
|
|
size,
|
|
className,
|
|
<path d="M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z" />,
|
|
);
|
|
|
|
export const UserIcon = ({ size = 20, className }: IconProps): ReactElement =>
|
|
base(
|
|
size,
|
|
className,
|
|
<>
|
|
<path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2" />
|
|
<circle cx="12" cy="7" r="4" />
|
|
</>,
|
|
);
|
|
|
|
export const ChevronDownIcon = ({ size = 20, className }: IconProps): ReactElement =>
|
|
base(size, className, <polyline points="6 9 12 15 18 9" />);
|
|
|
|
export const CameraIcon = ({ size = 20, className }: IconProps): ReactElement =>
|
|
base(
|
|
size,
|
|
className,
|
|
<>
|
|
<path d="M23 19a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h4l2-3h6l2 3h4a2 2 0 0 1 2 2z" />
|
|
<circle cx="12" cy="13" r="4" />
|
|
</>,
|
|
);
|
|
|
|
export const MegaphoneIcon = ({ size = 20, className }: IconProps): ReactElement =>
|
|
base(
|
|
size,
|
|
className,
|
|
<>
|
|
<path d="M3 11l17-7v16L3 13v-2z" />
|
|
<path d="M7.5 13.5V19a1.5 1.5 0 0 0 3 0v-4" />
|
|
</>,
|
|
);
|
|
|
|
export const ForwardIcon = ({ size = 20, className }: IconProps): ReactElement =>
|
|
base(
|
|
size,
|
|
className,
|
|
<>
|
|
<polyline points="15 17 20 12 15 7" />
|
|
<path d="M4 18v-2a4 4 0 0 1 4-4h12" />
|
|
</>,
|
|
);
|
|
|
|
export const SelectIcon = ({ size = 20, className }: IconProps): ReactElement =>
|
|
base(
|
|
size,
|
|
className,
|
|
<>
|
|
<circle cx="12" cy="12" r="10" />
|
|
<polyline points="8 12 11 15 16 9" />
|
|
</>,
|
|
);
|
|
|
|
export const ReplyIcon = ({ size = 20, className }: IconProps): ReactElement =>
|
|
base(
|
|
size,
|
|
className,
|
|
<>
|
|
<polyline points="9 17 4 12 9 7" />
|
|
<path d="M20 18v-2a4 4 0 0 0-4-4H4" />
|
|
</>,
|
|
);
|
|
|
|
// Zovi brand mark (the "bubble Z") — filled glyph only; the container supplies
|
|
// the gradient tile so one asset works at every size.
|
|
export const BrandGlyph = ({ size = 20, className }: IconProps): ReactElement => (
|
|
<svg
|
|
width={size}
|
|
height={size}
|
|
viewBox="0 0 512 512"
|
|
fill="currentColor"
|
|
aria-hidden="true"
|
|
className={className}
|
|
>
|
|
<path d="M118 124H394V208L268 304H394V388H196L118 458V304L244 208H118Z" />
|
|
</svg>
|
|
);
|