Skip to content

Commit

Permalink
feat: Configure expanded sidebar items (#592)
Browse files Browse the repository at this point in the history
  • Loading branch information
renemennab authored May 14, 2024
1 parent 4bb4349 commit b748fcb
Show file tree
Hide file tree
Showing 7 changed files with 212 additions and 76 deletions.
18 changes: 13 additions & 5 deletions src/components/Sidebar.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import {
type ComponentProps,
type Dispatch,
type Ref,
type SetStateAction,
createContext,
forwardRef,
useContext,
useMemo,
useState,
} from 'react'
import styled from 'styled-components'

Expand All @@ -14,10 +17,12 @@ type SidebarVariant = 'app' | 'console'
type SidebarBaseProps = {
layout?: SidebarLayout
variant: SidebarVariant
isExpanded?: boolean
setIsExpanded?: Dispatch<SetStateAction<boolean>>
}
type SidebarProps = SidebarBaseProps & ComponentProps<typeof SidebarSC>

const SIDEBAR_WIDTH = 64
export const SIDEBAR_WIDTH = 64
const SIDEBAR_HEIGHT = 56

const SidebarContext = createContext<SidebarBaseProps | null>(null)
Expand Down Expand Up @@ -49,29 +54,32 @@ const SidebarSC = styled.div<{
: $variant === 'console'
? theme.colors.grey[950]
: theme.colors['fill-one'],

borderRight: $isHorizontal ? 'none' : theme.borders.default,
borderBottom: $isHorizontal ? theme.borders.default : 'none',
overflowY: 'hidden',
overflow: 'visible',
}))

function SidebarRef(
{ layout = 'vertical', variant = 'app', ...props }: SidebarProps,
ref: Ref<any>
) {
const [isExpanded, setIsExpanded] = useState<boolean>(false)

const contextVal = useMemo(
() => ({
layout,
variant,
isExpanded,
setIsExpanded,
}),
[layout, variant]
[layout, variant, isExpanded, setIsExpanded]
)

return (
<SidebarContext.Provider value={contextVal}>
<SidebarSC
$isHorizontal={layout === 'horizontal'}
$variant={variant}
$isExpanded={isExpanded}
ref={ref}
{...props}
/>
Expand Down
27 changes: 27 additions & 0 deletions src/components/SidebarExpandButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { type MouseEvent } from 'react'

import { HamburgerMenuCollapseIcon, HamburgerMenuIcon } from '../icons'

import { useSidebar } from './Sidebar'
import SidebarItem from './SidebarItem'

function SidebarExpandButton() {
const { setIsExpanded, isExpanded } = useSidebar()

return (
<SidebarItem
tooltip="Expand"
className="sidebar-expand"
clickable
expandedLabel="Collapse"
onClick={(e: MouseEvent) => {
e.stopPropagation()
setIsExpanded((x: boolean) => !x)
}}
>
{isExpanded ? <HamburgerMenuCollapseIcon /> : <HamburgerMenuIcon />}
</SidebarItem>
)
}

export default SidebarExpandButton
63 changes: 63 additions & 0 deletions src/components/SidebarExpandWrapper.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import { useOutsideClick } from 'honorable'
import { type ReactNode, useEffect, useRef } from 'react'

import styled from 'styled-components'

import { SIDEBAR_WIDTH, useSidebar } from './Sidebar'

export const SIDEBAR_EXPANDED_WIDTH = 180

function SidebarExpandWrapper({
pathname,
...props
}: {
pathname?: string
children: ReactNode[]
}) {
const { layout, isExpanded, setIsExpanded } = useSidebar()
const isHorizontal = layout === 'horizontal'
const ref = useRef(null)

useOutsideClick(ref, () => {
setIsExpanded(false)
})

useEffect(() => {
setIsExpanded(false)
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [pathname])

return (
<Animated
$isExpanded={isExpanded}
$isHorizontal={isHorizontal}
ref={ref}
{...props}
/>
)
}

export default SidebarExpandWrapper

const Animated = styled.div<{
$isExpanded: boolean
$isHorizontal: boolean
}>(({ theme, $isExpanded, $isHorizontal }) => ({
display: 'flex',
flexDirection: $isHorizontal ? 'row' : 'column',
position: 'relative',
alignItems: 'center',
borderBottom: $isHorizontal ? '' : `1px solid ${theme.colors.border}`,
gap: $isHorizontal ? theme.spacing.medium : theme.spacing.xsmall,
borderRight: $isHorizontal ? undefined : `1px solid ${theme.colors.border}`,
width: $isExpanded ? SIDEBAR_EXPANDED_WIDTH : SIDEBAR_WIDTH,
minWidth: $isExpanded ? SIDEBAR_EXPANDED_WIDTH : SIDEBAR_WIDTH,
maxWidth: $isExpanded ? SIDEBAR_EXPANDED_WIDTH : SIDEBAR_WIDTH,
height: '100%',
backgroundColor: 'inherit',
transition: 'all 0.2s ease',
zIndex: 10,
':last-of-type': {
borderBottom: 'none',
},
}))
53 changes: 36 additions & 17 deletions src/components/SidebarItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,22 +8,27 @@ import { type SidebarVariant, useSidebar } from './Sidebar'
type SidebarItemProps = ComponentProps<typeof ItemSC> & {
clickable?: boolean
tooltip?: string
expandedLabel?: string
active?: boolean
}

function SidebarItemRef(
{ children, clickable = false, tooltip = '', ...props }: SidebarItemProps,
ref: Ref<any>
) {
function SidebarItemRef({
children,
tooltip = '',
expandedLabel = '',
className,
...props
}: SidebarItemProps) {
const { isExpanded } = useSidebar()

return (
<WithTooltip tooltip={tooltip}>
<Item
clickable={clickable}
ref={ref}
{...props}
>
{children}
</Item>
<WithTooltip
tooltip={tooltip}
className={className}
{...props}
>
{children}
{isExpanded && expandedLabel ? expandedLabel : null}
</WithTooltip>
)
}
Expand All @@ -32,9 +37,19 @@ function WithTooltipRef(
{ children, clickable, tooltip = '', ...props }: SidebarItemProps,
ref: Ref<any>
) {
const { layout } = useSidebar()
const { layout, isExpanded } = useSidebar()

if (!tooltip) return <> {children}</>
if (!tooltip || isExpanded)
return (
<Item
layout={layout}
clickable={clickable}
ref={ref}
{...props}
>
{children}
</Item>
)

return (
<Tooltip
Expand Down Expand Up @@ -63,10 +78,14 @@ const ItemSC = styled.div<{
}>(({ theme, $clickable, $active, $isHorizontal, $variant }) => ({
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
width: $isHorizontal ? undefined : 32,
height: 32,
justifyContent: 'flex-start',
gap: theme.spacing.xsmall,
textDecoration: 'none',
whiteSpace: 'nowrap',
width: $isHorizontal ? undefined : '100%',
height: $isHorizontal ? undefined : 40,
flexGrow: 0,
padding: $isHorizontal ? undefined : theme.spacing.small,
borderRadius: '3px',
overflow: 'hidden',
color: theme.colors['icon-light'],
Expand Down
1 change: 1 addition & 0 deletions src/components/SidebarSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ function SidebarSectionRef(
borderBottom={isHorizontal ? '' : '1px solid border'}
gap={isHorizontal ? 'medium' : 'xsmall'}
padding={12}
width={isHorizontal ? 'auto' : '100%'}
{...styles}
{...props}
/>
Expand Down
7 changes: 6 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,13 @@ export {
export type { TooltipProps } from './components/Tooltip'
export { default as Tooltip } from './components/Tooltip'
export { default as FormTitle } from './components/FormTitle'
export { default as Sidebar } from './components/Sidebar'
export { default as Sidebar, SIDEBAR_WIDTH } from './components/Sidebar'
export { default as SidebarSection } from './components/SidebarSection'
export { default as SidebarExpandButton } from './components/SidebarExpandButton'
export {
default as SidebarExpandWrapper,
SIDEBAR_EXPANDED_WIDTH,
} from './components/SidebarExpandWrapper'
export { default as SidebarItem } from './components/SidebarItem'
export { default as Modal } from './components/Modal'
export { default as Flyover } from './components/Flyover'
Expand Down
Loading

0 comments on commit b748fcb

Please sign in to comment.