diff --git a/apps/docs/components/docs/components/codeblock.tsx b/apps/docs/components/docs/components/codeblock.tsx index 0b591ba92..51a21f9b1 100644 --- a/apps/docs/components/docs/components/codeblock.tsx +++ b/apps/docs/components/docs/components/codeblock.tsx @@ -1,5 +1,5 @@ import React, {forwardRef, useEffect} from "react"; -import {clsx, getUniqueID} from "@nextui-org/shared-utils"; +import {clsx, dataAttr, getUniqueID} from "@nextui-org/shared-utils"; import BaseHighlight, {Language, PrismTheme, defaultProps} from "prism-react-renderer"; import {debounce} from "lodash"; @@ -11,13 +11,15 @@ interface CodeblockProps { codeString: string; metastring?: string; theme?: PrismTheme; + children?: React.ReactNode; showLines?: boolean; removeIndent?: boolean; hideScrollBar?: boolean; className?: string; - children?: (props: any) => React.ReactNode; } +type HighlightStyle = "inserted" | "deleted" | undefined; + const RE = /{([\d,-]+)}/; const calculateLinesToHighlight = (meta?: string) => { @@ -64,6 +66,32 @@ const Codeblock = forwardRef( const lastSelectionText = React.useRef(null); + const isDiff = language.includes("diff"); + + const codeLang = isDiff ? (language.split("-")[1] as Language) : language; + + let highlightStyle: HighlightStyle[] = []; + + if (isDiff) { + let code: string[] = []; + + highlightStyle = codeString.split?.("\n").map((line) => { + if (line.startsWith("+")) { + code.push(line.substr(1)); + + return "inserted"; + } + if (line.startsWith("-")) { + code.push(line.substr(1)); + + return "deleted"; + } + code.push(line); + }); + + codeString = code.join("\n"); + } + useEffect(() => { const handleSelectionChange = () => { if (!window.getSelection) return; @@ -105,7 +133,7 @@ const Codeblock = forwardRef( @@ -138,6 +166,8 @@ const Codeblock = forwardRef( shouldHighlightLine(i), }, )} + data-deleted={dataAttr(highlightStyle?.[i] === "deleted")} + data-inserted={dataAttr(highlightStyle?.[i] === "inserted")} > {showLines && ( {i + 1} diff --git a/apps/docs/components/navbar.tsx b/apps/docs/components/navbar.tsx index 6cd9e08a6..035802264 100644 --- a/apps/docs/components/navbar.tsx +++ b/apps/docs/components/navbar.tsx @@ -247,7 +247,7 @@ export const Navbar: FC = ({children, routes, mobileRoutes = [], sl 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" + href="/blog/v2.2.0" variant="dot" onClick={() => handlePressNavbarItem("Introducing v2.2.0", "/blog/v2.2.0")} > diff --git a/apps/docs/content/blog/v2.2.0.mdx b/apps/docs/content/blog/v2.2.0.mdx index 6777a0034..d7cbb5804 100644 --- a/apps/docs/content/blog/v2.2.0.mdx +++ b/apps/docs/content/blog/v2.2.0.mdx @@ -1,7 +1,7 @@ --- title: "Introducing v2.2.0 🚀" -description: "NextUI v2.2.0 is here with Client side router support, 3 new components including the Autocomplete, and more." -date: "2023-11-03" +description: "NextUI v2.2.0 is here! Dive into client-side router support, discover 3 new components including the Autocomplete, and more." +date: "2023-11-04" image: "/blog/v2.2.0.jpg" tags: ["nextui", "autocomplete", "breadcrumbs", "client side router", "slider"] author: @@ -11,143 +11,418 @@ author: avatar: "/avatars/junior-garcia.jpeg" --- -import {selectContent} from "@/content/components/select"; -import {listboxContent} from "@/content/components/listbox"; -import {scrollShadowContent} from "@/content/components/scroll-shadow"; - +import {autocompleteContent} from "@/content/components/autocomplete"; +import {sliderContent} from "@/content/components/slider"; +import {breadcrumbsContent} from "@/content/components/breadcrumbs"; NextUI v2 -We are thrilled to announce the latest update to NextUI, version **2.1.0**! This release introduces some game-changing -additions that many of you have eagerly been waiting for. +We are excited to announce the latest update to NextUI, version **2.2.0**! This release introduces 3 new components, +support for client-side routing, and more. -First on the list is the highly-anticipated **Select** component. Fully customizable and beautifully designed, supports both single and -multi-select modes and is accessible out of the box. +## What's New in v2.2.0? -But that's not all. We're also rolling out two more incredible components **Listbox** and **ScrollShadow**. The new -**Listbox** allows you to make list manipulations more efficient and visually appealing. Meanwhile, the -**ScrollShadow** component adds an elegant shadow effect to scrollable areas, enhancing the UI aesthetics while -also improving usability. +- [Client Side Routing](#client-side-routing) - Allows you to seamlessly incorporate client-side routers. +- [Autocomplete](/docs/components/autocomplete) - Combines a text input with a listbox, allowing users to filter a list of options. +- [Slider](/docs/components/slider) - Allows users to make selections from a range of values. +- [Breadcrumbs](/docs/components/breadcrumbs) - Displays a hierarchy of links to the current page or resource in an application. +- [Other Changes](#other-changes) - Includes styling improvements, accessibility and usability enhancements. -## Select + -Creating a select component that is both accessible and customizable is a challenging task. We've spent a lot of time +## Client Side Routing + +By default, links perform native browser navigation when they are interacted with. However, many apps and +frameworks use client side routers to avoid a full page reload when navigating between pages. + +NextUI now natively supports client-side routing in components such as [Link](/docs/components/link), [Tabs](/docs/components/tabs), +[Breadcrumbs](/docs/components/breadcrumbs), [Listbox](/docs/components/listbox), [Dropdown](/docs/components/dropdown) and many others offering +the flexibility to be rendered as HTML links, allowing you to seamlessly incorporate client-side routers. See the [Routing](/docs/guide/routing) guide to +learn how it set it up in your app. + +The `NextUIProvider` component configures all NextUI components within it to navigate using the +client side router you provide. + +> **Note**: Client side routing is based on [React Aria Routing](https://react-spectrum.adobe.com/react-aria/routing.html). + +### Next.js Example + +- App Router + + Go to your `app/providers.tsx` or `app/providers.jsx` (create it if it doesn't exist) and add the + `useRouter` hook from `next/navigation`, it returns a router object that can be used to perform navigation. + + ```tsx + // app/providers.tsx + "use client"; + + import {NextUIProvider} from "@nextui-org/react"; + + export function Providers({children}: {children: React.ReactNode}) { + const router = useRouter(); + + return {children}; + } + ``` + +- Pages Router + + Go to pages`/_app.js` or `pages/_app.tsx` (create it if it doesn't exist) and add the`useRouter` hook + from `next/router`, it returns a router object that can be used to perform navigation. + + ```tsx + // pages/_app.tsx + import type {AppProps} from "next/app"; + import {useRouter} from "next/router"; + import {NextUIProvider} from "@nextui-org/react"; + + function MyApp({Component, pageProps}: AppProps) { + const router = useRouter(); + + return ( + + + + ); + } + + export default MyApp; + ``` + +- Usage + + Now that you have set up the `NextUIProvider` in your app, you can use the `href` prop in the `Tabs`, + `Listbox` and `Dropdown` items to navigate between pages. + + The [Link](/docs/components/link) component will also use the `navigate` function from the + `NextUIProvider` to navigate between pages. + + ```jsx + import { + Tabs, + Tab, + Listbox, + ListboxItem, + Dropdown, + DropdownTrigger, + DropdownMenu, + DropdownItem, + Button, + Link, + } from "@nextui-org/react"; + + function App() { + return ( + <> + + + Home + + + About + + + + + Home + + + About + + + + + + + + + Home + + + About + + + + Home + About + + ); + } + ``` + + + +## Autocomplete + +Creating an autocomplete component that is both accessible and customizable is a challenging task. We've spent a lot of time researching and testing different approaches to come up with a solution that works for everyone. The result is a component that is easy to use, fully accessible, and highly customizable. -The new **Select** component includes: +The new **Autocomplete** component includes: - Support for selecting a single option. -- Support for selecting multiple options. - Support for disabled options. -- Support for sections. -- Labeling support for accessibility. -- Exposed to assistive technology as a button with a listbox popup using ARIA (combined with [Listbox](/docs/components/listbox)). +- Support for groups of items in sections. +- Support for filtering a list of options by typing. +- Support for controlled and uncontrolled options, selection and input value. +- Support for custom filter functions. +- Async loading and infinite scrolling support. +- Required and invalid states exposed to assistive technology via ARIA. - Support for description and error message help text linked to the input via ARIA. -- Support for mouse, touch, and keyboard interactions. -- Tab stop focus management. -- Asynchronous options loading. -- Keyboard support for opening the listbox using the arrow keys, including automatically focusing the first or last item accordingly. -- Typeahead to allow selecting options by typing text, even without opening the listbox. -- Browser autofill integration via a hidden native ` + ... + + ); +}`; +``` + +Dropdown Changes + +```diff-jsx + + ... + +``` + + We hope you enjoy these new components and the new features. We're excited to see what you build with them! diff --git a/apps/docs/content/components/slider/custom-styles.ts b/apps/docs/content/components/slider/custom-styles.ts index afcc7d27e..94269cc8b 100644 --- a/apps/docs/content/components/slider/custom-styles.ts +++ b/apps/docs/content/components/slider/custom-styles.ts @@ -7,7 +7,7 @@ export default function App() { step={100} maxValue={1000} minValue={0} - defaultValue={[100, 300]} + defaultValue={[0, 800]} showSteps={true} showTooltip={true} showOutline={true} diff --git a/apps/docs/content/components/slider/visible-steps.ts b/apps/docs/content/components/slider/visible-steps.ts index 132b6ce78..da06557c7 100644 --- a/apps/docs/content/components/slider/visible-steps.ts +++ b/apps/docs/content/components/slider/visible-steps.ts @@ -6,6 +6,7 @@ export default function App() { Home About - - Home - About + + + + + + Home + About + Home About diff --git a/apps/docs/public/blog/v2.2.0_2x.jpg b/apps/docs/public/blog/v2.2.0_2x.jpg new file mode 100644 index 000000000..f6ef97791 Binary files /dev/null and b/apps/docs/public/blog/v2.2.0_2x.jpg differ diff --git a/apps/docs/styles/prism.css b/apps/docs/styles/prism.css index 311f6fa65..890009554 100644 --- a/apps/docs/styles/prism.css +++ b/apps/docs/styles/prism.css @@ -146,6 +146,37 @@ @apply opacity-0; } +/** + * ---------------------------------------- + * Highlighter styles + * ---------------------------------------- + */ + +.token-line[data-inserted="true"] { + background: rgb(83, 180, 215, 0.15); +} + +.token-line[data-inserted="true"]:before { + content: "+"; + color: rgb(83, 180, 215); + position: absolute; + left: 5px; + top: 0; +} + +.token-line[data-deleted="true"] { + background: rgb(178, 41, 78, 0.2); +} + +.token-line[data-deleted="true"]:before { + content: "-"; + color: rgb(178, 41, 78); + position: absolute; + left: 5px; + top: 0; +} + + /** * ---------------------------------------- * Code snippet styles @@ -191,3 +222,5 @@ .token.language-javascript { @apply text-code-language-javascript; } + +