Skip to content

Commit

Permalink
*feat AppHeader
Browse files Browse the repository at this point in the history
*feat AppSidebar
  • Loading branch information
Sodik committed Sep 2, 2024
1 parent 4ece87c commit 975f728
Show file tree
Hide file tree
Showing 9 changed files with 34 additions and 65 deletions.
16 changes: 11 additions & 5 deletions packages/ui/__stories__/AppSidebar.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,25 @@ import React from 'react'
import { Story } from '@storybook/react'
import { Disc, HardDrive, Wifi, Activity, Droplet, Airplay } from 'react-feather'

import { AppSidebar, AppSidebarSection, AppSidebarMenuItemCounter, AppSidebarItem, AppSidebarProps } from '../src/AppSidebar'
import {
AppSidebar,
AppSidebarSection,
AppSidebarMenuItemCounter,
AppSidebarItem,
AppSidebarProps,
AppSidebarFavorites,
} from '../src/AppSidebar'

export default {
title: 'App/Sidebar',
component: AppSidebar,
}

const Template: Story<AppSidebarProps> = (props) => (
const Template: Story<Partial<AppSidebarProps>> = (props) => (
<AppSidebar footer={<span>24/08/14 01:49 PM Ver. 5.5.0</span>} {...props}>
<AppSidebarFavorites>{({ items }) => items.map((item) => <AppSidebarItem key={item} id={item} title={item} />)}</AppSidebarFavorites>
<AppSidebarSection active id="maps" title="Maps wan replication" ariaLabel="maps" icon={Disc}>
<a href="/">
<AppSidebarItem id="1" title="Test" active />
</a>
<AppSidebarItem id="1" title="Test" active wrapper={({ children }) => <a href="/">{children}</a>} />
<AppSidebarItem title="Wan healthcheck replication" />
<AppSidebarItem title="Test 2" />
</AppSidebarSection>
Expand Down
4 changes: 3 additions & 1 deletion packages/ui/src/AppHeader/AppHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,19 @@ import styles from './AppHeader.module.scss'
export interface AppHeaderProps {
name: ReactNode
className?: string
children?: ReactNode
environment?: 'production'
logoProps: AppHeaderLogoProps
clusterSelectProps?: SelectClusterProps
menuContent?: AppHeaderMenuProps['children']
}

export const AppHeader = ({ name, className, environment, clusterSelectProps, logoProps, menuContent }: AppHeaderProps) => (
export const AppHeader = ({ name, className, children, environment, clusterSelectProps, logoProps, menuContent }: AppHeaderProps) => (
<header className={cls(styles.root, className)}>
<AppHeaderLogo {...logoProps} />
<span className={styles.name}>{name}</span>
{clusterSelectProps && <SelectCluster {...clusterSelectProps} />}
{children}
{environment && <EnvironmentBadge environment={environment} />}
<div className={styles.aside}>{menuContent && <AppHeaderMenu>{menuContent}</AppHeaderMenu>}</div>
</header>
Expand Down
1 change: 1 addition & 0 deletions packages/ui/src/AppSidebar/AppSidebar.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ $offset: c.$grid * 4;
color: c.$colorNeutralLight;
text-align: center;
margin-top: auto;
word-break: break-all;
padding: 0 c.$grid * 4 c.$grid * 2.5;
font-size: c.$fontSizeBodySmall;
}
Expand Down
25 changes: 3 additions & 22 deletions packages/ui/src/AppSidebar/AppSidebar.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import React, { ReactNode, useCallback, useState } from 'react'
import React, { ReactNode, useCallback } from 'react'
import cn from 'classnames'
import { ChevronsLeft, ChevronsRight } from 'react-feather'
import createPersistedState from 'use-persisted-state'

import { IconButton } from '../IconButton'
import { AppSidebarFavorites } from './AppSidebarFavorites'
import { appSidebarContext, FavoriteItem } from './appSidebarContext'
import { appSidebarContext } from './appSidebarContext'

import styles from './AppSidebar.module.scss'

Expand All @@ -30,25 +29,13 @@ export const AppSidebar = ({
const usePersistedFavoritesState = createPersistedState<string[]>('sideBarFavorites')

const [favorites, setFavorites] = usePersistedFavoritesState([])
const [registeredFavorites, setRegisteredFavorites] = useState<Record<string, FavoriteItem>>({})
const [isOpen, setIsOpen] = usePersistedSidebarStorageState(initialOpen)

const toggle = useCallback(() => setIsOpen((value) => !value), [setIsOpen])
const open = useCallback(() => setIsOpen(true), [setIsOpen])
const close = useCallback(() => setIsOpen(false), [setIsOpen])
const registerFavorite = useCallback(
(item: FavoriteItem) => setRegisteredFavorites((value) => ({ ...value, [item.id]: item })),
[setRegisteredFavorites],
)
const unregisterFavorite = useCallback(
// eslint-disable-next-line @typescript-eslint/no-unused-vars
(id: string) => setRegisteredFavorites(({ [id]: _, ...value }) => value),
[setRegisteredFavorites],
)
const isCollapsed = controlledOpen !== undefined ? !controlledOpen : !isOpen

console.log(controlledOpen, isCollapsed)

return (
<aside className={cn(styles.root, { [styles.collapsed]: isCollapsed }, className)}>
<IconButton size="medium" icon={!isCollapsed ? ChevronsLeft : ChevronsRight} onClick={toggle} className={styles.toggle} />
Expand All @@ -59,17 +46,11 @@ export const AppSidebar = ({
isOpen: !isCollapsed,
toggle,
favorites,
registeredFavorites,
setFavorites,
registerFavorite,
unregisterFavorite,
}}
>
<div className={styles.wrapper}>
<div className={styles.content}>
<AppSidebarFavorites />
{children}
</div>
<div className={styles.content}>{children}</div>
{footer && <footer className={styles.footer}>{footer}</footer>}
</div>
</appSidebarContext.Provider>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useContext, useEffect, useMemo } from 'react'
import React, { useContext, useMemo } from 'react'
import cn from 'classnames'
import { Star } from 'react-feather'

Expand All @@ -9,13 +9,11 @@ import styles from './AppSidebarFavoriteButton.module.scss'

export interface AppSidebarFavoriteButtonProps {
id: string
title: string
className?: string
registrable?: boolean
}

export const AppSidebarFavoriteButton = ({ id, title, className, registrable }: AppSidebarFavoriteButtonProps) => {
const { favorites, setFavorites, registerFavorite, unregisterFavorite } = useContext(appSidebarContext)
export const AppSidebarFavoriteButton = ({ id, className }: AppSidebarFavoriteButtonProps) => {
const { favorites, setFavorites } = useContext(appSidebarContext)
const isFavoriteItem = useMemo(() => favorites.find((item) => item === id), [favorites, id])

const handleToggleFavorite = () => {
Expand All @@ -26,17 +24,6 @@ export const AppSidebarFavoriteButton = ({ id, title, className, registrable }:
}
}

useEffect(() => {
if (registrable) {
registerFavorite({ id, title })
}
return () => {
if (registrable) {
unregisterFavorite(id)
}
}
}, [registerFavorite, registrable, id, title, unregisterFavorite])

return (
<IconButton
className={cn(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,26 +1,29 @@
import React, { useContext } from 'react'
import React, { ReactNode, useContext } from 'react'
import { Star } from 'react-feather'

import { AppSidebarItem } from '../AppSidebarItem'
import { AppSidebarSection } from '../AppSidebarSection'
import { appSidebarContext } from '../appSidebarContext'

import styles from './AppSidebarFavorites.module.scss'

export const AppSidebarFavorites = () => {
const { favorites, registeredFavorites } = useContext(appSidebarContext)
export interface AppSidebarFavoritesProps {
children: (props: { items: string[] }) => ReactNode
}

export const AppSidebarFavorites = ({ children }: AppSidebarFavoritesProps) => {
const { favorites } = useContext(appSidebarContext)

return Object.keys(registeredFavorites).length > 0 ? (
return (
<AppSidebarSection active={false} ariaLabel="favorites" id="favorites" title="Favorites" icon={Star}>
<div className={styles.content}>
{favorites.length > 0 ? (
favorites.map((id) => <AppSidebarItem key={id} id={id} registrable={false} title={registeredFavorites[id].title} />)
children({ items: favorites })
) : (
<div className={styles.placeholder} data-test="sidebar-menu-no-favorites">
No favorites
</div>
)}
</div>
</AppSidebarSection>
) : null
)
}
6 changes: 2 additions & 4 deletions packages/ui/src/AppSidebar/AppSidebarItem/AppSidebarItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import cn from 'classnames'
import { Icon as FeatherIcon } from 'react-feather'

import { Icon } from '../../Icon'
import { Button, ButtonColor } from '../../Button'
import { Tooltip } from '../../Tooltip'
import { Button, ButtonColor } from '../../Button'
import { appSidebarContext } from '../appSidebarContext'
import { AppSidebarFavoriteButton } from '../AppSidebarFavoriteButton'
import { appSidebarSectionContext } from '../AppSidebarSection/appSidebarSectionContext'
Expand All @@ -22,7 +22,6 @@ export type AppSidebarItemProps = {
color?: ButtonColor
onClick?: () => void
available?: boolean
registrable?: boolean
adornment?: ReactNode
wrapper?: (props: { children: ReactElement | string }) => ReactElement
} & DataTestProp &
Expand All @@ -42,7 +41,6 @@ export const AppSidebarItem = ({
color = 'light',
adornment,
available,
registrable = true,
'data-test': dataTest,
wrapper: Wrapper = Component,
}: AppSidebarItemProps) => {
Expand All @@ -51,7 +49,7 @@ export const AppSidebarItem = ({

return (
<div className={cn(styles.root, { [styles.collapsed]: !isOpen, [styles.nested]: !!ctx })} data-test={dataTest}>
{id && <AppSidebarFavoriteButton id={id} title={title} registrable={registrable} className={styles.favorite} />}
{id && ctx && <AppSidebarFavoriteButton id={id} className={styles.favorite} />}
<Wrapper>
<Button
variant="text"
Expand Down
10 changes: 0 additions & 10 deletions packages/ui/src/AppSidebar/appSidebarContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,12 @@ import { createContext } from 'react'

const noOp: () => void = () => undefined

export interface FavoriteItem {
id: string
title: string
}
export interface AppSidebarContext {
isOpen: boolean
open: () => void
close: () => void
toggle: () => void
favorites: string[]
unregisterFavorite: (id: string) => void
registerFavorite: (item: FavoriteItem) => void
registeredFavorites: Record<string, FavoriteItem>
setFavorites: (cb: (value: string[]) => string[]) => void
}
export const appSidebarContext = createContext<AppSidebarContext>({
Expand All @@ -24,7 +17,4 @@ export const appSidebarContext = createContext<AppSidebarContext>({
isOpen: true,
favorites: [],
setFavorites: () => [],
registeredFavorites: {},
registerFavorite: noOp,
unregisterFavorite: noOp,
})
1 change: 1 addition & 0 deletions packages/ui/src/AppSidebar/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export * from './AppSidebar'
export * from './AppSidebarItem'
export * from './AppSidebarSection'
export * from './AppSidebarFavorites'
export * from './AppSidebarMenuItemCounter'

0 comments on commit 975f728

Please sign in to comment.