diff --git a/packages/next/src/client/components/react-dev-overlay/_experimental/internal/components/Errors/error-overlay-floating-header/error-overlay-floating-header.tsx b/packages/next/src/client/components/react-dev-overlay/_experimental/internal/components/Errors/error-overlay-floating-header/error-overlay-floating-header.tsx index 99074949000f3..4124bf0a4322c 100644 --- a/packages/next/src/client/components/react-dev-overlay/_experimental/internal/components/Errors/error-overlay-floating-header/error-overlay-floating-header.tsx +++ b/packages/next/src/client/components/react-dev-overlay/_experimental/internal/components/Errors/error-overlay-floating-header/error-overlay-floating-header.tsx @@ -2,7 +2,7 @@ import type { ReadyRuntimeError } from '../../../helpers/get-error-by-type' import type { VersionInfo } from '../../../../../../../../server/dev/parse-version-info' import { ErrorOverlayPagination } from '../error-overlay-pagination/error-overlay-pagination' -import { VersionStalenessInfo } from '../../VersionStalenessInfo' +import { VersionStalenessInfo } from '../../VersionStalenessInfo/VersionStalenessInfo' import { noop as css } from '../../../helpers/noop-template' type ErrorOverlayFloatingHeaderProps = { diff --git a/packages/next/src/client/components/react-dev-overlay/_experimental/internal/components/VersionStalenessInfo/VersionStalenessInfo.tsx b/packages/next/src/client/components/react-dev-overlay/_experimental/internal/components/VersionStalenessInfo/VersionStalenessInfo.tsx index 03787cb8ca35d..17032c0d1fd87 100644 --- a/packages/next/src/client/components/react-dev-overlay/_experimental/internal/components/VersionStalenessInfo/VersionStalenessInfo.tsx +++ b/packages/next/src/client/components/react-dev-overlay/_experimental/internal/components/VersionStalenessInfo/VersionStalenessInfo.tsx @@ -1,9 +1,12 @@ import type { VersionInfo } from '../../../../../../../server/dev/parse-version-info' +import { noop as css } from '../../helpers/noop-template' export function VersionStalenessInfo({ versionInfo, + isTurbopack = !!process.env.TURBOPACK, }: { versionInfo: VersionInfo | undefined + isTurbopack?: boolean }) { if (!versionInfo) return null const { staleness } = versionInfo @@ -12,11 +15,11 @@ export function VersionStalenessInfo({ if (!text) return null return ( - - - + + + {text} - {' '} + {' '} {staleness === 'fresh' || staleness === 'newer-than-npm' || staleness === 'unknown' ? null : ( @@ -28,7 +31,7 @@ export function VersionStalenessInfo({ (learn more) )} - {process.env.TURBOPACK ? ' (Turbopack)' : ''} + {isTurbopack && Turbopack} ) } @@ -37,7 +40,7 @@ export function getStaleness({ installed, staleness, expected }: VersionInfo) { let text = '' let title = '' let indicatorClass = '' - const versionLabel = `Next.js (${installed})` + const versionLabel = `Next.js ${installed}` switch (staleness) { case 'newer-than-npm': case 'fresh': @@ -47,18 +50,18 @@ export function getStaleness({ installed, staleness, expected }: VersionInfo) { break case 'stale-patch': case 'stale-minor': - text = `${versionLabel} out of date` + text = `${versionLabel} (stale)` title = `There is a newer version (${expected}) available, upgrade recommended! ` indicatorClass = 'stale' break case 'stale-major': { - text = `${versionLabel} is outdated` + text = `${versionLabel} (outdated)` title = `An outdated version detected (latest is ${expected}), upgrade is highly recommended!` indicatorClass = 'outdated' break } case 'stale-prerelease': { - text = `${versionLabel} is outdated` + text = `${versionLabel} (stale)` title = `There is a newer canary version (${expected}) available, please upgrade! ` indicatorClass = 'stale' break @@ -70,3 +73,64 @@ export function getStaleness({ installed, staleness, expected }: VersionInfo) { } return { text, indicatorClass, title } } + +export const styles = css` + .nextjs-container-build-error-version-status { + display: flex; + justify-content: center; + align-items: center; + gap: var(--size-1); + + padding: var(--size-1_5) var(--size-2); + background: var(--color-background-100); + box-shadow: var(--shadow-sm); + + border: 1px solid var(--color-gray-400); + border-radius: var(--rounded-full); + + color: var(--color-gray-900); + font-size: var(--size-font-11); + font-weight: 500; + line-height: var(--size-4); + } + + .version-staleness-indicator.fresh { + fill: var(--color-green-800); + stroke: var(--color-green-300); + } + .version-staleness-indicator.stale { + fill: var(--color-amber-800); + stroke: var(--color-amber-300); + } + .version-staleness-indicator.outdated { + fill: var(--color-red-800); + stroke: var(--color-red-300); + } + + .turbopack-text { + background: linear-gradient(280deg, #0096ff 0%, #ff1e56 100%); + background-clip: text; + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + } + + @media (prefers-color-scheme: dark) { + .turbopack-text { + background: linear-gradient(280deg, #45b2ff 0%, #ff6d92 100%); + } + } +` + +function Eclipse({ className }: { className: string }) { + return ( + + + + ) +} diff --git a/packages/next/src/client/components/react-dev-overlay/_experimental/internal/components/VersionStalenessInfo/index.tsx b/packages/next/src/client/components/react-dev-overlay/_experimental/internal/components/VersionStalenessInfo/index.tsx deleted file mode 100644 index 51b4b085355b7..0000000000000 --- a/packages/next/src/client/components/react-dev-overlay/_experimental/internal/components/VersionStalenessInfo/index.tsx +++ /dev/null @@ -1,2 +0,0 @@ -export { styles } from './styles' -export { VersionStalenessInfo } from './VersionStalenessInfo' diff --git a/packages/next/src/client/components/react-dev-overlay/_experimental/internal/components/VersionStalenessInfo/styles.ts b/packages/next/src/client/components/react-dev-overlay/_experimental/internal/components/VersionStalenessInfo/styles.ts deleted file mode 100644 index d18218051bf13..0000000000000 --- a/packages/next/src/client/components/react-dev-overlay/_experimental/internal/components/VersionStalenessInfo/styles.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { noop as css } from '../../helpers/noop-template' - -const styles = css` - .nextjs-container-build-error-version-status { - flex: 1; - text-align: right; - font-size: var(--size-font-small); - } - .nextjs-container-build-error-version-status span { - display: inline-block; - width: 10px; - height: 10px; - border-radius: 5px; - background: var(--color-ansi-bright-black); - } - .nextjs-container-build-error-version-status span.fresh { - background: var(--color-ansi-green); - } - .nextjs-container-build-error-version-status span.stale { - background: var(--color-ansi-yellow); - } - .nextjs-container-build-error-version-status span.outdated { - background: var(--color-ansi-red); - } -` - -export { styles } diff --git a/packages/next/src/client/components/react-dev-overlay/_experimental/internal/components/VersionStalenessInfo/version-staleness-info.stories.tsx b/packages/next/src/client/components/react-dev-overlay/_experimental/internal/components/VersionStalenessInfo/version-staleness-info.stories.tsx new file mode 100644 index 0000000000000..1b4391dc67400 --- /dev/null +++ b/packages/next/src/client/components/react-dev-overlay/_experimental/internal/components/VersionStalenessInfo/version-staleness-info.stories.tsx @@ -0,0 +1,94 @@ +import type { Meta, StoryObj } from '@storybook/react' +import { VersionStalenessInfo } from './VersionStalenessInfo' +import { withShadowPortal } from '../../storybook/with-shadow-portal' + +const meta: Meta = { + title: 'VersionStalenessInfo', + component: VersionStalenessInfo, + parameters: { + layout: 'centered', + }, + decorators: [withShadowPortal], +} + +export default meta +type Story = StoryObj + +// Mock version info for different scenarios +const mockVersionInfo = { + fresh: { + installed: '15.0.0', + expected: '15.0.0', + staleness: 'fresh' as const, + }, + stalePatch: { + installed: '15.0.0', + expected: '15.0.1', + staleness: 'stale-patch' as const, + }, + staleMinor: { + installed: '15.0.0', + expected: '15.1.0', + staleness: 'stale-minor' as const, + }, + staleMajor: { + installed: '14.0.0', + expected: '15.0.0', + staleness: 'stale-major' as const, + }, + stalePrerelease: { + installed: '15.0.0-canary.0', + expected: '15.0.0-canary.1', + staleness: 'stale-prerelease' as const, + }, + newerThanNpm: { + installed: '15.0.0-canary.1', + expected: '15.0.0-canary.0', + staleness: 'newer-than-npm' as const, + }, +} + +export const Fresh: Story = { + args: { + versionInfo: mockVersionInfo.fresh, + }, +} + +export const StalePatch: Story = { + args: { + versionInfo: mockVersionInfo.stalePatch, + }, +} + +export const StaleMinor: Story = { + args: { + versionInfo: mockVersionInfo.staleMinor, + }, +} + +export const StaleMajor: Story = { + args: { + versionInfo: mockVersionInfo.staleMajor, + }, +} + +export const StalePrerelease: Story = { + args: { + versionInfo: mockVersionInfo.stalePrerelease, + }, +} + +export const NewerThanNpm: Story = { + args: { + versionInfo: mockVersionInfo.newerThanNpm, + }, +} + +export const Turbopack: Story = { + args: { + versionInfo: { + ...mockVersionInfo.fresh, + }, + isTurbopack: true, + }, +} diff --git a/packages/next/src/client/components/react-dev-overlay/_experimental/internal/styles/Base.tsx b/packages/next/src/client/components/react-dev-overlay/_experimental/internal/styles/Base.tsx index 329326bed98fd..28062f96a8d7c 100644 --- a/packages/next/src/client/components/react-dev-overlay/_experimental/internal/styles/Base.tsx +++ b/packages/next/src/client/components/react-dev-overlay/_experimental/internal/styles/Base.tsx @@ -14,6 +14,8 @@ export function Base() { --size-gap-triple: 24px; --size-gap-quad: 32px; + --size-font-11: 11px; + --size-font-smaller: 12px; --size-font-small: 14px; --size-font: 16px; --size-font-big: 20px; diff --git a/packages/next/src/client/components/react-dev-overlay/_experimental/internal/styles/ComponentStyles.tsx b/packages/next/src/client/components/react-dev-overlay/_experimental/internal/styles/ComponentStyles.tsx index 035f4e3e37aea..5cde9df7126d5 100644 --- a/packages/next/src/client/components/react-dev-overlay/_experimental/internal/styles/ComponentStyles.tsx +++ b/packages/next/src/client/components/react-dev-overlay/_experimental/internal/styles/ComponentStyles.tsx @@ -7,7 +7,7 @@ import { styles as overlay } from '../components/Overlay/styles' import { styles as footer } from '../components/Errors/error-overlay-footer/styles' import { styles as terminal } from '../components/Terminal/styles' import { styles as toast } from '../components/Toast' -import { styles as versionStaleness } from '../components/VersionStalenessInfo' +import { styles as versionStaleness } from '../components/VersionStalenessInfo/VersionStalenessInfo' import { styles as buildErrorStyles } from '../container/BuildError' import { styles as containerErrorStyles } from '../container/Errors' import { styles as containerRuntimeErrorStyles } from '../container/RuntimeError' diff --git a/packages/next/src/client/components/react-dev-overlay/_experimental/internal/styles/colors.tsx b/packages/next/src/client/components/react-dev-overlay/_experimental/internal/styles/colors.tsx index 3d32b3c99917c..90f7236c5a8a0 100644 --- a/packages/next/src/client/components/react-dev-overlay/_experimental/internal/styles/colors.tsx +++ b/packages/next/src/client/components/react-dev-overlay/_experimental/internal/styles/colors.tsx @@ -6,11 +6,11 @@ export function Colors() {