feat: add maxHeight prop with sectionContent wrapper to SidebarSection
Adds position and maxHeight to SidebarSectionProps and wraps children in a .sectionContent div when the section is open, enabling scrollable constrained height via inline style. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -324,4 +324,73 @@ describe('Sidebar compound component', () => {
|
|||||||
const item = screen.getByText('Admin').closest('[role="button"]')!
|
const item = screen.getByText('Admin').closest('[role="button"]')!
|
||||||
expect(item.className).toMatch(/bottomItemActive/)
|
expect(item.className).toMatch(/bottomItemActive/)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// 17. renders sectionContent wrapper with maxHeight when open
|
||||||
|
it('renders section content wrapper with maxHeight style when open', () => {
|
||||||
|
const { container } = render(
|
||||||
|
<Wrapper>
|
||||||
|
<Sidebar>
|
||||||
|
<Sidebar.Section
|
||||||
|
icon={<span>ic</span>}
|
||||||
|
label="Apps"
|
||||||
|
open
|
||||||
|
onToggle={vi.fn()}
|
||||||
|
maxHeight="200px"
|
||||||
|
>
|
||||||
|
<div>child</div>
|
||||||
|
</Sidebar.Section>
|
||||||
|
</Sidebar>
|
||||||
|
</Wrapper>,
|
||||||
|
)
|
||||||
|
|
||||||
|
const contentWrapper = container.querySelector('.sectionContent')
|
||||||
|
expect(contentWrapper).toBeInTheDocument()
|
||||||
|
expect(contentWrapper).toHaveStyle({ maxHeight: '200px' })
|
||||||
|
expect(screen.getByText('child')).toBeInTheDocument()
|
||||||
|
})
|
||||||
|
|
||||||
|
// 18. renders sectionContent wrapper without maxHeight when not provided
|
||||||
|
it('renders section content wrapper without inline maxHeight when maxHeight is not provided', () => {
|
||||||
|
const { container } = render(
|
||||||
|
<Wrapper>
|
||||||
|
<Sidebar>
|
||||||
|
<Sidebar.Section
|
||||||
|
icon={<span>ic</span>}
|
||||||
|
label="Apps"
|
||||||
|
open
|
||||||
|
onToggle={vi.fn()}
|
||||||
|
>
|
||||||
|
<div>child</div>
|
||||||
|
</Sidebar.Section>
|
||||||
|
</Sidebar>
|
||||||
|
</Wrapper>,
|
||||||
|
)
|
||||||
|
|
||||||
|
const contentWrapper = container.querySelector('.sectionContent')
|
||||||
|
expect(contentWrapper).toBeInTheDocument()
|
||||||
|
expect(contentWrapper).not.toHaveStyle({ maxHeight: '200px' })
|
||||||
|
expect(screen.getByText('child')).toBeInTheDocument()
|
||||||
|
})
|
||||||
|
|
||||||
|
// 19. does not render sectionContent wrapper when section is closed
|
||||||
|
it('does not render section content wrapper when section is closed', () => {
|
||||||
|
const { container } = render(
|
||||||
|
<Wrapper>
|
||||||
|
<Sidebar>
|
||||||
|
<Sidebar.Section
|
||||||
|
icon={<span>ic</span>}
|
||||||
|
label="Apps"
|
||||||
|
open={false}
|
||||||
|
onToggle={vi.fn()}
|
||||||
|
maxHeight="200px"
|
||||||
|
>
|
||||||
|
<div>child</div>
|
||||||
|
</Sidebar.Section>
|
||||||
|
</Sidebar>
|
||||||
|
</Wrapper>,
|
||||||
|
)
|
||||||
|
|
||||||
|
const contentWrapper = container.querySelector('.sectionContent')
|
||||||
|
expect(contentWrapper).not.toBeInTheDocument()
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -26,6 +26,8 @@ interface SidebarSectionProps {
|
|||||||
active?: boolean
|
active?: boolean
|
||||||
children: ReactNode
|
children: ReactNode
|
||||||
className?: string
|
className?: string
|
||||||
|
position?: 'top' | 'bottom'
|
||||||
|
maxHeight?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
interface SidebarFooterProps {
|
interface SidebarFooterProps {
|
||||||
@@ -83,6 +85,8 @@ function SidebarSection({
|
|||||||
active,
|
active,
|
||||||
children,
|
children,
|
||||||
className,
|
className,
|
||||||
|
position: _position,
|
||||||
|
maxHeight,
|
||||||
}: SidebarSectionProps) {
|
}: SidebarSectionProps) {
|
||||||
const { collapsed, onCollapseToggle } = useSidebarContext()
|
const { collapsed, onCollapseToggle } = useSidebarContext()
|
||||||
|
|
||||||
@@ -125,7 +129,14 @@ function SidebarSection({
|
|||||||
{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>
|
||||||
{open && children}
|
{open && (
|
||||||
|
<div
|
||||||
|
className={styles.sectionContent}
|
||||||
|
style={maxHeight ? { maxHeight } : undefined}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user