fix(sidebar): move search below Header, remove section chevrons
All checks were successful
Build & Publish / publish (push) Successful in 1m3s
All checks were successful
Build & Publish / publish (push) Successful in 1m3s
- Search input now renders between Sidebar.Header and first Section instead of above Header (fixes cameleer3-server#120) - Remove ChevronRight/ChevronDown from section headers — the entire row is already clickable, chevrons added visual noise Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,11 +1,9 @@
|
|||||||
import { type ReactNode } from 'react'
|
import { type ReactNode, Children, isValidElement } from 'react'
|
||||||
import {
|
import {
|
||||||
Search,
|
Search,
|
||||||
X,
|
X,
|
||||||
ChevronsLeft,
|
ChevronsLeft,
|
||||||
ChevronsRight,
|
ChevronsRight,
|
||||||
ChevronRight,
|
|
||||||
ChevronDown,
|
|
||||||
} from 'lucide-react'
|
} from 'lucide-react'
|
||||||
import styles from './Sidebar.module.css'
|
import styles from './Sidebar.module.css'
|
||||||
import { SidebarContext, useSidebarContext } from './SidebarContext'
|
import { SidebarContext, useSidebarContext } from './SidebarContext'
|
||||||
@@ -124,9 +122,6 @@ function SidebarSection({
|
|||||||
aria-label={open ? `Collapse ${label}` : `Expand ${label}`}
|
aria-label={open ? `Collapse ${label}` : `Expand ${label}`}
|
||||||
onKeyDown={(e) => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); onToggle() } }}
|
onKeyDown={(e) => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); onToggle() } }}
|
||||||
>
|
>
|
||||||
<span className={styles.treeSectionChevronBtn} aria-hidden="true">
|
|
||||||
{open ? <ChevronDown size={12} /> : <ChevronRight size={12} />}
|
|
||||||
</span>
|
|
||||||
{icon && <span className={styles.sectionIcon}>{icon}</span>}
|
{icon && <span className={styles.sectionIcon}>{icon}</span>}
|
||||||
<span className={styles.treeSectionLabel}>{label}</span>
|
<span className={styles.treeSectionLabel}>{label}</span>
|
||||||
</div>
|
</div>
|
||||||
@@ -199,7 +194,20 @@ function SidebarRoot({
|
|||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Search (only when expanded and handler provided) */}
|
{/* Render Header first, then search, then remaining children */}
|
||||||
|
{(() => {
|
||||||
|
const childArray = Children.toArray(children)
|
||||||
|
const headerIdx = childArray.findIndex(
|
||||||
|
(child) => isValidElement(child) && child.type === SidebarHeader,
|
||||||
|
)
|
||||||
|
const header = headerIdx >= 0 ? childArray[headerIdx] : null
|
||||||
|
const rest = headerIdx >= 0
|
||||||
|
? [...childArray.slice(0, headerIdx), ...childArray.slice(headerIdx + 1)]
|
||||||
|
: childArray
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{header}
|
||||||
{onSearchChange && !collapsed && (
|
{onSearchChange && !collapsed && (
|
||||||
<div className={styles.searchWrap}>
|
<div className={styles.searchWrap}>
|
||||||
<div className={styles.searchInner}>
|
<div className={styles.searchInner}>
|
||||||
@@ -226,8 +234,10 @@ function SidebarRoot({
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
{rest}
|
||||||
{children}
|
</>
|
||||||
|
)
|
||||||
|
})()}
|
||||||
</aside>
|
</aside>
|
||||||
</SidebarContext.Provider>
|
</SidebarContext.Provider>
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user