oneie
Version:
Build apps, websites, and AI agents in English. Zero-interaction setup for AI agents (Claude Code, Cursor, Windsurf). Download to your computer, run in the cloud, deploy to the edge. Open source and free forever.
250 lines (178 loc) • 8.52 kB
Markdown
---
title: Layout
dimension: things
category: plans
tags: ai
related_dimensions: groups
scope: global
created: 2025-11-03
updated: 2025-11-03
version: 1.0.0
ai_context: |
This document is part of the things dimension in the plans category.
Location: one/things/plans/layout.md
Purpose: Documents sidebar layout fix - comprehensive analysis
Related dimensions: groups
For AI agents: Read this to understand layout.
---
# Sidebar Layout Fix - Comprehensive Analysis
## Problem Statement
The sidebar is overlapping the main content instead of pushing it to the right. Content is being hidden behind the fixed sidebar.
## Root Cause Analysis
### How shadcn Sidebar SHOULD Work
From analyzing the official dashboard-01 example, the shadcn sidebar uses a **three-part layout system**:
1. **SidebarProvider** - Creates a flex container wrapper
```tsx
<div className="group/sidebar-wrapper flex min-h-svh w-full">
```
2. **Sidebar Component** - Has TWO nested divs:
- **Spacer div**: Takes up space in the flex layout (`w-[--sidebar-width]`)
- **Fixed overlay**: The actual visible sidebar (`fixed inset-y-0`)
3. **SidebarInset** - The main content area with `flex-1 w-full`
### The Mechanism
```
┌─────────────────────────────────────────────────────┐
│ SidebarProvider (flex container) │
│ ┌──────────┬────────────────────────────────────┐ │
│ │ Sidebar │ SidebarInset │ │
│ │ ┌──────┐ │ ┌────────────────────────────────┐ │ │
│ │ │Spacer│ │ │ Main Content │ │ │
│ │ │16rem │ │ │ (flex-1 takes remaining space) │ │ │
│ │ └──────┘ │ │ │ │ │
│ │ ┌──────┐ │ │ │ │ │
│ │ │Fixed │ │ │ │ │ │
│ │ │Overlay│ │ │ │ │ │
│ │ └──────┘ │ │ │ │ │
│ └──────────┴────────────────────────────────────┘ │
└─────────────────────────────────────────────────────┘
```
- **Spacer**: `w-[--sidebar-width]` (16rem when expanded, 3rem when collapsed)
- **Fixed Overlay**: Position fixed, visually overlays the spacer
- **Content**: `flex-1` grows to fill remaining space after spacer
## Current Issues in Our Implementation
### Issue 1: Spacer Div Missing `flex-shrink: 0`
**Location**: `src/components/ui/sidebar.tsx` line 234-243
Current:
```tsx
<div
className={cn(
"relative h-svh w-[--sidebar-width] bg-transparent transition-[width] duration-200 ease-linear",
// ...
)}
/>
```
**Problem**: Without `shrink-0`, the spacer can shrink to accommodate `SidebarInset`'s `w-full`, making it collapse to 0 width.
### Issue 2: SidebarInset Using Both `w-full` and `flex-1`
**Location**: `src/components/ui/sidebar.tsx` line 334
Current:
```tsx
className={cn(
'relative flex w-full flex-1 flex-col bg-background',
'peer-data-[state=collapsed]:pl-[--sidebar-width-icon] peer-data-[state=expanded]:pl-[--sidebar-width]',
// ...
)}
```
**Problem**:
1. `w-full` (width: 100%) conflicts with flex layout
2. The padding-left I added is WRONG - the spacer should handle positioning, not padding
3. CSS custom properties in arbitrary values `pl-[--sidebar-width]` don't work in Tailwind
### Issue 3: User Modifications to Sidebar Component
**Location**: `src/components/ui/sidebar.tsx` line 227, 246
The user (or formatter) changed:
- Line 227: `hidden md:block` → `block`
- Line 246: `hidden h-svh w-[--sidebar-width] transition-[left,right,width] duration-200 ease-linear md:flex` → `flex h-svh w-[--sidebar-width] transition-[left,right,width] duration-200 ease-linear`
This removes the mobile/desktop breakpoint behavior.
## Solution Plan
### Step 1: Fix Spacer Div - Add `shrink-0`
The spacer MUST NOT shrink. It should hold its width to push content.
**Change in `sidebar.tsx` line 236**:
```tsx
'relative h-svh w-[--sidebar-width] shrink-0 bg-transparent transition-[width] duration-200 ease-linear',
```
### Step 2: Remove Incorrect Padding from SidebarInset
The SidebarInset should NOT have padding-left. Let flex layout handle positioning.
**Change in `sidebar.tsx` line 334**:
```tsx
'relative flex min-w-0 flex-1 flex-col bg-background',
// Remove: w-full (causes width issues)
// Remove: peer-data padding classes I added
// Add: min-w-0 (allows flex item to shrink below content size if needed)
```
### Step 3: Restore Mobile Behavior (Optional)
If we want proper mobile/desktop behavior, restore the breakpoints:
**Line 227**: Change back to `hidden text-sidebar-foreground md:block`
**Line 246**: Add `md:` prefix to `flex`
### Step 4: Verify CSS Variables Are Set
Ensure SidebarProvider sets the CSS variables:
```tsx
style={{
'--sidebar-width': SIDEBAR_WIDTH, // 16rem
'--sidebar-width-icon': SIDEBAR_WIDTH_ICON, // 3rem
}}
```
## Expected Outcome
After fixes:
1. **Expanded**: Spacer is 16rem, content starts at 16rem from left
2. **Collapsed**: Spacer is 3rem, content starts at 3rem from left
3. **Mobile**: Sidebar is offcanvas overlay (if breakpoints restored)
4. **Transitions**: Smooth width changes on toggle
## Implementation Order
1. ✅ Research complete
2. ✅ Create this plan document
3. ✅ Fix spacer div with `shrink-0`
4. ✅ Fix SidebarInset - remove `w-full` and padding, add `min-w-0`
5. ✅ Restore mobile breakpoints (`hidden md:block` and `hidden md:flex`)
6. ✅ Verify CSS variables are set correctly
7. ⏳ Test in browser at http://localhost:4321
8. ⏳ Verify responsive behavior across breakpoints
## Key Learnings
1. **Flex layout is key**: The spacer takes up space, content fills remaining
2. **No padding needed**: Content positioning is automatic via flex
3. **`shrink-0` is critical**: Prevents spacer from collapsing
4. **CSS custom properties**: Must be set via inline styles, can't use in Tailwind arbitrary classes
5. **`w-full` breaks flex**: Use `flex-1` and `min-w-0` instead for flex items
## Implementation Summary
### Files Modified
**`src/components/ui/sidebar.tsx`**
#### Change 1: Sidebar Container (Line 229)
```tsx
// Before: className="group peer block text-sidebar-foreground"
// After: className="group peer hidden text-sidebar-foreground md:block"
```
Restores mobile responsiveness - sidebar hidden on mobile, uses Sheet component instead.
#### Change 2: Spacer Div (Line 238)
```tsx
// Before: 'relative h-svh w-[--sidebar-width] bg-transparent ...'
// After: 'relative h-svh w-[--sidebar-width] shrink-0 bg-transparent ...'
```
Added `shrink-0` to prevent the spacer from collapsing in flex layout.
#### Change 3: Fixed Overlay (Line 248)
```tsx
// Before: 'fixed inset-y-0 z-10 flex h-svh w-[--sidebar-width] ...'
// After: 'fixed inset-y-0 z-10 hidden h-svh w-[--sidebar-width] ... md:flex'
```
Restores mobile responsiveness - fixed overlay hidden on mobile.
#### Change 4: SidebarInset (Line 336)
```tsx
// Before: 'relative flex w-full flex-1 flex-col bg-background'
// 'peer-data-[state=collapsed]:pl-[--sidebar-width-icon] ...'
// After: 'relative flex min-w-0 flex-1 flex-col bg-background'
```
- Removed `w-full` (conflicts with flex layout)
- Removed incorrect padding classes
- Added `min-w-0` (allows proper flex shrinking)
### CSS Variables Verified (Lines 143-144)
```tsx
'--sidebar-width': SIDEBAR_WIDTH, // 16rem
'--sidebar-width-icon': SIDEBAR_WIDTH_ICON, // 3rem
```
## Testing Checklist
- [ ] Sidebar visible on desktop
- [ ] Content positioned correctly (not overlapping)
- [ ] Smooth transition when toggling sidebar
- [ ] Collapsed state shows icons only (3rem width)
- [ ] Expanded state shows full sidebar (16rem width)
- [ ] Content width adjusts automatically
- [ ] Mobile: Sidebar uses Sheet overlay (hidden by default)
- [ ] No horizontal scrollbar
- [ ] Keyboard shortcut 'b' works for toggle