feat(homepage): enhance localization and integrate loading label for code snippet

- Added 'loadingLabel' to the Props type in GregCoreRandomSnippet for dynamic loading text.
- Updated English localization to include 'codeSnippetLoading' for improved user experience.
- Modified the homepage to utilize the new loading label in the GregCoreRandomSnippet component, enhancing clarity during content loading.

This commit improves the user interface by providing a more informative loading state for code snippets.
This commit is contained in:
Marvin
2026-04-10 04:03:23 +02:00
parent b8df049b4e
commit 533c7a2729
5 changed files with 130 additions and 90 deletions

View File

@@ -3,8 +3,8 @@ import BrowserOnly from '@docusaurus/BrowserOnly';
import {GREG_CORE_SNIPPETS} from '../data/gregCoreSnippets'; import {GREG_CORE_SNIPPETS} from '../data/gregCoreSnippets';
type Props = { type Props = {
/** e.g. "Random sample from gregCore" */
caption: string; caption: string;
loadingLabel: string;
}; };
/** /**
@@ -51,7 +51,7 @@ export function GregCoreRandomSnippet(props: Props): JSX.Element {
aria-busy aria-busy
> >
<div className="flex min-h-[280px] items-center justify-center rounded-lg bg-surface-container-lowest p-6"> <div className="flex min-h-[280px] items-center justify-center rounded-lg bg-surface-container-lowest p-6">
<span className="text-sm text-on-surface-variant">Loading code sample</span> <span className="text-sm text-on-surface-variant">{props.loadingLabel}</span>
</div> </div>
</div> </div>
}> }>

View File

@@ -3,60 +3,66 @@ import { homepageShellEn } from './sharedLinks';
export const en: HomepageContent = { export const en: HomepageContent = {
...homepageShellEn, ...homepageShellEn,
heroLine1: 'DATACENTER MODDING HUB.', heroLine1: 'Play with mods.',
heroLine2: 'SMART LIKE GREG.', heroLine2: 'Ship with confidence.',
heroSub1: 'Install mods, use the Workshop, fix common issues — without digging through engine docs.', heroSub1:
heroSub2: 'Technical reference for authors lives under Developers in the wiki.', 'Player guides cover install, Workshop, and common fixes—without engine deep dives.',
ctaStart: 'HELP FOR PLAYERS', heroSub2: 'Authors get hooks, APIs, and repo layout under Developers in the wiki.',
ctaMods: 'MOD CATALOG', ctaStart: 'Player guides',
ctaModManager: 'DOWNLOAD MOD MANAGER', ctaMods: 'Mod catalog',
ctaModManager: 'Download Greg Mod Manager',
modManagerSectionTitle: 'Greg Mod Manager', modManagerSectionTitle: 'Greg Mod Manager',
modManagerSectionBody: modManagerSectionBody:
'The Gregtools desktop app for Workshop browsing, uploads, dependency checks, and project metadata. Builds are published on GitHub — use the button below to open the latest release (the URL always tracks the newest version).', 'Desktop app from the Gregtools project: Workshop browsing, installs, dependency checks, and project metadata. The download button opens GitHubs latest release (the URL always points at the newest build).',
modManagerDownloadLabel: 'Download latest release', modManagerDownloadLabel: 'Download latest release',
modManagerLatestHint: modManagerLatestHint: 'Uses GitHubs /releases/latest redirect so you always get current assets.',
'Uses GitHubs /releases/latest redirect so you always land on the current release assets.', docsPaths: 'Documentation',
docsPaths: 'Documentation paths', featureTitles: [
featureTitles: ['Play with mods', 'Workshop & updates', 'Clear docs', 'Community'], 'Player-first guides',
'Workshop and updates',
'Structured wiki',
'Community',
],
featureDescriptions: [ featureDescriptions: [
'Step-by-step paths for installing and troubleshooting — no repo jargon on day one.', 'Step-by-step install and troubleshooting. No repository jargon on day one.',
'GregModManager and release channels explain where builds come from.', 'Greg Mod Manager and the release-channels page explain where mods are published.',
'A few flat player pages up top; author pages stay under Developers.', 'Short paths for players; technical depth lives under Developers.',
'Discord and GitHub for help — framework internals only when you need them.', 'Discord and GitHub for support—dig into gregCore only when you need to.',
], ],
comingSoon: 'Coming soon', comingSoon: 'Coming soon',
comingSoonText: comingSoonText:
'`datacentermods.com` is in preparation. Until launch, use the wiki **For players** and the **Mod catalog**.', 'datacentermods.com is in preparation. Until it launches, use the player guides in the wiki and the mod catalog on this site.',
communityTitle: 'Community & maintainers', communityTitle: 'Community',
communityText: 'This portal is designed for gregFramework docs and community-built plugins across the Data Center ecosystem.', communityText:
docsEndUserTitle: 'End-user', 'This site documents gregFramework, community mods, and plugins for Data Center Simulator.',
docsEndUserTitle: 'Players',
docsEndUserDescription: 'Install, update, FAQ, troubleshooting.', docsEndUserDescription: 'Install, update, FAQ, troubleshooting.',
docsModDevsTitle: 'Mod developers', docsModDevsTitle: 'Mod developers',
docsModDevsDescription: 'Debug workflows, setup, hooks and references.', docsModDevsDescription: 'Setup, debugging, hooks, and references.',
docsContributorsTitle: 'Contributors', docsContributorsTitle: 'Contributors',
docsContributorsDescription: 'Conventions, CI checks, contribution workflow.', docsContributorsDescription: 'Conventions, CI, and docs workflow.',
docsCapabilityTitle: 'Capability matrix', docsCapabilityTitle: 'Capability matrix',
docsCapabilityDescription: 'Complete feature map and implementation use cases.', docsCapabilityDescription: 'Feature map and implementation notes.',
ecosystemTitle: 'Ecosystem coverage', ecosystemTitle: 'Ecosystem',
ecosystemCoreTitle: 'gregFramework core', ecosystemCoreTitle: 'gregFramework core',
ecosystemCoreDescription: 'Hook system, FFI bridge, event contracts and runtime architecture.', ecosystemCoreDescription: 'Hooks, events, optional FFI bridge, and runtime architecture.',
ecosystemCoreCta: 'Open core docs', ecosystemCoreCta: 'Open core docs',
ecosystemRustTitle: 'Standalone Rust', ecosystemRustTitle: 'Rust and FFI',
ecosystemRustDescription: 'Rust/FFI implementation guides for external and standalone runtimes.', ecosystemRustDescription: 'Guides for external and standalone runtimes.',
ecosystemRustCta: 'Open Rust/FFI docs', ecosystemRustCta: 'Open Rust / FFI docs',
ecosystemMultiplayerTitle: 'Multiplayer & plugins', ecosystemMultiplayerTitle: 'Multiplayer and plugins',
ecosystemMultiplayerDescription: 'Multiplayer roadmap, plugin docs, and community module references.', ecosystemMultiplayerDescription: 'Roadmap, plugin docs, and related modules.',
ecosystemMultiplayerCta: 'Open multiplayer docs', ecosystemMultiplayerCta: 'Open multiplayer docs',
gregTitle: 'The legend of Greg', gregTitle: 'Greg',
gregText1: gregText1:
'Greg is the tireless server technician of this project. He looks like he has not slept for months, and he is usually quiet — but once a rack fails or a mod breaks, Greg is already there.', 'Greg is the projects mascot: the technician who shows up when a rack misbehaves or a build breaks. Calm, practical, slightly tired.',
gregText2: gregText2:
'He quietly fulfills your wishes: more uptime, cleaner configs, better logs and less deployment drama. He does not ask much, he just ships.', 'The framework tries to be the same—clear docs, predictable hooks, less guesswork when you mod or maintain.',
gregQuote: '"Be smart. Be like Greg."', gregQuote: 'Be smart. Be like Greg.',
supportTitle: 'Support', supportTitle: 'Issues and feedback',
supportText: 'Report bugs, request docs for new community plugins, and track workstreams.', supportText: 'Report bugs, suggest doc improvements, and follow work on GitHub.',
supportCta: 'Open GitHub issues', supportCta: 'GitHub issues',
availableModsLabel: 'Available mods', availableModsLabel: 'Mod catalog',
repositoryLabel: 'Repository', repositoryLabel: 'gregFramework on GitHub',
joinLabel: 'JOIN', joinLabel: 'Discord',
}; };

View File

@@ -1,41 +1,49 @@
import type {HomepageContent, HomepageDocLink} from './types'; import type {HomepageContent, HomepageDocLink} from './types';
/** Player-first links — technical docs live under /wiki/developers */ /** Player-facing wiki entry points */
export const sharedKnowledgeLinksEn: HomepageDocLink[] = [ export const sharedKnowledgeLinksEn: HomepageDocLink[] = [
{title: 'Wiki home', description: 'Short entry — players vs developers.', link: '/wiki'},
{ {
title: 'For players', title: 'Wiki home',
description: 'Install, update, troubleshooting.', description: 'Overview: players, authors, and where each topic lives.',
link: '/wiki',
},
{
title: 'Player guides',
description: 'Install mods, updates, troubleshooting, and FAQs.',
link: '/wiki/guides/players/overview', link: '/wiki/guides/players/overview',
}, },
{ {
title: 'Greg Mod Manager', title: 'Greg Mod Manager',
description: 'Browse, install, and manage Workshop mods (Gregtools desktop app).', description: 'Desktop app for the Workshop: browse, install, and manage mods.',
link: '/wiki/guides/players/enduser-workshop', link: '/wiki/guides/players/enduser-workshop',
}, },
{ {
title: 'Release channels', title: 'Release channels',
description: 'Steam Workshop vs GitHub for builds.', description: 'Where builds come from: Steam Workshop and GitHub.',
link: '/wiki/reference/release-channels', link: '/wiki/reference/release-channels',
}, },
{title: 'Mod catalog', description: 'Modules with docs and download links.', link: '/mods'}, {
title: 'Mod catalog',
description: 'Listings with docs, versions, and download links.',
link: '/mods',
},
]; ];
/** Authors & contributors — one hop to the full technical tree */ /** Authors and repo contributors */
export const sharedWorkflowLinksEn: HomepageDocLink[] = [ export const sharedWorkflowLinksEn: HomepageDocLink[] = [
{ {
title: 'Developers (hub)', title: 'Developers hub',
description: 'Framework, mods, plugins, reference, roadmap — all technical links.', description: 'Framework, hooks, plugins, reference material, and roadmap.',
link: '/wiki/developers', link: '/wiki/developers',
}, },
{ {
title: 'Mod developer guide', title: 'Mod developer guide',
description: 'Hooks, setup, and workflow entry.', description: 'MelonLoader setup, gregCore hooks, and workflow.',
link: '/wiki/guides/mod-developers/overview', link: '/wiki/guides/mod-developers/overview',
}, },
{ {
title: 'Contributor workflow', title: 'Contributor workflow',
description: 'Docs site and repo conventions.', description: 'How this docs site and the repos are maintained.',
link: '/wiki/contributors/docusaurus-workflow', link: '/wiki/contributors/docusaurus-workflow',
}, },
]; ];
@@ -50,24 +58,33 @@ export const homepageShellEn: Pick<
| 'codeSectionTitle' | 'codeSectionTitle'
| 'codeSectionLead' | 'codeSectionLead'
| 'codeSnippetCaption' | 'codeSnippetCaption'
| 'codeSnippetLoading'
| 'codeSectionBullets'
| 'ctaDiscordTitle' | 'ctaDiscordTitle'
| 'ctaDiscordLead' | 'ctaDiscordLead'
| 'ctaDiscordButton' | 'ctaDiscordButton'
| 'knowledgeLinks' | 'knowledgeLinks'
| 'workflowLinks' | 'workflowLinks'
> = { > = {
heroBadge: 'gregFramework · docs live', heroBadge: 'Documentation · Data Center modding',
heroBrandLine1: 'greg', heroBrandLine1: 'greg',
heroBrandLine2Gradient: 'Framework', heroBrandLine2Gradient: 'Framework',
knowledgeSectionTitle: 'Players — start here', knowledgeSectionTitle: 'Start here',
workflowSectionTitle: 'Authors & contributors', workflowSectionTitle: 'For authors and contributors',
codeSectionTitle: 'Building on gregFramework', codeSectionTitle: 'How mods connect to the game',
codeSectionLead: codeSectionLead:
'C# mods on MelonLoader, Harmony hooks in gregCore, and optional Rust bridges — author details are under Developers.', 'Mods use MelonLoader and Harmony. gregCore turns game methods into stable greg.* events your code can subscribe to—details are under Developers.',
codeSnippetCaption: 'Random sample from gregCore', codeSnippetCaption: 'Random excerpt from gregCore',
ctaDiscordTitle: 'Community', codeSnippetLoading: 'Loading code sample…',
ctaDiscordLead: 'Questions about playing or building — ask in Discord.', codeSectionBullets: [
ctaDiscordButton: 'Join Discord', 'gregCore patches the game and emits typed greg.* hook names (see greg_hooks.json).',
'The wiki and catalog list each mod with releases and dependencies.',
'Source is split across repos (for example gregCore, gregMods, gregExtensions, gregWiki).',
],
ctaDiscordTitle: 'Questions?',
ctaDiscordLead:
'Ask in Discord for install issues, mod compatibility, or help building on gregFramework.',
ctaDiscordButton: 'Open Discord',
knowledgeLinks: sharedKnowledgeLinksEn, knowledgeLinks: sharedKnowledgeLinksEn,
workflowLinks: sharedWorkflowLinksEn, workflowLinks: sharedWorkflowLinksEn,
}; };

View File

@@ -25,8 +25,12 @@ export type HomepageContent = {
workflowSectionTitle: string; workflowSectionTitle: string;
codeSectionTitle: string; codeSectionTitle: string;
codeSectionLead: string; codeSectionLead: string;
/** Homepage #code — random gregCore excerpt */ /** Homepage #code — random gregCore excerpt (card title) */
codeSnippetCaption: string; codeSnippetCaption: string;
/** Shown while BrowserOnly mounts */
codeSnippetLoading: string;
/** Three bullets beside the gregCore snippet */
codeSectionBullets: [string, string, string];
ctaDiscordTitle: string; ctaDiscordTitle: string;
ctaDiscordLead: string; ctaDiscordLead: string;
ctaDiscordButton: string; ctaDiscordButton: string;

View File

@@ -21,6 +21,26 @@ const GREG_MODMANAGER_LATEST =
const viewport = {once: true, margin: '-90px'}; const viewport = {once: true, margin: '-90px'};
/** Inline `greg_hooks.json` in copy when the string contains that token. */
function formatBulletWithOptionalCode(text: string): React.ReactNode {
if (!text.includes('greg_hooks.json')) {
return text;
}
const parts = text.split('greg_hooks.json');
return (
<>
{parts.map((part, i) => (
<React.Fragment key={i}>
{part}
{i < parts.length - 1 ? (
<code className="text-xs">greg_hooks.json</code>
) : null}
</React.Fragment>
))}
</>
);
}
function buildVariants(reducedMotion: boolean) { function buildVariants(reducedMotion: boolean) {
const section: Variants = reducedMotion const section: Variants = reducedMotion
? {hidden: {opacity: 0}, show: {opacity: 1}} ? {hidden: {opacity: 0}, show: {opacity: 1}}
@@ -81,7 +101,7 @@ export default function HomePage(): JSX.Element {
return ( return (
<Layout <Layout
title="Home" title="Home"
description="Help for Data Center players using mods — plus developer docs under /wiki/developers." description="gregFramework documentation: player guides, mod catalog, and developer references for Data Center Simulator."
> >
<main className="bg-background text-on-surface font-sans min-h-screen editorial-bleed bg-hero-gradient"> <main className="bg-background text-on-surface font-sans min-h-screen editorial-bleed bg-hero-gradient">
<section className="hero-motion-wrap relative flex min-h-[72vh] flex-col items-center justify-center overflow-hidden px-4 py-24 text-center"> <section className="hero-motion-wrap relative flex min-h-[72vh] flex-col items-center justify-center overflow-hidden px-4 py-24 text-center">
@@ -301,27 +321,20 @@ export default function HomePage(): JSX.Element {
{t.codeSectionLead} {t.codeSectionLead}
</p> </p>
<ul className="space-y-4 text-on-surface-variant"> <ul className="space-y-4 text-on-surface-variant">
<li className="flex items-start gap-3"> {t.codeSectionBullets.map((line) => (
<span className="material-symbols-outlined mt-0.5 text-primary"> <li key={line} className="flex items-start gap-3">
<span className="material-symbols-outlined mt-0.5 shrink-0 text-primary">
check_circle check_circle
</span> </span>
<span>MelonLoader + Harmony: gregCore emits typed <code className="text-xs">greg.*</code> events</span> <span>{formatBulletWithOptionalCode(line)}</span>
</li>
<li className="flex items-start gap-3">
<span className="material-symbols-outlined mt-0.5 text-primary">
check_circle
</span>
<span>Plugins and mods documented beside release metadata</span>
</li>
<li className="flex items-start gap-3">
<span className="material-symbols-outlined mt-0.5 text-primary">
check_circle
</span>
<span>Split repos: gregCore, gregMods, gregExtensions, gregWiki</span>
</li> </li>
))}
</ul> </ul>
</div> </div>
<GregCoreRandomSnippet caption={t.codeSnippetCaption} /> <GregCoreRandomSnippet
caption={t.codeSnippetCaption}
loadingLabel={t.codeSnippetLoading}
/>
</div> </div>
</motion.section> </motion.section>