diff --git a/frontends/ui/src/adapters/ui/icons.tsx b/frontends/ui/src/adapters/ui/icons.tsx
index 14db1d57..54c48d49 100644
--- a/frontends/ui/src/adapters/ui/icons.tsx
+++ b/frontends/ui/src/adapters/ui/icons.tsx
@@ -111,6 +111,7 @@ export const Copy = createIcon('copy-generic')
export const Download = createIcon('download')
export const Upload = createIcon('upload')
export const Share = createIcon('share')
+export const OpenExternal = createIcon('open-external')
export const Refresh = createIcon('refresh')
// ---------------------------------------------------------------------------
diff --git a/frontends/ui/src/features/layout/components/AppBar.spec.tsx b/frontends/ui/src/features/layout/components/AppBar.spec.tsx
index 536cf45a..017d6bbb 100644
--- a/frontends/ui/src/features/layout/components/AppBar.spec.tsx
+++ b/frontends/ui/src/features/layout/components/AppBar.spec.tsx
@@ -10,6 +10,7 @@ import { AppBar } from './AppBar'
const mockToggleSessionsPanel = vi.fn()
const mockOpenRightPanel = vi.fn()
const mockCloseRightPanel = vi.fn()
+const mockSetTheme = vi.fn()
vi.mock('../store', () => ({
useLayoutStore: () => ({
@@ -17,6 +18,8 @@ vi.mock('../store', () => ({
rightPanel: null,
openRightPanel: mockOpenRightPanel,
closeRightPanel: mockCloseRightPanel,
+ theme: 'system',
+ setTheme: mockSetTheme,
}),
}))
@@ -66,7 +69,7 @@ describe('AppBar', () => {
expect(screen.getByRole('button', { name: /create new session/i })).toBeDisabled()
expect(screen.getByRole('button', { name: /toggle sessions sidebar/i })).toBeDisabled()
expect(screen.getByRole('button', { name: /add data sources/i })).toBeDisabled()
- expect(screen.getByRole('button', { name: /open settings/i })).toBeDisabled()
+ expect(screen.getByRole('button', { name: /open documentation/i })).not.toBeDisabled()
})
test('enables action buttons when authenticated', () => {
@@ -75,7 +78,7 @@ describe('AppBar', () => {
expect(screen.getByRole('button', { name: /create new session/i })).not.toBeDisabled()
expect(screen.getByRole('button', { name: /toggle sessions sidebar/i })).not.toBeDisabled()
expect(screen.getByRole('button', { name: /add data sources/i })).not.toBeDisabled()
- expect(screen.getByRole('button', { name: /open settings/i })).not.toBeDisabled()
+ expect(screen.getByRole('button', { name: /open documentation/i })).not.toBeDisabled()
})
test('calls onNewSession when logo button clicked', async () => {
@@ -117,16 +120,6 @@ describe('AppBar', () => {
expect(mockOpenRightPanel).toHaveBeenCalledWith('data-sources')
})
- test('opens settings panel when Settings clicked', async () => {
- const user = userEvent.setup()
-
- render()
-
- await user.click(screen.getByRole('button', { name: /open settings/i }))
-
- expect(mockOpenRightPanel).toHaveBeenCalledWith('settings')
- })
-
test('renders Docs button that opens in new tab', () => {
render()
@@ -168,8 +161,9 @@ describe('AppBar', () => {
})
await user.click(avatarButton)
- // Popover should show "Default User" and info message
+ // Popover should show "Default User", theme control, and info message
expect(screen.getByText('Default User')).toBeInTheDocument()
+ expect(screen.getByRole('radiogroup', { name: /theme/i })).toBeInTheDocument()
expect(screen.getByText('Authentication Not Configured')).toBeInTheDocument()
})
@@ -193,7 +187,7 @@ describe('AppBar', () => {
expect(screen.getByRole('button', { name: /create new session/i })).not.toBeDisabled()
expect(screen.getByRole('button', { name: /toggle sessions sidebar/i })).not.toBeDisabled()
expect(screen.getByRole('button', { name: /add data sources/i })).not.toBeDisabled()
- expect(screen.getByRole('button', { name: /open settings/i })).not.toBeDisabled()
+ expect(screen.getByRole('button', { name: /open documentation/i })).not.toBeDisabled()
})
test('shows session title when auth is disabled', () => {
diff --git a/frontends/ui/src/features/layout/components/AppBar.tsx b/frontends/ui/src/features/layout/components/AppBar.tsx
index 6919c343..d11124df 100644
--- a/frontends/ui/src/features/layout/components/AppBar.tsx
+++ b/frontends/ui/src/features/layout/components/AppBar.tsx
@@ -5,7 +5,7 @@
* AppBar Component
*
* Top navigation bar with menu toggle, logo, session title,
- * and action buttons (Add Sources, Settings, Docs, User Avatar).
+ * and action buttons (Add Sources, Docs, User Avatar).
*
* Shows different states based on authentication:
* - Auth disabled: Default User avatar with info tooltip (no sign in/out)
@@ -15,10 +15,11 @@
'use client'
-import { type FC, useCallback, useState } from 'react'
+import { type CSSProperties, type FC, useCallback, useState } from 'react'
import { Flex, Text, Button, Logo, Avatar, Popover, Divider } from '@/adapters/ui'
-import { Menu, Globe, Settings, Book, Lock, Logout, ChevronRight, Info } from '@/adapters/ui/icons'
+import { Menu, Globe, Book, Lock, Logout, OpenExternal, Info, Moon, Sun } from '@/adapters/ui/icons'
import { useLayoutStore } from '../store'
+import type { ThemeMode } from '../types'
interface AppBarProps {
/** Current session title to display */
@@ -43,6 +44,17 @@ interface AppBarProps {
onSignOut?: () => void
}
+/** Transparent popover shell with outline only (no KUI fill/shadow). */
+const USER_MENU_POPOVER_CLASS =
+ '!bg-transparent !p-0 !shadow-none rounded-[var(--radius-md)] border border-base text-primary'
+
+const USER_MENU_POPOVER_STYLE: CSSProperties = {
+ backgroundColor: 'transparent',
+ boxShadow: 'none',
+ padding: 0,
+ marginTop: 4,
+}
+
/**
* Main navigation bar at the top of the application.
* Controls sidebar toggles and navigation actions.
@@ -74,15 +86,6 @@ export const AppBar: FC = ({
}
}, [rightPanel, openRightPanel, closeRightPanel, isAuthenticated])
- const handleSettingsClick = useCallback(() => {
- if (!isAuthenticated) return
- if (rightPanel === 'settings') {
- closeRightPanel()
- } else {
- openRightPanel('settings')
- }
- }, [rightPanel, openRightPanel, closeRightPanel, isAuthenticated])
-
const handleDocsClick = useCallback(() => {
window.open('https://github.com/NVIDIA-AI-Blueprints/aiq', '_blank')
}, [])
@@ -164,21 +167,6 @@ export const AppBar: FC = ({
Data Sources
-
-
-
@@ -200,6 +188,8 @@ export const AppBar: FC = ({
onOpenChange={setIsUserMenuOpen}
side="bottom"
align="end"
+ className={USER_MENU_POPOVER_CLASS}
+ style={USER_MENU_POPOVER_STYLE}
slotContent={}
>