Skip to content

Commit 69cfb8c

Browse files
committed
Merge branch 'main' of github.com:Lissy93/networking-toolbox into feat/new-lookps-for-dns
2 parents 6b77868 + 2ec3de9 commit 69cfb8c

File tree

3 files changed

+69
-8
lines changed

3 files changed

+69
-8
lines changed

src/lib/components/furniture/TopNav.svelte

Lines changed: 50 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<script lang="ts">
22
import { page } from '$app/stores';
3-
import { TOP_NAV, SUB_NAV, isActive, type NavItem, type NavGroup } from '$lib/constants/nav';
3+
import { TOP_NAV, SUB_NAV, isActive, type NavItem, type NavGroup, isGroupWithActiveItem, isGroupWithActiveSubDropdown } from '$lib/constants/nav';
44
import Icon from '$lib/components/global/Icon.svelte';
55
import { navbarDisplay } from '$lib/stores/navbarDisplay';
66
import { bookmarks } from '$lib/stores/bookmarks';
@@ -133,7 +133,9 @@
133133
>
134134
<a
135135
href={item.href}
136-
class="nav-link {isActive(currentPath, item.href) ? 'active' : ''}"
136+
class="nav-link"
137+
class:active={isActive(currentPath, item.href)}
138+
class:dropdown-open={hasSubPages(item.href) && activeDropdown === item.href}
137139
aria-current={isActive(currentPath, item.href) ? 'page' : undefined}
138140
aria-expanded={activeDropdown === item.href}
139141
aria-haspopup={hasSubPages(item.href)}
@@ -182,6 +184,8 @@
182184
<!-- Nav group with secondary dropdown -->
183185
<div
184186
class="nav-group"
187+
class:active={isGroupWithActiveItem(currentPath, subItem)}
188+
class:dropdown-open={isGroupWithActiveSubDropdown(activeSubDropdown, subItem)}
185189
class:has-secondary={subItem.items.length > 0}
186190
role="menuitem"
187191
tabindex="0"
@@ -222,7 +226,8 @@
222226
{#each subItem.items.filter((i) => i.label) as groupItem (groupItem.href)}
223227
<a
224228
href={groupItem.href}
225-
class="dropdown-link {isActive(currentPath, groupItem.href) ? 'active' : ''}"
229+
class="dropdown-link"
230+
class:active={isActive(currentPath, groupItem.href)}
226231
aria-current={isActive(currentPath, groupItem.href) ? 'page' : undefined}
227232
>
228233
<div class="link-content">
@@ -296,7 +301,8 @@
296301
flex-shrink: 0;
297302
}
298303
299-
&:hover {
304+
&:hover,
305+
&.dropdown-open {
300306
color: var(--text-primary);
301307
background: var(--surface-hover);
302308
.dropdown-icon {
@@ -325,6 +331,7 @@
325331
left: 0;
326332
z-index: 5;
327333
overflow: visible;
334+
margin-top: var(--spacing-sm);
328335
}
329336
330337
.primary-dropdown {
@@ -355,6 +362,9 @@
355362
max-height: 80vh;
356363
overflow-y: auto;
357364
overflow-x: visible;
365+
366+
scrollbar-width: thin;
367+
scrollbar-color: color-mix(in srgb, var(--color-primary), transparent 10%) transparent;
358368
}
359369
360370
.dropdown-link {
@@ -429,19 +439,46 @@
429439
padding-top: var(--spacing-xs);
430440
border-top: 1px solid var(--border-secondary);
431441
}
432-
442+
443+
&:has(+ .dropdown-link) {
444+
margin-bottom: var(--spacing-xs);
445+
padding-bottom: var(--spacing-xs);
446+
border-bottom: 1px solid var(--border-secondary);
447+
}
448+
449+
&.has-secondary,
450+
&.active {
451+
.group-title {
452+
padding: var(--spacing-sm) var(--spacing-md);
453+
border-radius: var(--radius-md);
454+
}
455+
}
456+
433457
&.has-secondary {
434458
cursor: pointer;
435-
459+
436460
.group-title {
437-
border-radius: var(--radius-md);
438461
transition: background-color 0.15s ease;
439-
462+
440463
&:hover {
441464
background: var(--surface-hover);
442465
}
443466
}
444467
}
468+
469+
&.dropdown-open {
470+
.group-title {
471+
transition: background-color none;
472+
background: var(--surface-hover);
473+
}
474+
}
475+
476+
&.active {
477+
.group-title {
478+
color: var(--color-primary);
479+
background: color-mix(in srgb, var(--color-primary), transparent 95%);
480+
}
481+
}
445482
}
446483
447484
.group-title {
@@ -480,6 +517,11 @@
480517
pointer-events: auto;
481518
white-space: normal;
482519
520+
max-height: 80vh;
521+
overflow-y: auto;
522+
scrollbar-width: thin;
523+
scrollbar-color: color-mix(in srgb, var(--color-primary), transparent 10%) transparent;
524+
483525
// Smart positioning: try right first, auto-fallback to left
484526
left: calc(100% + 0.5rem);
485527
transform-origin: left center;

src/lib/components/global/ToolCard.svelte

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@
6767
on:click={toggleBookmark}
6868
aria-label={isBookmarked ? 'Remove bookmark' : 'Add bookmark'}
6969
>
70+
<div class="bookmark-icon">
7071
{#if isBookmarked}
7172
{#if isHovered}
7273
<Icon name="bookmark-remove" size="sm" />
@@ -77,6 +78,7 @@
7778
<Icon name="bookmark-add" size="md" />
7879
{/if}
7980
<!-- <Icon name={isBookmarked ? 'bookmark-remove' : 'bookmark-add'} size="sm" /> -->
81+
</div>
8082
</button>
8183
{/if}
8284
</div>
@@ -195,6 +197,7 @@
195197
background: var(--surface-hover);
196198
color: var(--color-success);
197199
transform: scale(1.15);
200+
border-radius: 100%;
198201
199202
&::before {
200203
width: 100%;
@@ -206,6 +209,12 @@
206209
transform: scale(0.95);
207210
}
208211
212+
& .bookmark-icon {
213+
display: flex;
214+
width: fit-content;
215+
height: fit-content;
216+
}
217+
209218
&.bookmarked {
210219
color: var(--text-secondary);
211220
opacity: 1;

src/lib/constants/nav.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2032,6 +2032,16 @@ export function isActive(pathname: string, href: string): boolean {
20322032
return pathname === href || pathname.startsWith(href + '/');
20332033
}
20342034

2035+
export function isGroupWithActiveItem(pathname: string, groupItem: NavGroup): boolean {
2036+
if (groupItem.items.length === 0) return false;
2037+
return groupItem.items.some((item) => isActive(pathname, item.href));
2038+
}
2039+
2040+
export function isGroupWithActiveSubDropdown(activeSubDropdown: string | null, groupItem: NavGroup): boolean {
2041+
if (groupItem.items.length === 0) return false;
2042+
return 'title' in groupItem && activeSubDropdown === groupItem.title;
2043+
}
2044+
20352045
// Helper function to extract all nav items from mixed structure
20362046
function extractAllNavItems(navStructure: (NavItem | NavGroup)[]): NavItem[] {
20372047
const items: NavItem[] = [];

0 commit comments

Comments
 (0)