Skip to content

Commit

Permalink
Sidebar should be toggleable
Browse files Browse the repository at this point in the history
- saw this in a couple other places, looked easy and harmless enough to implement
  • Loading branch information
mrdjohnson committed Apr 9, 2024
1 parent fd8d90f commit 82876f2
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 11 deletions.
2 changes: 1 addition & 1 deletion src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ function App() {
<OmniBar />

<section className="drawer-content flex h-screen max-h-full w-full flex-grow flex-row gap-4 overflow-hidden text-xl">
<aside className="hidden h-full w-[260px] min-w-[260px] lg:block" role="complementary">
<aside className="hidden lg:block" role="complementary">
<SideBar />
</aside>

Expand Down
51 changes: 41 additions & 10 deletions src/containers/SideBar.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
import { useEffect, useState } from 'react'
import { useEffect, useMemo, useState } from 'react'
import { observer } from 'mobx-react-lite'
import { Accordion } from '@chakra-ui/react'
import useMedia from 'use-media'

import { ChatSettingsSection } from '~/components/chat/ChatSettingsSection'
import { ChatListSection } from '~/components/chat/ChatListSection'

import { chatStore } from '~/models/ChatStore'
import { settingStore } from '~/models/SettingStore'

import MediaEject from '~/icons/MediaEject'

export type AccordionSectionProps = {
isOpen: boolean
Expand All @@ -15,6 +19,18 @@ export type AccordionSectionProps = {
export const SideBar = observer(() => {
const [openIndex, setOpenIndex] = useState(1)

const isMobile = useMedia('(max-width: 1024px)')

const { isSidebarOpen } = settingStore

const width = useMemo(() => {
if (isMobile) {
return 'w-full'
}

return 'transition-[width] duration-300 ease-in-out ' + (isSidebarOpen ? ' w-[260px]' : ' w-0')
}, [isMobile, isSidebarOpen])

const handleSectionClicked = () => {
// clicking on self or other will open other
setOpenIndex((openIndex + 1) % 2)
Expand All @@ -25,14 +41,29 @@ export const SideBar = observer(() => {
}, [chatStore.selectedChat])

return (
<Accordion
className="flex h-full flex-1 flex-col flex-nowrap gap-2 self-stretch rounded-md bg-base-300 p-2"
onChange={(index: number) => setOpenIndex(index)}
index={openIndex}
>
<ChatSettingsSection isOpen={openIndex === 0} onSectionClicked={handleSectionClicked} />

<ChatListSection isOpen={openIndex === 1} onSectionClicked={handleSectionClicked} />
</Accordion>
<div className={'group/sidebar relative h-full ' + width}>
<Accordion
className={
'flex h-full flex-1 flex-col flex-nowrap gap-2 self-stretch rounded-md bg-base-300 p-2 transition-opacity duration-300 ease-in-out' +
(settingStore.isSidebarOpen || isMobile ? ' opacity-100' : ' opacity-0')
}
onChange={(index: number) => setOpenIndex(index)}
index={openIndex}
>
<ChatSettingsSection isOpen={openIndex === 0} onSectionClicked={handleSectionClicked} />

<ChatListSection isOpen={openIndex === 1} onSectionClicked={handleSectionClicked} />
</Accordion>

<button
className={
'group absolute top-[45%] z-20 opacity-30 transition-all duration-300 ease-in-out hover:opacity-100 group-hover/sidebar:opacity-100' +
(isSidebarOpen ? ' -right-4' : ' -right-8')
}
onClick={settingStore.toggleSidebar}
>
<MediaEject className={'h-8 ' + (isSidebarOpen ? '-rotate-90' : 'rotate-90')} />
</button>
</div>
)
})
17 changes: 17 additions & 0 deletions src/icons/MediaEject.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// https://icon-sets.iconify.design/typcn/media-eject/

// special shoutout to https://yqnn.github.io/svg-path-editor/ which allowed me to split the path

// note: this icon has group based hover code built into it
export default function MediaEject({ className }: { className?: string }) {
return (
<svg xmlns="http://www.w3.org/2000/svg" className={className || 'h-4 w-4'} viewBox="0 0 24 24">
<path
fill="currentColor"
className="opacity-0 transition-all duration-300 ease-in-out group-hover:opacity-100 "
d="m1.433-5.396L12 4l-6.433 6.604A2 2 0 0 0 7 14h10a2 2 0 0 0 1.433-3.396"
/>
<path fill="currentColor" d="M17 16H7a2 2 0 0 0 0 4h10a2 2 0 0 0 0-4" />
</svg>
)
}
5 changes: 5 additions & 0 deletions src/models/SettingStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ export const SettingStore = types
// general settings
theme: types.optional(types.string, '_system'),
pwaNeedsUpdate: types.optional(types.boolean, false),
isSidebarOpen: types.optional(types.boolean, true),

// image generation settings
a1111Enabled: types.maybe(types.boolean),
Expand All @@ -51,6 +52,10 @@ export const SettingStore = types
let updateServiceWorker: undefined | (() => void)

return {
toggleSidebar() {
self.isSidebarOpen = !self.isSidebarOpen
},

openSettingsModal(panelName: SettingPanelOptionsType | 'initial' = 'initial') {
self._settingsPanelName = panelName
},
Expand Down

0 comments on commit 82876f2

Please sign in to comment.