Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(app): add wardrobe panel open/close button #138

Merged
merged 1 commit into from
Feb 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion app/components/header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ export function HeaderLink({ className, ...etc }: LinkProps) {
)
}

export function HeaderActions() {
export function HeaderActions({ children }: PropsWithChildren) {
const matches = useMatches()
const user = useOptionalUser()
const isLoginPage = matches.some(
Expand Down Expand Up @@ -109,6 +109,7 @@ export function HeaderActions() {
</Link>
)}
<ThemeSwitcher />
{children}
</div>
)
}
Expand Down
80 changes: 61 additions & 19 deletions app/routes/_wardrobe.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Outlet, Link, useLoaderData, useFetcher } from '@remix-run/react'
import { type LoaderFunctionArgs, type SerializeFrom } from '@vercel/remix'
import { Minus } from 'lucide-react'
import { Minus, PanelRightClose, PanelRightOpen } from 'lucide-react'
import {
type Dispatch,
type SetStateAction,
Expand All @@ -13,7 +13,11 @@ import { type Product } from 'routes/_wardrobe.products._index'

import { Avatar } from 'components/avatar'
import { Empty } from 'components/empty'
import { Header } from 'components/header'
import {
HeaderWrapper,
HeaderActions,
HeaderBreadcrumbs,
} from 'components/header'
import {
Layout,
LayoutLeft,
Expand Down Expand Up @@ -52,37 +56,75 @@ type ProductsContextT = [Product[], Dispatch<SetStateAction<Product[]>>]
const ProductsContext = createContext<ProductsContextT>([[], () => {}])
export const useProducts = () => useContext(ProductsContext)

type SidebarOpenContextT = [boolean, Dispatch<SetStateAction<boolean>>]
const SidebarOpenContext = createContext<SidebarOpenContextT>([false, () => {}])
const useSidebarOpen = () => useContext(SidebarOpenContext)

// Wardrobe sidebar UI to allow users to save pieces to looks and curate their
// library of saved shows, products, and looks (their "wardrobe" per se).
//
// Right now, this is very rudimentary, but I'm keeping the code paths around as
// they'll probably be a useful starting point for when I spend time to actually
// make this "wardrobe" feature set useful.
//
// Users can always collapse this panel. It will remain collapsed by default and
// the open state will be persisted in localStorage.
export default function WardrobePage() {
const user = useOptionalUser()
const sidebarOpenState = useState(false)
return (
<ProductsContext.Provider value={useState<Product[]>([])}>
<Layout className='h-auto fixed inset-0'>
<LayoutLeft>
<Content />
</LayoutLeft>
{user && (
<>
<LayoutDivider />
<LayoutRight className='flex flex-col'>
<WardrobeHeader />
<Looks />
</LayoutRight>
</>
)}
</Layout>
</ProductsContext.Provider>
<SidebarOpenContext.Provider value={sidebarOpenState}>
<ProductsContext.Provider value={useState<Product[]>([])}>
<Layout className='h-auto fixed inset-0'>
<LayoutLeft>
<Content />
</LayoutLeft>
{sidebarOpenState[0] === true && user != null && (
<>
<LayoutDivider />
<LayoutRight className='flex flex-col'>
<WardrobeHeader />
<Looks />
</LayoutRight>
</>
)}
</Layout>
</ProductsContext.Provider>
</SidebarOpenContext.Provider>
)
}

function Content() {
const user = useOptionalUser()
return (
<main className='h-full flex flex-col overflow-hidden'>
<Header className='flex-none' />
<HeaderWrapper className='flex-none'>
<HeaderBreadcrumbs />
<HeaderActions>{user != null && <SidebarToggleButton />}</HeaderActions>
</HeaderWrapper>
<Outlet />
</main>
)
}

function SidebarToggleButton() {
const [sidebarOpen, setSidebarOpen] = useSidebarOpen()
return (
<Button
size='icon'
variant='ghost'
aria-label={sidebarOpen ? 'Close sidebar' : 'Open sidebar'}
onClick={() => setSidebarOpen((open) => !open)}
>
{sidebarOpen ? (
<PanelRightClose className='w-3 h-3' />
) : (
<PanelRightOpen className='w-3 h-3' />
)}
</Button>
)
}

function WardrobeHeader() {
return (
<header className='p-3 border-b border-gray-200 dark:border-gray-800'>
Expand Down
Loading