Files
vending-machine-game/src/pages/game/startScreen/StartScreen.jsx
T
HamedandClaude Opus 5.5 5a4dffc9a3 feat: minimal HUD with one floating menu and objective chip
Phase 4 of turning the game into the company landing page.

- Only the menu button, a compact objective chip and the touch
  controls stay on screen; speed shows only while driving.
- The objective chip shows the next goal in one line, its distance and
  an arrow that turns towards it (replaces the compass strip); tapping
  it opens the mission list.
- One floating menu holds map, missions, status, products, real-world,
  camera, stable mode, sound, graphics, minimap, fullscreen, help,
  restart and back to the start screen. It closes on a second tap, a
  tap outside, Escape, or after an action.
- Missions, status and help open as sheets; street label, rank bar,
  status panel, toolbar and compass are gone. The minimap is optional
  and off by default.
- Share the icon set and sheet dialog between start screen and HUD.
- Layout checked for phone portrait, landscape and safe areas.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-31 08:50:29 +03:30

75 lines
2.8 KiB
React

import { useState } from 'react';
import { GameNode } from '@/components/shared/GameNode.jsx';
import { COMPANY } from '@/config/company.js';
import { ASSETS } from '@/config/assets.js';
import { strings } from '@/i18n/fa.js';
import { Icon } from '@/components/shared/Icon.jsx';
import { StartOptions } from './StartOptions.jsx';
import { InfoSheet } from './InfoSheet.jsx';
// Company information links under the start buttons, with their icons.
const SECTIONS = [
['about', 'building'],
['contact', 'phone'],
['address', 'map'],
['faq', 'help'],
['careers', 'briefcase'],
['gallery', 'image'],
['social', 'share'],
];
/** @typedef {{nodes: object, actions: object}} StartScreenProps */
/**
* Landing-page style start screen over the slowly orbiting 3D factory: brand, the four ways
* into the game, and the company information a website would normally show.
* @param {StartScreenProps} props - Interface snapshots and actions.
* @returns {import('react').ReactElement} Start screen.
*/
export function StartScreen({ nodes, actions }) {
const [section, setSection] = useState(null);
const text = strings.landing;
return (
<GameNode as="section" id="landing" aria-labelledby="landing-title" model={nodes.landing}>
<div className="landing-panel">
<header className="flex items-center gap-3">
<img src={ASSETS.brand.logo} alt={text.logoAlt} className="h-12 w-12 rounded-xl" />
<div>
<p className="text-lg font-bold">{COMPANY.shortName}</p>
<p className="text-sm text-primary">{COMPANY.tagline}</p>
</div>
</header>
<div className="my-6 md:my-10">
<h1 id="landing-title" className="text-2xl font-black leading-snug md:text-4xl">
{text.heading}
</h1>
<p className="mt-3 max-w-md opacity-80">{text.intro}</p>
</div>
<StartOptions actions={actions} />
<nav aria-label={text.sectionsLabel} className="mt-6 flex flex-wrap gap-2">
{SECTIONS.map(([key, icon]) => (
<button key={key} type="button" className="start-chip" onClick={() => setSection(key)}>
<Icon name={icon} className="h-4 w-4" />
{key === 'about' ? text.history : text.sections[key]}
</button>
))}
<GameNode
as="button"
id="install"
type="button"
className="start-chip"
hidden
model={nodes.install}
onAction={() => actions.emit('install')}
>
<Icon name="download" className="h-4 w-4" />
{text.install}
</GameNode>
</nav>
<p className="mt-6 hidden text-xs opacity-60 md:block">{text.keys}</p>
</div>
<InfoSheet section={section} onClose={() => setSection(null)} />
</GameNode>
);
}