Skip to content

Commit

Permalink
refactor: drawer to popover
Browse files Browse the repository at this point in the history
  • Loading branch information
jxom committed Nov 25, 2023
1 parent 9517f94 commit 1aac645
Show file tree
Hide file tree
Showing 11 changed files with 90 additions and 128 deletions.
32 changes: 32 additions & 0 deletions src/app/components/MobileTopNav.css.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
fontWeightVars,
lineHeightVars,
primitiveColorVars,
sidebarVars,
spaceVars,
topNavVars,
viewportVars,
Expand Down Expand Up @@ -135,6 +136,21 @@ export const outlineTrigger = style(
'outlineTrigger',
)

export const outlinePopover = style(
{
display: 'none',
overflowY: 'scroll',
padding: spaceVars['16'],
maxHeight: '80vh',
'@media': {
[viewportVars['max-1080px']]: {
display: 'block',
},
},
},
'outlinePopover',
)

export const section = style({ display: 'flex', height: '100%', gap: spaceVars[16] }, 'section')

export const separator = style(
Expand All @@ -146,6 +162,22 @@ export const separator = style(
'separator',
)

export const sidebarPopover = style(
{
display: 'none',
overflowY: 'scroll',
padding: `${sidebarVars.verticalPadding} ${sidebarVars.horizontalPadding}`,
maxHeight: '80vh',
width: sidebarVars.width,
'@media': {
[viewportVars['max-1080px']]: {
display: 'block',
},
},
},
'sidebarPopover',
)

export const title = style(
{
fontSize: fontSizeVars['18'],
Expand Down
50 changes: 31 additions & 19 deletions src/app/components/MobileTopNav.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
import clsx from 'clsx'
import { type ComponentType, useMemo } from 'react'
import { type ComponentType, useMemo, useState } from 'react'
import { useLocation } from 'react-router-dom'

import type { ParsedSocialItem, Sidebar, SidebarItem } from '../../config.js'
import type * as Config from '../../config.js'
import { useConfig } from '../hooks/useConfig.js'
import { visibleDark, visibleLight } from '../styles/utils.css.js'
import { Icon } from './Icon.js'
import * as styles from './MobileTopNav.css.js'
import { Outline } from './Outline.js'
import { Popover } from './Popover.js'
import { Sidebar } from './Sidebar.js'
import { ChevronRight } from './icons/ChevronRight.js'
import { ChevronUp } from './icons/ChevronUp.js'
import { Discord } from './icons/Discord.js'
Expand Down Expand Up @@ -61,15 +64,15 @@ const iconsForIcon = {
discord: Discord,
github: GitHub,
x: X,
} satisfies Record<ParsedSocialItem['type'], ComponentType>
} satisfies Record<Config.ParsedSocialItem['type'], ComponentType>

const sizesForTypes = {
discord: '21px',
github: '18px',
x: '16px',
} satisfies Record<ParsedSocialItem['type'], string>
} satisfies Record<Config.ParsedSocialItem['type'], string>

function SocialButton({ icon, label, link, type }: ParsedSocialItem) {
function SocialButton({ icon, label, link, type }: Config.ParsedSocialItem) {
return (
<a className={styles.button} href={link} target="_blank" rel="noopener noreferrer">
<Icon
Expand All @@ -84,16 +87,15 @@ function SocialButton({ icon, label, link, type }: ParsedSocialItem) {

export function Curtain({
enableScrollToTop,
MenuTrigger,
OutlineTrigger,
}: {
enableScrollToTop?: boolean
MenuTrigger: React.ElementType
OutlineTrigger: React.ElementType
}) {
const config = useConfig()
const { pathname } = useLocation()

const [isOutlineOpen, setOutlineOpen] = useState(false)
const [isSidebarOpen, setSidebarOpen] = useState(false)

const sidebarItemTitle = useMemo(() => {
if (!config.sidebar) return
const sidebarItem = getSidebarItemFromPathname({
Expand All @@ -114,10 +116,15 @@ export function Curtain({
<div className={styles.curtain}>
<div className={styles.curtainGroup}>
<div className={styles.curtainItem}>
<MenuTrigger className={styles.menuTrigger}>
<Icon label="Menu" icon={Menu} size="13px" />
{title}
</MenuTrigger>
<Popover.Root modal open={isSidebarOpen} onOpenChange={setSidebarOpen}>
<Popover.Trigger className={styles.menuTrigger}>
<Icon label="Menu" icon={Menu} size="13px" />
{title}
</Popover.Trigger>
<Popover className={styles.sidebarPopover}>
<Sidebar onClickItem={() => setSidebarOpen(false)} />
</Popover>
</Popover.Root>
</div>
</div>
<div className={styles.curtainGroup}>
Expand All @@ -137,10 +144,15 @@ export function Curtain({
</>
)}
<div className={styles.curtainItem}>
<OutlineTrigger className={styles.outlineTrigger}>
On this page
<Icon label="On this page" icon={ChevronRight} size="10px" />
</OutlineTrigger>
<Popover.Root modal open={isOutlineOpen} onOpenChange={setOutlineOpen}>
<Popover.Trigger className={styles.outlineTrigger}>
On this page
<Icon label="On this page" icon={ChevronRight} size="10px" />
</Popover.Trigger>
<Popover className={styles.outlinePopover}>
<Outline onClickItem={() => setOutlineOpen(false)} showTitle={false} />
</Popover>
</Popover.Root>
</div>
</div>
</div>
Expand All @@ -150,11 +162,11 @@ export function Curtain({
function getSidebarItemFromPathname({
sidebar,
pathname: pathname_,
}: { sidebar: Sidebar; pathname: string }): SidebarItem {
}: { sidebar: Config.Sidebar; pathname: string }): Config.SidebarItem {
const pathname = pathname_.replace(/(.+)\/$/, '$1')
return sidebar.find((item) => {
if (item.path === pathname) return true
if (item.children) return getSidebarItemFromPathname({ sidebar, pathname })
return false
}) as SidebarItem
}) as Config.SidebarItem
}
1 change: 0 additions & 1 deletion src/app/components/Popover.css.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,5 @@ export const root = style({
border: `1px solid ${primitiveColorVars.border}`,
borderRadius: borderRadiusVars[4],
margin: `0 ${spaceVars[6]}`,
padding: spaceVars[16],
zIndex: zIndexVars.popover,
})
8 changes: 0 additions & 8 deletions src/app/components/Sidebar.css.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,9 @@ import {
} from '../styles/vars.css.js'

export const root = style({
backgroundColor: primitiveColorVars.backgroundDark,
display: 'flex',
flexDirection: 'column',
height: '100vh',
gap: spaceVars['12'],
padding: `${spaceVars['0']} ${sidebarVars.horizontalPadding}`,
width: sidebarVars.width,
'@media': {
'screen and (max-width: 1080px)': {
Expand Down Expand Up @@ -92,11 +89,6 @@ export const navigation = style(
paddingTop: spaceVars['16'],
},
},
'@media': {
[viewportVars['max-1080px']]: {
paddingTop: spaceVars['24'],
},
},
},
'navigation',
)
Expand Down
7 changes: 5 additions & 2 deletions src/app/components/Sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,16 @@ import { Discord } from './icons/Discord.js'
import { GitHub } from './icons/GitHub.js'
import { X } from './icons/X.js'

export function Sidebar({ onClickItem }: { onClickItem?: MouseEventHandler<HTMLAnchorElement> }) {
export function Sidebar({
className,
onClickItem,
}: { className?: string; onClickItem?: MouseEventHandler<HTMLAnchorElement> }) {
const config = useConfig()
const { sidebar } = config

if (!sidebar) return null
return (
<aside className={styles.root}>
<aside className={clsx(styles.root, className)}>
<div className={styles.logo}>
<Link to="/" style={{ alignItems: 'center', display: 'flex', height: '100%' }}>
{config.logoUrl ? (
Expand Down
47 changes: 0 additions & 47 deletions src/app/components/SidebarDrawer.css.ts

This file was deleted.

21 changes: 0 additions & 21 deletions src/app/components/SidebarDrawer.tsx

This file was deleted.

9 changes: 9 additions & 0 deletions src/app/layouts/DocsLayout.css.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,8 @@ export const gutterRight = style(
export const outlinePopover = style(
{
display: 'none',
overflowY: 'scroll',
height: `calc(100vh - ${topNavVars.height} - ${topNavVars.curtainHeight})`,
'@media': {
[viewportVars['max-1080px']]: {
display: 'block',
Expand All @@ -128,6 +130,13 @@ export const outlinePopover = style(
'outlinePopover',
)

export const sidebar = style(
{
padding: `${spaceVars['0']} ${sidebarVars.horizontalPadding}`,
},
'sidebar',
)

export const sidebarDrawer = style(
{
display: 'none',
Expand Down
30 changes: 3 additions & 27 deletions src/app/layouts/DocsLayout.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,18 @@
import { type ReactNode, useState } from 'react'
import type { ReactNode } from 'react'
import { useInView } from 'react-intersection-observer'

import { Content } from '../components/Content.js'
import { DesktopTopNav } from '../components/DesktopTopNav.js'
import { MobileTopNav } from '../components/MobileTopNav.js'
import { Outline } from '../components/Outline.js'
import { Popover } from '../components/Popover.js'
import { Sidebar } from '../components/Sidebar.js'
import { SidebarDrawer } from '../components/SidebarDrawer.js'
import * as styles from './DocsLayout.css.js'

export function DocsLayout({
children,
}: {
children: ReactNode
}) {
const [isOutlineOpen, setOutlineOpen] = useState(false)
const [isSidebarOpen, setSidebarOpen] = useState(false)

const { ref, inView } = useInView({
initialInView: true,
rootMargin: '100px 0px 0px 0px',
Expand All @@ -26,34 +21,15 @@ export function DocsLayout({
return (
<div className={styles.root}>
<div className={styles.gutterLeft}>
<Sidebar />
<Sidebar className={styles.sidebar} />
</div>
<div ref={ref} className={styles.gutterTop}>
<DesktopTopNav />
<MobileTopNav />
</div>
<div className={styles.gutterTopCurtain}>
<DesktopTopNav.Curtain />

<SidebarDrawer.Root open={isSidebarOpen} onOpenChange={setSidebarOpen}>
<Popover.Root open={isOutlineOpen} onOpenChange={setOutlineOpen}>
<MobileTopNav.Curtain
enableScrollToTop={!inView}
MenuTrigger={SidebarDrawer.Trigger}
OutlineTrigger={Popover.Trigger}
/>
<SidebarDrawer className={styles.sidebarDrawer}>
<Sidebar onClickItem={() => setSidebarOpen(false)} />
</SidebarDrawer>
<Popover className={styles.outlinePopover}>
<Outline
onClickItem={() => setOutlineOpen(false)}
highlightActive={false}
showTitle={false}
/>
</Popover>
</Popover.Root>
</SidebarDrawer.Root>
<MobileTopNav.Curtain enableScrollToTop={!inView} />
</div>
<div className={styles.content}>
<Content>{children}</Content>
Expand Down
5 changes: 5 additions & 0 deletions src/app/styles/global.css.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,3 +50,8 @@ globalStyle(`${Content} > *:not(:last-child)`, {
globalStyle(`${Content} > *:last-child`, {
marginBottom: spaceVars['0'],
})

globalStyle('#app[aria-hidden="true"]', {
background: primitiveColorVars.background,
filter: 'brightness(0.5)',
})
Loading

0 comments on commit 1aac645

Please sign in to comment.