feat(nx-dev): update top-level navbar

This commit is contained in:
Juri 2024-11-20 11:16:29 +01:00 committed by Juri Strumpflohner
parent 6904789b10
commit 9921496d64
22 changed files with 322 additions and 403 deletions

View File

@ -2,7 +2,7 @@
title: Improve your architecture and CI pipeline times with Nx projects
slug: improve-architecture-and-ci-times-with-projects
authors: [Philip Fulcher]
tags: [nx, enterprise]
tags: [nx, 'customer story']
cover_image: '/blog/images/2024-10-25/header.avif'
pinned: true
---

View File

@ -2,6 +2,7 @@ import type { Metadata, ResolvingMetadata } from 'next';
import { blogApi } from '../../../lib/blog.api';
import { BlogDetails } from '@nx/nx-dev/ui-blog';
import { DefaultLayout } from '@nx/nx-dev/ui-common';
import { tryNxCloudForFree } from '../../../lib/components/headerCtaConfigs';
interface BlogPostDetailProps {
params: { slug: string };
@ -44,12 +45,13 @@ export async function generateStaticParams() {
export default async function BlogPostDetail({
params: { slug },
}: BlogPostDetailProps) {
const ctaHeaderConfig = [tryNxCloudForFree];
const blog = await blogApi.getBlogPostBySlug(slug);
return blog ? (
<>
{/* This empty div is necessary as app router does not automatically scroll on route changes */}
<div></div>
<DefaultLayout>
<DefaultLayout headerCTAConfig={ctaHeaderConfig}>
<BlogDetails post={blog} />
</DefaultLayout>
</>

View File

@ -3,6 +3,10 @@ import { blogApi } from '../../lib/blog.api';
import { BlogContainer } from '@nx/nx-dev/ui-blog';
import { DefaultLayout } from '@nx/nx-dev/ui-common';
import { Suspense } from 'react';
import {
requestFreeTrial,
tryNxCloudForFree,
} from '../../lib/components/headerCtaConfigs';
export const metadata: Metadata = {
title: 'Nx Blog - Updates from the Nx & Nx Cloud team',
@ -34,11 +38,13 @@ async function getBlogTags() {
}
export default async function BlogIndex() {
const ctaHeaderConfig = [tryNxCloudForFree];
const blogs = await getBlogs();
const tags = await getBlogTags();
return (
<Suspense>
<DefaultLayout>
<DefaultLayout headerCTAConfig={ctaHeaderConfig}>
<BlogContainer blogPosts={blogs} tags={tags} />
</DefaultLayout>
</Suspense>

View File

@ -9,7 +9,11 @@ import {
Statistics,
} from '@nx/nx-dev/ui-cloud';
import { CallToAction, DefaultLayout } from '@nx/nx-dev/ui-common';
import {
ButtonLinkProps,
CallToAction,
DefaultLayout,
} from '@nx/nx-dev/ui-common';
import type { Metadata } from 'next';
@ -37,8 +41,18 @@ export const metadata: Metadata = {
};
export default function NxCloudPage(): JSX.Element {
const headerCTAConfig: ButtonLinkProps[] = [
{
href: '/pricing',
variant: 'primary',
size: 'small',
title: 'Get started for free',
children: 'Get started for free',
},
];
return (
<DefaultLayout>
<DefaultLayout headerCTAConfig={headerCTAConfig}>
<Hero />
<TrustedBy />

View File

@ -1,10 +1,11 @@
import { DefaultLayout } from '@nx/nx-dev/ui-common';
import { ButtonLinkProps, DefaultLayout } from '@nx/nx-dev/ui-common';
import {
CallToAction,
GetStarted,
Hero,
PowerpackFeatures,
} from '@nx/nx-dev/ui-powerpack';
import { contactButton } from '../../lib/components/headerCtaConfigs';
import type { Metadata } from 'next';
@ -32,8 +33,18 @@ export const metadata: Metadata = {
};
export default function NxPowerPackPage(): JSX.Element {
const headerCTAConfig: ButtonLinkProps[] = [
{
href: 'https://cloud.nx.app/powerpack/purchase?licenseBusinessType=small&utm_source=nx.dev&utm_medium=referral&utm_campaign=nx-powerpackurl',
variant: 'primary',
size: 'small',
title: 'Request a free trial',
children: 'Request a free trial',
},
];
return (
<DefaultLayout>
<DefaultLayout headerCTAConfig={headerCTAConfig}>
<Hero />
<div className="mt-32 scroll-mt-32 lg:mt-56" id="features">

View File

@ -12,6 +12,7 @@ import {
Testimonials,
TrustedBy,
} from '@nx/nx-dev/ui-common';
import { gotoAppButton } from '../../lib/components/headerCtaConfigs';
export const metadata: Metadata = {
title: 'Nx Cloud - Available Plans',
@ -38,7 +39,7 @@ export const metadata: Metadata = {
export default function PricingPage() {
return (
<DefaultLayout>
<DefaultLayout headerCTAConfig={[gotoAppButton]}>
<PlansDisplay />
<div className="mt-18 lg:mt-32">
<TrustedBy utmSource="pricingpage" utmCampaign="pricing" />

View File

@ -0,0 +1,41 @@
import { ButtonLinkProps } from '@nx/nx-dev/ui-common';
import { NxCloudAnimatedIcon } from '@nx/nx-dev/ui-icons';
export const requestFreeTrial: ButtonLinkProps = {
href: '/contact/sales',
variant: 'primary',
size: 'small',
title: 'Request a free trial',
children: 'Request a free trial',
};
export const tryNxCloudForFree: ButtonLinkProps = {
href: '/pricing',
variant: 'primary',
size: 'small',
title: 'Try Nx Cloud for free',
children: 'Try Nx Cloud for free',
};
export const gotoAppButton: ButtonLinkProps = {
href: 'https://nx.app/?utm_source=nx.dev&utm_medium=header-menu',
variant: 'secondary',
size: 'small',
target: '_blank',
title: 'Log in to your Nx Cloud Account',
children: (
<>
<NxCloudAnimatedIcon className="h-4 w-4" aria-hidden="true" />
<span>Go to app</span>
</>
),
};
export const contactButton: ButtonLinkProps = {
href: '/contact',
variant: 'secondary',
size: 'small',
target: '_blank',
title: 'Contact Us',
children: <span>Contact</span>,
};

View File

@ -6,6 +6,7 @@ import {
Hero,
OssProjects,
} from '@nx/nx-dev/ui-customers';
import { tryNxCloudForFree } from '../lib/components/headerCtaConfigs';
export function Customers(): JSX.Element {
const router = useRouter();
@ -33,7 +34,7 @@ export function Customers(): JSX.Element {
type: 'website',
}}
/>
<DefaultLayout>
<DefaultLayout headerCTAConfig={[tryNxCloudForFree]}>
<div>
<Hero />
</div>

View File

@ -13,6 +13,7 @@ import {
SolveYourCi,
} from '@nx/nx-dev/ui-enterprise';
import { TrialCallout } from '@nx/nx-dev/ui-pricing';
import { requestFreeTrial } from '../lib/components/headerCtaConfigs';
export function Enterprise(): JSX.Element {
const router = useRouter();
@ -40,7 +41,7 @@ export function Enterprise(): JSX.Element {
type: 'website',
}}
/>
<DefaultLayout>
<DefaultLayout headerCTAConfig={[requestFreeTrial]}>
<div>
<Hero />
</div>

View File

@ -8,8 +8,15 @@ import {
TeamAndCommunity,
WorkBetterAchieveMoreShipQuicker,
} from '@nx/nx-dev/ui-home';
import {
requestFreeTrial,
gotoAppButton,
contactButton,
} from '../lib/components/headerCtaConfigs';
export default function Index(): JSX.Element {
const headerCTAConfig = [contactButton];
return (
<>
<NextSeo
@ -34,7 +41,7 @@ export default function Index(): JSX.Element {
}}
/>
<h1 className="sr-only">Build system with advanced CI capabilities.</h1>
<DefaultLayout isHome>
<DefaultLayout isHome headerCTAConfig={headerCTAConfig}>
<Hero />
<div className="mt-16 lg:-mt-32">
<Statistics />

View File

@ -7,6 +7,7 @@ import { ComponentProps, Fragment, useState } from 'react';
import { ButtonLink, SectionHeading } from '@nx/nx-dev/ui-common';
import { MovingBorder } from '@nx/nx-dev/ui-animations';
import Image from 'next/image';
import { NxCloudAnimatedIcon } from '@nx/nx-dev/ui-icons';
export function Hero(): JSX.Element {
const [isOpen, setIsOpen] = useState(false);
@ -31,7 +32,8 @@ export function Hero(): JSX.Element {
variant="primary"
size="default"
>
Get started
<NxCloudAnimatedIcon className="h-4 w-4" aria-hidden="true" />
<span>Go to app</span>
</ButtonLink>
<ButtonLink
href="/ci/intro/ci-with-nx"

View File

@ -25,12 +25,12 @@ export * from './lib/square-dotted-pattern';
export * from './lib/live-stream-notifier';
export { resourceMenuItems } from './lib/headers/menu-items';
export { solutionsMenuItems } from './lib/headers/menu-items';
export { productsMenuItems as solutionsMenuItems } from './lib/headers/menu-items';
export { eventItems } from './lib/headers/menu-items';
export { learnItems } from './lib/headers/menu-items';
export { companyItems } from './lib/headers/menu-items';
export type { MenuItem } from './lib/headers/menu-items';
export { solutions as plans } from './lib/headers/menu-items';
export { ossProducts as plans } from './lib/headers/menu-items';
export { featuresItems } from './lib/headers/menu-items';
export { DefaultMenuItem } from './lib/headers/default-menu-item';
export { MobileMenuItem } from './lib/headers/mobile-menu-item';

View File

@ -17,6 +17,12 @@ interface ButtonProps {
children: ReactNode | ReactNode[];
}
export type ButtonLinkProps = ButtonProps & {
className?: string;
href: string;
title: string;
} & AnchorHTMLAttributes<HTMLAnchorElement>;
const variantStyles: Record<AllowedVariants, string> = {
primary:
'bg-blue-500 dark:bg-sky-500 text-white group-hover:bg-blue-600 dark:group-hover:bg-sky-600 group-focus:ring-2 group-focus:ring-blue-500 dark:group-focus:ring-sky-500 focus:group-ring-offset-2',
@ -99,11 +105,7 @@ export const ButtonLink = forwardRef(function (
variant = 'primary',
title = '',
...props
}: ButtonProps & {
className?: string;
href: string;
title: string;
} & AnchorHTMLAttributes<HTMLAnchorElement>,
}: ButtonLinkProps,
ref: ForwardedRef<HTMLAnchorElement>
): JSX.Element {
return (

View File

@ -1,21 +1,23 @@
import { Footer } from './footer';
import { Header } from './headers/header';
import { PropsWithChildren } from 'react';
import cx from 'classnames';
import { ButtonLinkProps } from './button';
export function DefaultLayout({
isHome = false,
children,
hideHeader = false,
hideFooter = false,
headerCTAConfig,
}: {
isHome?: boolean;
hideHeader?: boolean;
hideFooter?: boolean;
headerCTAConfig?: ButtonLinkProps[];
} & PropsWithChildren): JSX.Element {
return (
<div className="w-full overflow-hidden dark:bg-slate-950">
{!hideHeader && <Header />}
{!hideHeader && <Header ctaButtons={headerCTAConfig} />}
<div className="relative isolate">
<div
className="absolute inset-x-0 -top-40 -z-10 h-full transform-gpu overflow-hidden blur-3xl sm:-top-80"

View File

@ -1,5 +1,7 @@
'use client';
import { Fragment, type JSX } from 'react';
import { GitHubIcon } from '@nx/nx-dev/ui-icons';
import {
Bars3Icon,
ChevronDownIcon,
@ -13,9 +15,13 @@ import { ButtonLink } from '../button';
import { Popover, Transition } from '@headlessui/react';
import { TwoColumnsMenu } from './two-columns-menu';
import {
companyItems,
eventItems,
featuresItems,
learnItems,
ossProducts,
resourceMenuItems,
solutionsMenuItems,
productsMenuItems,
} from './menu-items';
import { SectionsMenu } from './sections-menu';
import { DiscordIcon } from '../discord-icon';
@ -224,103 +230,6 @@ export function DocumentationHeader({
className="items-justified hidden justify-center space-x-2 text-sm lg:flex"
>
<h2 className="sr-only">Main navigation</h2>
{/*FEATURES*/}
<Popover className="relative">
{({ open }) => (
<>
<Popover.Button
className={cx(
open ? 'text-blue-500 dark:text-sky-500' : '',
'group inline-flex items-center gap-2 px-3 py-2 font-medium leading-tight outline-0 dark:text-slate-200'
)}
>
<span
className={cx(
open ? 'text-blue-500 dark:text-sky-500' : '',
'transition duration-150 ease-in-out group-hover:text-blue-500 dark:group-hover:text-sky-500'
)}
>
Features
</span>
<ChevronDownIcon
aria-hidden="true"
className={cx(
open
? 'rotate-180 transform text-blue-500 dark:text-sky-500'
: '',
'h-3 w-3 transition duration-150 ease-in-out group-hover:text-blue-500 dark:group-hover:text-sky-500'
)}
/>
</Popover.Button>
<Transition
as={Fragment}
enter="transition ease-out duration-200"
enterFrom="opacity-0 translate-y-1"
enterTo="opacity-100 translate-y-0"
leave="transition ease-in duration-150"
leaveFrom="opacity-100 translate-y-0"
leaveTo="opacity-0 translate-y-1"
>
<Popover.Panel className="absolute z-30 mt-3 w-max max-w-3xl xl:max-w-3xl">
<SectionsMenu sections={featuresItems} />
</Popover.Panel>
</Transition>
</>
)}
</Popover>
{/*SOLUTIONS*/}
<Popover className="relative">
{({ open }) => (
<>
<Popover.Button
className={cx(
open ? 'text-blue-500 dark:text-sky-500' : '',
'group inline-flex items-center px-3 py-2 font-medium leading-tight outline-0 dark:text-slate-200'
)}
>
<span
className={cx(
open ? 'text-blue-500 dark:text-sky-500' : '',
'transition duration-150 ease-in-out group-hover:text-blue-500 dark:group-hover:text-sky-500'
)}
>
Solutions
</span>
<ChevronDownIcon
className={cx(
open
? 'rotate-180 transform text-blue-500 dark:text-sky-500'
: '',
'ml-2 h-3 w-3 transition duration-150 ease-in-out group-hover:text-blue-500 dark:group-hover:text-sky-500'
)}
aria-hidden="true"
/>
</Popover.Button>
<Transition
as={Fragment}
enter="transition ease-out duration-200"
enterFrom="opacity-0 translate-y-1"
enterTo="opacity-100 translate-y-0"
leave="transition ease-in duration-150"
leaveFrom="opacity-100 translate-y-0"
leaveTo="opacity-0 translate-y-1"
>
<Popover.Panel className="absolute z-30 mt-3 w-max max-w-2xl">
<SectionsMenu sections={solutionsMenuItems} />
</Popover.Panel>
</Transition>
</>
)}
</Popover>
<Link
href="/getting-started/intro"
title="Documentation"
className="hidden px-3 py-2 font-medium leading-tight hover:text-blue-500 md:inline-flex dark:text-slate-200 dark:hover:text-sky-500"
prefetch={false}
>
Docs
</Link>
<Link
href="/blog"
title="Blog"
@ -329,14 +238,6 @@ export function DocumentationHeader({
>
Blog
</Link>
<Link
href="/pricing"
title="Nx Cloud"
className="hidden gap-2 px-3 py-2 font-medium leading-tight hover:text-blue-500 md:inline-flex dark:text-slate-200 dark:hover:text-sky-500"
prefetch={false}
>
CI Pricing
</Link>
{/*RESOURCES*/}
<Popover className="relative">
{({ open }) => (
@ -377,6 +278,40 @@ export function DocumentationHeader({
</>
)}
</Popover>
<div className="hidden h-6 w-px bg-slate-200 md:block dark:bg-slate-700" />
<Link
href="/nx-cloud"
title="Nx Cloud"
className="hidden gap-2 px-3 py-2 font-medium leading-tight hover:text-blue-500 md:inline-flex dark:text-slate-200 dark:hover:text-sky-500"
prefetch={false}
>
Nx Cloud
</Link>
<Link
href="/pricing"
title="Pricing"
className="hidden gap-2 px-3 py-2 font-medium leading-tight hover:text-blue-500 md:inline-flex dark:text-slate-200 dark:hover:text-sky-500"
prefetch={false}
>
Pricing
</Link>
<div className="hidden h-6 w-px bg-slate-200 md:block dark:bg-slate-700" />
<Link
href="/powerpack"
title="Nx Powerpack"
className="hidden gap-2 px-3 py-2 font-medium leading-tight hover:text-blue-500 md:inline-flex dark:text-slate-200 dark:hover:text-sky-500"
prefetch={false}
>
Powerpack
</Link>
<Link
href="/enterprise"
title="Nx Enterprise"
className="hidden gap-2 px-3 py-2 font-medium leading-tight hover:text-blue-500 md:inline-flex dark:text-slate-200 dark:hover:text-sky-500"
prefetch={false}
>
Enterprise
</Link>
</nav>
</div>
<div className="hidden flex-grow lg:flex">{/* SPACER */}</div>
@ -385,22 +320,14 @@ export function DocumentationHeader({
role="menu"
className="items-justified hidden justify-center space-x-4 lg:flex"
>
<Link
className="hidden cursor-pointer px-3 py-2 text-sm font-medium leading-tight hover:text-blue-500 md:inline-flex dark:text-slate-200 dark:hover:text-sky-500"
title="Contact Us"
href="/contact"
prefetch={false}
>
Contact
</Link>
<ButtonLink
href="https://nx.app/?utm_source=nx.dev&utm_medium=header-menu"
title="Go to app"
variant="secondary"
href="/nx-cloud"
title="Try Nx Cloud for free"
variant="primary"
size="small"
>
<NxCloudAnimatedIcon className="h-4 w-4" aria-hidden="true" />
<span>Go to app</span>
<span>Try Nx Cloud for free</span>
</ButtonLink>
</nav>
</div>

View File

@ -8,15 +8,16 @@ import {
import cx from 'classnames';
import Link from 'next/link';
import { Fragment, useEffect, useState } from 'react';
import { ButtonLink } from '../button';
import { ButtonLink, ButtonLinkProps } from '../button';
import {
companyItems,
eventItems,
featuresItems,
learnItems,
solutions,
ossProducts,
resourceMenuItems,
solutionsMenuItems,
productsMenuItems,
enterpriseResourcesMenuItems,
} from './menu-items';
import { MobileMenuItem } from './mobile-menu-item';
import { SectionsMenu } from './sections-menu';
@ -24,7 +25,11 @@ import { TwoColumnsMenu } from './two-columns-menu';
import { AlgoliaSearch } from '@nx/nx-dev/feature-search';
import { GitHubIcon, NxCloudAnimatedIcon, NxIcon } from '@nx/nx-dev/ui-icons';
export function Header(): JSX.Element {
interface HeaderProps {
ctaButtons?: ButtonLinkProps[];
}
export function Header({ ctaButtons }: HeaderProps): JSX.Element {
let [isOpen, setIsOpen] = useState(false);
// We need to close the popover if the route changes or the window is resized to prevent the popover from being stuck open.
@ -42,6 +47,19 @@ export function Header(): JSX.Element {
};
}, []);
const defaultCtaButtons: ButtonLinkProps[] = [
{
href: '/nx-cloud',
variant: 'primary',
size: 'small',
target: '_blank',
title: 'Try Nx Cloud for free',
children: <span>Try Nx Cloud for free</span>,
},
];
const buttonsToRender = ctaButtons || defaultCtaButtons;
return (
<div className="fixed inset-x-0 top-0 isolate z-[5] flex px-4 print:hidden">
<div
@ -69,95 +87,6 @@ export function Header(): JSX.Element {
className="items-justified flex items-center justify-center space-x-2 py-0.5"
>
<h2 className="sr-only">Main navigation</h2>
{/*FEATURES*/}
<Popover className="relative">
{({ open }) => (
<>
<Popover.Button
className={cx(
open ? 'text-blue-500 dark:text-sky-500' : '',
'group inline-flex items-center gap-2 px-3 py-2 font-medium leading-tight outline-0 dark:text-slate-200'
)}
>
<span
className={cx(
open ? 'text-blue-500 dark:text-sky-500' : '',
'transition duration-150 ease-in-out group-hover:text-blue-500 dark:group-hover:text-sky-500'
)}
>
Features
</span>
<ChevronDownIcon
aria-hidden="true"
className={cx(
open
? 'rotate-180 transform text-blue-500 dark:text-sky-500'
: '',
'h-3 w-3 transition duration-150 ease-in-out group-hover:text-blue-500 dark:group-hover:text-sky-500'
)}
/>
</Popover.Button>
<Transition
as={Fragment}
enter="transition ease-out duration-200"
enterFrom="opacity-0 translate-y-1"
enterTo="opacity-100 translate-y-0"
leave="transition ease-in duration-150"
leaveFrom="opacity-100 translate-y-0"
leaveTo="opacity-0 translate-y-1"
>
<Popover.Panel className="absolute z-10 mt-3 w-max max-w-3xl xl:max-w-3xl">
<SectionsMenu sections={featuresItems} />
</Popover.Panel>
</Transition>
</>
)}
</Popover>
{/*SOLUTIONS*/}
<Popover className="relative">
{({ open }) => (
<>
<Popover.Button
className={cx(
open ? 'text-blue-500 dark:text-sky-500' : '',
'group inline-flex items-center px-3 py-2 font-medium leading-tight outline-0 dark:text-slate-200'
)}
>
<span
className={cx(
open ? 'text-blue-500 dark:text-sky-500' : '',
'transition duration-150 ease-in-out group-hover:text-blue-500 dark:group-hover:text-sky-500'
)}
>
Solutions
</span>
<ChevronDownIcon
className={cx(
open
? 'rotate-180 transform text-blue-500 dark:text-sky-500'
: '',
'ml-2 h-3 w-3 transition duration-150 ease-in-out group-hover:text-blue-500 dark:group-hover:text-sky-500'
)}
aria-hidden="true"
/>
</Popover.Button>
<Transition
as={Fragment}
enter="transition ease-out duration-200"
enterFrom="opacity-0 translate-y-1"
enterTo="opacity-100 translate-y-0"
leave="transition ease-in duration-150"
leaveFrom="opacity-100 translate-y-0"
leaveTo="opacity-0 translate-y-1"
>
<Popover.Panel className="absolute z-10 mt-3 w-max max-w-2xl">
<SectionsMenu sections={solutionsMenuItems} />
</Popover.Panel>
</Transition>
</>
)}
</Popover>
<Link
href="/getting-started/intro"
title="Documentation"
@ -174,14 +103,6 @@ export function Header(): JSX.Element {
>
Blog
</Link>
<Link
href="/pricing"
title="Nx Cloud"
className="hidden gap-2 px-3 py-2 font-medium leading-tight hover:text-blue-500 md:inline-flex dark:text-slate-200 dark:hover:text-sky-500"
prefetch={false}
>
CI Pricing
</Link>
{/*RESOURCES*/}
<Popover className="relative">
{({ open }) => (
@ -215,14 +136,49 @@ export function Header(): JSX.Element {
leaveFrom="opacity-100 translate-y-0"
leaveTo="opacity-0 translate-y-1"
>
<Popover.Panel className="absolute left-60 z-10 mt-3 w-max max-w-2xl -translate-x-1/2 transform lg:left-20">
<Popover.Panel className="absolute left-60 z-30 mt-3 w-max max-w-2xl -translate-x-1/2 transform lg:left-20">
<SectionsMenu sections={resourceMenuItems} />
</Popover.Panel>
</Transition>
</>
)}
</Popover>
<div className="opacity-50 hover:opacity-100">
<div className="hidden h-6 w-px bg-slate-200 md:block dark:bg-slate-700" />
<Link
href="/nx-cloud"
title="Nx Cloud"
className="hidden gap-2 px-3 py-2 font-medium leading-tight hover:text-blue-500 md:inline-flex dark:text-slate-200 dark:hover:text-sky-500"
prefetch={false}
>
Nx Cloud
</Link>
<Link
href="/pricing"
title="Pricing"
className="hidden gap-2 px-3 py-2 font-medium leading-tight hover:text-blue-500 md:inline-flex dark:text-slate-200 dark:hover:text-sky-500"
prefetch={false}
>
Pricing
</Link>
<div className="hidden h-6 w-px bg-slate-200 md:block dark:bg-slate-700" />
<Link
href="/powerpack"
title="Nx Powerpack"
className="hidden gap-2 px-3 py-2 font-medium leading-tight hover:text-blue-500 md:inline-flex dark:text-slate-200 dark:hover:text-sky-500"
prefetch={false}
>
Powerpack
</Link>
<Link
href="/enterprise"
title="Nx Enterprise"
className="hidden gap-2 px-3 py-2 font-medium leading-tight hover:text-blue-500 md:inline-flex dark:text-slate-200 dark:hover:text-sky-500"
prefetch={false}
>
Enterprise
</Link>
<div className="hidden h-6 w-px bg-slate-200 md:block dark:bg-slate-700" />
<div className="px-3 opacity-50 hover:opacity-100">
<AlgoliaSearch tiny={true} />
</div>
</nav>
@ -230,24 +186,9 @@ export function Header(): JSX.Element {
{/*SECONDARY NAVIGATION*/}
<div className="flex-shrink-0 text-sm">
<nav className="flex items-center justify-center space-x-1">
<Link
className="hidden cursor-pointer px-3 py-2 font-medium leading-tight hover:text-blue-500 md:inline-flex dark:text-slate-200 dark:hover:text-sky-500"
title="Contact Us"
href="/contact"
prefetch={false}
>
Contact
</Link>
<ButtonLink
href="https://cloud.nx.app"
variant="secondary"
size="small"
target="_blank"
title="Log in to your Nx Cloud Account"
>
<NxCloudAnimatedIcon className="h-4 w-4" aria-hidden="true" />
<span>Go to app</span>
</ButtonLink>
{buttonsToRender.map((buttonProps, index) => (
<ButtonLink key={index} {...buttonProps} />
))}
<a
title="Nx is open source, check the code on GitHub"
href="https://github.com/nrwl/nx"
@ -359,90 +300,17 @@ export function Header(): JSX.Element {
</div>
<div className="relative mt-6 flex-1 px-4 sm:px-6">
<ButtonLink
href="https://cloud.nx.app"
href="/nx-cloud"
variant="primary"
size="small"
target="_blank"
title="Log in to your Nx Cloud Account"
title="Try Nx Cloud for free"
className="w-full"
>
Go to app
Try Nx Cloud for free
</ButtonLink>
<div className="mt-4 divide-y divide-slate-200 border-b border-slate-200 dark:divide-slate-800 dark:border-slate-800">
{/*FEATURES*/}
<Disclosure as="div">
{({ open }) => (
<>
<Disclosure.Button
className={cx(
open
? 'text-blue-500 dark:text-sky-500'
: 'tex-slate-800 dark:text-slate-200',
'flex w-full items-center justify-between py-4 text-left text-base font-medium focus:outline-none'
)}
>
<span>Features</span>
<ChevronDownIcon
aria-hidden="true"
className={cx(
open
? 'rotate-180 transform text-blue-500 dark:text-sky-500'
: 'tex-slate-800 dark:text-slate-200',
'h-3 w-3 transition duration-150 ease-in-out group-hover:text-blue-500 dark:group-hover:text-sky-500'
)}
/>
</Disclosure.Button>
<Disclosure.Panel
as="ul"
className="space-y-1 pb-2"
>
{Object.values(featuresItems)
.flat()
.map((item) => (
<MobileMenuItem
key={item.name}
item={item}
/>
))}
</Disclosure.Panel>
</>
)}
</Disclosure>
{/*SOLUTIONS*/}
<Disclosure as="div">
{({ open }) => (
<>
<Disclosure.Button
className={cx(
open
? 'text-blue-500 dark:text-sky-500'
: 'tex-slate-800 dark:text-slate-200',
'flex w-full items-center justify-between py-4 text-left text-base font-medium focus:outline-none'
)}
>
<span>Solutions</span>
<ChevronDownIcon
aria-hidden="true"
className={cx(
open
? 'rotate-180 transform text-blue-500 dark:text-sky-500'
: 'tex-slate-800 dark:text-slate-200',
'h-3 w-3 transition duration-150 ease-in-out group-hover:text-blue-500 dark:group-hover:text-sky-500'
)}
/>
</Disclosure.Button>
<Disclosure.Panel as="ul" className="space-y-1">
{solutions.map((item) => (
<MobileMenuItem
key={item.name}
item={item}
/>
))}
</Disclosure.Panel>
</>
)}
</Disclosure>
<Link
href="/getting-started/intro"
title="Documentation"
@ -459,24 +327,16 @@ export function Header(): JSX.Element {
>
Blog
</Link>
<Link
href="/pricing"
title="Nx Cloud"
className="flex w-full gap-2 py-4 font-medium leading-tight hover:text-blue-500 dark:text-slate-200 dark:hover:text-sky-500"
prefetch={false}
>
CI Pricing
</Link>
{/*RESOURCES*/}
{/*Resources*/}
<Disclosure as="div">
{({ open }) => (
<>
<Disclosure.Button
className={cx(
'flex w-full items-center justify-between py-4 text-left text-base font-medium focus:outline-none',
open
? 'text-blue-500 dark:text-sky-500'
: 'tex-slate-800 dark:text-slate-200'
: 'tex-slate-800 dark:text-slate-200',
'flex w-full items-center justify-between py-4 text-left text-base font-medium focus:outline-none'
)}
>
<span>Resources</span>
@ -494,19 +354,9 @@ export function Header(): JSX.Element {
as="ul"
className="space-y-1 pb-2"
>
{learnItems.map((item) => (
<MobileMenuItem
key={item.name}
item={item}
/>
))}
{eventItems.map((item) => (
<MobileMenuItem
key={item.name}
item={item}
/>
))}
{companyItems.map((item) => (
{Object.values(resourceMenuItems)
.flat()
.map((item) => (
<MobileMenuItem
key={item.name}
item={item}
@ -516,6 +366,38 @@ export function Header(): JSX.Element {
</>
)}
</Disclosure>
<Link
href="/nx-cloud"
title="Nx Cloud"
className="flex w-full gap-2 py-4 font-medium leading-tight hover:text-blue-500 dark:text-slate-200 dark:hover:text-sky-500"
prefetch={false}
>
Nx Cloud
</Link>
<Link
href="/pricing"
title="Pricing"
className="flex w-full gap-2 py-4 font-medium leading-tight hover:text-blue-500 dark:text-slate-200 dark:hover:text-sky-500"
prefetch={false}
>
Pricing
</Link>
<Link
href="/powerpack"
title="Powerpack"
className="flex w-full gap-2 py-4 font-medium leading-tight hover:text-blue-500 dark:text-slate-200 dark:hover:text-sky-500"
prefetch={false}
>
Powerpack
</Link>
<Link
href="/enterprise"
title="Enterprise"
className="flex w-full gap-2 py-4 font-medium leading-tight hover:text-blue-500 dark:text-slate-200 dark:hover:text-sky-500"
prefetch={false}
>
Enterprise
</Link>
<Link
href="/contact"
title="Contact"

View File

@ -16,6 +16,7 @@ import {
MicrophoneIcon,
VideoCameraIcon,
CheckBadgeIcon,
BookOpenIcon,
} from '@heroicons/react/24/outline';
import { FC, SVGProps } from 'react';
import { DiscordIcon } from '../discord-icon';
@ -126,11 +127,30 @@ export const featuresItems: Record<string, MenuItem[]> = {
},
],
};
export const solutions: MenuItem[] = [
export const ossProducts: MenuItem[] = [
{
name: 'Nx',
description: 'Smart Monorepos - Fast CI',
href: '/getting-started/intro',
icon: null,
isNew: false,
isHighlight: false,
},
{
name: 'Nx Console',
description: 'Editor integration for VSCode, Cursor and IntelliJ IDEs',
href: '/getting-started/editor-setup',
icon: null,
isNew: false,
isHighlight: false,
},
];
export const enterpriseProducts: MenuItem[] = [
{
name: 'Nx Cloud',
description:
'End-to-end solution for smart, efficient and maintainable CI.',
'Nx Cloud is the end-to-end solution for smart, efficient and maintainable CI',
href: '/nx-cloud',
icon: null,
isNew: false,
@ -148,7 +168,7 @@ export const solutions: MenuItem[] = [
{
name: 'Nx Enterprise',
description:
'The ultimate Nx & Nx Cloud toolchain, tailored to your needs.',
"Accelerate your organization's journey to tighter collaboration, better developer experience, and speed…lots of speed.",
href: '/enterprise',
icon: null,
isNew: false,
@ -258,10 +278,7 @@ export const companyItems: MenuItem[] = [
isHighlight: false,
},
];
export const solutionsMenuItems = {
'Helping you grow': solutions,
// 'Use cases': useCaseItems
};
export const resourceMenuItems = {
Learn: learnItems,
Events: eventItems,

View File

@ -208,16 +208,16 @@ export function SidebarMobile({
general: [
{ name: 'Home', href: '/', current: false },
{ name: 'Blog', href: '/blog', current: false },
{ name: 'Community', href: '/community', current: false },
{ name: 'Launch Nx', href: '/launch-nx', current: false },
{ name: 'Resources', href: '/resources', current: false },
{ name: 'Nx Cloud', href: '/nx-cloud', current: false },
{
name: 'Contact',
href: '/contact',
name: 'Powerpack',
href: '/powerpack',
current: false,
},
{
name: 'Go to app',
href: 'https://cloud.nx.app',
name: 'Enterprise',
href: '/enterprise',
current: false,
},
],

View File

@ -20,9 +20,9 @@ export function Hero(): JSX.Element {
href="/contact"
variant="contrast"
size="default"
title="Join us"
title="Contact us"
>
Reach out
Contact us
</ButtonLink>
<a

View File

@ -17,26 +17,25 @@ export function Hero(): JSX.Element {
Accelerate your organization's journey to tighter collaboration,
better developer experience, and speedlots of speed.
</SectionHeading>
<div className="mt-10">
<div className="mt-10 items-center justify-center gap-x-6">
<ButtonLink
href="/contact/engineering"
title="Talk to the engineering team"
href="/contact/sales"
title="Request a free trial"
variant="primary"
size="default"
>
Talk to engineering
Request a free trial
</ButtonLink>
<p className="mt-6 italic">
Ready to talk terms?{' '}
Got questions?{' '}
<Link
href="/contact/sales"
href="/contact/engineering"
title="Talk to the sales team"
className="font-semibold underline"
prefetch={false}
>
Speak directly to sales
Talk to an engineer.
</Link>
.
</p>
</div>
</div>

View File

@ -4,14 +4,8 @@ import { ShaderGradient, ShaderGradientCanvas } from 'shadergradient';
import { BlurFade, usePrefersReducedMotion } from '@nx/nx-dev/ui-animations';
import { Theme, useTheme } from '@nx/nx-dev/ui-theme';
import { useState } from 'react';
import Link from 'next/link';
import { useIsomorphicLayoutEffect } from '@nx/nx-dev/ui-primitives';
import {
MonorepoWorldIcon,
RustIcon,
TypeScriptIcon,
} from '@nx/nx-dev/ui-icons';
import { motion, MotionConfig } from 'framer-motion';
import { RustIcon, TypeScriptIcon } from '@nx/nx-dev/ui-icons';
export function Hero(): JSX.Element {
return (
@ -76,12 +70,12 @@ export function Hero(): JSX.Element {
Learn about Nx on CI
</ButtonLink>
<ButtonLink
href="/contact?utm_medium=website&utm_campaign=homepage_links&utm_content=cta_hero_get_started"
title="Get started"
href="/nx-cloud"
title="Try Nx Cloud for free"
variant="secondary"
size="default"
>
Contact us
Try Nx Cloud for free
</ButtonLink>
</div>

View File

@ -18,6 +18,16 @@ export function PlansDisplay(): ReactElement {
<SectionHeading as="p" variant="subtitle" className="mt-6">
Level up your CI with Nx Cloud
</SectionHeading>
<div className="mt-10 flex items-center justify-center gap-x-6">
<ButtonLink
href="/contact/engineering"
title="Talk to the engineering team"
variant="secondary"
size="default"
>
Got questions? Talk to our team
</ButtonLink>
</div>
</header>
<div className="mt-20 flow-root">
<div className="isolate -mt-16 grid max-w-full grid-cols-1 gap-6 sm:mx-auto lg:mt-0 lg:grid-cols-3 xl:-mx-4 xl:gap-8">
@ -57,7 +67,7 @@ export function PlansDisplay(): ReactElement {
}
className="w-full"
>
Get started
Start now
</ButtonLink>
</div>
<ul className="mt-4 divide-y divide-slate-200 text-sm dark:divide-slate-800">
@ -161,7 +171,7 @@ export function PlansDisplay(): ReactElement {
}
className="w-full"
>
Get started
Free to start
</ButtonLink>
</div>
<ul className="mt-4 divide-y divide-slate-200 text-sm dark:divide-slate-800">
@ -266,21 +276,21 @@ export function PlansDisplay(): ReactElement {
</p>
<div className="my-12">
<ButtonLink
href="/enterprise"
href="/contact/sales"
aria-describedby="enterprise-plan"
title="Enterprise"
size="default"
variant="secondary"
onClick={() =>
sendCustomEvent(
'learn-enterprise-click',
'request-enterprise-trial',
'plans-table',
'pricing-plans'
)
}
className="w-full"
>
Learn more
Request a trial
</ButtonLink>
</div>
<ul className="mt-4 divide-y divide-slate-200 text-sm dark:divide-slate-800">