Add separate MobileTitleBar component for mobile layout

- Create MobileTitleBar component with fixed top position
- Split title bar from tabs bar on mobile (title always on top)
- Add data-has-actions attribute for action button detection
- Track --tab-pill-height CSS variable for tab buttons
- Remove extra padding from mobile content padding-top
- Hide tabs container when no tabs or actions present

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-05 16:52:34 +01:00
parent c85a7f9258
commit 97494679ec
20 changed files with 397 additions and 197 deletions

View File

@@ -1,6 +1,7 @@
import { useEffect, useState } from 'react';
import { useTranslation } from '../contexts/LanguageContext';
import { useSidebar } from '../contexts/SidebarContext';
import MobileTitleBar from '../components/MobileTitleBar';
import TabsScroller from '../components/TabsScroller';
import { SwipeableContent } from '../components/SwipeableContent';
import { apiKeysAPI } from '../api/client';
@@ -90,11 +91,13 @@ export default function APIKeys() {
return (
<SwipeableContent className="main-content api-keys-root">
<MobileTitleBar
title={t.apiKeysPage.title}
menuLabel={t.theme.toggleMenu}
onMenuClick={toggleMobileMenu}
/>
<div className="page-tabs-container">
<TabsScroller className="page-tabs-slider">
<button className="mobile-menu-btn" onClick={toggleMobileMenu} aria-label={t.theme.toggleMenu}>
<span className="material-symbols-outlined">menu</span>
</button>
<div className="page-title-section">
<span className="page-title-text">{t.apiKeysPage.title}</span>
</div>

View File

@@ -2,6 +2,7 @@ import { useState, useCallback } from 'react';
import { useAuth } from '../contexts/AuthContext';
import { useTranslation } from '../contexts/LanguageContext';
import { useSidebar } from '../contexts/SidebarContext';
import MobileTitleBar from '../components/MobileTitleBar';
import TabsScroller from '../components/TabsScroller';
import GeneralTab from '../components/admin/GeneralTab';
import UsersTab from '../components/admin/UsersTab';
@@ -40,11 +41,13 @@ export default function AdminPanel({ initialTab = 'general' }: { initialTab?: Ta
return (
<main className="main-content admin-panel-root">
<MobileTitleBar
title={t.admin.panel}
menuLabel={t.theme.toggleMenu}
onMenuClick={toggleMobileMenu}
/>
<div className="page-tabs-container">
<TabsScroller className="page-tabs-slider" showArrows>
<button className="mobile-menu-btn" onClick={toggleMobileMenu} aria-label={t.theme.toggleMenu}>
<span className="material-symbols-outlined">menu</span>
</button>
<div className="page-title-section">
<span className="page-title-text">{t.admin.panel}</span>
</div>

View File

@@ -1,5 +1,6 @@
import { useTranslation } from '../contexts/LanguageContext';
import { useSidebar } from '../contexts/SidebarContext';
import MobileTitleBar from '../components/MobileTitleBar';
import TabsScroller from '../components/TabsScroller';
import { SwipeableContent } from '../components/SwipeableContent';
@@ -9,11 +10,13 @@ export default function Dashboard() {
return (
<SwipeableContent className="main-content">
<MobileTitleBar
title={t.dashboard.title}
menuLabel={t.theme.toggleMenu}
onMenuClick={toggleMobileMenu}
/>
<div className="page-tabs-container">
<TabsScroller className="page-tabs-slider">
<button className="mobile-menu-btn" onClick={toggleMobileMenu} aria-label={t.theme.toggleMenu}>
<span className="material-symbols-outlined">menu</span>
</button>
<div className="page-title-section">
<span className="page-title-text">{t.dashboard.title}</span>
</div>

View File

@@ -1,5 +1,6 @@
import { useTranslation } from '../contexts/LanguageContext';
import { useSidebar } from '../contexts/SidebarContext';
import MobileTitleBar from '../components/MobileTitleBar';
import TabsScroller from '../components/TabsScroller';
import { SwipeableContent } from '../components/SwipeableContent';
import '../styles/AdminPanel.css';
@@ -10,11 +11,13 @@ export default function Feature1() {
return (
<SwipeableContent className="main-content">
<MobileTitleBar
title={t.feature1.title}
menuLabel={t.theme.toggleMenu}
onMenuClick={toggleMobileMenu}
/>
<div className="page-tabs-container">
<TabsScroller className="page-tabs-slider">
<button className="mobile-menu-btn" onClick={toggleMobileMenu} aria-label={t.theme.toggleMenu}>
<span className="material-symbols-outlined">menu</span>
</button>
<div className="page-title-section">
<span className="page-title-text">{t.feature1.title}</span>
</div>

View File

@@ -1,5 +1,6 @@
import { useTranslation } from '../contexts/LanguageContext';
import { useSidebar } from '../contexts/SidebarContext';
import MobileTitleBar from '../components/MobileTitleBar';
import TabsScroller from '../components/TabsScroller';
import { SwipeableContent } from '../components/SwipeableContent';
import '../styles/AdminPanel.css';
@@ -10,11 +11,13 @@ export default function Feature2() {
return (
<SwipeableContent className="main-content">
<MobileTitleBar
title={t.features.feature2}
menuLabel={t.theme.toggleMenu}
onMenuClick={toggleMobileMenu}
/>
<div className="page-tabs-container">
<TabsScroller className="page-tabs-slider">
<button className="mobile-menu-btn" onClick={toggleMobileMenu} aria-label={t.theme.toggleMenu}>
<span className="material-symbols-outlined">menu</span>
</button>
<div className="page-title-section">
<span className="page-title-text">{t.features.feature2}</span>
</div>

View File

@@ -1,5 +1,6 @@
import { useTranslation } from '../contexts/LanguageContext';
import { useSidebar } from '../contexts/SidebarContext';
import MobileTitleBar from '../components/MobileTitleBar';
import TabsScroller from '../components/TabsScroller';
import { SwipeableContent } from '../components/SwipeableContent';
import '../styles/AdminPanel.css';
@@ -10,11 +11,13 @@ export default function Feature3() {
return (
<SwipeableContent className="main-content">
<MobileTitleBar
title={t.features.feature3}
menuLabel={t.theme.toggleMenu}
onMenuClick={toggleMobileMenu}
/>
<div className="page-tabs-container">
<TabsScroller className="page-tabs-slider">
<button className="mobile-menu-btn" onClick={toggleMobileMenu} aria-label={t.theme.toggleMenu}>
<span className="material-symbols-outlined">menu</span>
</button>
<div className="page-title-section">
<span className="page-title-text">{t.features.feature3}</span>
</div>

View File

@@ -1,6 +1,7 @@
import { useEffect, useState } from 'react';
import { useTranslation } from '../contexts/LanguageContext';
import { useSidebar } from '../contexts/SidebarContext';
import MobileTitleBar from '../components/MobileTitleBar';
import TabsScroller from '../components/TabsScroller';
import { SwipeableContent } from '../components/SwipeableContent';
import { useNotifications } from '../contexts/NotificationsContext';
@@ -96,11 +97,13 @@ export default function Notifications() {
return (
<SwipeableContent className="main-content notifications-root">
<MobileTitleBar
title={t.notificationsPage.title}
menuLabel={t.theme.toggleMenu}
onMenuClick={toggleMobileMenu}
/>
<div className="page-tabs-container">
<TabsScroller className="page-tabs-slider">
<button className="mobile-menu-btn" onClick={toggleMobileMenu} aria-label={t.theme.toggleMenu}>
<span className="material-symbols-outlined">menu</span>
</button>
<div className="page-title-section">
<span className="page-title-text">{t.notificationsPage.title}</span>
</div>

View File

@@ -1,6 +1,7 @@
import { useEffect, useMemo, useRef, useState } from 'react';
import { useTranslation } from '../contexts/LanguageContext';
import { useSidebar } from '../contexts/SidebarContext';
import MobileTitleBar from '../components/MobileTitleBar';
import TabsScroller from '../components/TabsScroller';
import { SwipeableContent } from '../components/SwipeableContent';
import '../styles/Search.css';
@@ -78,11 +79,13 @@ export default function Search() {
return (
<SwipeableContent className="main-content search-root">
<MobileTitleBar
title={t.searchPage.title}
menuLabel={t.theme.toggleMenu}
onMenuClick={toggleMobileMenu}
/>
<div className="page-tabs-container">
<TabsScroller className="page-tabs-slider">
<button className="mobile-menu-btn" onClick={toggleMobileMenu} aria-label={t.theme.toggleMenu}>
<span className="material-symbols-outlined">menu</span>
</button>
<div className="page-title-section">
<span className="page-title-text">{t.searchPage.title}</span>
</div>

View File

@@ -1,6 +1,7 @@
import { useEffect, useState } from 'react';
import { useTranslation } from '../contexts/LanguageContext';
import { useSidebar } from '../contexts/SidebarContext';
import MobileTitleBar from '../components/MobileTitleBar';
import TabsScroller from '../components/TabsScroller';
import { SwipeableContent } from '../components/SwipeableContent';
import { sessionsAPI, twoFactorAPI } from '../api/client';
@@ -153,11 +154,13 @@ export default function Settings() {
return (
<SwipeableContent className="main-content settings-page-root">
<MobileTitleBar
title={t.settings.title}
menuLabel={t.theme.toggleMenu}
onMenuClick={toggleMobileMenu}
/>
<div className="page-tabs-container">
<TabsScroller className="page-tabs-slider">
<button className="mobile-menu-btn" onClick={toggleMobileMenu} aria-label={t.theme.toggleMenu}>
<span className="material-symbols-outlined">menu</span>
</button>
<div className="page-title-section">
<span className="page-title-text">{t.settings.title}</span>
</div>

View File

@@ -1,6 +1,7 @@
import { useEffect, useMemo, useState } from 'react';
import type { FormEvent } from 'react';
import Sidebar from '../components/Sidebar';
import MobileTitleBar from '../components/MobileTitleBar';
import TabsScroller from '../components/TabsScroller';
import { SwipeableContent } from '../components/SwipeableContent';
import { useAuth } from '../contexts/AuthContext';
@@ -182,11 +183,13 @@ export default function Users() {
<div className="app-layout">
<Sidebar />
<SwipeableContent className="main-content users-root">
<MobileTitleBar
title={t.admin.userManagement}
menuLabel={t.theme.toggleMenu}
onMenuClick={toggleMobileMenu}
/>
<div className="page-tabs-container">
<TabsScroller className="page-tabs-slider">
<button className="mobile-menu-btn" onClick={toggleMobileMenu} aria-label={t.theme.toggleMenu}>
<span className="material-symbols-outlined">menu</span>
</button>
<div className="page-title-section">
<span className="page-title-text">{t.admin.userManagement}</span>
</div>

View File

@@ -1,6 +1,7 @@
import { useEffect, useMemo, useState } from 'react';
import { useTranslation } from '../../contexts/LanguageContext';
import { useSidebar } from '../../contexts/SidebarContext';
import MobileTitleBar from '../../components/MobileTitleBar';
import TabsScroller from '../../components/TabsScroller';
import { SwipeableContent } from '../../components/SwipeableContent';
import { analyticsAPI } from '../../api/client';
@@ -47,11 +48,13 @@ export default function Analytics() {
return (
<SwipeableContent className="main-content admin-analytics-root">
<MobileTitleBar
title={t.analyticsPage.title}
menuLabel={t.theme.toggleMenu}
onMenuClick={toggleMobileMenu}
/>
<div className="page-tabs-container">
<TabsScroller className="page-tabs-slider">
<button className="mobile-menu-btn" onClick={toggleMobileMenu} aria-label={t.theme.toggleMenu}>
<span className="material-symbols-outlined">menu</span>
</button>
<div className="page-title-section">
<span className="page-title-text">{t.analyticsPage.title}</span>
</div>

View File

@@ -1,6 +1,7 @@
import { useEffect, useMemo, useState } from 'react';
import { useTranslation } from '../../contexts/LanguageContext';
import { useSidebar } from '../../contexts/SidebarContext';
import MobileTitleBar from '../../components/MobileTitleBar';
import TabsScroller from '../../components/TabsScroller';
import { SwipeableContent } from '../../components/SwipeableContent';
import { auditAPI } from '../../api/client';
@@ -60,11 +61,13 @@ export default function AuditLogs() {
return (
<SwipeableContent className="main-content admin-audit-root">
<MobileTitleBar
title={t.auditPage.title}
menuLabel={t.theme.toggleMenu}
onMenuClick={toggleMobileMenu}
/>
<div className="page-tabs-container">
<TabsScroller className="page-tabs-slider">
<button className="mobile-menu-btn" onClick={toggleMobileMenu} aria-label={t.theme.toggleMenu}>
<span className="material-symbols-outlined">menu</span>
</button>
<div className="page-title-section">
<span className="page-title-text">{t.auditPage.title}</span>
</div>

View File

@@ -5,6 +5,7 @@ import { useSidebar } from '../../contexts/SidebarContext';
import { useModules, TOGGLEABLE_MODULES } from '../../contexts/ModulesContext';
import type { ModuleId } from '../../contexts/ModulesContext';
import Feature1Tab from '../../components/admin/Feature1Tab';
import MobileTitleBar from '../../components/MobileTitleBar';
import { SwipeTabs } from '../../components/SwipeTabs';
import TabsScroller from '../../components/TabsScroller';
import '../../styles/AdminPanel.css';
@@ -780,11 +781,13 @@ export default function Features() {
return (
<main className="main-content admin-panel-root">
<MobileTitleBar
title={t.featuresPage.title}
menuLabel={t.theme.toggleMenu}
onMenuClick={toggleMobileMenu}
/>
<div className="page-tabs-container">
<TabsScroller className="page-tabs-slider" ref={tabsContainerRef} showArrows>
<button className="mobile-menu-btn" onClick={toggleMobileMenu} aria-label={t.theme.toggleMenu}>
<span className="material-symbols-outlined">menu</span>
</button>
<div className="page-title-section">
<span className="page-title-text">{t.featuresPage.title}</span>
</div>

View File

@@ -2,6 +2,7 @@ import { useState, useEffect } from 'react';
import { useTranslation } from '../../contexts/LanguageContext';
import { useSidebar } from '../../contexts/SidebarContext';
import Sidebar from '../../components/Sidebar';
import MobileTitleBar from '../../components/MobileTitleBar';
import TabsScroller from '../../components/TabsScroller';
import { SwipeableContent } from '../../components/SwipeableContent';
import { settingsAPI } from '../../api/client';
@@ -61,11 +62,13 @@ export default function Settings() {
<div className="app-layout">
<Sidebar />
<SwipeableContent className="main-content settings-root">
<MobileTitleBar
title={t.settings.title}
menuLabel={t.theme.toggleMenu}
onMenuClick={toggleMobileMenu}
/>
<div className="page-tabs-container">
<TabsScroller className="page-tabs-slider">
<button className="mobile-menu-btn" onClick={toggleMobileMenu} aria-label={t.theme.toggleMenu}>
<span className="material-symbols-outlined">menu</span>
</button>
<div className="page-title-section">
<span className="page-title-text">{t.settings.title}</span>
</div>

View File

@@ -1,6 +1,7 @@
import { useAuth } from '../../contexts/AuthContext';
import { useTranslation } from '../../contexts/LanguageContext';
import { useSidebar } from '../../contexts/SidebarContext';
import MobileTitleBar from '../../components/MobileTitleBar';
import TabsScroller from '../../components/TabsScroller';
import { SwipeableContent } from '../../components/SwipeableContent';
import '../../styles/AdminPanel.css';
@@ -16,11 +17,14 @@ export default function Sources() {
return (
<SwipeableContent className="main-content admin-panel-root">
<MobileTitleBar
title={t.sourcesPage.title}
menuLabel={t.theme.toggleMenu}
onMenuClick={toggleMobileMenu}
variant="admin"
/>
<div className="admin-tabs-container">
<TabsScroller className="admin-tabs-slider">
<button className="mobile-menu-btn" onClick={toggleMobileMenu} aria-label={t.theme.toggleMenu}>
<span className="material-symbols-outlined">menu</span>
</button>
<div className="admin-title-section">
<span className="admin-title-text">{t.sourcesPage.title}</span>
</div>

View File

@@ -6,6 +6,7 @@ import { useAuth } from '../../contexts/AuthContext';
import { useSidebar } from '../../contexts/SidebarContext';
import type { SidebarMode } from '../../contexts/SidebarContext';
import { ChromePicker, HuePicker } from 'react-color';
import MobileTitleBar from '../../components/MobileTitleBar';
import { SwipeTabs } from '../../components/SwipeTabs';
import TabsScroller from '../../components/TabsScroller';
import '../../styles/ThemeSettings.css';
@@ -778,12 +779,14 @@ export default function ThemeSettings() {
{tooltip.text}
</div>
)}
<MobileTitleBar
title={t.theme.title}
menuLabel={t.theme.toggleMenu}
onMenuClick={toggleMobileMenu}
/>
{/* Modern Tab Navigation */}
<div className="page-tabs-container">
<TabsScroller className="page-tabs-slider" showArrows>
<button className="mobile-menu-btn" onClick={toggleMobileMenu} aria-label={t.theme.toggleMenu}>
<span className="material-symbols-outlined">menu</span>
</button>
<div className="page-title-section">
<span className="page-title-text">{t.theme.title}</span>
</div>