nextui/apps/docs/components/navbar.tsx
Junior Garcia 7abd68941a
v2.2.0 🕹️ (#1777)
* feat: Slider Component (#1686)

* feat(slider): initial structure

* chore(slider): readme improved

* fix: fixed border color of slider track

* docs: added range story

* feat: added rtl support to slider

* feat: improved value label formatting

* feat: refactor styling and add colors support to slider

* chore: improved thumb color

* docs: improved slider stories

* chore(slider): default color changed by foreground

* Update packages/core/theme/src/components/slider.ts

Co-authored-by: Jakob Guddas <github@jguddas.de>

* feat: added fillOffset prop

* Update packages/components/slider/src/use-slider.ts

* fix(slider): animation

* Update packages/components/slider/src/use-slider.ts

* Update packages/core/theme/src/components/slider.ts

* feat: slider steps

* refactor: renamed variables

* feat: improved slider step styling

* fix: hide infinite steps

* fix: fixed step transparency issue

* fix: fixed thumb focus issue

* Update packages/components/slider/src/use-slider.ts

Co-authored-by: Junior Garcia <jrgarciadev@gmail.com>

* feat(slider): vertical orientation added, start & end content, bug fixes

* chore(slider): tests added

* fix(docs): scrollbar added to the sidebar (#1743)

* feat(slider): marks added

* chore(slider): example ts-doc changed

* feat(slider): vertical marks support

* feat(core): slider tooltip support added, popover modified (#1746)

* Feat/slider custom styles (#1751)

* feat(slider): custom styles story added

* fix(slider): custom styles on different sizes

* Fix/slider tooltip android position (#1753)

* feat(slider): custom styles story added

* fix(slider): tooltip update position dependecies added

* fix(popover): arrow placements improved

* feat(slider): docs started, custom thumb and custom output stories added

* feat(slider): render function added to custom render the slider parts

* feat(slider): docs in progress, new properties and examples added

* fix(slider): some issues fixed, output renamed to value, documentation improved

* feat(slider): docs done

* chore: changeset

---------

Co-authored-by: Jakob Guddas <github@jguddas.de>

* Client side routing (#1764)

* feat(slider): initial structure

* chore(slider): readme improved

* fix: fixed border color of slider track

* docs: added range story

* feat: added rtl support to slider

* feat: improved value label formatting

* feat: refactor styling and add colors support to slider

* chore: improved thumb color

* docs: improved slider stories

* chore(slider): default color changed by foreground

* Update packages/core/theme/src/components/slider.ts

Co-authored-by: Jakob Guddas <github@jguddas.de>

* feat: added fillOffset prop

* Update packages/components/slider/src/use-slider.ts

* fix(slider): animation

* Update packages/components/slider/src/use-slider.ts

* Update packages/core/theme/src/components/slider.ts

* feat: slider steps

* refactor: renamed variables

* feat: improved slider step styling

* fix: hide infinite steps

* fix: fixed step transparency issue

* fix: fixed thumb focus issue

* Update packages/components/slider/src/use-slider.ts

Co-authored-by: Junior Garcia <jrgarciadev@gmail.com>

* feat(slider): vertical orientation added, start & end content, bug fixes

* chore(slider): tests added

* feat(slider): marks added

* chore(slider): example ts-doc changed

* feat(slider): vertical marks support

* feat(core): slider tooltip support added, popover modified (#1746)

* Feat/slider custom styles (#1751)

* feat(slider): custom styles story added

* fix(slider): custom styles on different sizes

* Fix/slider tooltip android position (#1753)

* feat(slider): custom styles story added

* fix(slider): tooltip update position dependecies added

* fix(popover): arrow placements improved

* feat(slider): docs started, custom thumb and custom output stories added

* feat(slider): render function added to custom render the slider parts

* feat(slider): docs in progress, new properties and examples added

* fix(slider): some issues fixed, output renamed to value, documentation improved

* feat(slider): docs done

* chore: changeset

* chore: react aria packages upgraded

* feat(system): router provider added

* feat: client side routing support added to items components

* chore(docs): routing docs started

* chore: changeset

* feat(docs): client side routing documented

* feat(pagination): client router support added to pagination

* fix(link): csr added

---------

Co-authored-by: Jakob Guddas <github@jguddas.de>

* feat: added RTL support to accordion component (#1725)

* feat: added RTL support to accordion component

* Create healthy-cobras-crash.md

* feat: added RTL support to avatar and avatar group component (#1727)

* feat: added RTL support to avatar and avatar group components

* Create tender-penguins-love.md

* Update tender-penguins-love.md

* feat: added RTL support to button group component (#1726)

* feat: added RTL support to button component

* feat: added RTL support to button component

* Create orange-bobcats-kneel.md

* Update button.ts

* refactor(root): styles refactor (#1688)

* refactor(root): styles refactor

* chore(tabs): remove needless type extends

* fix(tabs): typecheck

* Breadcrumbs component (#1794)

* feat(components): breadcrumbs initial structure

* feat(breadcrumbs): tests and examples added

* feat(docs): breadcrumbs documentation done

* feat(docs): breadcrumbs docs done

* chore(breadcrumbs): readme changed

* fix(slider): Place last dragged slider handle over the other handle (#1778)

* Set `data-focused` in handle

* Style focused handle on top

* Add tests

* fix(core): tests and build

* fix(button): show only spinner if button isLoading & isIconOnly (#1800)

* fix(button): show only spinner if button isLoading & isIconOnly

* chore: add changeset

* fix(button): remove repeating code

* Fix blur/opaque Popover (#1812)

* fix(popover): double underlay click

* chore: use ref instead of a state

* Feat/controlled scroll shadow (#1819)

* feat(scroll-shadow): logic improved, controlled support added

* feat(scroll-shadow): controlled visibility

* fix(scroll-shadow): visibility tests

* Autocomplete component (Single Selection) (#1797)

* feat(autocomplete): initial structure

* feat(core): use press custom hook implemented, autocomplete improved, input and select animations fixed

* chore(button): add console.log on press

* feat(core): select & input label position, autocomplete improvements, listbox and menu empty state

* chore: tailwind-variants upgraded

* chore: autocomplete stories in progress

* fix: input and select label placement

* fix(autocomplete): popover trigger

* chore(root): react-aria pkgs and framer-motion upgraded

* fix(input,select): outside label scale removed

* feat(autocomplete): more stories and use cases supported

* fix(core): custom items support on collection-based comps, menu generic items support added

* chore(core): tailwind-variants upgraded, custom tv function adapted

* chore(docs): select on-change controlled e.g. changed, sandpack theme fixed

* chore(autocomplete): docs started, tests added

* chore: in progress

* feat(menu): top and end content added, autocomplete docs improved

* feat(docs): autocomplete documentation almost done

* fix(input): outside styles

* feat(docs): autocomplete async filtering added

* chore(docs): autocomplete highlighted lines added

* feat(docs): autocomplete a11y and slots added

* feat(docs): autocomplete a11y and slots added

* feat(docs): autocomplete docs done

* fix(root): peer dependencies (#1848)

* Fix/small issues (#1851)

* fix(input): visible outline

* fix(button): button group radius prop

* chore(navbar): menu item active status added

* fix(docs): pagination missing keys custom items

* fix(core): extendVariants support added to collection-based components

* fix(theme): card body padding

* chore(theme): transition added to menu/listbox items

* fix(input): textarea styles fixed, new prop added

* chore(input): textarea height animated

* feat(button): hover opacity added

* chore(textarea): hide scroll when the limit hasn't been reached

* chore(docs): updated badge added to textarea

* feat(docs): blog v2.2.0 image and entry added

* fix(avatar): ring primary color

* chore(docs): tabs added again, autocomplete iframes removed

---------

Co-authored-by: Jakob Guddas <github@jguddas.de>
Co-authored-by: Maurici Abad Gutierrez <hello@mauriciabad.com>
Co-authored-by: Ivan Kucher <dev.kucher@gmail.com>
2023-11-03 11:05:16 -03:00

360 lines
11 KiB
TypeScript

"use client";
import {useRef, useState, FC, ReactNode, Key} from "react";
import {
link,
Navbar as NextUINavbar,
NavbarContent,
NavbarMenu,
NavbarMenuToggle,
NavbarBrand,
NavbarItem,
Link,
Button,
Kbd,
Dropdown,
DropdownMenu,
DropdownItem,
DropdownTrigger,
Chip,
} from "@nextui-org/react";
import {dataFocusVisibleClasses} from "@nextui-org/theme";
import {ChevronDownIcon, LinkIcon} from "@nextui-org/shared-icons";
import {isAppleDevice} from "@react-aria/utils";
import {clsx} from "@nextui-org/shared-utils";
import NextLink from "next/link";
import {usePathname} from "next/navigation";
import {includes} from "lodash";
import {motion, AnimatePresence} from "framer-motion";
import {useEffect} from "react";
import {usePress} from "@react-aria/interactions";
import {useFocusRing} from "@react-aria/focus";
import {currentVersion} from "@/utils/version";
import {siteConfig} from "@/config/site";
import {Route} from "@/libs/docs/page";
import {LargeLogo, SmallLogo, ThemeSwitch} from "@/components";
import {
TwitterIcon,
GithubIcon,
DiscordIcon,
HeartFilledIcon,
SearchLinearIcon,
} from "@/components/icons";
import {useIsMounted} from "@/hooks/use-is-mounted";
import {DocsSidebar} from "@/components/docs/sidebar";
import {useCmdkStore} from "@/components/cmdk";
import {trackEvent} from "@/utils/va";
export interface NavbarProps {
routes: Route[];
mobileRoutes?: Route[];
tag?: string;
slug?: string;
children?: ReactNode;
}
export const Navbar: FC<NavbarProps> = ({children, routes, mobileRoutes = [], slug, tag}) => {
const [isMenuOpen, setIsMenuOpen] = useState<boolean | undefined>(false);
const [commandKey, setCommandKey] = useState<"ctrl" | "command">("command");
const ref = useRef<HTMLElement>(null);
const isMounted = useIsMounted();
const pathname = usePathname();
const cmdkStore = useCmdkStore();
useEffect(() => {
if (isMenuOpen) {
setIsMenuOpen(false);
}
}, [pathname]);
useEffect(() => {
setCommandKey(isAppleDevice() ? "command" : "ctrl");
}, []);
const handleOpenCmdk = () => {
cmdkStore.onOpen();
trackEvent("Navbar - Search", {
name: "navbar - search",
action: "press",
category: "cmdk",
});
};
const {pressProps} = usePress({
onPress: handleOpenCmdk,
});
const {focusProps, isFocusVisible} = useFocusRing();
const docsPaths = [
"/docs/guide/introduction",
"/docs/guide/installation",
"/docs/guide/upgrade-to-v2",
];
const searchButton = (
<Button
aria-label="Quick search"
className="text-sm font-normal text-default-500 bg-default-400/20 dark:bg-default-500/20"
endContent={
<Kbd className="hidden py-0.5 px-2 lg:inline-block" keys={commandKey}>
K
</Kbd>
}
startContent={
<SearchLinearIcon
className="text-base text-default-400 pointer-events-none flex-shrink-0"
size={18}
strokeWidth={2}
/>
}
onPress={handleOpenCmdk}
>
Quick Search...
</Button>
);
if (pathname.includes("/examples")) {
return null;
}
const navLinkClasses = clsx(link({color: "foreground"}), "data-[active=true]:text-primary");
const handleVersionChange = (key: Key) => {
if (key === "v1") {
const newWindow = window.open("https://v1.nextui.org", "_blank", "noopener,noreferrer");
if (newWindow) newWindow.opener = null;
}
};
const handlePressNavbarItem = (name: string, url: string) => {
trackEvent("NavbarItem", {
name,
action: "press",
category: "navbar",
data: url,
});
};
return (
<NextUINavbar
ref={ref}
className={clsx({
"z-[100001]": isMenuOpen,
})}
isMenuOpen={isMenuOpen}
maxWidth="xl"
position="sticky"
onMenuOpenChange={setIsMenuOpen}
>
<NavbarContent className="basis-1/5 sm:basis-full" justify="start">
<NavbarBrand as="li" className="gap-3 max-w-fit">
<NextLink
aria-label="Home"
className="flex justify-start items-center gap-2 tap-highlight-transparent transition-opacity active:opacity-50"
href="/"
onClick={() => handlePressNavbarItem("Home", "/")}
>
<SmallLogo className="w-6 h-6 md:hidden" />
<LargeLogo className="h-5 md:h-6" />
</NextLink>
{ref.current ? (
<Dropdown placement="bottom-start" portalContainer={ref.current}>
<AnimatePresence>
{isMounted && (
<motion.div animate={{opacity: 1}} exit={{opacity: 0}} initial={{opacity: 0}}>
<DropdownTrigger>
<Button
className="hidden text-xs h-6 w-[74px] py-1 min-w-fit sm:flex gap-0.5 bg-default-400/20 dark:bg-default-500/20"
endContent={<ChevronDownIcon className="text-tiny" />}
radius="full"
size="sm"
variant="flat"
>
v{currentVersion}
</Button>
</DropdownTrigger>
</motion.div>
)}
</AnimatePresence>
<DropdownMenu
aria-label="NextUI versions"
defaultSelectedKeys={["v2"]}
selectionMode="single"
onAction={handleVersionChange}
>
<DropdownItem key="v2">v{currentVersion}</DropdownItem>
<DropdownItem key="v1" endContent={<LinkIcon />}>
v1.0.0
</DropdownItem>
</DropdownMenu>
</Dropdown>
) : (
<div className="w-[74px]" />
)}
</NavbarBrand>
<ul className="hidden lg:flex gap-4 justify-start items-center">
<NavbarItem>
<NextLink
className={navLinkClasses}
color="foreground"
data-active={includes(docsPaths, pathname)}
href="/docs/guide/introduction"
onClick={() => handlePressNavbarItem("Docs", "/docs/guide/introduction")}
>
Docs
</NextLink>
</NavbarItem>
<NavbarItem>
<NextLink
className={navLinkClasses}
color="foreground"
data-active={includes(pathname, "components")}
href="/docs/components/avatar"
onClick={() => handlePressNavbarItem("Components", "/docs/components/avatar")}
>
Components
</NextLink>
</NavbarItem>
<NavbarItem>
<NextLink
className={navLinkClasses}
color="foreground"
data-active={includes(pathname, "blog")}
href="/blog"
onClick={() => handlePressNavbarItem("Blog", "/blog")}
>
Blog
</NextLink>
</NavbarItem>
<NavbarItem>
<NextLink
className={navLinkClasses}
color="foreground"
data-active={includes(pathname, "figma")}
href="/figma"
onClick={() => handlePressNavbarItem("Figma", "/figma")}
>
Figma
</NextLink>
</NavbarItem>
<NavbarItem>
<Chip
as={NextLink}
className="hover:bg-default-100 border-default-200/80 dark:border-default-100/80 transition-colors cursor-pointer"
color="secondary"
href="/blog/v2.1.0"
variant="dot"
onClick={() => handlePressNavbarItem("Introducing v2.2.0", "/blog/v2.2.0")}
>
Introducing v2.2.0&nbsp;
<span aria-label="rocket emoji" role="img">
🚀
</span>
</Chip>
</NavbarItem>
</ul>
</NavbarContent>
<NavbarContent className="flex w-full gap-2 sm:hidden" justify="end">
<NavbarItem className="flex h-full items-center">
<Link
isExternal
aria-label="Github"
className="p-1"
href="https://github.com/nextui-org/nextui"
onClick={() => handlePressNavbarItem("Github", "https://github.com/nextui-org/nextui")}
>
<GithubIcon className="text-default-600 dark:text-default-500" />
</Link>
</NavbarItem>
<NavbarItem className="flex h-full items-center">
<ThemeSwitch />
</NavbarItem>
<NavbarItem className="flex h-full items-center">
<button
className={clsx(
"transition-opacity p-1 hover:opacity-80 rounded-full cursor-pointer outline-none",
// focus ring
...dataFocusVisibleClasses,
)}
data-focus-visible={isFocusVisible}
{...focusProps}
{...pressProps}
>
<SearchLinearIcon className="mt-px text-default-600 dark:text-default-500" size={20} />
</button>
</NavbarItem>
<NavbarItem className="w-10 h-full">
<NavbarMenuToggle
aria-label={isMenuOpen ? "Close menu" : "Open menu"}
className="w-full h-full pt-1"
/>
</NavbarItem>
</NavbarContent>
<NavbarContent className="hidden sm:flex basis-1/5 sm:basis-full" justify="end">
<NavbarItem className="hidden sm:flex">
<Link
isExternal
aria-label="Twitter"
className="p-1"
href={siteConfig.links.twitter}
onPress={() => handlePressNavbarItem("Twitter", siteConfig.links.twitter)}
>
<TwitterIcon className="text-default-600 dark:text-default-500" />
</Link>
<Link
isExternal
aria-label="Discord"
className="p-1"
href={siteConfig.links.discord}
onPress={() => handlePressNavbarItem("Discord", siteConfig.links.discord)}
>
<DiscordIcon className="text-default-600 dark:text-default-500" />
</Link>
<Link
isExternal
aria-label="Github"
className="p-1"
href={siteConfig.links.github}
onPress={() => handlePressNavbarItem("Github", siteConfig.links.github)}
>
<GithubIcon className="text-default-600 dark:text-default-500" />
</Link>
<ThemeSwitch />
</NavbarItem>
<NavbarItem className="hidden lg:flex">{searchButton}</NavbarItem>
<NavbarItem className="hidden md:flex">
<Button
isExternal
as={Link}
className="group text-sm font-normal text-default-600 bg-default-400/20 dark:bg-default-500/20"
href={siteConfig.links.sponsor}
startContent={
<HeartFilledIcon className="text-danger group-data-[hover=true]:animate-heartbeat" />
}
variant="flat"
onPress={() => handlePressNavbarItem("Sponsor", siteConfig.links.sponsor)}
>
Sponsor
</Button>
</NavbarItem>
<NavbarMenuToggle
aria-label={isMenuOpen ? "Close menu" : "Open menu"}
className="hidden sm:flex lg:hidden ml-4"
/>
</NavbarContent>
<NavbarMenu>
<DocsSidebar className="mt-4" routes={[...mobileRoutes, ...routes]} slug={slug} tag={tag} />
{children}
</NavbarMenu>
</NextUINavbar>
);
};