feat(calendar): improve navigation layout controls and sidebar integration

- Add layout control icons (sidebar/bottom-bar) for better UX
- Position FABs on right side for consistent minimization direction
- Fix app switcher dropdown direction (opens up when nav at bottom)
- Add isToolbarCollapsed store for toolbar state management
- Create CalendarToolbarContent component for reusable toolbar elements
- Improve sidebar toolbar integration with proper vertical layout
- Hide PillViewSwitcher sliding indicator in vertical mode
- Add scrollbar to sidebar toolbar content
- Ensure all toolbar buttons are full-width and left-aligned in sidebar

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Till-JS 2025-12-12 13:13:45 +01:00
parent 287a62a3fb
commit 81f77c424c
5 changed files with 261 additions and 10 deletions

View file

@ -1191,37 +1191,85 @@
flex-direction: column;
align-items: stretch;
gap: 0.5rem;
width: 100%;
}
/* All buttons in sidebar toolbar - full width, left aligned */
.sidebar-toolbar-content :global(.pill-toolbar-btn),
.sidebar-toolbar-content :global(.pill-dropdown .trigger-button) {
.sidebar-toolbar-content :global(.pill-dropdown .trigger-button),
.sidebar-toolbar-content :global(button) {
width: 100%;
justify-content: flex-start;
text-align: left;
background: transparent;
border: 1px solid transparent;
box-shadow: none;
}
.sidebar-toolbar-content :global(.pill-toolbar-btn:hover),
.sidebar-toolbar-content :global(.pill-dropdown .trigger-button:hover) {
.sidebar-toolbar-content :global(.pill-dropdown .trigger-button:hover),
.sidebar-toolbar-content :global(button:hover) {
background: rgba(0, 0, 0, 0.05);
}
:global(.dark) .sidebar-toolbar-content :global(.pill-toolbar-btn:hover),
:global(.dark) .sidebar-toolbar-content :global(.pill-dropdown .trigger-button:hover) {
:global(.dark) .sidebar-toolbar-content :global(.pill-dropdown .trigger-button:hover),
:global(.dark) .sidebar-toolbar-content :global(button:hover) {
background: rgba(255, 255, 255, 0.1);
}
/* Style for PillViewSwitcher in sidebar */
/* Style for PillViewSwitcher in sidebar - vertical layout */
.sidebar-toolbar-content :global(.pill-view-switcher) {
flex-direction: column;
gap: 0.25rem;
width: 100%;
padding: 0;
background: transparent;
border: none;
box-shadow: none;
}
.sidebar-toolbar-content :global(.pill-view-switcher .view-option) {
/* Hide the sliding indicator in vertical mode */
.sidebar-toolbar-content :global(.pill-view-switcher .sliding-indicator) {
display: none;
}
.sidebar-toolbar-content :global(.pill-view-switcher .switcher-btn) {
width: 100%;
justify-content: flex-start;
padding: 0.5rem 0.875rem;
border-radius: 9999px;
background: transparent;
border: 1px solid transparent;
}
.sidebar-toolbar-content :global(.pill-view-switcher .switcher-btn:hover) {
background: rgba(0, 0, 0, 0.05);
}
:global(.dark) .sidebar-toolbar-content :global(.pill-view-switcher .switcher-btn:hover) {
background: rgba(255, 255, 255, 0.1);
}
.sidebar-toolbar-content :global(.pill-view-switcher .switcher-btn.active) {
background: color-mix(in srgb, var(--pill-primary-color, #3b82f6) 15%, transparent 85%);
border-color: color-mix(in srgb, var(--pill-primary-color, #3b82f6) 25%, transparent 75%);
}
:global(.dark) .sidebar-toolbar-content :global(.pill-view-switcher .switcher-btn.active) {
background: color-mix(in srgb, var(--pill-primary-color, #3b82f6) 25%, transparent 75%);
border-color: color-mix(in srgb, var(--pill-primary-color, #3b82f6) 35%, transparent 65%);
}
/* PillTimeRangeSelector in sidebar */
.sidebar-toolbar-content :global(.pill-time-range-selector),
.sidebar-toolbar-content :global(.pill-dropdown) {
width: 100%;
}
/* PillCalendarSelector in sidebar */
.sidebar-toolbar-content :global(.calendar-selector) {
width: 100%;
}
/* Mobile: Sidebar container adjustments */

View file

@ -50,6 +50,7 @@
.pill-toolbar.position-bottom {
top: auto;
bottom: var(--toolbar-bottom-offset, 70px);
transition: bottom 0.3s ease;
}
/* Mobile: always position above bottom nav */

View file

@ -57,6 +57,8 @@
appIcon?: string;
primaryColor?: string;
autoFocus?: boolean;
/** Bottom offset from viewport bottom (default: '70px') */
bottomOffset?: string;
}
let {
@ -72,6 +74,7 @@
appIcon = 'search',
primaryColor = '#8b5cf6',
autoFocus = true,
bottomOffset = '70px',
}: Props = $props();
let searchQuery = $state('');
@ -239,7 +242,10 @@
}
</script>
<div class="quick-input-bar" style="--primary-color: {primaryColor}">
<div
class="quick-input-bar"
style="--primary-color: {primaryColor}; --bottom-offset: {bottomOffset}"
>
<!-- Results Panel (above input) -->
{#if showPanel}
<div class="results-panel" transition:slide={{ duration: 150 }}>
@ -411,15 +417,15 @@
<style>
.quick-input-bar {
position: fixed;
top: 0;
bottom: calc(var(--bottom-offset, 70px) + env(safe-area-inset-bottom, 0px));
left: 0;
right: 0;
z-index: 90;
padding: 0.75rem 1rem;
padding-top: calc(0.75rem + env(safe-area-inset-top));
pointer-events: none;
/* Fixed height to prevent layout shift when results appear */
height: 72px;
transition: bottom 0.3s ease;
}
.input-container,
@ -588,11 +594,11 @@
/* Results Panel */
.results-panel {
position: absolute;
top: 100%;
bottom: 100%;
left: 1rem;
right: 1rem;
max-width: 700px;
margin: 0.5rem auto 0;
margin: 0 auto 0.5rem;
max-height: 320px;
overflow-y: auto;
background: rgba(255, 255, 255, 0.95);