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:
@@ -29,13 +29,31 @@
|
||||
|
||||
/* ========== PAGE STRUCTURE ========== */
|
||||
|
||||
/* Page header container - centered with symmetric padding */
|
||||
/* Page header container - fixed at top */
|
||||
.page-tabs-container,
|
||||
.admin-tabs-container {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
padding: 0.75rem;
|
||||
background: transparent;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: var(--sidebar-width);
|
||||
right: 0;
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
/* Handle collapsed sidebar for fixed header (desktop only) */
|
||||
@media (min-width: 769px) {
|
||||
[data-sidebar-collapsed='true'] .page-tabs-container,
|
||||
[data-sidebar-collapsed='true'] .admin-tabs-container {
|
||||
left: var(--sidebar-width-collapsed);
|
||||
}
|
||||
}
|
||||
|
||||
/* Add top padding to content to account for fixed header */
|
||||
.page-content,
|
||||
.admin-tab-swipe {
|
||||
padding-top: calc(var(--page-padding-y) + 60px);
|
||||
}
|
||||
|
||||
/* Ensure no extra margin from body */
|
||||
@@ -76,7 +94,6 @@ label,
|
||||
gap: 4px;
|
||||
box-shadow: var(--shadow-md);
|
||||
max-width: 100%;
|
||||
backdrop-filter: blur(14px) saturate(1.15);
|
||||
overflow-x: auto;
|
||||
overflow-y: hidden;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
@@ -423,8 +440,9 @@ label,
|
||||
padding: var(--page-padding-y-tablet) var(--page-padding-x-tablet);
|
||||
}
|
||||
|
||||
.page-content {
|
||||
padding: var(--page-padding-y-tablet) var(--page-padding-x-tablet);
|
||||
.page-content,
|
||||
.admin-tab-swipe {
|
||||
padding-top: calc(var(--page-padding-y-tablet) + 60px);
|
||||
}
|
||||
|
||||
.admin-tab-content {
|
||||
@@ -472,6 +490,12 @@ label,
|
||||
.page-tabs-container,
|
||||
.admin-tabs-container {
|
||||
padding: 0.75rem;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.page-content,
|
||||
.admin-tab-swipe {
|
||||
padding-top: calc(var(--page-padding-y-mobile) + 60px);
|
||||
}
|
||||
|
||||
.page-tabs-slider,
|
||||
@@ -517,29 +541,29 @@ label,
|
||||
}
|
||||
|
||||
/* Hide title section when tabs are present on mobile */
|
||||
.page-tabs-slider:has(.page-tab-btn) .page-title-section,
|
||||
.page-tabs-slider:has(.admin-tab-btn) .page-title-section,
|
||||
.admin-tabs-slider:has(.admin-tab-btn) .admin-title-section,
|
||||
.admin-tabs-slider:has(.page-tab-btn) .admin-title-section {
|
||||
.page-tabs-slider[data-has-tabs='true'] .page-title-section,
|
||||
.page-tabs-slider[data-has-tabs='true'] .admin-title-section,
|
||||
.admin-tabs-slider[data-has-tabs='true'] .page-title-section,
|
||||
.admin-tabs-slider[data-has-tabs='true'] .admin-title-section {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Add padding-left when tabs are present to avoid logo overlap */
|
||||
.page-tabs-slider:has(.page-tab-btn),
|
||||
.page-tabs-slider:has(.admin-tab-btn),
|
||||
.admin-tabs-slider:has(.admin-tab-btn),
|
||||
.admin-tabs-slider:has(.page-tab-btn) {
|
||||
.page-tabs-slider[data-has-tabs='true'],
|
||||
.admin-tabs-slider[data-has-tabs='true'] {
|
||||
padding-left: 72px;
|
||||
}
|
||||
|
||||
/* Center title section absolutely when no tabs are present on mobile */
|
||||
.page-tabs-slider:not(:has(.page-tab-btn)):not(:has(.admin-tab-btn)),
|
||||
.admin-tabs-slider:not(:has(.admin-tab-btn)):not(:has(.page-tab-btn)) {
|
||||
.page-tabs-slider[data-has-tabs='false'],
|
||||
.admin-tabs-slider[data-has-tabs='false'] {
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.page-tabs-slider:not(:has(.page-tab-btn)):not(:has(.admin-tab-btn)) .page-title-section,
|
||||
.admin-tabs-slider:not(:has(.admin-tab-btn)):not(:has(.page-tab-btn)) .admin-title-section {
|
||||
.page-tabs-slider[data-has-tabs='false'] .page-title-section,
|
||||
.page-tabs-slider[data-has-tabs='false'] .admin-title-section,
|
||||
.admin-tabs-slider[data-has-tabs='false'] .page-title-section,
|
||||
.admin-tabs-slider[data-has-tabs='false'] .admin-title-section {
|
||||
display: flex;
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
@@ -550,8 +574,10 @@ label,
|
||||
}
|
||||
|
||||
/* Lighter icon color in dark theme when only title is shown */
|
||||
.page-tabs-slider:not(:has(.page-tab-btn)):not(:has(.admin-tab-btn)) .page-title-section .material-symbols-outlined,
|
||||
.admin-tabs-slider:not(:has(.admin-tab-btn)):not(:has(.page-tab-btn)) .admin-title-section .material-symbols-outlined {
|
||||
.page-tabs-slider[data-has-tabs='false'] .page-title-section .material-symbols-outlined,
|
||||
.page-tabs-slider[data-has-tabs='false'] .admin-title-section .material-symbols-outlined,
|
||||
.admin-tabs-slider[data-has-tabs='false'] .page-title-section .material-symbols-outlined,
|
||||
.admin-tabs-slider[data-has-tabs='false'] .admin-title-section .material-symbols-outlined {
|
||||
color: var(--color-text-secondary);
|
||||
}
|
||||
|
||||
@@ -767,8 +793,7 @@ label,
|
||||
@supports (color: color-mix(in srgb, black, white)) {
|
||||
[data-theme='dark'] .page-tabs-slider,
|
||||
[data-theme='dark'] .admin-tabs-slider {
|
||||
background: color-mix(in srgb, var(--color-bg-sidebar) 88%, transparent);
|
||||
backdrop-filter: blur(18px) saturate(1.15);
|
||||
background: color-mix(in srgb, var(--color-bg-sidebar) 95%, transparent);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -815,3 +840,122 @@ label,
|
||||
[data-theme='dark'][data-accent='auto'] .admin-tab-btn.active:focus-visible {
|
||||
box-shadow: 0 0 25px 4px rgba(229, 231, 235, 0.5);
|
||||
}
|
||||
|
||||
/* ========== TAB BAR POSITION ========== */
|
||||
|
||||
/*
|
||||
* Tab bar positioning system:
|
||||
* - 'top': default, no changes needed
|
||||
* - 'bottom': fixed at bottom on all screens (only when tabs are present)
|
||||
* - 'responsive': top on desktop (>768px), bottom on mobile (<=768px)
|
||||
*
|
||||
* Uses data-has-tabs set by TabsScroller to avoid :has() support issues.
|
||||
*/
|
||||
|
||||
/* Bottom position - fixed at bottom (global setting for all pages) */
|
||||
/* Note: Primary positioning is handled by TabsScroller component with inline styles.
|
||||
These CSS rules serve as fallback/additional styling. */
|
||||
[data-tab-position='bottom'] .page-tabs-container,
|
||||
[data-tab-position='bottom'] .admin-tabs-container {
|
||||
position: fixed;
|
||||
top: auto;
|
||||
bottom: 0;
|
||||
left: var(--sidebar-width);
|
||||
right: 0;
|
||||
z-index: 100;
|
||||
padding: 0.5rem;
|
||||
padding-bottom: calc(0.5rem + env(safe-area-inset-bottom, 0px));
|
||||
}
|
||||
|
||||
/* Handle collapsed sidebar */
|
||||
[data-tab-position='bottom'][data-sidebar-collapsed='true'] .page-tabs-container,
|
||||
[data-tab-position='bottom'][data-sidebar-collapsed='true'] .admin-tabs-container {
|
||||
left: var(--sidebar-width-collapsed);
|
||||
}
|
||||
|
||||
/* Adjust slider styling for bottom position */
|
||||
[data-tab-position='bottom'] .page-tabs-slider,
|
||||
[data-tab-position='bottom'] .admin-tabs-slider {
|
||||
width: 100%;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
|
||||
/* Hide title section when bar is at bottom (only on pages with tabs) */
|
||||
[data-tab-position='bottom'] .page-tabs-slider[data-has-tabs='true'] .page-title-section,
|
||||
[data-tab-position='bottom'] .page-tabs-slider[data-has-tabs='true'] .admin-title-section,
|
||||
[data-tab-position='bottom'] .admin-tabs-slider[data-has-tabs='true'] .page-title-section,
|
||||
[data-tab-position='bottom'] .admin-tabs-slider[data-has-tabs='true'] .admin-title-section {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Hide divider when bar is at bottom */
|
||||
[data-tab-position='bottom'] .page-tabs-slider .page-tabs-divider,
|
||||
[data-tab-position='bottom'] .page-tabs-slider .admin-tabs-divider,
|
||||
[data-tab-position='bottom'] .admin-tabs-slider .page-tabs-divider,
|
||||
[data-tab-position='bottom'] .admin-tabs-slider .admin-tabs-divider {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Add bottom padding to main content when bar is at bottom */
|
||||
[data-tab-position='bottom'] .main-content {
|
||||
padding-bottom: calc(72px + env(safe-area-inset-bottom, 0px));
|
||||
}
|
||||
|
||||
/* Mobile: full width at bottom */
|
||||
@media (max-width: 768px) {
|
||||
[data-tab-position='bottom'] .page-tabs-container,
|
||||
[data-tab-position='bottom'] .admin-tabs-container {
|
||||
left: 0;
|
||||
}
|
||||
|
||||
/* Override collapsed state on mobile */
|
||||
[data-tab-position='bottom'][data-sidebar-collapsed='true'] .page-tabs-container,
|
||||
[data-tab-position='bottom'][data-sidebar-collapsed='true'] .admin-tabs-container {
|
||||
left: 0;
|
||||
}
|
||||
|
||||
/* Keep proper spacing for mobile menu button - inherits padding-left: 72px from mobile rules */
|
||||
}
|
||||
|
||||
/* Responsive position - top on desktop, bottom on mobile */
|
||||
@media (max-width: 768px) {
|
||||
[data-tab-position='responsive'] .page-tabs-container,
|
||||
[data-tab-position='responsive'] .admin-tabs-container {
|
||||
position: fixed;
|
||||
top: auto;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 100;
|
||||
padding: 0.5rem;
|
||||
padding-bottom: calc(0.5rem + env(safe-area-inset-bottom, 0px));
|
||||
}
|
||||
|
||||
[data-tab-position='responsive'] .page-tabs-slider,
|
||||
[data-tab-position='responsive'] .admin-tabs-slider {
|
||||
width: 100%;
|
||||
justify-content: flex-start;
|
||||
/* padding-left: 72px inherited from mobile rules for menu button spacing */
|
||||
}
|
||||
|
||||
/* Hide title section when bar is at bottom (only on pages with tabs) */
|
||||
[data-tab-position='responsive'] .page-tabs-slider[data-has-tabs='true'] .page-title-section,
|
||||
[data-tab-position='responsive'] .page-tabs-slider[data-has-tabs='true'] .admin-title-section,
|
||||
[data-tab-position='responsive'] .admin-tabs-slider[data-has-tabs='true'] .page-title-section,
|
||||
[data-tab-position='responsive'] .admin-tabs-slider[data-has-tabs='true'] .admin-title-section {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Hide divider when bar is at bottom */
|
||||
[data-tab-position='responsive'] .page-tabs-slider .page-tabs-divider,
|
||||
[data-tab-position='responsive'] .page-tabs-slider .admin-tabs-divider,
|
||||
[data-tab-position='responsive'] .admin-tabs-slider .page-tabs-divider,
|
||||
[data-tab-position='responsive'] .admin-tabs-slider .admin-tabs-divider {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Add bottom padding to main content */
|
||||
[data-tab-position='responsive'] .main-content {
|
||||
padding-bottom: calc(72px + env(safe-area-inset-bottom, 0px));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user