|
3 | 3 | import Providers from "./Providers.svelte"; |
4 | 4 |
|
5 | 5 | let activeTab: "models" | "providers" = "models"; |
| 6 | + let mobileMenuOpen = false; |
6 | 7 |
|
7 | 8 | const GITHUB_URL = "https://github.com/BerriAI/litellm"; |
8 | 9 | const DOCS_URL = "https://docs.litellm.ai"; |
| 10 | +
|
| 11 | + function toggleMobileMenu() { |
| 12 | + mobileMenuOpen = !mobileMenuOpen; |
| 13 | + } |
| 14 | +
|
| 15 | + function closeMobileMenu() { |
| 16 | + mobileMenuOpen = false; |
| 17 | + } |
| 18 | +
|
| 19 | + function selectTab(tab: "models" | "providers") { |
| 20 | + activeTab = tab; |
| 21 | + closeMobileMenu(); |
| 22 | + } |
9 | 23 | </script> |
10 | 24 |
|
11 | 25 | <div class="app-container"> |
12 | 26 | <!-- Header --> |
13 | 27 | <header class="header"> |
14 | 28 | <div class="header-content"> |
15 | | - <div class="left-section"> |
16 | | - <div class="logo-section-header"> |
17 | | - <span class="logo-emoji">🚅</span> |
18 | | - <span class="logo-text-header">LiteLLM</span> |
19 | | - </div> |
| 29 | + <div class="logo-section-header"> |
| 30 | + <span class="logo-emoji">🚅</span> |
| 31 | + <span class="logo-text-header">LiteLLM</span> |
| 32 | + </div> |
| 33 | + |
| 34 | + <!-- Desktop Navigation --> |
| 35 | + <div class="desktop-nav"> |
20 | 36 | <div class="tabs"> |
21 | | - <button |
22 | | - class="tab" |
| 37 | + <button |
| 38 | + class="tab" |
23 | 39 | class:active={activeTab === "models"} |
24 | | - on:click={() => activeTab = "models"} |
| 40 | + on:click={() => selectTab("models")} |
25 | 41 | > |
26 | 42 | Models |
27 | 43 | </button> |
28 | | - <button |
29 | | - class="tab" |
| 44 | + <button |
| 45 | + class="tab" |
30 | 46 | class:active={activeTab === "providers"} |
31 | | - on:click={() => activeTab = "providers"} |
| 47 | + on:click={() => selectTab("providers")} |
32 | 48 | > |
33 | 49 | AI Gateway - Endpoints & Providers |
34 | 50 | </button> |
35 | 51 | </div> |
| 52 | + <nav class="nav-links"> |
| 53 | + <a href={DOCS_URL} target="_blank" rel="noopener noreferrer" class="nav-link">Docs</a> |
| 54 | + <a href={GITHUB_URL} target="_blank" rel="noopener noreferrer" class="nav-link">GitHub</a> |
| 55 | + </nav> |
36 | 56 | </div> |
37 | | - <nav class="nav-links"> |
38 | | - <a href={DOCS_URL} target="_blank" rel="noopener noreferrer" class="nav-link">Docs</a> |
39 | | - <a href={GITHUB_URL} target="_blank" rel="noopener noreferrer" class="nav-link">GitHub</a> |
40 | | - </nav> |
| 57 | + |
| 58 | + <!-- Mobile Menu Button --> |
| 59 | + <button |
| 60 | + class="mobile-menu-btn" |
| 61 | + on:click={toggleMobileMenu} |
| 62 | + aria-label="Toggle menu" |
| 63 | + aria-expanded={mobileMenuOpen} |
| 64 | + > |
| 65 | + <span class="hamburger" class:open={mobileMenuOpen}></span> |
| 66 | + </button> |
41 | 67 | </div> |
| 68 | + |
| 69 | + <!-- Mobile Menu --> |
| 70 | + {#if mobileMenuOpen} |
| 71 | + <div class="mobile-menu"> |
| 72 | + <div class="mobile-tabs"> |
| 73 | + <button |
| 74 | + class="mobile-tab" |
| 75 | + class:active={activeTab === "models"} |
| 76 | + on:click={() => selectTab("models")} |
| 77 | + > |
| 78 | + Models |
| 79 | + </button> |
| 80 | + <button |
| 81 | + class="mobile-tab" |
| 82 | + class:active={activeTab === "providers"} |
| 83 | + on:click={() => selectTab("providers")} |
| 84 | + > |
| 85 | + AI Gateway - Endpoints & Providers |
| 86 | + </button> |
| 87 | + </div> |
| 88 | + <div class="mobile-links"> |
| 89 | + <a href={DOCS_URL} target="_blank" rel="noopener noreferrer" class="mobile-link" on:click={closeMobileMenu}>Docs</a> |
| 90 | + <a href={GITHUB_URL} target="_blank" rel="noopener noreferrer" class="mobile-link" on:click={closeMobileMenu}>GitHub</a> |
| 91 | + </div> |
| 92 | + </div> |
| 93 | + {/if} |
42 | 94 | </header> |
43 | 95 |
|
44 | 96 | <!-- Content --> |
|
98 | 150 | justify-content: space-between; |
99 | 151 | } |
100 | 152 |
|
101 | | - .left-section { |
| 153 | + .desktop-nav { |
102 | 154 | display: flex; |
103 | 155 | align-items: center; |
104 | 156 | gap: 2rem; |
|
162 | 214 | .nav-link:hover { |
163 | 215 | color: var(--litellm-primary); |
164 | 216 | } |
| 217 | +
|
| 218 | + /* Mobile Menu Button - Hidden on desktop */ |
| 219 | + .mobile-menu-btn { |
| 220 | + display: none; |
| 221 | + background: none; |
| 222 | + border: none; |
| 223 | + cursor: pointer; |
| 224 | + padding: 0.5rem; |
| 225 | + z-index: 101; |
| 226 | + } |
| 227 | +
|
| 228 | + .hamburger { |
| 229 | + display: block; |
| 230 | + width: 24px; |
| 231 | + height: 2px; |
| 232 | + background-color: #1a1a1a; |
| 233 | + position: relative; |
| 234 | + transition: background-color 0.2s ease; |
| 235 | + } |
| 236 | +
|
| 237 | + .hamburger::before, |
| 238 | + .hamburger::after { |
| 239 | + content: ""; |
| 240 | + position: absolute; |
| 241 | + width: 24px; |
| 242 | + height: 2px; |
| 243 | + background-color: #1a1a1a; |
| 244 | + left: 0; |
| 245 | + transition: transform 0.3s ease; |
| 246 | + } |
| 247 | +
|
| 248 | + .hamburger::before { |
| 249 | + top: -7px; |
| 250 | + } |
| 251 | +
|
| 252 | + .hamburger::after { |
| 253 | + top: 7px; |
| 254 | + } |
| 255 | +
|
| 256 | + /* Hamburger animation when open */ |
| 257 | + .hamburger.open { |
| 258 | + background-color: transparent; |
| 259 | + } |
| 260 | +
|
| 261 | + .hamburger.open::before { |
| 262 | + transform: rotate(45deg) translate(5px, 5px); |
| 263 | + } |
| 264 | +
|
| 265 | + .hamburger.open::after { |
| 266 | + transform: rotate(-45deg) translate(5px, -5px); |
| 267 | + } |
| 268 | +
|
| 269 | + /* Mobile Menu Panel */ |
| 270 | + .mobile-menu { |
| 271 | + display: none; |
| 272 | + background: #ffffff; |
| 273 | + border-top: 1px solid #e5e7eb; |
| 274 | + padding: 1rem; |
| 275 | + } |
| 276 | +
|
| 277 | + .mobile-tabs { |
| 278 | + display: flex; |
| 279 | + flex-direction: column; |
| 280 | + gap: 0.5rem; |
| 281 | + margin-bottom: 1rem; |
| 282 | + padding-bottom: 1rem; |
| 283 | + border-bottom: 1px solid #e5e7eb; |
| 284 | + } |
| 285 | +
|
| 286 | + .mobile-tab { |
| 287 | + padding: 0.75rem 1rem; |
| 288 | + border: none; |
| 289 | + background: transparent; |
| 290 | + color: #6b7280; |
| 291 | + font-weight: 500; |
| 292 | + font-size: 1rem; |
| 293 | + cursor: pointer; |
| 294 | + text-align: left; |
| 295 | + border-radius: 8px; |
| 296 | + transition: all 0.2s ease; |
| 297 | + } |
| 298 | +
|
| 299 | + .mobile-tab:hover { |
| 300 | + background-color: #f3f4f6; |
| 301 | + color: #1a1a1a; |
| 302 | + } |
| 303 | +
|
| 304 | + .mobile-tab.active { |
| 305 | + background-color: #f3f4f6; |
| 306 | + color: #1a1a1a; |
| 307 | + } |
| 308 | +
|
| 309 | + .mobile-links { |
| 310 | + display: flex; |
| 311 | + flex-direction: column; |
| 312 | + gap: 0.5rem; |
| 313 | + } |
| 314 | +
|
| 315 | + .mobile-link { |
| 316 | + padding: 0.75rem 1rem; |
| 317 | + color: #1a1a1a; |
| 318 | + text-decoration: none; |
| 319 | + font-weight: 500; |
| 320 | + font-size: 1rem; |
| 321 | + border-radius: 8px; |
| 322 | + transition: all 0.2s ease; |
| 323 | + } |
| 324 | +
|
| 325 | + .mobile-link:hover { |
| 326 | + background-color: #f3f4f6; |
| 327 | + color: var(--litellm-primary); |
| 328 | + } |
| 329 | +
|
| 330 | + /* Mobile Responsive */ |
| 331 | + @media (max-width: 768px) { |
| 332 | + .header-content { |
| 333 | + padding: 0.75rem 1rem; |
| 334 | + } |
| 335 | +
|
| 336 | + .desktop-nav { |
| 337 | + display: none; |
| 338 | + } |
| 339 | +
|
| 340 | + .mobile-menu-btn { |
| 341 | + display: block; |
| 342 | + } |
| 343 | +
|
| 344 | + .mobile-menu { |
| 345 | + display: block; |
| 346 | + } |
| 347 | + } |
165 | 348 | </style> |
166 | 349 |
|
0 commit comments