Skip to content

Commit 6276f3f

Browse files
authored
Merge pull request #1 from Chesars/feature/mobile-hamburger-menu
Fix: add responsive hamburger menu for mobile navigation
2 parents 4f63d89 + df6480b commit 6276f3f

File tree

1 file changed

+199
-22
lines changed

1 file changed

+199
-22
lines changed

src/Main.svelte

Lines changed: 199 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,23 @@
44
import Providers from "./Providers.svelte";
55
66
let activeTab: "models" | "providers" = "models";
7+
let mobileMenuOpen = false;
78
89
const GITHUB_URL = "https://github.com/BerriAI/litellm";
910
const DOCS_URL = "https://docs.litellm.ai";
11+
12+
function toggleMobileMenu() {
13+
mobileMenuOpen = !mobileMenuOpen;
14+
}
15+
16+
function closeMobileMenu() {
17+
mobileMenuOpen = false;
18+
}
19+
20+
function selectTab(tab: "models" | "providers") {
21+
activeTab = tab;
22+
closeMobileMenu();
23+
}
1024
const PROVIDERS_URL = "https://raw.githubusercontent.com/BerriAI/litellm/main/provider_endpoints_support.json";
1125
const MODELS_URL = "https://raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json";
1226
@@ -61,33 +75,71 @@
6175
<!-- Header -->
6276
<header class="header">
6377
<div class="header-content">
64-
<div class="left-section">
65-
<div class="logo-section-header">
66-
<span class="logo-emoji">🚅</span>
67-
<span class="logo-text-header">LiteLLM</span>
68-
</div>
78+
<div class="logo-section-header">
79+
<span class="logo-emoji">🚅</span>
80+
<span class="logo-text-header">LiteLLM</span>
81+
</div>
82+
83+
<!-- Desktop Navigation -->
84+
<div class="desktop-nav">
6985
<div class="tabs">
70-
<button
71-
class="tab"
86+
<button
87+
class="tab"
7288
class:active={activeTab === "models"}
73-
on:click={() => activeTab = "models"}
89+
on:click={() => selectTab("models")}
7490
>
7591
Models
7692
</button>
77-
<button
78-
class="tab"
93+
<button
94+
class="tab"
7995
class:active={activeTab === "providers"}
80-
on:click={() => activeTab = "providers"}
96+
on:click={() => selectTab("providers")}
8197
>
8298
AI Gateway - Endpoints & Providers
8399
</button>
84100
</div>
101+
<nav class="nav-links">
102+
<a href={DOCS_URL} target="_blank" rel="noopener noreferrer" class="nav-link">Docs</a>
103+
<a href={GITHUB_URL} target="_blank" rel="noopener noreferrer" class="nav-link">GitHub</a>
104+
</nav>
85105
</div>
86-
<nav class="nav-links">
87-
<a href={DOCS_URL} target="_blank" rel="noopener noreferrer" class="nav-link">Docs</a>
88-
<a href={GITHUB_URL} target="_blank" rel="noopener noreferrer" class="nav-link">GitHub</a>
89-
</nav>
106+
107+
<!-- Mobile Menu Button -->
108+
<button
109+
class="mobile-menu-btn"
110+
on:click={toggleMobileMenu}
111+
aria-label="Toggle menu"
112+
aria-expanded={mobileMenuOpen}
113+
>
114+
<span class="hamburger" class:open={mobileMenuOpen}></span>
115+
</button>
90116
</div>
117+
118+
<!-- Mobile Menu -->
119+
{#if mobileMenuOpen}
120+
<div class="mobile-menu">
121+
<div class="mobile-tabs">
122+
<button
123+
class="mobile-tab"
124+
class:active={activeTab === "models"}
125+
on:click={() => selectTab("models")}
126+
>
127+
Models
128+
</button>
129+
<button
130+
class="mobile-tab"
131+
class:active={activeTab === "providers"}
132+
on:click={() => selectTab("providers")}
133+
>
134+
AI Gateway - Endpoints & Providers
135+
</button>
136+
</div>
137+
<div class="mobile-links">
138+
<a href={DOCS_URL} target="_blank" rel="noopener noreferrer" class="mobile-link" on:click={closeMobileMenu}>Docs</a>
139+
<a href={GITHUB_URL} target="_blank" rel="noopener noreferrer" class="mobile-link" on:click={closeMobileMenu}>GitHub</a>
140+
</div>
141+
</div>
142+
{/if}
91143
</header>
92144

93145
<!-- Statistics Section -->
@@ -171,7 +223,7 @@
171223
justify-content: space-between;
172224
}
173225
174-
.left-section {
226+
.desktop-nav {
175227
display: flex;
176228
align-items: center;
177229
gap: 2rem;
@@ -236,6 +288,137 @@
236288
color: var(--litellm-primary);
237289
}
238290
291+
/* Mobile Menu Button - Hidden on desktop */
292+
.mobile-menu-btn {
293+
display: none;
294+
background: none;
295+
border: none;
296+
cursor: pointer;
297+
padding: 0.5rem;
298+
z-index: 101;
299+
}
300+
301+
.hamburger {
302+
display: block;
303+
width: 24px;
304+
height: 2px;
305+
background-color: #1a1a1a;
306+
position: relative;
307+
transition: background-color 0.2s ease;
308+
}
309+
310+
.hamburger::before,
311+
.hamburger::after {
312+
content: "";
313+
position: absolute;
314+
width: 24px;
315+
height: 2px;
316+
background-color: #1a1a1a;
317+
left: 0;
318+
transition: transform 0.3s ease;
319+
}
320+
321+
.hamburger::before {
322+
top: -7px;
323+
}
324+
325+
.hamburger::after {
326+
top: 7px;
327+
}
328+
329+
/* Hamburger animation when open */
330+
.hamburger.open {
331+
background-color: transparent;
332+
}
333+
334+
.hamburger.open::before {
335+
transform: rotate(45deg) translate(5px, 5px);
336+
}
337+
338+
.hamburger.open::after {
339+
transform: rotate(-45deg) translate(5px, -5px);
340+
}
341+
342+
/* Mobile Menu Panel */
343+
.mobile-menu {
344+
display: none;
345+
background: #ffffff;
346+
border-top: 1px solid #e5e7eb;
347+
padding: 1rem;
348+
}
349+
350+
.mobile-tabs {
351+
display: flex;
352+
flex-direction: column;
353+
gap: 0.5rem;
354+
margin-bottom: 1rem;
355+
padding-bottom: 1rem;
356+
border-bottom: 1px solid #e5e7eb;
357+
}
358+
359+
.mobile-tab {
360+
padding: 0.75rem 1rem;
361+
border: none;
362+
background: transparent;
363+
color: #6b7280;
364+
font-weight: 500;
365+
font-size: 1rem;
366+
cursor: pointer;
367+
text-align: left;
368+
border-radius: 8px;
369+
transition: all 0.2s ease;
370+
}
371+
372+
.mobile-tab:hover {
373+
background-color: #f3f4f6;
374+
color: #1a1a1a;
375+
}
376+
377+
.mobile-tab.active {
378+
background-color: #f3f4f6;
379+
color: #1a1a1a;
380+
}
381+
382+
.mobile-links {
383+
display: flex;
384+
flex-direction: column;
385+
gap: 0.5rem;
386+
}
387+
388+
.mobile-link {
389+
padding: 0.75rem 1rem;
390+
color: #1a1a1a;
391+
text-decoration: none;
392+
font-weight: 500;
393+
font-size: 1rem;
394+
border-radius: 8px;
395+
transition: all 0.2s ease;
396+
}
397+
398+
.mobile-link:hover {
399+
background-color: #f3f4f6;
400+
color: var(--litellm-primary);
401+
}
402+
403+
/* Mobile Responsive */
404+
@media (max-width: 768px) {
405+
.header-content {
406+
padding: 0.75rem 1rem;
407+
}
408+
409+
.desktop-nav {
410+
display: none;
411+
}
412+
413+
.mobile-menu-btn {
414+
display: block;
415+
}
416+
417+
.mobile-menu {
418+
display: block;
419+
}
420+
}
421+
239422
/* Statistics Section */
240423
.stats-section {
241424
max-width: 1400px;
@@ -304,12 +487,6 @@
304487
font-size: 0.6875rem;
305488
}
306489
307-
.left-section {
308-
flex-direction: column;
309-
align-items: flex-start;
310-
gap: 1rem;
311-
}
312-
313490
.tabs {
314491
width: 100%;
315492
flex-wrap: wrap;

0 commit comments

Comments
 (0)