From 0228b3f2b15235012a214fa6f8076ee7f8708a47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C4=B0dris=20=C3=87elik?= Date: Tue, 27 Jan 2026 15:35:08 +0300 Subject: [PATCH 1/2] feat: implement AdminTopbar and enhance core components for admin layout --- .../admin/layout/AdminTopbar.stories.svelte | 111 +++++++ .../admin/layout/AdminTopbar.svelte | 281 ++++++++++++++++++ .../src/components/core/buttons/Button.svelte | 50 ++-- .../components/core/buttons/IconButton.svelte | 5 +- .../components/core/forms/SearchInput.svelte | 23 +- .../src/components/core/layout/Col.svelte | 63 +++- .../src/components/core/layout/Row.svelte | 44 ++- .../src/components/core/media/Avatar.svelte | 10 +- .../core/overlay-navigation/Dropdown.svelte | 47 +-- .../core/overlay-navigation/Menu.svelte | 129 +++++--- 10 files changed, 655 insertions(+), 108 deletions(-) create mode 100644 hexawebshare/src/components/admin/layout/AdminTopbar.stories.svelte diff --git a/hexawebshare/src/components/admin/layout/AdminTopbar.stories.svelte b/hexawebshare/src/components/admin/layout/AdminTopbar.stories.svelte new file mode 100644 index 00000000..6b9f1e1a --- /dev/null +++ b/hexawebshare/src/components/admin/layout/AdminTopbar.stories.svelte @@ -0,0 +1,111 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/hexawebshare/src/components/admin/layout/AdminTopbar.svelte b/hexawebshare/src/components/admin/layout/AdminTopbar.svelte index 315da078..5145ad7a 100644 --- a/hexawebshare/src/components/admin/layout/AdminTopbar.svelte +++ b/hexawebshare/src/components/admin/layout/AdminTopbar.svelte @@ -2,3 +2,284 @@ SPDX-FileCopyrightText: 2025 hexaTune LLC SPDX-License-Identifier: MIT --> + + + + + {#if isMobileSearchOpen} + + + { + onSearch?.(q); + if (q) isMobileSearchOpen = false; + }} + /> + + + {:else} + + + + + + + + + + + + + + {#if onSearch} + + {/if} + + + + + + + {#if onSearch} + + (isMobileSearchOpen = true)} + > + + + + + + + + {/if} + + + {#if notifications.length > 0} + + {#snippet trigger()} +
+ + + + + + {#if unreadCount > 0} + + {/if} +
+ {/snippet} + + {#snippet children()} + + {/snippet} + + {:else} + console.log('No notifications')} + > + + + + + + + {/if} + + + {#if isLoggedIn} + + {#snippet trigger()} + + {/snippet} + + + + {:else} + @@ -538,3 +530,20 @@ SPDX-License-Identifier: MIT {/if} + + diff --git a/hexawebshare/src/components/core/overlay-navigation/Menu.svelte b/hexawebshare/src/components/core/overlay-navigation/Menu.svelte index ba91d9df..5f517e60 100644 --- a/hexawebshare/src/components/core/overlay-navigation/Menu.svelte +++ b/hexawebshare/src/components/core/overlay-navigation/Menu.svelte @@ -18,7 +18,7 @@ SPDX-License-Identifier: MIT /** * Label text displayed in the menu item */ - label: string; + label?: string; /** * Optional description or subtitle */ @@ -32,6 +32,15 @@ SPDX-License-Identifier: MIT * @default false */ disabled?: boolean; + /** + * Type of the menu item + * @default 'item' + */ + type?: 'item' | 'title' | 'divider'; + /** + * Visual variant of the item + */ + variant?: 'default' | 'error'; /** * Whether the item is active/selected * @default false @@ -142,7 +151,13 @@ SPDX-License-Identifier: MIT // Compute item classes based on state const getItemClasses = (item: MenuItem, index: number) => - [item.active && 'active', item.disabled && 'disabled', focusedIndex === index && 'focus'] + [ + item.type === 'title' && 'menu-title', + item.active && 'active', + item.disabled && 'disabled', + item.variant === 'error' && 'text-error', + focusedIndex === index && 'focus' + ] .filter(Boolean) .join(' '); @@ -278,56 +293,72 @@ SPDX-License-Identifier: MIT VALIDATION: WAI-ARIA Authoring Practices Guide + DaisyUI v4.x menu documentation --> {#each items as item, index (item.id)} -
  • - {#if item.href && !item.disabled} - handleItemClick(item, index)} - onkeydown={(e) => handleKeyDown(e, item, index)} - onfocus={() => handleFocus(index)} - onblur={handleBlur} - > - {#if item.icon} - - {/if} - - - {#if item.description} - + {#if item.type === 'title'} +
  • + +
  • + {:else if item.type === 'divider'} + + {:else} +
  • + {#if item.href && !item.disabled} + handleItemClick(item, index)} + onkeydown={(e) => handleKeyDown(e, item, index)} + onfocus={() => handleFocus(index)} + onblur={handleBlur} + > + {#if item.icon} + {/if} - - - {:else} - - {/if} -
  • + + + {#if item.description} + + {/if} + + + {/if} + + {/if} {#if item.divider && index < items.length - 1} - + {/if} {/each} {/if} From 57ef92108107e7d1d1bb6209adf9784a3d91453b Mon Sep 17 00:00:00 2001 From: husamettinarabaci Date: Wed, 28 Jan 2026 11:00:51 +0300 Subject: [PATCH 2/2] fix(AdminTopbar): remove hardcoded strings and add missing event handlers - Remove console.log statements with embedded strings - Add onNotificationClick callback for notification item clicks - Add onEmptyNotificationClick callback for empty notification state - Add onLoginClick callback for login button - Implement handleNotificationClick handler to pass notification ID - Update Storybook argTypes with new callback actions - Document custom CSS in Dropdown component per AGENTS.MD requirements --- .../admin/layout/AdminTopbar.stories.svelte | 3 +++ .../admin/layout/AdminTopbar.svelte | 24 ++++++++++++++++--- .../core/overlay-navigation/Dropdown.svelte | 17 ++++++++++++- 3 files changed, 40 insertions(+), 4 deletions(-) diff --git a/hexawebshare/src/components/admin/layout/AdminTopbar.stories.svelte b/hexawebshare/src/components/admin/layout/AdminTopbar.stories.svelte index 6b9f1e1a..abd7b0cf 100644 --- a/hexawebshare/src/components/admin/layout/AdminTopbar.stories.svelte +++ b/hexawebshare/src/components/admin/layout/AdminTopbar.stories.svelte @@ -14,6 +14,9 @@ SPDX-License-Identifier: MIT argTypes: { onToggleSidebar: { action: 'toggleSidebar' }, onSearch: { action: 'search' }, + onNotificationClick: { action: 'notificationClicked' }, + onEmptyNotificationClick: { action: 'emptyNotificationClicked' }, + onLoginClick: { action: 'loginClicked' }, user: { control: 'object' }, notifications: { control: 'object' }, loginLabel: { control: 'text' }, diff --git a/hexawebshare/src/components/admin/layout/AdminTopbar.svelte b/hexawebshare/src/components/admin/layout/AdminTopbar.svelte index 5145ad7a..a796881e 100644 --- a/hexawebshare/src/components/admin/layout/AdminTopbar.svelte +++ b/hexawebshare/src/components/admin/layout/AdminTopbar.svelte @@ -50,6 +50,9 @@ SPDX-License-Identifier: MIT onProfileClick?: () => void; onSettingsClick?: () => void; onLogoutClick?: () => void; + onNotificationClick?: (notificationId: string) => void; + onEmptyNotificationClick?: () => void; + onLoginClick?: () => void; // Icons profileIcon?: string; settingsIcon?: string; @@ -75,6 +78,9 @@ SPDX-License-Identifier: MIT onProfileClick, onSettingsClick, onLogoutClick, + onNotificationClick, + onEmptyNotificationClick, + onLoginClick, profileIcon = '👤', settingsIcon = '⚙️', logoutIcon = '🚪', @@ -106,6 +112,13 @@ SPDX-License-Identifier: MIT { id: 'sep', type: 'divider', label: '' }, { id: 'logout', label: logoutLabel, icon: logoutIcon, variant: 'error', onClick: onLogoutClick } ]; + + // Handle notification item click + function handleNotificationClick(item: MenuItem) { + if (onNotificationClick && typeof item.id === 'string') { + onNotificationClick(item.id); + } + } @@ -222,7 +235,12 @@ SPDX-License-Identifier: MIT {/snippet} {#snippet children()} - + {/snippet} {:else} @@ -230,7 +248,7 @@ SPDX-License-Identifier: MIT variant="ghost" circle ariaLabel={notificationsLabel} - onclick={() => console.log('No notifications')} + onclick={onEmptyNotificationClick} > console.log('Login')} + onclick={onLoginClick} /> {/if} diff --git a/hexawebshare/src/components/core/overlay-navigation/Dropdown.svelte b/hexawebshare/src/components/core/overlay-navigation/Dropdown.svelte index 13610cf5..e044bfdf 100644 --- a/hexawebshare/src/components/core/overlay-navigation/Dropdown.svelte +++ b/hexawebshare/src/components/core/overlay-navigation/Dropdown.svelte @@ -532,7 +532,22 @@ SPDX-License-Identifier: MIT