♻️ refactor(calendar): remove sidebar mode from PillNavigation

Simplify the bottom bars by removing the unused sidebar mode:
- Remove isSidebarMode prop from all components
- Remove sidebar-related CSS classes and styles
- Simplify CalendarToolbar to pure wrapper component
- Remove localStorage persistence for sidebar mode

This removes ~230 lines of unused code across 8 files.
This commit is contained in:
Till-JS 2026-02-02 19:06:32 +01:00
parent c475923864
commit 12a900346c
8 changed files with 23 additions and 254 deletions

View file

@ -3,93 +3,26 @@
import CalendarToolbarContent from './CalendarToolbarContent.svelte';
interface Props {
isSidebarMode?: boolean;
isCollapsed?: boolean;
isMobile?: boolean;
bottomOffset?: string;
onModeChange?: (isSidebar: boolean) => void;
onCollapsedChange?: (isCollapsed: boolean) => void;
}
let {
isSidebarMode = false,
isCollapsed = true,
isMobile = false,
bottomOffset = '70px',
onModeChange,
onCollapsedChange,
}: Props = $props();
function toggleSidebarMode() {
onModeChange?.(!isSidebarMode);
}
</script>
<ExpandableToolbar
{isCollapsed}
{onCollapsedChange}
{isSidebarMode}
{bottomOffset}
collapsedTitle="Kalender-Optionen"
expandedTitle="Schließen"
>
<CalendarToolbarContent />
{#snippet rightActions()}
<button
onclick={toggleSidebarMode}
class="layout-btn"
title={isSidebarMode ? 'Zur Bottom-Navigation' : 'Zur Sidebar-Navigation'}
>
<svg class="layout-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24">
{#if isSidebarMode}
<!-- Bottom bar layout icon -->
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M3 3h18v9H3V3zm0 12h18v6H3v-6z"
/>
{:else}
<!-- Sidebar layout icon -->
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M3 3h7v18H3V3zm9 0h9v18h-9V3z"
/>
{/if}
</svg>
</button>
{/snippet}
</ExpandableToolbar>
<style>
/* Layout toggle button - app-specific style */
.layout-btn {
display: flex;
align-items: center;
justify-content: center;
padding: 0.5rem;
background: transparent;
border: none;
cursor: pointer;
color: hsl(var(--color-muted-foreground));
border-radius: 9999px;
transition: all 0.15s ease;
}
.layout-btn:hover {
background: rgba(0, 0, 0, 0.05);
color: hsl(var(--color-foreground));
}
:global(.dark) .layout-btn:hover {
background: rgba(255, 255, 255, 0.1);
}
.layout-icon {
width: 1rem;
height: 1rem;
}
</style>

View file

@ -27,12 +27,11 @@
}
interface Props {
isSidebarMode?: boolean;
isToolbarExpanded?: boolean;
hasTagStrip?: boolean; // Whether TagStrip is visible below
}
let { isSidebarMode = false, isToolbarExpanded = false, hasTagStrip = false }: Props = $props();
let { isToolbarExpanded = false, hasTagStrip = false }: Props = $props();
// Get event count for a day (max 5 dots displayed)
function getEventCount(date: Date): number {
@ -245,7 +244,6 @@
<div
class="date-strip-wrapper"
class:sidebar-mode={isSidebarMode}
class:toolbar-expanded={isToolbarExpanded}
class:compact={settingsStore.dateStripCompact}
class:has-tag-strip={hasTagStrip}
@ -340,15 +338,6 @@
bottom: calc(210px + env(safe-area-inset-bottom, 0px)); /* Extra space for toolbar */
}
/* When PillNav is in sidebar mode, no PillNav at bottom - just InputBar */
.date-strip-wrapper.sidebar-mode {
bottom: calc(70px + env(safe-area-inset-bottom, 0px));
}
.date-strip-wrapper.sidebar-mode.toolbar-expanded {
bottom: calc(140px + env(safe-area-inset-bottom, 0px));
}
/* When TagStrip is visible below, add extra offset */
.date-strip-wrapper.has-tag-strip {
bottom: calc(210px + env(safe-area-inset-bottom, 0px)); /* +70px for TagStrip */
@ -358,14 +347,6 @@
bottom: calc(280px + env(safe-area-inset-bottom, 0px));
}
.date-strip-wrapper.has-tag-strip.sidebar-mode {
bottom: calc(140px + env(safe-area-inset-bottom, 0px));
}
.date-strip-wrapper.has-tag-strip.sidebar-mode.toolbar-expanded {
bottom: calc(210px + env(safe-area-inset-bottom, 0px));
}
.today-button {
position: absolute;
right: 100%;

View file

@ -5,18 +5,12 @@
import DateStripContextMenu from './DateStripContextMenu.svelte';
interface Props {
isSidebarMode?: boolean;
isToolbarExpanded?: boolean;
isMobile?: boolean;
hasTagStrip?: boolean;
}
let {
isSidebarMode = false,
isToolbarExpanded = false,
isMobile = false,
hasTagStrip = false,
}: Props = $props();
let { isToolbarExpanded = false, isMobile = false, hasTagStrip = false }: Props = $props();
let contextMenu: DateStripContextMenu;
@ -35,7 +29,6 @@
<div
class="datestrip-fab-container"
class:sidebar-mode={isSidebarMode}
class:toolbar-expanded={isToolbarExpanded}
class:mobile={isMobile}
class:has-tag-strip={hasTagStrip}
@ -66,22 +59,10 @@
left 0.2s ease;
}
.datestrip-fab-container.sidebar-mode {
bottom: calc(9px + env(safe-area-inset-bottom, 0px));
/* In sidebar mode, InputBar is 700px wide, so position accordingly */
left: calc(50% - 350px - 8px - 54px);
}
.datestrip-fab-container.toolbar-expanded {
bottom: calc(140px + 9px + env(safe-area-inset-bottom, 0px));
}
.datestrip-fab-container.sidebar-mode.toolbar-expanded {
bottom: calc(70px + 9px + env(safe-area-inset-bottom, 0px));
/* In sidebar mode, InputBar is 700px wide */
left: calc(50% - 350px - 8px - 54px);
}
@media (max-width: 900px) {
.datestrip-fab-container {
left: 1rem;
@ -109,10 +90,6 @@
bottom: calc(210px + 9px + env(safe-area-inset-bottom, 0px));
}
.datestrip-fab-container.has-tag-strip.sidebar-mode {
bottom: calc(70px + 9px + env(safe-area-inset-bottom, 0px));
}
.datestrip-fab-container.has-tag-strip.mobile {
bottom: calc(140px + 72px + 8px + env(safe-area-inset-bottom, 0px));
}

View file

@ -7,12 +7,6 @@
import { DotsThree, Plus, X } from '@manacore/shared-icons';
import TagStripModal from './TagStripModal.svelte';
interface Props {
isSidebarMode?: boolean;
}
let { isSidebarMode = false }: Props = $props();
let showModal = $state(false);
function handleTagClick(tagId: string) {
@ -62,7 +56,7 @@
});
</script>
<div class="tag-strip-wrapper" class:sidebar-mode={isSidebarMode}>
<div class="tag-strip-wrapper">
<div class="tag-strip-container">
<!-- Clear Filter Button (always rendered to prevent layout shift) -->
<button
@ -117,7 +111,7 @@
</div>
<!-- Tags Modal -->
<TagStripModal visible={showModal} onClose={handleCloseModal} {isSidebarMode} />
<TagStripModal visible={showModal} onClose={handleCloseModal} />
<style>
.tag-strip-wrapper {
@ -133,11 +127,6 @@
transition: bottom 0.2s ease;
}
/* When PillNav is in sidebar mode, TagStrip at very bottom */
.tag-strip-wrapper.sidebar-mode {
bottom: calc(0px + env(safe-area-inset-bottom, 0px));
}
.tag-strip-container {
display: flex;
align-items: center;

View file

@ -19,10 +19,9 @@
interface Props {
visible: boolean;
onClose: () => void;
isSidebarMode?: boolean;
}
let { visible, onClose, isSidebarMode = false }: Props = $props();
let { visible, onClose }: Props = $props();
// Search state
let searchQuery = $state('');
@ -376,13 +375,7 @@
<div class="modal-backdrop" onclick={onClose}></div>
<!-- Modal -->
<div
class="tag-modal"
class:sidebar-mode={isSidebarMode}
role="dialog"
aria-modal="true"
aria-label="Tags"
>
<div class="tag-modal" role="dialog" aria-modal="true" aria-label="Tags">
<!-- Header -->
<div class="modal-header">
<h2 class="modal-title">Tags</h2>
@ -797,10 +790,6 @@
border: 1px solid rgba(255, 255, 255, 0.1);
}
.tag-modal.sidebar-mode {
bottom: calc(70px + env(safe-area-inset-bottom, 0px));
}
.modal-header {
display: flex;
align-items: center;

View file

@ -5,12 +5,11 @@
import ViewModePillContextMenu from './ViewModePillContextMenu.svelte';
interface Props {
isSidebarMode?: boolean;
isToolbarExpanded?: boolean;
isMobile?: boolean;
}
let { isSidebarMode = false, isToolbarExpanded = false, isMobile = false }: Props = $props();
let { isToolbarExpanded = false, isMobile = false }: Props = $props();
let contextMenu: ViewModePillContextMenu;
@ -66,7 +65,6 @@
<!-- svelte-ignore a11y_no_static_element_interactions -->
<div
class="view-mode-pill"
class:sidebar-mode={isSidebarMode}
class:toolbar-expanded={isToolbarExpanded}
class:mobile={isMobile}
oncontextmenu={handleContextMenu}
@ -165,16 +163,6 @@
bottom: calc(140px + 9px + env(safe-area-inset-bottom, 0px));
}
/* Sidebar mode positioning */
.view-mode-pill.sidebar-mode {
bottom: calc(9px + env(safe-area-inset-bottom, 0px));
right: calc(50% - 350px - 70px + 54px + 8px);
}
.view-mode-pill.sidebar-mode.toolbar-expanded {
bottom: calc(70px + 9px + env(safe-area-inset-bottom, 0px));
}
/* Responsive - on smaller screens, FAB is at right: 1rem */
@media (max-width: 900px) {
.view-mode-pill {

View file

@ -20,10 +20,9 @@
interface Props {
visible: boolean;
onClose: () => void;
isSidebarMode?: boolean;
}
let { visible, onClose, isSidebarMode = false }: Props = $props();
let { visible, onClose }: Props = $props();
// Calendar management state
let editingCalendar = $state<Calendar | null>(null);
@ -220,13 +219,7 @@
<div class="modal-backdrop" onclick={onClose}></div>
<!-- Modal -->
<div
class="settings-modal"
class:sidebar-mode={isSidebarMode}
role="dialog"
aria-modal="true"
aria-label="Einstellungen"
>
<div class="settings-modal" role="dialog" aria-modal="true" aria-label="Einstellungen">
<!-- Header -->
<div class="modal-header">
<h2 class="modal-title">Einstellungen</h2>
@ -792,10 +785,6 @@
border: 1px solid rgba(255, 255, 255, 0.1);
}
.settings-modal.sidebar-mode {
bottom: calc(70px + env(safe-area-inset-bottom, 0px));
}
.modal-header {
display: flex;
align-items: center;

View file

@ -39,11 +39,7 @@
} from '@manacore/shared-theme';
import type { ThemeVariant } from '@manacore/shared-theme';
import { filterHiddenNavItems } from '@manacore/shared-theme';
import {
isSidebarMode as sidebarModeStore,
isNavCollapsed as collapsedStore,
isToolbarCollapsed as toolbarCollapsedStore,
} from '$lib/stores/navigation';
import { isToolbarCollapsed as toolbarCollapsedStore } from '$lib/stores/navigation';
import { getLanguageDropdownItems, getCurrentLanguageLabel } from '@manacore/shared-i18n';
import { getPillAppItems } from '@manacore/shared-branding';
import { setLocale, supportedLocales } from '$lib/i18n';
@ -160,8 +156,6 @@
}
}
let isSidebarMode = $state(false);
let isCollapsed = $state(false);
let isToolbarCollapsed = $state(true); // Default to collapsed - FAB next to InputBar
// Mobile detection for responsive layout
@ -483,27 +477,6 @@
}
}
function handleModeChange(isSidebar: boolean) {
isSidebarMode = isSidebar;
sidebarModeStore.set(isSidebar);
if (typeof localStorage !== 'undefined') {
localStorage.setItem('calendar-nav-sidebar', String(isSidebar));
}
}
function handleCollapsedChange(collapsed: boolean) {
isCollapsed = collapsed;
collapsedStore.set(collapsed);
if (typeof localStorage !== 'undefined') {
localStorage.setItem('calendar-nav-collapsed', String(collapsed));
}
}
function handleToolbarModeChange(isSidebar: boolean) {
// Sync toolbar mode with nav mode
handleModeChange(isSidebar);
}
function handleToolbarCollapsedChange(collapsed: boolean) {
isToolbarCollapsed = collapsed;
toolbarCollapsedStore?.set(collapsed);
@ -595,20 +568,6 @@
}
}
// Initialize sidebar mode from localStorage
const savedSidebar = localStorage.getItem('calendar-nav-sidebar');
if (savedSidebar === 'true') {
isSidebarMode = true;
sidebarModeStore.set(true);
}
// Initialize collapsed state from localStorage
const savedCollapsed = localStorage.getItem('calendar-nav-collapsed');
if (savedCollapsed === 'true') {
isCollapsed = true;
collapsedStore.set(true);
}
// Initialize toolbar collapsed state from localStorage (default is now collapsed)
const savedToolbarCollapsed = localStorage.getItem('calendar-toolbar-collapsed');
if (savedToolbarCollapsed === 'false') {
@ -635,10 +594,6 @@
homeRoute="/"
onToggleTheme={handleToggleTheme}
{isDark}
{isSidebarMode}
onModeChange={handleModeChange}
{isCollapsed}
onCollapsedChange={handleCollapsedChange}
desktopPosition="bottom"
showThemeToggle={true}
showThemeVariants={true}
@ -673,14 +628,12 @@
{#if showCalendarToolbar}
{#if settingsStore.dateStripCollapsed}
<DateStripFab
{isSidebarMode}
isToolbarExpanded={!isToolbarCollapsed}
{isMobile}
hasTagStrip={!settingsStore.tagStripCollapsed}
/>
{:else}
<DateStrip
{isSidebarMode}
isToolbarExpanded={!isToolbarCollapsed}
hasTagStrip={!settingsStore.tagStripCollapsed}
/>
@ -689,17 +642,15 @@
<!-- Tag strip (only on main calendar page, when not collapsed) - directly above PillNav -->
{#if showCalendarToolbar && !settingsStore.tagStripCollapsed}
<TagStrip {isSidebarMode} />
<TagStrip />
{/if}
<!-- Calendar toolbar (only on main calendar page, not in sidebar mode) -->
{#if showCalendarToolbar && !isSidebarMode}
<!-- Calendar toolbar (only on main calendar page) -->
{#if showCalendarToolbar}
<CalendarToolbar
{isSidebarMode}
isCollapsed={isToolbarCollapsed}
{isMobile}
bottomOffset={settingsStore.tagStripCollapsed ? '70px' : '140px'}
onModeChange={handleToolbarModeChange}
onCollapsedChange={handleToolbarCollapsedChange}
/>
{/if}
@ -721,16 +672,11 @@
appIcon="calendar"
bottomOffset={isMobile
? `${70 + tagStripOffset}px`
: isSidebarMode
? `${tagStripOffset}px`
: showCalendarToolbar && !isToolbarCollapsed
? `${140 + tagStripOffset}px`
: `${70 + tagStripOffset}px`}
hasFabRight={showCalendarToolbar && !isSidebarMode}
hasFabLeft={!isMobile &&
showCalendarToolbar &&
!isSidebarMode &&
settingsStore.dateStripCollapsed}
: showCalendarToolbar && !isToolbarCollapsed
? `${140 + tagStripOffset}px`
: `${70 + tagStripOffset}px`}
hasFabRight={showCalendarToolbar}
hasFabLeft={!isMobile && showCalendarToolbar && settingsStore.dateStripCollapsed}
defaultOptions={calendarOptions}
selectedDefaultId={selectedDefaultCalendarId}
defaultOptionLabel="Standard-Kalender"
@ -744,11 +690,9 @@
class="voice-button-wrapper"
style="--bottom-offset: {isMobile
? `${70 + tagStripOffset}px`
: isSidebarMode
? `${tagStripOffset}px`
: showCalendarToolbar && !isToolbarCollapsed
? `${140 + tagStripOffset}px`
: `${70 + tagStripOffset}px`}"
: showCalendarToolbar && !isToolbarCollapsed
? `${140 + tagStripOffset}px`
: `${70 + tagStripOffset}px`}"
>
<VoiceRecordButton onResult={handleVoiceResult} size={40} />
</div>
@ -768,8 +712,6 @@
<main
class="main-content bg-background"
class:sidebar-mode={isSidebarMode && !isCollapsed}
class:floating-mode={!isSidebarMode && !isCollapsed}
class:has-toolbar={showCalendarToolbar}
class:immersive={settingsStore.immersiveModeEnabled}
>
@ -794,11 +736,7 @@
<InputBarHelpModal open={helpModalOpen} onClose={handleCloseHelpModal} mode={helpModalMode} />
<!-- Settings Modal -->
<SettingsModal
visible={showSettingsModal}
onClose={() => (showSettingsModal = false)}
{isSidebarMode}
/>
<SettingsModal visible={showSettingsModal} onClose={() => (showSettingsModal = false)} />
<style>
.layout-container {
@ -820,8 +758,6 @@
.main-content {
transition: all 300ms ease;
position: relative;
/* Space for QuickInputBar at bottom */
padding-bottom: calc(80px + env(safe-area-inset-bottom));
/* Flex container for children */
flex: 1;
display: flex;
@ -829,13 +765,8 @@
min-height: 0;
}
.main-content.floating-mode {
padding-top: 70px;
}
/* Extra padding when DateStrip is at bottom (toolbar is now a FAB) */
.main-content.floating-mode.has-toolbar {
padding-top: 0;
.main-content.has-toolbar {
padding-bottom: calc(
220px + env(safe-area-inset-bottom)
); /* DateStrip + PillNav + QuickInputBar */
@ -854,9 +785,6 @@
height: calc(100vh - 70px);
padding-bottom: 0;
}
.main-content.floating-mode {
padding-top: 0; /* No top padding on mobile - everything is at bottom */
}
}
/* Mobile: Fixed height, internal scrolling only */
@ -872,10 +800,6 @@
}
}
.main-content.sidebar-mode {
padding-left: 180px;
}
.content-wrapper {
max-width: 100%;
margin-left: auto;
@ -949,7 +873,6 @@
/* Adjust InputBar when FABs are visible (toolbar FAB on right, DateStripFab on left) */
/* For a centered InputBar with max-width 450px, left edge is at 50% - 225px */
/* DateStripFab is positioned at: 50% - 225px - 8px gap - 54px fab width */
/* Note: In sidebar mode, InputBar uses default 700px max-width */
:global(.quick-input-bar.has-fab-right .input-container),
:global(.quick-input-bar.has-fab-left .input-container) {
max-width: 450px;