diff --git a/js/documentation/pages/_app.tsx b/js/documentation/pages/_app.tsx index 356ec612a1..b7cb23e843 100644 --- a/js/documentation/pages/_app.tsx +++ b/js/documentation/pages/_app.tsx @@ -42,6 +42,7 @@ import MainContent from '@src/components/MainContent' import PageFooter from '@src/components/PageFooter' import { ContentContainer, + MainColumn, PageGrid, SideCarContainer, SideNavContainer, @@ -56,6 +57,7 @@ import { ROOT_TITLE, } from '@src/consts' import { NavDataProvider } from '@src/contexts/NavDataContext' +import { RestNavProvider } from '@src/contexts/RestNavContext' import { collectHeadings } from '@src/markdoc/utils/parseHeadings' import { getNavData } from '@src/NavData' @@ -169,29 +171,35 @@ function App({ Component, pageProps = {}, swrConfig }: MyAppProps) { )} - - - - - - {isClient ? ( - Loading table of contents...}> - - - ) : ( - + + + + + {toc?.length > 0 && ( + + {isClient ? ( + Loading table of contents...} + > + + + ) : ( + + )} + )} - + )} @@ -211,13 +219,15 @@ function App({ Component, pageProps = {}, swrConfig }: MyAppProps) { - - - - {app} - - - + + + + + {app} + + + + diff --git a/js/documentation/src/components/DocsSearch.tsx b/js/documentation/src/components/DocsSearch.tsx new file mode 100644 index 0000000000..28f7ed991c --- /dev/null +++ b/js/documentation/src/components/DocsSearch.tsx @@ -0,0 +1,184 @@ +import { + AiSparkleFilledIcon, + Button, + IconFrame, + SearchIcon, +} from '@pluralsh/design-system' + +import styled from 'styled-components' + +import { mqs } from './Breakpoints' + +function SearchTrigger({ compact = false }: { compact?: boolean }) { + if (compact) { + return ( + } + className="docs-search-trigger" + /> + ) + } + + return ( + + + Search docs... + ⌘K + + ) +} + +function AskAiTrigger({ compact = false }: { compact?: boolean }) { + if (compact) { + return ( + } + className="docs-ai-trigger" + /> + ) + } + + return ( + } + > + Ask AI + + ) +} + +export function DocsSearch() { + return ( + <> + + + + + + + + + + + + + + + ) +} + +const AskAiButton = styled(Button)({ + height: 40, + minHeight: 40, +}) + +const SearchBar = styled.button(({ theme }) => ({ + display: 'flex', + alignItems: 'center', + gap: theme.spacing.small, + width: 220, + [mqs.threeColumn]: { + width: 360, + maxWidth: '32vw', + }, + height: 40, + padding: `0 ${theme.spacing.xsmall}px 0 ${theme.spacing.medium}px`, + border: theme.borders.input, + borderRadius: theme.borderRadiuses.medium, + background: theme.colors['fill-one'], + color: theme.colors['text-xlight'], + cursor: 'pointer', + ...theme.partials.text.body2, + '.searchIcon': { + flexShrink: 0, + color: theme.colors['text-light'], + }, + '.placeholder': { + flex: 1, + minWidth: 0, + textAlign: 'left', + overflow: 'hidden', + textOverflow: 'ellipsis', + whiteSpace: 'nowrap', + }, + '&:hover': { + background: theme.colors['fill-one-hover'], + color: theme.colors['text-light'], + }, + '&:focus, &:focus-visible': { + outline: 'none', + }, + '&:focus-visible': { + ...theme.partials.focus.default, + }, +})) + +const Kbd = styled.span(({ theme }) => ({ + ...theme.partials.text.caption, + display: 'inline-flex', + alignItems: 'center', + justifyContent: 'center', + flexShrink: 0, + minWidth: 28, + height: 22, + padding: `0 ${theme.spacing.xsmall}px`, + borderRadius: theme.borderRadiuses.medium, + background: theme.colors['fill-two'], + color: theme.colors['text-xlight'], +})) + +const CenterCluster = styled.div(({ theme }) => ({ + display: 'none', + [mqs.fullHeader]: { + display: 'flex', + alignItems: 'center', + gap: theme.spacing.small, + position: 'absolute', + left: '50%', + top: '50%', + transform: 'translate(-50%, -50%)', + zIndex: 1, + }, +})) + +const ToolbarCluster = styled.div(({ theme }) => ({ + display: 'flex', + alignItems: 'center', + gap: theme.spacing.xsmall, + [mqs.fullHeader]: { + display: 'none', + }, +})) + +const WideAskAi = styled.div({ + display: 'none', + [mqs.threeColumn]: { + display: 'block', + }, +}) + +const NarrowAskAi = styled.div({ + display: 'block', + [mqs.threeColumn]: { + display: 'none', + }, +}) diff --git a/js/documentation/src/components/ExternalScripts.tsx b/js/documentation/src/components/ExternalScripts.tsx index daad5052d6..0d6b7ce632 100644 --- a/js/documentation/src/components/ExternalScripts.tsx +++ b/js/documentation/src/components/ExternalScripts.tsx @@ -102,13 +102,27 @@ function KapaWidget() { src="https://widget.kapa.ai/kapa-widget.bundle.js" data-website-id="8288b978-8aca-4409-9cbd-de12c446cf07" data-project-name="Plural" - data-view-mode="sidebar" + data-view-mode="default" + data-button-hide="true" + data-launcher-button-hidden="true" data-modal-open-on-command-k="true" + data-modal-command-k-search-mode-default="true" data-search-mode-enabled="true" + data-modal-override-open-selector-search=".docs-search-trigger" + data-modal-override-open-selector=".docs-ai-trigger" data-mcp-enabled="true" data-mcp-server-url="https://plural.mcp.kapa.ai" data-project-color="#5D63F4" data-project-logo="https://docs.plural.sh/favicon-192.png" + data-kapa-branding-hidden="true" + data-color-scheme="dark" + data-surface-color-dark="#12151B" + data-surface-elevated-color-dark="#1B1F27" + data-surface-hover-color-dark="#252932" + data-text-color-dark="#EEF0F1" + data-text-muted-color-dark="#A1A5B0" + data-border-color-dark="#303540" + data-anchor-color-dark="#5D63F4" /> ) } diff --git a/js/documentation/src/components/FullNav.tsx b/js/documentation/src/components/FullNav.tsx index 77473face1..14bd00cdb0 100644 --- a/js/documentation/src/components/FullNav.tsx +++ b/js/documentation/src/components/FullNav.tsx @@ -72,6 +72,8 @@ export const NavButtons = styled(NavButtonsUnstyled)<{ desktop: boolean }>( export const NavWrap = styled.div((_) => ({ position: 'relative', flexGrow: 1, + flex: 1, + minHeight: 0, })) function NavButton({ @@ -102,7 +104,7 @@ export function FullNav({ const previousPath = usePrevious(thisPath) useEffect(() => { - if (thisPath !== previousPath) { + if (previousPath && thisPath !== previousPath) { if (setIsOpen) { setIsOpen(false) } diff --git a/js/documentation/src/components/GlobalStyles.tsx b/js/documentation/src/components/GlobalStyles.tsx index 2f7704bf84..b74c552985 100644 --- a/js/documentation/src/components/GlobalStyles.tsx +++ b/js/documentation/src/components/GlobalStyles.tsx @@ -22,6 +22,8 @@ const GlobalStyles = createGlobalStyle(({ theme }) => ({ ':root': { '--top-nav-height': '72px', '--menu-extra-bpad': '0px', + '--docs-sidenav-width': '306px', + '--docs-sidecar-width': '220px', }, 'a:any-link': { color: 'unset', @@ -39,7 +41,7 @@ const GlobalStyles = createGlobalStyle(({ theme }) => ({ }, body: { margin: 0, - overflowX: 'hidden', + overflowX: 'clip', color: theme.colors.text, backgroundColor: theme.colors['fill-zero'], ...fillAvailable('minHeight'), diff --git a/js/documentation/src/components/MainContent.tsx b/js/documentation/src/components/MainContent.tsx index e2f32fbdc2..9f90a194c2 100644 --- a/js/documentation/src/components/MainContent.tsx +++ b/js/documentation/src/components/MainContent.tsx @@ -15,12 +15,21 @@ import Breadcrumbs from './Breadcrumbs' import { FooterLink } from './PageFooter' import { PagePropsContext } from './PagePropsContext' -const ContentWrapper = styled.div(({ theme }) => ({ - marginTop: theme.spacing.xlarge, +const ContentWrapper = styled.div((_) => ({ + minWidth: 0, })) const BreadcrumbsWrapper = styled.div(({ theme }) => ({ - marginTop: theme.spacing.xlarge, + display: 'flex', + alignItems: 'center', + width: '100%', + minWidth: 0, + minHeight: 40, + marginBottom: theme.spacing.large, + '& > *': { + minWidth: 0, + width: '100%', + }, })) const Title = styled.h1(({ theme }) => ({ diff --git a/js/documentation/src/components/MobileMenu.tsx b/js/documentation/src/components/MobileMenu.tsx index 4ed11f12be..c9909f450d 100644 --- a/js/documentation/src/components/MobileMenu.tsx +++ b/js/documentation/src/components/MobileMenu.tsx @@ -1,15 +1,19 @@ -import { DiscordIcon } from '@pluralsh/design-system' +import { useRef, useState } from 'react' + +import { ArrowLeftIcon, Button, DiscordIcon } from '@pluralsh/design-system' import styled from 'styled-components' import { useIsomorphicLayoutEffect } from 'usehooks-ts' import { DISCORD_LINK } from '@src/consts' +import { useRestNav } from '@src/contexts/RestNavContext' -import { FullNav, type NavContextValue } from './FullNav' +import { FullNav, NavButtons, type NavContextValue } from './FullNav' import GithubStars from './GithubStars' import useScrollLock from './hooks/useScrollLock' import { MainLink } from './PageHeader' import { SocialLink } from './PageHeaderButtons' +import { SidebarNav } from './RestApiReference/SidebarNav' import { TopHeading } from './SideNav' type MobileMenuProps = NavContextValue & { @@ -73,6 +77,20 @@ export const PluralMenu = styled(PluralMenuContent)( }) ) +const Panel = styled.div<{ $hidden: boolean }>(({ $hidden }) => ({ + display: $hidden ? 'none' : 'flex', + flexDirection: 'column', + flex: 1, + minHeight: 0, +})) + +const DocsNavWrap = styled.div({ + display: 'flex', + flexDirection: 'column', + flex: 1, + minHeight: 0, +}) + const Content = styled.div(({ theme }) => ({ pointerEvents: 'all', position: 'absolute', @@ -84,23 +102,66 @@ const Content = styled.div(({ theme }) => ({ background: theme.colors['fill-one'], display: 'flex', flexDirection: 'column', + minHeight: 0, + overflow: 'hidden', + [`${NavButtons}`]: { + position: 'relative', + zIndex: 1, + flexShrink: 0, + }, })) function MobileMenu({ isOpen, setIsOpen, className }: MobileMenuProps) { const [, setScrollLock] = useScrollLock(false) + const restNav = useRestNav() + const [showDocsMenu, setShowDocsMenu] = useState(false) useIsomorphicLayoutEffect(() => { setScrollLock(isOpen) }, [isOpen, setScrollLock]) + const wasOpen = useRef(isOpen) + + useIsomorphicLayoutEffect(() => { + if (isOpen && !wasOpen.current) { + setShowDocsMenu(false) + } + wasOpen.current = isOpen + }, [isOpen]) + + const showRestNav = !!restNav && !showDocsMenu + return (
- + {restNav && ( + + + + + + + )} + + + + +
) diff --git a/js/documentation/src/components/PageGrid.tsx b/js/documentation/src/components/PageGrid.tsx index e34243bb9a..d8493a92dd 100644 --- a/js/documentation/src/components/PageGrid.tsx +++ b/js/documentation/src/components/PageGrid.tsx @@ -2,23 +2,37 @@ import styled from 'styled-components' import { mqs } from './Breakpoints' -export const PageGrid = styled.div((_p) => ({ - display: 'flex', - flexDirection: 'row', +export const PageGrid = styled.div({ + display: 'grid', + gridTemplateColumns: 'minmax(0, 1fr)', width: '100%', - maxWidth: 1588, - marginLeft: 'auto', - marginRight: 'auto', - position: 'relative', -})) + minHeight: 'calc(100vh - var(--top-nav-height))', + [mqs.twoColumn]: { + gridTemplateColumns: 'var(--docs-sidenav-width) minmax(0, 1fr)', + }, +}) export const SideNavContainer = styled.div(({ theme }) => ({ display: 'none', [mqs.twoColumn]: { display: 'block', - flex: '0 0 300px', - marginRight: 'auto', - marginLeft: theme.spacing.large, + minWidth: 0, + backgroundColor: theme.colors['fill-one'], + }, +})) + +export const MainColumn = styled.div(({ theme }) => ({ + display: 'flex', + justifyContent: 'center', + alignItems: 'flex-start', + minWidth: 0, + width: '100%', + padding: `0 ${theme.spacing.large}px`, + [mqs.twoColumn]: { + padding: `0 ${theme.spacing.xlarge}px`, + }, + [mqs.maxWidth]: { + padding: '0 64px', }, })) @@ -27,25 +41,38 @@ export const SideCarContainer = styled.div(({ theme }) => ({ [mqs.threeColumn]: { position: 'sticky', - marginRight: theme.spacing.large, top: 'var(--top-nav-height)', - bottom: 0, + alignSelf: 'flex-start', + flex: '0 0 var(--docs-sidecar-width)', + width: 'var(--docs-sidecar-width)', maxHeight: 'calc(100vh - var(--top-nav-height))', - flex: '0 0 200px', + overflow: 'auto', display: 'block', - }, -})) - -export const ContentContainer = styled.main(({ theme }) => ({ - flex: '1 1', - marginRight: theme.spacing.large, - marginLeft: theme.spacing.large, - // Don't remove this min width, or it will paradoxically allow - // the content to stretch wider than the flex container - minWidth: '100px', - [mqs.threeColumn]: { - maxWidth: 896, - marginRight: theme.spacing.xlarge, marginLeft: theme.spacing.xlarge, }, })) + +export const ContentContainer = styled.main<{ $wide?: boolean }>( + ({ theme, $wide }) => ({ + flex: '1 1 auto', + minWidth: 0, + width: '100%', + padding: `${theme.spacing.medium}px 0 ${theme.spacing.xxxlarge}px`, + ...(!$wide + ? { + maxWidth: 896, + [mqs.threeColumn]: { + maxWidth: 960, + }, + [mqs.maxWidth]: { + maxWidth: 1120, + }, + } + : { + maxWidth: 1120, + [mqs.maxWidth]: { + maxWidth: 1280, + }, + }), + }) +) diff --git a/js/documentation/src/components/PageHeader.tsx b/js/documentation/src/components/PageHeader.tsx index c431373c38..a2b724c3c6 100644 --- a/js/documentation/src/components/PageHeader.tsx +++ b/js/documentation/src/components/PageHeader.tsx @@ -8,8 +8,10 @@ import { useKey } from 'rooks' import styled from 'styled-components' import { DISCORD_LINK } from '@src/consts' +import { getBarePathFromPath } from '@src/utils/text' import { BreakpointIsGreaterOrEqual, mqs, useBreakpoint } from './Breakpoints' +import { DocsSearch } from './DocsSearch' import GithubStars from './GithubStars' import MobileMenu from './MobileMenu' import { HamburgerButton, SocialLink } from './PageHeaderButtons' @@ -20,8 +22,9 @@ const Filler = styled.div((_) => ({ function PageHeaderUnstyled({ ...props }) { const [menuIsOpen, setMenuIsOpen] = useState(false) - const { pathname } = useRouter() - const prevPathname = usePrevious(pathname) + const { asPath } = useRouter() + const thisPath = getBarePathFromPath(asPath) + const prevPath = usePrevious(thisPath) const breakpoint = useBreakpoint() @@ -32,10 +35,10 @@ function PageHeaderUnstyled({ ...props }) { }, [breakpoint]) useEffect(() => { - if (pathname !== prevPathname) { + if (prevPath && thisPath !== prevPath) { setMenuIsOpen(false) } - }, [pathname, prevPathname]) + }, [thisPath, prevPath]) useKey(['Escape'], () => { setMenuIsOpen(false) @@ -59,6 +62,7 @@ function PageHeaderUnstyled({ ...props }) {
+
({ display: 'flex', alignItems: 'center', justifyContent: 'left', - paddingLeft: theme.spacing.large, + paddingLeft: 40, paddingRight: theme.spacing.large, + borderBottom: theme.borders['fill-one'], [mqs.fullHeader]: { - paddingLeft: 40, + paddingLeft: 0, paddingRight: 40, }, '.socialIcons': { display: 'none', - [mqs.fullHeader]: { + [mqs.maxWidth]: { display: 'flex', flexDirection: 'row', gap: theme.spacing.medium, @@ -136,11 +141,20 @@ const PageHeader = styled(PageHeaderUnstyled)(({ theme }) => ({ }, '.logo': { width: 162, + maxWidth: '100%', + minWidth: 0, + display: 'block', + }, + '.leftSection': { + display: 'flex', + alignItems: 'center', + gap: theme.spacing.medium, [mqs.fullHeader]: { - // width: 216, + paddingLeft: 40, + paddingRight: theme.spacing.large, }, }, - '.rightSection, .leftSection': { + '.rightSection': { display: 'flex', alignItems: 'center', gap: theme.spacing.medium, @@ -171,7 +185,7 @@ const PageHeaderLinks = styled(({ ...props }) => (
))(({ theme }) => ({ display: 'none', - [mqs.fullHeader]: { + [mqs.threeColumn]: { display: 'flex', gap: theme.spacing.xsmall, }, diff --git a/js/documentation/src/components/PageHeaderButtons.tsx b/js/documentation/src/components/PageHeaderButtons.tsx index e3d532c18c..93b50be4a1 100644 --- a/js/documentation/src/components/PageHeaderButtons.tsx +++ b/js/documentation/src/components/PageHeaderButtons.tsx @@ -38,6 +38,7 @@ export const SocialLink = styled(ButtonFillTwo)(({ theme }) => ({ export const HamburgerButtonWrap = styled(ButtonFillTwo)((_) => ({ width: 40, height: 40, + flexShrink: 0, alignItems: 'center', justifyContent: 'center', [mqs.fullHeader]: { @@ -50,7 +51,10 @@ export function HamburgerButton({ ...props }: { isOpen: boolean } & ComponentPropsWithoutRef<'a'>) { return ( - + {!isOpen && } {isOpen && } diff --git a/js/documentation/src/components/RestApiReference/RestApiReference.styles.ts b/js/documentation/src/components/RestApiReference/RestApiReference.styles.ts index f910316297..5b9a4c8f3d 100644 --- a/js/documentation/src/components/RestApiReference/RestApiReference.styles.ts +++ b/js/documentation/src/components/RestApiReference/RestApiReference.styles.ts @@ -2,14 +2,21 @@ import styled from 'styled-components' // ─── Content layout (uses shared PageGrid from PageGrid.tsx) ─────────────────── -export const RestContentWrapper = styled.div(({ theme }) => ({ - marginTop: theme.spacing.xlarge, - padding: `0 ${theme.spacing.xlarge}px`, +export const RestContentWrapper = styled.div((_) => ({ + minWidth: 0, })) export const BreadcrumbsWrapper = styled.div(({ theme }) => ({ - marginTop: theme.spacing.xlarge, + display: 'flex', + alignItems: 'center', + width: '100%', + minWidth: 0, + minHeight: 40, marginBottom: theme.spacing.large, + '& > *': { + minWidth: 0, + width: '100%', + }, })) export const ContentGrid = styled.div(({ theme }) => ({ diff --git a/js/documentation/src/components/RestApiReference/SidebarNav.tsx b/js/documentation/src/components/RestApiReference/SidebarNav.tsx index 6d8f78f00f..6b7e4b1dec 100644 --- a/js/documentation/src/components/RestApiReference/SidebarNav.tsx +++ b/js/documentation/src/components/RestApiReference/SidebarNav.tsx @@ -5,6 +5,7 @@ import { useMemo, useState } from 'react' +import { Input2, SearchIcon } from '@pluralsh/design-system' import NextLink from 'next/link' import isEmpty from 'lodash/isEmpty' @@ -14,62 +15,60 @@ import { MethodBadge } from './MethodBadge' import type { ApiSection, Endpoint } from '@src/lib/openapi-rest' -const Sidebar = styled.aside(({ theme: _theme }) => ({ - position: 'sticky', - top: 'var(--top-nav-height)', - height: 'calc(100vh - var(--top-nav-height))', - width: 300, - flexShrink: 0, +const Sidebar = styled.aside<{ $overlay?: boolean }>(({ $overlay }) => ({ display: 'flex', flexDirection: 'column', overflow: 'hidden', + width: '100%', + ...($overlay + ? { + flex: 1, + minHeight: 0, + position: 'relative', + } + : { + position: 'sticky', + top: 'var(--top-nav-height)', + height: 'calc(100vh - var(--top-nav-height))', + flexShrink: 0, + }), })) -const SidebarInner = styled.div(({ theme }) => ({ - position: 'absolute', - top: 0, - left: 0, - right: 0, - bottom: 0, - overflowY: 'auto', - backgroundColor: theme.colors['fill-one'], - borderRight: theme.borders.default, - paddingBottom: theme.spacing.xlarge, -})) +const SidebarInner = styled.div<{ $overlay?: boolean }>( + ({ theme, $overlay }) => ({ + overflowY: 'auto', + backgroundColor: theme.colors['fill-one'], + borderRight: $overlay ? 'none' : theme.borders['fill-one'], + paddingBottom: theme.spacing.xlarge, + paddingLeft: theme.spacing.medium, + paddingRight: theme.spacing.medium, + ...($overlay + ? { + flex: 1, + minHeight: 0, + position: 'relative', + } + : { + position: 'absolute', + top: 0, + left: 0, + right: 0, + bottom: 0, + }), + }) +) const SearchWrapper = styled.div(({ theme }) => ({ - padding: `${theme.spacing.medium}px ${theme.spacing.medium}px`, + padding: `${theme.spacing.medium}px 0`, position: 'sticky', top: 0, backgroundColor: theme.colors['fill-one'], zIndex: 1, })) -const SearchInput = styled.div(({ theme }) => ({ - display: 'flex', - alignItems: 'center', - gap: theme.spacing.small, - background: theme.colors['fill-two'] ?? theme.colors['fill-zero'], - border: theme.borders.default, - borderRadius: theme.borderRadiuses.medium, - padding: `${theme.spacing.xsmall}px ${theme.spacing.medium}px`, - '&:focus-within': { - borderColor: theme.colors['border-primary'], - }, - '.icon': { - color: theme.colors['text-xlight'], - flexShrink: 0, - }, - input: { - flex: 1, - background: 'transparent', - border: 'none', - outline: 'none', - color: theme.colors.text, - ...theme.partials.text.body2, - '::placeholder': { color: theme.colors['text-xlight'] }, - }, -})) +const FilterInput = styled(Input2)({ + width: '100%', +}) const SectionGroup = styled.div(({ theme }) => ({ display: 'block', @@ -94,7 +93,7 @@ const EndpointLabel = styled.span(({ theme }) => ({ textOverflow: 'ellipsis', whiteSpace: 'nowrap', ...theme.partials.text.body2, - color: theme.colors['text-light'], + color: theme.colors['text-xlight'], })) const EndpointRowLink = styled(NextLink)<{ $active: boolean }>( @@ -110,10 +109,7 @@ const EndpointRowLink = styled(NextLink)<{ $active: boolean }>( textAlign: 'left', textDecoration: 'none', color: 'inherit', - borderStartStartRadius: theme.borderRadiuses.medium, - borderEndStartRadius: theme.borderRadiuses.medium, - borderStartEndRadius: 0, - borderEndEndRadius: 0, + borderRadius: theme.borderRadiuses.medium, backgroundColor: $active ? theme.colors['action-primary'] : 'transparent', '&:hover': { backgroundColor: $active @@ -126,32 +122,6 @@ const EndpointRowLink = styled(NextLink)<{ $active: boolean }>( }) ) -function SearchIcon() { - return ( - - - - - ) -} - export const AUTH_PAGE_ID = '__authentication__' const TopNavItemLink = styled(NextLink)<{ $active: boolean }>( @@ -167,12 +137,9 @@ const TopNavItemLink = styled(NextLink)<{ $active: boolean }>( cursor: 'pointer', textAlign: 'left', textDecoration: 'none', - borderStartStartRadius: theme.borderRadiuses.medium, - borderEndStartRadius: theme.borderRadiuses.medium, - borderStartEndRadius: 0, - borderEndEndRadius: 0, + borderRadius: theme.borderRadiuses.medium, backgroundColor: $active ? theme.colors['action-primary'] : 'transparent', - color: $active ? theme.colors.text : theme.colors['text-light'], + color: $active ? theme.colors.text : theme.colors['text-xlight'], '&:hover': { backgroundColor: $active ? theme.colors['action-primary-hover'] @@ -191,9 +158,11 @@ const TopNavDivider = styled.hr(({ theme }) => ({ export function SidebarNav({ sections, selectedId, + overlay = false, }: { sections: ApiSection[] selectedId: string + overlay?: boolean }) { const [filter, setFilter] = useState('') @@ -220,24 +189,16 @@ export function SidebarNav({ const showAuthItem = !filter return ( - - + + - - - - - setFilter(e.target.value)} - aria-label="Filter API endpoints" - /> - + } + value={filter} + onChange={(e) => setFilter(e.currentTarget.value)} + inputProps={{ 'aria-label': 'Filter API endpoints' }} + />