spb/zyquo-cloud-web Public MIT
Zyquo Cloud Web — every cloud model, one beautiful chat, entirely in your browser.
TypeScript 81.9%
CSS 8.9%
JavaScript 7.5%
Shell 1.1%
HTML 0.6%
1/*2 * icons.tsx3 * Zyquo Cloud Web4 *5 * Author: Simon-Pierre Boucher6 * Mail: contact@spboucher.ai7 *8 * Minimal inline SVG icon set (stroke-based, currentColor) — no icon9 * dependency (every dependency is key-theft surface). 16×16 grid.10 */1112import type { ReactNode } from 'react'1314function I({ children, size = 14 }: { children: ReactNode; size?: number }) {15 return (16 <svg17 width={size}18 height={size}19 viewBox="0 0 16 16"20 fill="none"21 stroke="currentColor"22 strokeWidth="1.5"23 strokeLinecap="round"24 strokeLinejoin="round"25 aria-hidden="true"26 >27 {children}28 </svg>29 )30}3132export const IconSend = ({ size = 13 }: { size?: number }) => (33 <I size={size}>34 <path d="M8 13V3M3.5 7.5 8 3l4.5 4.5" />35 </I>36)37export const IconStop = ({ size = 11 }: { size?: number }) => (38 <svg width={size} height={size} viewBox="0 0 16 16" fill="currentColor" aria-hidden="true">39 <rect x="3" y="3" width="10" height="10" rx="2" />40 </svg>41)42export const IconPlus = ({ size = 13 }: { size?: number }) => (43 <I size={size}>44 <path d="M8 3v10M3 8h10" />45 </I>46)47export const IconSearch = ({ size = 12 }: { size?: number }) => (48 <I size={size}>49 <circle cx="7" cy="7" r="4.5" />50 <path d="m10.5 10.5 3 3" />51 </I>52)53export const IconGear = ({ size = 14 }: { size?: number }) => (54 <I size={size}>55 <circle cx="8" cy="8" r="2.2" />56 <path d="M8 1.8v2M8 12.2v2M1.8 8h2M12.2 8h2M3.6 3.6l1.4 1.4M11 11l1.4 1.4M12.4 3.6 11 5M5 11l-1.4 1.4" />57 </I>58)59export const IconTrash = ({ size = 12 }: { size?: number }) => (60 <I size={size}>61 <path d="M2.5 4.5h11M6.5 2.5h3M4 4.5 4.8 13.5h6.4L12 4.5M6.5 7v4M9.5 7v4" />62 </I>63)64export const IconPin = ({ size = 11 }: { size?: number }) => (65 <I size={size}>66 <path d="M9.5 2 14 6.5l-3 1-2 4-1.5-1.5L3 14.5 1.5 13l4.5-4.5L4.5 7l4-2z" />67 </I>68)69export const IconCopy = ({ size = 11 }: { size?: number }) => (70 <I size={size}>71 <rect x="5.5" y="5.5" width="8" height="8" rx="1.5" />72 <path d="M10.5 3.5v-1h-8v8h1" />73 </I>74)75export const IconEdit = ({ size = 11 }: { size?: number }) => (76 <I size={size}>77 <path d="m2.5 13.5.6-3 8-8 2.4 2.4-8 8-3 .6zM9.5 4l2.5 2.5" />78 </I>79)80export const IconRefresh = ({ size = 11 }: { size?: number }) => (81 <I size={size}>82 <path d="M13 8a5 5 0 1 1-1.5-3.5M13 2v3h-3" />83 </I>84)85export const IconChevronDown = ({ size = 8 }: { size?: number }) => (86 <I size={size}>87 <path d="m3 5.5 5 5 5-5" strokeWidth="2.2" />88 </I>89)90export const IconChevronRight = ({ size = 8 }: { size?: number }) => (91 <I size={size}>92 <path d="m5.5 3 5 5-5 5" strokeWidth="2.2" />93 </I>94)95export const IconStar = ({ size = 11, filled = false }: { size?: number; filled?: boolean }) => (96 <svg97 width={size}98 height={size}99 viewBox="0 0 16 16"100 fill={filled ? 'currentColor' : 'none'}101 stroke="currentColor"102 strokeWidth="1.3"103 strokeLinejoin="round"104 aria-hidden="true"105 >106 <path d="M8 1.5 10 6l4.8.4-3.6 3.2 1 4.7L8 11.8l-4.2 2.5 1-4.7L1.2 6.4 6 6z" />107 </svg>108)109export const IconEye = ({ size = 10 }: { size?: number }) => (110 <I size={size}>111 <path d="M1.5 8s2.5-4.5 6.5-4.5S14.5 8 14.5 8 12 12.5 8 12.5 1.5 8 1.5 8z" />112 <circle cx="8" cy="8" r="2" />113 </I>114)115export const IconBrain = ({ size = 10 }: { size?: number }) => (116 <I size={size}>117 <path d="M8 2.5c-3 0-5 2-5 4.5 0 1.6.8 3 2 3.8V13c0 .8.7 1.5 1.5 1.5h3c.8 0 1.5-.7 1.5-1.5v-2.2c1.2-.8 2-2.2 2-3.8 0-2.5-2-4.5-5-4.5z" />118 <path d="M6 7.5h4M8 7.5v3" />119 </I>120)121export const IconWrench = ({ size = 10 }: { size?: number }) => (122 <I size={size}>123 <path d="M9.5 6.5 13 3a3.5 3.5 0 0 1-4.6 4.6L4 12a1.4 1.4 0 0 1-2-2l4.4-4.4A3.5 3.5 0 0 1 11 1l-2.5 2.5 1 2 2-1z" />124 </I>125)126export const IconPaperclip = ({ size = 14 }: { size?: number }) => (127 <I size={size}>128 <path d="m13 7.5-5 5a3.2 3.2 0 0 1-4.5-4.5l5.5-5.5a2.2 2.2 0 0 1 3 3L6.7 10.8a1.1 1.1 0 0 1-1.5-1.5L10 4.5" />129 </I>130)131export const IconX = ({ size = 11 }: { size?: number }) => (132 <I size={size}>133 <path d="m3.5 3.5 9 9M12.5 3.5l-9 9" />134 </I>135)136export const IconMenu = ({ size = 15 }: { size?: number }) => (137 <I size={size}>138 <path d="M2.5 4.5h11M2.5 8h11M2.5 11.5h11" />139 </I>140)141export const IconSliders = ({ size = 13 }: { size?: number }) => (142 <I size={size}>143 <path d="M2.5 5h11M2.5 11h11" />144 <circle cx="6" cy="5" r="1.6" fill="var(--z-surface)" />145 <circle cx="10" cy="11" r="1.6" fill="var(--z-surface)" />146 </I>147)148export const IconQuote = ({ size = 11 }: { size?: number }) => (149 <I size={size}>150 <path d="M3 10.5c0-4 1.5-6 4-7-1.5 2-1.5 3.5-1 4a2 2 0 1 1-3 3zM9 10.5c0-4 1.5-6 4-7-1.5 2-1.5 3.5-1 4a2 2 0 1 1-3 3z" />151 </I>152)153export const IconBranch = ({ size = 11 }: { size?: number }) => (154 <I size={size}>155 <circle cx="4" cy="4" r="1.8" />156 <circle cx="4" cy="12" r="1.8" />157 <circle cx="12" cy="7" r="1.8" />158 <path d="M4 5.8v4.4M4 8c0-2 6-1 8-1" />159 </I>160)161export const IconCheck = ({ size = 11 }: { size?: number }) => (162 <I size={size}>163 <path d="m2.5 8.5 3.5 3.5 7.5-8" />164 </I>165)166export const IconDownload = ({ size = 12 }: { size?: number }) => (167 <I size={size}>168 <path d="M8 2.5v8M4.5 7 8 10.5 11.5 7M2.5 13.5h11" />169 </I>170)171export const IconColumns = ({ size = 12 }: { size?: number }) => (172 <I size={size}>173 <rect x="2" y="2.5" width="12" height="11" rx="1.5" />174 <path d="M8 2.5v11" />175 </I>176)177export const IconInfo = ({ size = 12 }: { size?: number }) => (178 <I size={size}>179 <circle cx="8" cy="8" r="6" />180 <path d="M8 7.5V11M8 5.2v.1" />181 </I>182)183export const IconArrowDown = ({ size = 10 }: { size?: number }) => (184 <I size={size}>185 <path d="M8 3v10M3.5 8.5 8 13l4.5-4.5" />186 </I>187)188export const IconLightbulb = ({ size = 14 }: { size?: number }) => (189 <I size={size}>190 <path d="M8 1.5a4.5 4.5 0 0 1 2.5 8.2c-.5.4-.5 1-.5 1.8h-4c0-.8 0-1.4-.5-1.8A4.5 4.5 0 0 1 8 1.5zM6.5 13.5h3" />191 </I>192)193export const IconCode = ({ size = 14 }: { size?: number }) => (194 <I size={size}>195 <path d="m5 4.5-4 3.5 4 3.5M11 4.5l4 3.5-4 3.5" />196 </I>197)198export const IconDoc = ({ size = 14 }: { size?: number }) => (199 <I size={size}>200 <path d="M4 1.5h5.5L13 5v9.5H4zM9.5 1.5V5H13" />201 <path d="M6 8h5M6 10.5h5" />202 </I>203)204export const IconGlobe = ({ size = 14 }: { size?: number }) => (205 <I size={size}>206 <circle cx="8" cy="8" r="6" />207 <path d="M2 8h12M8 2c1.8 1.8 2.5 3.8 2.5 6S9.8 12.2 8 14c-1.8-1.8-2.5-3.8-2.5-6S6.2 3.8 8 2z" />208 </I>209)210export const IconMic = ({ size = 13 }: { size?: number }) => (211 <I size={size}>212 <rect x="6" y="1.5" width="4" height="8" rx="2" />213 <path d="M3.5 7.5a4.5 4.5 0 0 0 9 0M8 12v2.5" />214 </I>215)216export const IconSpeaker = ({ size = 11 }: { size?: number }) => (217 <I size={size}>218 <path d="M2.5 6v4h2.5L9 13V3L5 6zM11 5.5a3.5 3.5 0 0 1 0 5" />219 </I>220)221export const IconCommand = ({ size = 13 }: { size?: number }) => (222 <I size={size}>223 <path d="M5.5 5.5h5v5h-5zM5.5 5.5H4a2 2 0 1 1 2-2v1.5M10.5 5.5H12a2 2 0 1 0-2-2v1.5M5.5 10.5H4a2 2 0 1 0 2 2v-1.5M10.5 10.5H12a2 2 0 1 1-2 2v-1.5" />224 </I>225)226227/** Provider glyphs — simple distinctive marks per provider. */228export function ProviderGlyph({ provider, size = 11 }: { provider: string; size?: number }) {229 switch (provider) {230 case 'openai':231 return (232 <I size={size}>233 <circle cx="8" cy="8" r="5.5" />234 <path d="M8 2.5v11M3.2 5.2l9.6 5.6M3.2 10.8l9.6-5.6" />235 </I>236 )237 case 'anthropic':238 return (239 <I size={size}>240 <path d="M3 13 8 3l5 10M5.2 9.5h5.6" />241 </I>242 )243 case 'xai':244 return (245 <I size={size}>246 <path d="m3 3 10 10M13 3 3 13" />247 </I>248 )249 case 'mistral':250 return (251 <I size={size}>252 <path d="M2.5 12V5M8 12V3M13.5 12V5M2.5 5c2 0 3-2 5.5-2s3.5 2 5.5 2" />253 </I>254 )255 case 'gemini':256 return (257 <I size={size}>258 <path d="M8 1.5C8.5 5 11 7.5 14.5 8 11 8.5 8.5 11 8 14.5 7.5 11 5 8.5 1.5 8 5 7.5 7.5 5 8 1.5z" />259 </I>260 )261 case 'qwen':262 return (263 <I size={size}>264 <circle cx="8" cy="8" r="5.5" />265 <path d="m10.5 10.5 3 3" />266 </I>267 )268 case 'deepseek':269 return (270 <I size={size}>271 <path d="M2 9c1.5-4 4-6.5 8-6.5 2 0 3.5.8 4 2-1 .3-2 1-2.5 2.5C10.5 10 7.5 13 4 13c-1 0-1.7-.3-2-1z" />272 </I>273 )274 case 'kimi':275 return (276 <I size={size}>277 <path d="M12.5 10.5A5.5 5.5 0 1 1 5.5 3.5a4.5 4.5 0 0 0 7 7z" />278 </I>279 )280 case 'perplexity':281 return (282 <I size={size}>283 <circle cx="8" cy="8" r="5.5" />284 <path d="M6 6.5c0-2.5 4-2.5 4 0 0 1.5-2 1.5-2 3M8 11.5v.1" />285 </I>286 )287 case 'together':288 return (289 <I size={size}>290 <circle cx="5.5" cy="5.5" r="2.5" />291 <circle cx="10.5" cy="10.5" r="2.5" />292 <circle cx="10.5" cy="5.5" r="2.5" />293 <circle cx="5.5" cy="10.5" r="2.5" />294 </I>295 )296 case 'deepinfra':297 return (298 <I size={size}>299 <path d="M8 1.5 14 5v6l-6 3.5L2 11V5z" />300 <path d="M8 8v6.5M8 8 2 5M8 8l6-3" />301 </I>302 )303 case 'cerebras':304 return (305 <I size={size}>306 <circle cx="8" cy="8" r="5.5" />307 <path d="M8 4.5A3.5 3.5 0 1 0 11.5 8" />308 </I>309 )310 default:311 return (312 <I size={size}>313 <circle cx="8" cy="8" r="5.5" />314 <path d="M8 5v3.5" />315 </I>316 )317 }318}319