chore: clean .gitignore cache
This commit is contained in:
556
docs/implementation/sidebar-fixed-header-ui-SPEC.md
Normal file
556
docs/implementation/sidebar-fixed-header-ui-SPEC.md
Normal file
@@ -0,0 +1,556 @@
|
||||
# UI/UX Improvements: Scrollable Sidebar & Fixed Header - Implementation Specification
|
||||
|
||||
**Status**: Planning Complete
|
||||
**Created**: 2025-12-21
|
||||
**Type**: Frontend Enhancement
|
||||
**Branch**: `feature/sidebar-scroll-and-fixed-header`
|
||||
|
||||
---
|
||||
|
||||
## Executive Summary
|
||||
|
||||
This specification provides a comprehensive implementation plan for two critical UI/UX improvements to the Charon frontend:
|
||||
|
||||
1. **Sidebar Menu Scrollable Area**: Make the sidebar navigation area scrollable to prevent the logout section from being pushed off-screen when submenus are expanded
|
||||
2. **Fixed Header Bar**: Make the desktop header bar static/fixed so it remains visible when scrolling the main content area
|
||||
|
||||
---
|
||||
|
||||
## Current Implementation Analysis
|
||||
|
||||
### Component Structure
|
||||
|
||||
#### 1. Layout Component (`/projects/Charon/frontend/src/components/Layout.tsx`)
|
||||
|
||||
The Layout component is the main container that orchestrates the entire application layout. It contains:
|
||||
|
||||
- **Mobile Header** (lines 127-143): Fixed header for mobile viewports (`lg:hidden`)
|
||||
- **Sidebar** (lines 127-322): Navigation sidebar with logo, menu items, and logout section
|
||||
- **Main Content Area** (lines 336-361): Contains the desktop header and page content
|
||||
|
||||
#### 2. Sidebar Structure
|
||||
|
||||
The sidebar has the following structure:
|
||||
|
||||
```tsx
|
||||
<aside className="... flex flex-col ...">
|
||||
{/* Logo Section */}
|
||||
<div className="h-20 flex items-center ...">
|
||||
{/* Logo/Banner */}
|
||||
</div>
|
||||
|
||||
{/* Menu Container */}
|
||||
<div className="flex flex-col flex-1 px-4 mt-16 lg:mt-6">
|
||||
{/* Navigation Menu */}
|
||||
<nav className="flex-1 space-y-1">
|
||||
{/* Menu items */}
|
||||
</nav>
|
||||
|
||||
{/* Version & Logout Section */}
|
||||
<div className="mt-2 border-t ...">
|
||||
{/* Version info and logout button */}
|
||||
</div>
|
||||
</div>
|
||||
</aside>
|
||||
```
|
||||
|
||||
**Current Issues**:
|
||||
|
||||
- Line 145: `flex flex-col flex-1` on the menu container allows it to grow indefinitely
|
||||
- Line 146: `<nav className="flex-1">` also uses `flex-1`, causing the navigation to expand and push the logout section down
|
||||
- No overflow control or max-height constraints
|
||||
- When submenus expand, they push the logout button and version info off the visible area
|
||||
|
||||
#### 3. Header Structure
|
||||
|
||||
Desktop header (lines 337-361):
|
||||
|
||||
```tsx
|
||||
<header className="hidden lg:flex items-center justify-between px-8 h-20 bg-white dark:bg-dark-sidebar border-b ...">
|
||||
{/* Left section with collapse button */}
|
||||
{/* Center section (empty) */}
|
||||
{/* Right section with user info, system status, notifications, theme toggle */}
|
||||
</header>
|
||||
```
|
||||
|
||||
**Current Issues**:
|
||||
|
||||
- The header is part of the main content's flex column
|
||||
- No `position: fixed` or `sticky` positioning
|
||||
- Scrolls away with the content area
|
||||
- Line 336: `<main>` has `overflow-auto`, allowing the entire main section to scroll, including the header
|
||||
|
||||
### Styling Approach
|
||||
|
||||
The application uses:
|
||||
|
||||
- **Tailwind CSS** for utility-first styling (`/projects/Charon/frontend/tailwind.config.js`)
|
||||
- **CSS Custom Properties** in `/projects/Charon/frontend/src/index.css` for design tokens
|
||||
- Inline Tailwind classes for component styling (no separate CSS modules)
|
||||
|
||||
---
|
||||
|
||||
## Implementation Plan
|
||||
|
||||
### Improvement 1: Scrollable Sidebar Menu
|
||||
|
||||
#### Goal
|
||||
|
||||
Create a scrollable middle section in the sidebar between the logo and logout areas, ensuring the logout button remains visible even when submenus are expanded.
|
||||
|
||||
#### Technical Approach
|
||||
|
||||
**File to Modify**: `/projects/Charon/frontend/src/components/Layout.tsx`
|
||||
|
||||
**Changes Required**:
|
||||
|
||||
1. **Logo Section** (lines 138-144): Keep fixed at top
|
||||
- Already has fixed height (`h-20`)
|
||||
- No changes needed
|
||||
|
||||
2. **Menu Container** (line 145): Restructure to enable proper flex layout
|
||||
- **Current**: `<div className="flex flex-col flex-1 px-4 mt-16 lg:mt-6">`
|
||||
- **New**: `<div className="flex flex-col flex-1 min-h-0 px-4 mt-16 lg:mt-6">`
|
||||
- **Reasoning**: Adding `min-h-0` prevents the flex item from exceeding its container
|
||||
|
||||
3. **Navigation Section** (line 146): Add scrollable overflow
|
||||
- **Current**: `<nav className="flex-1 space-y-1">`
|
||||
- **New**: `<nav className="flex-1 overflow-y-auto space-y-1">`
|
||||
- **Reasoning**: `overflow-y-auto` enables vertical scrolling when content exceeds available space
|
||||
|
||||
4. **Version/Logout Section** (lines 280-322): Keep fixed at bottom
|
||||
- **Current**: `<div className="mt-2 border-t border-gray-200 dark:border-gray-800 pt-4 ...">` (line 280)
|
||||
- **New**: `<div className="flex-shrink-0 mt-2 border-t border-gray-200 dark:border-gray-800 pt-4 ...">` (line 280)
|
||||
- **Reasoning**: `flex-shrink-0` prevents this section from being compressed when space is tight
|
||||
|
||||
5. **Collapsed Logout Section** (lines 307-322): Also add shrink prevention
|
||||
- **Current**: `<div className="mt-2 border-t border-gray-200 dark:border-gray-800 pt-4 pb-4">` (line 308)
|
||||
- **New**: `<div className="flex-shrink-0 mt-2 border-t border-gray-200 dark:border-gray-800 pt-4 pb-4">` (line 308)
|
||||
|
||||
#### CSS Properties Breakdown
|
||||
|
||||
| Property | Purpose | Impact |
|
||||
|----------|---------|--------|
|
||||
| `min-h-0` | Allows flex item to shrink below content size | Enables proper scrolling in flexbox |
|
||||
| `overflow-y-auto` | Shows vertical scrollbar when needed | Makes navigation scrollable |
|
||||
| `flex-shrink-0` | Prevents element from shrinking | Keeps logout section at fixed size |
|
||||
|
||||
#### Responsive Considerations
|
||||
|
||||
- **Mobile** (< 1024px): The sidebar is already in a slide-out panel, but the same scroll behavior will apply
|
||||
- **Desktop** (≥ 1024px): Scrolling will be more noticeable when sidebar is expanded and multiple submenus are open
|
||||
- **Collapsed Sidebar**: When collapsed (`isCollapsed === true`), only icons are shown, reducing the need for scrolling
|
||||
|
||||
#### Testing Scenarios
|
||||
|
||||
1. **Expanded Sidebar with All Submenus Open**:
|
||||
- Expand Settings submenu (5 items)
|
||||
- Expand Tasks submenu (4 items including nested Import submenu)
|
||||
- Expand Security submenu (6 items)
|
||||
- Verify logout button remains visible and accessible
|
||||
|
||||
2. **Collapsed Sidebar**:
|
||||
- Toggle sidebar to collapsed state
|
||||
- Verify collapsed logout button remains visible at bottom
|
||||
|
||||
3. **Mobile View**:
|
||||
- Open mobile sidebar
|
||||
- Expand multiple submenus
|
||||
- Verify scrolling works and logout is accessible
|
||||
|
||||
### Improvement 2: Fixed Header Bar
|
||||
|
||||
#### Goal
|
||||
|
||||
Make the desktop header bar remain visible at the top of the viewport when scrolling the main content area.
|
||||
|
||||
#### Technical Approach
|
||||
|
||||
**File to Modify**: `/projects/Charon/frontend/src/components/Layout.tsx`
|
||||
|
||||
**Changes Required**:
|
||||
|
||||
1. **Main Content Container** (line 336): Remove scrolling from main element
|
||||
- **Current**: `<main className={`flex-1 min-w-0 overflow-auto pt-16 lg:pt-0 flex flex-col transition-all duration-200 ${isCollapsed ? 'lg:ml-20' : 'lg:ml-64'}`}>`
|
||||
- **New**: `<main className={`flex-1 min-w-0 pt-16 lg:pt-0 flex flex-col transition-all duration-200 ${isCollapsed ? 'lg:ml-20' : 'lg:ml-64'}`}>`
|
||||
- **Reasoning**: Remove `overflow-auto` to prevent the entire main section from scrolling
|
||||
|
||||
2. **Desktop Header** (line 337): Make header sticky
|
||||
- **Current**: `<header className="hidden lg:flex items-center justify-between px-8 h-20 bg-white dark:bg-dark-sidebar border-b border-gray-200 dark:border-gray-800 relative">`
|
||||
- **New**: `<header className="hidden lg:flex items-center justify-between px-8 h-20 bg-white dark:bg-dark-sidebar border-b border-gray-200 dark:border-gray-800 sticky top-0 z-10">`
|
||||
- **Reasoning**:
|
||||
- `sticky top-0` makes the header stick to the top of its container
|
||||
- `z-10` ensures it stays above content when scrolling
|
||||
- Remove `relative` as `sticky` is the new positioning context
|
||||
|
||||
3. **Content Wrapper** (line 360): Add scrolling to content area only
|
||||
- **Current**: `<div className="p-4 lg:p-8 max-w-7xl mx-auto w-full">`
|
||||
- **New**: `<div className="flex-1 overflow-y-auto"><div className="p-4 lg:p-8 max-w-7xl mx-auto w-full">`
|
||||
- **Reasoning**: Wrap content in a scrollable container that excludes the header
|
||||
- **Note**: Add closing `</div>` before the closing `</main>` tag (after line 362)
|
||||
|
||||
#### CSS Properties Breakdown
|
||||
|
||||
| Property | Purpose | Impact |
|
||||
|----------|---------|--------|
|
||||
| `position: sticky` | Keeps element in place within scroll container | Header stays visible when scrolling |
|
||||
| `top-0` | Sticks to top edge of viewport | Header aligns with top of screen |
|
||||
| `z-index: 10` | Layering order | Ensures header appears above content |
|
||||
| `overflow-y-auto` | Vertical scrollbar when needed | Content scrolls independently |
|
||||
|
||||
#### Alternative Approach: Fixed Positioning
|
||||
|
||||
If `sticky` positioning causes issues (rare in modern browsers), use `fixed` positioning instead:
|
||||
|
||||
```tsx
|
||||
<header className="hidden lg:fixed lg:left-0 lg:right-0 lg:top-0 lg:flex items-center justify-between px-8 h-20 bg-white dark:bg-dark-sidebar border-b border-gray-200 dark:border-gray-800 z-10" style={{ paddingLeft: isCollapsed ? '5rem' : '16rem' }}>
|
||||
```
|
||||
|
||||
**Trade-offs**:
|
||||
|
||||
- `fixed` removes the element from document flow, requiring manual left padding
|
||||
- `sticky` is simpler and requires no layout adjustments
|
||||
- Recommend `sticky` as the primary solution
|
||||
|
||||
#### Layout Conflicts & Z-Index Considerations
|
||||
|
||||
**Current Z-Index Values in Layout**:
|
||||
|
||||
- Mobile overlay: `z-20` (line 330)
|
||||
- Notification dropdown: `z-20` (line in NotificationCenter.tsx)
|
||||
- Sidebar: `z-30` (line 132)
|
||||
- Mobile header: `z-40` (line 127)
|
||||
|
||||
**Recommended Z-Index Strategy**:
|
||||
|
||||
- Desktop header: `z-10` (new, ensures it's below sidebar and modals)
|
||||
- Sidebar: `z-30` (existing, stays above header)
|
||||
- Mobile header: `z-40` (existing, stays above sidebar on mobile)
|
||||
- Dropdowns/Modals: `z-50` (standard for dialogs, already used in some components)
|
||||
|
||||
**No conflicts expected** as desktop header (`z-10`) will be lower than sidebar (`z-30`) and mobile header (`z-40`).
|
||||
|
||||
#### Responsive Considerations
|
||||
|
||||
- **Mobile** (< 1024px):
|
||||
- Mobile header is already fixed (`fixed top-0`)
|
||||
- No changes needed for mobile behavior
|
||||
- Desktop header is hidden (`hidden lg:flex`)
|
||||
|
||||
- **Desktop** (≥ 1024px):
|
||||
- New sticky header behavior applies
|
||||
- Content scrolls independently
|
||||
- Header width automatically adjusts based on sidebar state (`isCollapsed`)
|
||||
|
||||
#### Testing Scenarios
|
||||
|
||||
1. **Desktop Scroll Behavior**:
|
||||
- Navigate to a page with long content (e.g., Proxy Hosts with many entries)
|
||||
- Scroll down the page
|
||||
- Verify header remains visible at top
|
||||
- Verify sidebar toggle button, notifications, and theme toggle remain accessible
|
||||
|
||||
2. **Sidebar Interaction**:
|
||||
- Toggle sidebar collapse/expand
|
||||
- Verify header adjusts smoothly without layout shift
|
||||
- Ensure header content remains properly aligned
|
||||
|
||||
3. **Content Overflow**:
|
||||
- Test on various screen heights (small laptop, large monitor)
|
||||
- Verify scrollbar appears on content area, not entire viewport
|
||||
|
||||
4. **Dropdown Interactions**:
|
||||
- Open notification center dropdown
|
||||
- Verify it appears above header (correct z-index)
|
||||
- Scroll content and ensure dropdown stays anchored to header
|
||||
|
||||
---
|
||||
|
||||
## Implementation Steps
|
||||
|
||||
### Phase 1: Sidebar Scrollable Area
|
||||
|
||||
1. **Backup current state**: Create a git branch for this feature
|
||||
|
||||
```bash
|
||||
git checkout -b feature/sidebar-scroll-and-fixed-header
|
||||
```
|
||||
|
||||
2. **Modify Layout.tsx**: Apply changes to sidebar structure
|
||||
- Line 145: Add `min-h-0` to menu container
|
||||
- Line 146: Add `overflow-y-auto` to navigation
|
||||
- Line 280: Add `flex-shrink-0` to version/logout section
|
||||
- Line 308: Add `flex-shrink-0` to collapsed logout section
|
||||
|
||||
3. **Test in development**:
|
||||
|
||||
```bash
|
||||
cd frontend
|
||||
npm run dev
|
||||
```
|
||||
|
||||
- Test all scenarios listed in "Testing Scenarios" section
|
||||
- Verify no visual regressions
|
||||
|
||||
4. **Browser compatibility check**:
|
||||
- Chrome/Edge (Chromium)
|
||||
- Firefox
|
||||
- Safari
|
||||
|
||||
### Phase 2: Fixed Header Bar
|
||||
|
||||
1. **Modify Layout.tsx**: Apply changes to header and main content
|
||||
- Line 336: Remove `overflow-auto` from main element
|
||||
- Line 337: Add `sticky top-0 z-10` to header, remove `relative`
|
||||
- Line 360: Wrap content in scrollable container
|
||||
|
||||
2. **Test in development**: Verify all scenarios in "Testing Scenarios" section
|
||||
|
||||
3. **Cross-browser testing**: Ensure sticky positioning works consistently
|
||||
|
||||
### Phase 3: Integration Testing
|
||||
|
||||
1. **Combined behavior**:
|
||||
- Test both improvements together
|
||||
- Verify no layout conflicts
|
||||
- Check z-index stacking works correctly
|
||||
|
||||
2. **Accessibility testing**:
|
||||
- Keyboard navigation with scrollable sidebar
|
||||
- Screen reader compatibility
|
||||
- Focus management when scrolling
|
||||
|
||||
3. **Performance check**:
|
||||
- Monitor for layout thrashing
|
||||
- Check for smooth 60fps scrolling
|
||||
- Verify no memory leaks with scroll event handlers (none should be needed)
|
||||
|
||||
### Phase 4: Production Deployment
|
||||
|
||||
1. **Create pull request** with screenshots/video demonstrating the improvements
|
||||
|
||||
2. **Code review checklist**:
|
||||
- [ ] All Tailwind classes are correctly applied
|
||||
- [ ] No visual regressions on mobile
|
||||
- [ ] No visual regressions on desktop
|
||||
- [ ] Z-index stacking is correct
|
||||
- [ ] Scrolling performance is smooth
|
||||
- [ ] Accessibility is maintained
|
||||
|
||||
3. **Merge and deploy** after approval
|
||||
|
||||
---
|
||||
|
||||
## Potential Issues & Mitigation
|
||||
|
||||
### Issue 1: Safari Sticky Positioning
|
||||
|
||||
**Problem**: Older Safari versions have inconsistent `position: sticky` support
|
||||
|
||||
**Mitigation**:
|
||||
|
||||
- Test on Safari 13+ (current support is excellent)
|
||||
- If issues arise, fall back to `position: fixed` approach
|
||||
- Use CSS feature detection if needed
|
||||
|
||||
### Issue 2: Scrollbar Styling
|
||||
|
||||
**Problem**: Default scrollbars may look inconsistent with dark theme
|
||||
|
||||
**Solution**: Add custom scrollbar styles to `/projects/Charon/frontend/src/index.css`:
|
||||
|
||||
```css
|
||||
/* Custom Scrollbar Styles */
|
||||
.overflow-y-auto::-webkit-scrollbar {
|
||||
width: 8px;
|
||||
}
|
||||
|
||||
.overflow-y-auto::-webkit-scrollbar-track {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.overflow-y-auto::-webkit-scrollbar-thumb {
|
||||
background-color: rgba(148, 163, 184, 0.3);
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.dark .overflow-y-auto::-webkit-scrollbar-thumb {
|
||||
background-color: rgba(148, 163, 184, 0.5);
|
||||
}
|
||||
|
||||
.overflow-y-auto::-webkit-scrollbar-thumb:hover {
|
||||
background-color: rgba(148, 163, 184, 0.6);
|
||||
}
|
||||
```
|
||||
|
||||
### Issue 3: Layout Shift on Sidebar Toggle
|
||||
|
||||
**Problem**: Collapsing/expanding sidebar might cause visible layout shift with fixed header
|
||||
|
||||
**Mitigation**:
|
||||
|
||||
- Already handled by Tailwind transitions: `transition-all duration-200`
|
||||
- Existing CSS transitions on line 132 and 336 will smooth the animation
|
||||
- No additional work needed
|
||||
|
||||
### Issue 4: Mobile Header Conflict
|
||||
|
||||
**Problem**: Mobile header is already fixed, might conflict with new desktop header behavior
|
||||
|
||||
**Mitigation**:
|
||||
|
||||
- Mobile header uses `lg:hidden` (line 127)
|
||||
- Desktop header uses `hidden lg:flex` (line 337)
|
||||
- No overlap between the two states
|
||||
- Already properly separated by breakpoints
|
||||
|
||||
---
|
||||
|
||||
## Configuration File Review
|
||||
|
||||
### `.gitignore`
|
||||
|
||||
**Review**: No changes needed for CSS/layout updates
|
||||
|
||||
- Already ignores common frontend build artifacts
|
||||
- No new files or directories will be created
|
||||
|
||||
### `codecov.yml`
|
||||
|
||||
**Status**: File does not exist in repository
|
||||
|
||||
- No changes needed
|
||||
|
||||
### `.dockerignore`
|
||||
|
||||
**Review**: No changes needed
|
||||
|
||||
- Layout changes are code modifications, not new files
|
||||
- All frontend source files are already properly handled
|
||||
|
||||
### `Dockerfile`
|
||||
|
||||
**Review**: No changes needed
|
||||
|
||||
- Layout changes are CSS/JSX modifications
|
||||
- Frontend build process remains unchanged
|
||||
- Build steps (lines 35-52) compile the app correctly regardless of layout changes
|
||||
|
||||
---
|
||||
|
||||
## Success Criteria
|
||||
|
||||
### Sidebar Scrollable Area
|
||||
|
||||
- [ ] Logout button always visible at bottom of sidebar
|
||||
- [ ] Smooth scrolling when menu items overflow
|
||||
- [ ] No layout jumps or visual glitches
|
||||
- [ ] Works in collapsed and expanded sidebar states
|
||||
- [ ] Mobile sidebar behaves correctly
|
||||
|
||||
### Fixed Header Bar
|
||||
|
||||
- [ ] Header remains visible when scrolling content
|
||||
- [ ] No layout shift or jank during scroll
|
||||
- [ ] All header buttons remain functional
|
||||
- [ ] Z-index layering is correct (dropdowns above header)
|
||||
- [ ] Sidebar toggle properly adjusts header width
|
||||
|
||||
### Overall
|
||||
|
||||
- [ ] No performance degradation
|
||||
- [ ] Maintains accessibility standards
|
||||
- [ ] Works across all supported browsers
|
||||
- [ ] Responsive behavior intact
|
||||
- [ ] Dark mode styling consistent
|
||||
|
||||
---
|
||||
|
||||
## File Change Summary
|
||||
|
||||
### Files to Modify
|
||||
|
||||
| File | Line Numbers | Changes |
|
||||
|------|--------------|---------|
|
||||
| `/projects/Charon/frontend/src/components/Layout.tsx` | 145 | Add `min-h-0` to menu container |
|
||||
| `/projects/Charon/frontend/src/components/Layout.tsx` | 146 | Add `overflow-y-auto` to navigation |
|
||||
| `/projects/Charon/frontend/src/components/Layout.tsx` | 280 | Add `flex-shrink-0` to version/logout section |
|
||||
| `/projects/Charon/frontend/src/components/Layout.tsx` | 308 | Add `flex-shrink-0` to collapsed logout section |
|
||||
| `/projects/Charon/frontend/src/components/Layout.tsx` | 336 | Remove `overflow-auto` from main element |
|
||||
| `/projects/Charon/frontend/src/components/Layout.tsx` | 337 | Add `sticky top-0 z-10`, remove `relative` |
|
||||
| `/projects/Charon/frontend/src/components/Layout.tsx` | 360-362 | Wrap content in scrollable container |
|
||||
| `/projects/Charon/frontend/src/index.css` | EOF | Optional: Add custom scrollbar styles |
|
||||
|
||||
### Files to Create
|
||||
|
||||
**None** - All changes are modifications to existing files
|
||||
|
||||
---
|
||||
|
||||
## Timeline Estimate
|
||||
|
||||
- **Phase 1 (Sidebar)**: 2-3 hours (implementation + testing)
|
||||
- **Phase 2 (Header)**: 2-3 hours (implementation + testing)
|
||||
- **Phase 3 (Integration)**: 2 hours (combined testing + refinements)
|
||||
- **Phase 4 (Deployment)**: 1 hour (PR, review, merge)
|
||||
|
||||
**Total**: 7-9 hours
|
||||
|
||||
---
|
||||
|
||||
## Additional Notes
|
||||
|
||||
### Design System Considerations
|
||||
|
||||
The application already uses a comprehensive design token system (see `/projects/Charon/frontend/src/index.css`):
|
||||
|
||||
- Spacing tokens (`--space-*`)
|
||||
- Color tokens (`--color-*`)
|
||||
- Transition tokens (`--transition-*`)
|
||||
|
||||
All proposed changes use existing Tailwind utilities that map to these tokens, ensuring consistency.
|
||||
|
||||
### Future Enhancements
|
||||
|
||||
After implementing these improvements, consider:
|
||||
|
||||
1. **Sidebar Width Persistence**: Store user's preferred sidebar width (collapsed/expanded) in localStorage (already implemented on line 29-33)
|
||||
|
||||
2. **Smooth Scroll to Active Item**: When a page loads, scroll the sidebar to show the active menu item:
|
||||
|
||||
```tsx
|
||||
useEffect(() => {
|
||||
const activeElement = document.querySelector('nav a[aria-current="page"]');
|
||||
activeElement?.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
|
||||
}, [location.pathname]);
|
||||
```
|
||||
|
||||
3. **Header Scroll Shadow**: Add a subtle shadow when content scrolls beneath header:
|
||||
|
||||
```tsx
|
||||
const [isScrolled, setIsScrolled] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
const handleScroll = (e) => {
|
||||
setIsScrolled(e.target.scrollTop > 0);
|
||||
};
|
||||
// Attach to content scroll container
|
||||
}, []);
|
||||
|
||||
<header className={`... ${isScrolled ? 'shadow-md' : ''}`}>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## References
|
||||
|
||||
- Tailwind CSS Flexbox: <https://tailwindcss.com/docs/flex>
|
||||
- CSS Position Sticky: <https://developer.mozilla.org/en-US/docs/Web/CSS/position#sticky>
|
||||
- Flexbox and Min-Height: <https://www.w3.org/TR/css-flexbox-1/#min-size-auto>
|
||||
|
||||
---
|
||||
|
||||
**Document Version**: 1.0
|
||||
**Created**: 2025-12-21
|
||||
**Author**: GitHub Copilot
|
||||
**Status**: Ready for Implementation
|
||||
Reference in New Issue
Block a user