Add tab bar position setting with edge swipe sidebar
- Add theme_tab_bar_position setting (top/bottom/responsive) - Tab bar is now fixed at top, stays visible during scroll - Bottom position uses fixed positioning with safe-area-inset - Add edge swipe gesture to open sidebar on mobile - Remove backdrop-filter for better scroll performance - Simplify TabsScroller by removing inline style manipulation 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import { useEffect, useRef, useState } from 'react';
|
||||
import { useTheme, COLOR_PALETTES } from '../../contexts/ThemeContext';
|
||||
import type { AccentColor, BorderRadius, SidebarStyle, Density, FontFamily, ColorPalette } from '../../contexts/ThemeContext';
|
||||
import type { AccentColor, BorderRadius, SidebarStyle, Density, FontFamily, ColorPalette, TabBarPosition } from '../../contexts/ThemeContext';
|
||||
import { useTranslation } from '../../contexts/LanguageContext';
|
||||
import { useAuth } from '../../contexts/AuthContext';
|
||||
import { useSidebar } from '../../contexts/SidebarContext';
|
||||
@@ -39,6 +39,8 @@ export default function ThemeSettings() {
|
||||
setColorPalette,
|
||||
customColors,
|
||||
setCustomColors,
|
||||
tabBarPosition,
|
||||
setTabBarPosition,
|
||||
saveThemeToBackend
|
||||
} = useTheme();
|
||||
const { t } = useTranslation();
|
||||
@@ -96,6 +98,11 @@ export default function ThemeSettings() {
|
||||
saveThemeToBackend({ colorPalette: palette }).catch(console.error);
|
||||
};
|
||||
|
||||
const handleTabBarPositionChange = async (position: TabBarPosition) => {
|
||||
setTabBarPosition(position);
|
||||
saveThemeToBackend({ tabBarPosition: position }).catch(console.error);
|
||||
};
|
||||
|
||||
// Color picker popup state
|
||||
const [colorPickerState, setColorPickerState] = useState<ColorPickerState>(null);
|
||||
const hasUserModifiedCustomColors = useRef(false);
|
||||
@@ -161,6 +168,12 @@ export default function ThemeSettings() {
|
||||
{ id: 'roboto', label: t.theme.fontOptions.roboto, description: t.theme.fontOptions.robotoDesc, fontStyle: 'Roboto' },
|
||||
];
|
||||
|
||||
const tabBarPositions: { id: TabBarPosition; label: string; description: string }[] = [
|
||||
{ id: 'top', label: t.theme.tabBarPositions?.top || 'Sopra', description: t.theme.tabBarPositions?.topDesc || 'Barra dei tab sempre in alto' },
|
||||
{ id: 'bottom', label: t.theme.tabBarPositions?.bottom || 'Sotto', description: t.theme.tabBarPositions?.bottomDesc || 'Barra dei tab sempre in basso' },
|
||||
{ id: 'responsive', label: t.theme.tabBarPositions?.responsive || 'Responsivo', description: t.theme.tabBarPositions?.responsiveDesc || 'In alto su desktop, in basso su mobile' },
|
||||
];
|
||||
|
||||
const palettes: { id: ColorPalette; label: string; description: string }[] = [
|
||||
{ id: 'monochrome', label: t.theme.palettes.monochrome, description: t.theme.palettes.monochromeDesc },
|
||||
{ id: 'default', label: t.theme.palettes.default, description: t.theme.palettes.defaultDesc },
|
||||
@@ -471,6 +484,40 @@ export default function ThemeSettings() {
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="theme-section">
|
||||
<div className="section-header">
|
||||
<h3 className="section-title">{t.theme.tabBarPosition || 'Posizione Tab'}</h3>
|
||||
</div>
|
||||
<div className="option-cards">
|
||||
{tabBarPositions.map((pos) => (
|
||||
<div
|
||||
key={pos.id}
|
||||
role="button"
|
||||
tabIndex={0}
|
||||
className={`option-card ${tabBarPosition === pos.id ? 'active' : ''}`}
|
||||
onClick={() => handleTabBarPositionChange(pos.id)}
|
||||
onKeyDown={(e) => {
|
||||
if (e.key === 'Enter' || e.key === ' ') {
|
||||
e.preventDefault();
|
||||
handleTabBarPositionChange(pos.id);
|
||||
}
|
||||
}}
|
||||
>
|
||||
<div className="option-preview">
|
||||
<div className={`tabbar-preview tabbar-preview-${pos.id}`}>
|
||||
<div className="tabbar-line"></div>
|
||||
<div className="tabbar-content"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="option-info">
|
||||
<span className="option-name">{pos.label}</span>
|
||||
<span className="option-description">{pos.description}</span>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user