diff --git a/nx-dev/nx-dev/app/react/page.tsx b/nx-dev/nx-dev/app/react/page.tsx new file mode 100644 index 0000000000..f1f35aec0a --- /dev/null +++ b/nx-dev/nx-dev/app/react/page.tsx @@ -0,0 +1,58 @@ +import { DefaultLayout } from '@nx/nx-dev/ui-common'; +import { + CallToAction, + Features, + GettingStarted, + Hero, +} from '@nx/nx-dev/ui-react'; +import { NxBenefitsVideo } from '@nx/nx-dev/ui-react'; + +import type { Metadata } from 'next'; + +export const metadata: Metadata = { + title: 'Nx For React', + description: + 'Add Nx to your React project for distributed task execution, intelligent caching, and affected commands.', + alternates: { + canonical: 'https://nx.dev/react', + }, + openGraph: { + url: 'https://nx.dev/react', + title: 'Nx For React', + description: + 'Add Nx to your React project for distributed task execution, intelligent caching, and affected commands.', + images: [ + { + url: 'https://nx.dev/socials/nx-react-media.png', + width: 800, + height: 421, + alt: 'Nx For React', + type: 'image/jpeg', + }, + ], + siteName: 'Nx', + type: 'website', + }, +}; + +export default function ReactPage(): JSX.Element { + return ( + + +
+ +
+
+
+ +
+
+
+ +
+
+ +
+
+ ); +} diff --git a/nx-dev/nx-dev/public/socials/nx-react-media.png b/nx-dev/nx-dev/public/socials/nx-react-media.png new file mode 100644 index 0000000000..7a68ca1b66 Binary files /dev/null and b/nx-dev/nx-dev/public/socials/nx-react-media.png differ diff --git a/nx-dev/nx-dev/redirect-rules.js b/nx-dev/nx-dev/redirect-rules.js index 02ee939403..3f50b3b7ab 100644 --- a/nx-dev/nx-dev/redirect-rules.js +++ b/nx-dev/nx-dev/redirect-rules.js @@ -656,7 +656,6 @@ const packagesIndexes = { '/nest': '/packages/nest', '/next': '/packages/next', '/node': '/packages/node', - '/react': '/packages/react', '/react-native': '/packages/react', '/rollup': '/packages/rollup', '/storybook': '/packages/storybook', @@ -879,7 +878,7 @@ const missingAndCatchAllRedirects = { // catch all '/(l|latest|p|previous)/(a|angular|r|react|n|node)/:path*': '/:path*', '/(l|latest|p|previous)/:path*': '/:path*', - '/(a|angular|r|react|n|node)/:path*': '/:path*', + '/(a|angular|n|node)/:path*': '/:path*', // Storybook '/(l|latest)/(r|react)/storybook/overview': '/storybook/overview-react', '/(l|latest)/(a|angular)/storybook/overview': '/storybook/overview-angular', diff --git a/nx-dev/ui-react/README.md b/nx-dev/ui-react/README.md new file mode 100644 index 0000000000..1ff2c3da8e --- /dev/null +++ b/nx-dev/ui-react/README.md @@ -0,0 +1,7 @@ +# ui-react + +This library was generated with [Nx](https://nx.dev). + +## Running unit tests + +Run `nx test ui-react` to execute the unit tests via [Jest](https://jestjs.io). diff --git a/nx-dev/ui-react/project.json b/nx-dev/ui-react/project.json new file mode 100644 index 0000000000..7fd119f721 --- /dev/null +++ b/nx-dev/ui-react/project.json @@ -0,0 +1,9 @@ +{ + "name": "ui-react", + "$schema": "../../node_modules/nx/schemas/project-schema.json", + "sourceRoot": "nx-dev/ui-react/src", + "projectType": "library", + "tags": [], + "// targets": "to see all targets run: nx show project ui-react --web", + "targets": {} +} diff --git a/nx-dev/ui-react/src/index.ts b/nx-dev/ui-react/src/index.ts new file mode 100644 index 0000000000..f41a696fd2 --- /dev/null +++ b/nx-dev/ui-react/src/index.ts @@ -0,0 +1 @@ +export * from './lib'; diff --git a/nx-dev/ui-react/src/lib/call-to-action.tsx b/nx-dev/ui-react/src/lib/call-to-action.tsx new file mode 100644 index 0000000000..1421be969e --- /dev/null +++ b/nx-dev/ui-react/src/lib/call-to-action.tsx @@ -0,0 +1,91 @@ +import { ButtonLink, SectionHeading } from '@nx/nx-dev/ui-common'; +import { GradleIcon, ReactIcon } from '@nx/nx-dev/ui-icons'; +import { cx } from '@nx/nx-dev/ui-primitives'; +import React, { ReactElement } from 'react'; +import Link from 'next/link'; + +export function CallToAction(): ReactElement { + return ( +
+ {/* Background pattern */} + + + {/* Gradient background */} +
+ ); +} diff --git a/nx-dev/ui-react/src/lib/feature-sections.tsx b/nx-dev/ui-react/src/lib/feature-sections.tsx new file mode 100644 index 0000000000..10de52f631 --- /dev/null +++ b/nx-dev/ui-react/src/lib/feature-sections.tsx @@ -0,0 +1,137 @@ +import { ReactElement } from 'react'; +import { ButtonLink, SectionHeading } from '@nx/nx-dev/ui-common'; + +export function FeatureSections(): ReactElement { + return ( +
+
+ + Supercharge your Java Projects{' '} + + with Nx + + + +
+ {/* Affected Section */} + + + {/* Remote Caching Section */} + + + {/* Distribution Section */} + + + {/* Atomizer Section */} + + + {/* Flaky Test Retries Section */} + +
+
+
+ ); +} + +interface FeatureSectionProps { + title: string; + description: string; + imageSrc: string; + alt: string; + tag: string; + href: string; + reversed?: boolean; +} + +function FeatureSection({ + title, + description, + imageSrc, + alt, + tag, + href, +}: FeatureSectionProps): ReactElement { + return ( +
+
+ {alt} +
+
+
+ + {tag} + +

+ {title} +

+

+ {description} +

+
+ + Learn more + + +
+
+
+
+ ); +} diff --git a/nx-dev/ui-react/src/lib/features.tsx b/nx-dev/ui-react/src/lib/features.tsx new file mode 100644 index 0000000000..be589c2c9a --- /dev/null +++ b/nx-dev/ui-react/src/lib/features.tsx @@ -0,0 +1,278 @@ +import { SectionHeading } from '@nx/nx-dev/ui-common'; +import { cx } from '@nx/nx-dev/ui-primitives'; +import React, { ReactElement } from 'react'; + +export function Features(): ReactElement { + return ( + <> + + Features + + +

+ Nx allows you to take existing React projects and add powerful + capabilities to your workflow. +

+ +
+ + + + + } + /> + + + + + + + } + /> + + + + + } + /> + + + + + + + + + + + } + /> + + + + + + + } + /> + + + + + + } + /> +
+ + ); +} + +interface FeatureCardProps { + title: string; + description: string; + icon: JSX.Element; + href?: string; +} + +function FeatureCard({ + title, + description, + icon, + href = '#', +}: FeatureCardProps): ReactElement { + return ( + +
+
+
+ {icon} +
+

{title}

+

{description}

+
+
+
+ ); +} diff --git a/nx-dev/ui-react/src/lib/hero.tsx b/nx-dev/ui-react/src/lib/hero.tsx new file mode 100644 index 0000000000..5b85f2a58e --- /dev/null +++ b/nx-dev/ui-react/src/lib/hero.tsx @@ -0,0 +1,152 @@ +/* eslint-disable @nx/enforce-module-boundaries */ +import { + ButtonLink, + SectionHeading, + Strong, + SectionDescription, +} from '@nx/nx-dev/ui-common'; +import { ReactIcon } from '@nx/nx-dev/ui-icons'; +/* eslint-enable @nx/enforce-module-boundaries */ +import { ReactElement } from 'react'; + +export function Hero(): ReactElement { + return ( +
+
+ {/* Logo displayed above the title */} +
+
+ +
+
+ + + Experience the{' '} + + power of Nx + {' '} +
+ in your{' '} + + React monorepo + +
+ + Get distributed tasks, intelligent caching, and target affected +
+ packages to optimize your build process and CI pipeline. +
+ +
+ + Get Started with Nx for React + + + + View Example Project{' '} + + +
+
+
+ ); +} + +export function GettingStarted(): ReactElement { + return ( +
+
+
+
+

+ Add Nx To An Existing Project +

+
+ +
+ + + + +
+ + {/* GitHub example project link */} +
+ + + + + View Example Project on GitHub + +
+
+
+ ); +} + +interface GetStartedCardProps { + title: string; + command: string; + description: string; +} + +function GetStartedCard({ + title, + command, + description, +}: GetStartedCardProps): ReactElement { + return ( +
+

+ {title} +

+
+ {command} +
+

+
+ ); +} diff --git a/nx-dev/ui-react/src/lib/index.ts b/nx-dev/ui-react/src/lib/index.ts new file mode 100644 index 0000000000..d77ea9f773 --- /dev/null +++ b/nx-dev/ui-react/src/lib/index.ts @@ -0,0 +1,7 @@ +export * from './hero'; +export * from './features'; +export * from './resources'; +export * from './call-to-action'; +export * from './feature-sections'; +export * from './webinar'; +export * from './nx-benefits-video'; diff --git a/nx-dev/ui-react/src/lib/nx-benefits-video/index.ts b/nx-dev/ui-react/src/lib/nx-benefits-video/index.ts new file mode 100644 index 0000000000..37369fa99a --- /dev/null +++ b/nx-dev/ui-react/src/lib/nx-benefits-video/index.ts @@ -0,0 +1 @@ +export * from './nx-benefits-video'; diff --git a/nx-dev/ui-react/src/lib/nx-benefits-video/nx-benefits-video.tsx b/nx-dev/ui-react/src/lib/nx-benefits-video/nx-benefits-video.tsx new file mode 100644 index 0000000000..63c9909865 --- /dev/null +++ b/nx-dev/ui-react/src/lib/nx-benefits-video/nx-benefits-video.tsx @@ -0,0 +1,267 @@ +'use client'; + +import { ComponentProps, ReactElement, useState } from 'react'; +import { SectionHeading, computeThumbnailURL } from '@nx/nx-dev/ui-common'; +import { + BoltIcon, + RocketLaunchIcon, + PuzzlePieceIcon, + PlayIcon, +} from '@heroicons/react/24/outline'; +import { VideoModal } from '@nx/nx-dev/ui-common'; +import { sendCustomEvent } from '@nx/nx-dev/feature-analytics'; +import { motion } from 'framer-motion'; +import { MovingBorder } from '@nx/nx-dev/ui-animations'; +import { cx } from '@nx/nx-dev/ui-primitives'; +import Image from 'next/image'; + +function PlayButton({ + className, + ...props +}: ComponentProps<'div'>): ReactElement { + const parent = { + initial: { + width: 82, + transition: { + when: 'afterChildren', + }, + }, + hover: { + width: 296, + transition: { + duration: 0.125, + type: 'tween', + ease: 'easeOut', + }, + }, + }; + const child = { + initial: { + opacity: 0, + x: -6, + }, + hover: { + x: 0, + opacity: 1, + transition: { + duration: 0.015, + type: 'tween', + ease: 'easeOut', + }, + }, + }; + + return ( +
+
+ +
+ +
+ + +
+ ); +} + +export function NxBenefitsVideo(): ReactElement { + const [isOpen, setIsOpen] = useState(false); + const videoUrl = 'https://youtu.be/qotrgWQKqZQ'; + const thumbnailUrl = computeThumbnailURL(videoUrl); + + return ( +
+
+
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + Nx tutorial video thumbnail + +
+ { + setIsOpen(true); + sendCustomEvent( + 'nx-benefits-video-click', + 'nx-benefits-video', + 'react' + ); + }} + /> +
+
+
+ +
+ +
+
+
+ + +
+
+
+ + +
+
+
+
+
+
+ + setIsOpen(false)} + videoUrl={videoUrl} + /> +
+ ); +} diff --git a/nx-dev/ui-react/src/lib/resources.tsx b/nx-dev/ui-react/src/lib/resources.tsx new file mode 100644 index 0000000000..e8504ea77d --- /dev/null +++ b/nx-dev/ui-react/src/lib/resources.tsx @@ -0,0 +1,71 @@ +import { ButtonLink, SectionHeading, TextLink } from '@nx/nx-dev/ui-common'; +import { cx } from '@nx/nx-dev/ui-primitives'; +import React, { ReactElement } from 'react'; + +export function Resources(): ReactElement { + return ( + <> + + Resources + +

+ Learn more about using Nx with Java projects with these resources. +

+ +
+ + + + + +
+ + ); +} + +interface ResourceCardProps { + title: string; + description: string; + linkText: string; + href: string; +} + +function ResourceCard({ + title, + description, + linkText, + href, +}: ResourceCardProps): ReactElement { + return ( +
+
+

{title}

+

{description}

+
+
+ + {linkText} + +
+
+ ); +} diff --git a/nx-dev/ui-react/src/lib/webinar.tsx b/nx-dev/ui-react/src/lib/webinar.tsx new file mode 100644 index 0000000000..f8af0ecd82 --- /dev/null +++ b/nx-dev/ui-react/src/lib/webinar.tsx @@ -0,0 +1,71 @@ +import { ButtonLink, SectionHeading, TextLink } from '@nx/nx-dev/ui-common'; +import { cx } from '@nx/nx-dev/ui-primitives'; +import React, { ReactElement } from 'react'; + +export function WebinarCallout(): ReactElement { + return ( + <> + + Resources + +

+ Learn more about using Nx with Java projects with these resources. +

+ +
+ + + + + +
+ + ); +} + +interface ResourceCardProps { + title: string; + description: string; + linkText: string; + href: string; +} + +function ResourceCard({ + title, + description, + linkText, + href, +}: ResourceCardProps): ReactElement { + return ( +
+
+

{title}

+

{description}

+
+
+ + {linkText} + +
+
+ ); +} diff --git a/nx-dev/ui-react/tsconfig.json b/nx-dev/ui-react/tsconfig.json new file mode 100644 index 0000000000..95cfeb243d --- /dev/null +++ b/nx-dev/ui-react/tsconfig.json @@ -0,0 +1,17 @@ +{ + "compilerOptions": { + "jsx": "react-jsx", + "allowJs": false, + "esModuleInterop": false, + "allowSyntheticDefaultImports": true, + "strict": true + }, + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.lib.json" + } + ], + "extends": "../../tsconfig.base.json" +} diff --git a/nx-dev/ui-react/tsconfig.lib.json b/nx-dev/ui-react/tsconfig.lib.json new file mode 100644 index 0000000000..578a3fb7dd --- /dev/null +++ b/nx-dev/ui-react/tsconfig.lib.json @@ -0,0 +1,23 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/out-tsc", + "types": [ + "node", + "@nx/react/typings/cssmodule.d.ts", + "@nx/react/typings/image.d.ts" + ] + }, + "exclude": [ + "jest.config.ts", + "src/**/*.spec.ts", + "src/**/*.test.ts", + "src/**/*.spec.tsx", + "src/**/*.test.tsx", + "src/**/*.spec.js", + "src/**/*.test.js", + "src/**/*.spec.jsx", + "src/**/*.test.jsx" + ], + "include": ["src/**/*.js", "src/**/*.jsx", "src/**/*.ts", "src/**/*.tsx"] +} diff --git a/tsconfig.base.json b/tsconfig.base.json index 0ad7744319..300eb202a6 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -117,6 +117,7 @@ "@nx/nx-dev/ui-powerpack": ["nx-dev/ui-powerpack/src/index.ts"], "@nx/nx-dev/ui-pricing": ["nx-dev/ui-pricing/src/index.ts"], "@nx/nx-dev/ui-primitives": ["nx-dev/ui-primitives/src/index.ts"], + "@nx/nx-dev/ui-react": ["nx-dev/ui-react/src/index.ts"], "@nx/nx-dev/ui-references": ["nx-dev/ui-references/src/index.ts"], "@nx/nx-dev/ui-remote-cache": ["nx-dev/ui-remote-cache/src/index.ts"], "@nx/nx-dev/ui-sponsor-card": ["nx-dev/ui-sponsor-card/src/index.ts"],