Step 29.8: Shipyard, Places, Start, Welcome and the remaining screens
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
4a33aed970
commit
613b06a83d
|
|
@ -352,7 +352,7 @@ function Totals({ summary }: { summary: Summary }) {
|
|||
return (
|
||||
<dl
|
||||
aria-label="Company totals"
|
||||
className="grid grid-flow-col gap-2 rounded-xl border border-cyan-400/30 bg-cyan-950/30 p-3"
|
||||
className="grid grid-flow-col gap-2 rounded-xl border border-glass-line bg-white/5 p-3"
|
||||
>
|
||||
{figures.map(([label, value, tone]) => (
|
||||
<div key={label}>
|
||||
|
|
|
|||
|
|
@ -4,13 +4,35 @@ import { useLoadedPlayer } from "../state/actions";
|
|||
/** Fleet's two views, Ships and Crew (decision 0.5.167). */
|
||||
export function FleetViews() {
|
||||
const state = useLoadedPlayer();
|
||||
const views = [
|
||||
{ to: "/fleet", label: `Ships ${state.ships.length}` },
|
||||
{ to: "/pilots", label: `Crew ${state.pilots.length}` },
|
||||
];
|
||||
return (
|
||||
<Views
|
||||
label="Fleet views"
|
||||
views={[
|
||||
{ to: "/fleet", label: `Ships ${state.ships.length}` },
|
||||
{ to: "/pilots", label: `Crew ${state.pilots.length}` },
|
||||
]}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
/** Places and HQs, under More (decision 0.5.167). */
|
||||
export function PlacesViews() {
|
||||
const state = useLoadedPlayer();
|
||||
return (
|
||||
<Views
|
||||
label="Places views"
|
||||
views={[
|
||||
{ to: "/locations", label: "Places" },
|
||||
{ to: "/hqs", label: `HQs ${state.bays.length}` },
|
||||
]}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
function Views({ label, views }: { label: string; views: { to: string; label: string }[] }) {
|
||||
return (
|
||||
<nav
|
||||
aria-label="Fleet views"
|
||||
aria-label={label}
|
||||
className="flex gap-0.5 rounded-xl border border-glass-line bg-black/25 p-0.5"
|
||||
>
|
||||
{views.map((view) => (
|
||||
|
|
|
|||
|
|
@ -124,7 +124,7 @@ function EntryLine({ entry, state }: { entry: LogEntry; state: PlayerState }) {
|
|||
{entry.loanRepayment > 0 && (
|
||||
<span className="text-ink-400">lender {formatCredits(entry.loanRepayment)}</span>
|
||||
)}
|
||||
{entry.xp > 0 && <span className="text-violet-300">+{entry.xp} XP</span>}
|
||||
{entry.xp > 0 && <span className="text-ink-300">+{entry.xp} XP</span>}
|
||||
</>
|
||||
);
|
||||
case "refuel":
|
||||
|
|
@ -202,7 +202,7 @@ function PilotSection({ log, state, open }: { log: PilotLog; state: PlayerState;
|
|||
<details open={open} className="rounded-xl border border-glass-line bg-black/25 p-3">
|
||||
<summary className="flex cursor-pointer items-baseline justify-between gap-2">
|
||||
<span className="font-display font-bold">{log.name}</span>
|
||||
{log.xp > 0 && <span className="text-xs text-violet-300">+{log.xp} XP</span>}
|
||||
{log.xp > 0 && <span className="text-xs text-ink-300">+{log.xp} XP</span>}
|
||||
</summary>
|
||||
{log.now && (
|
||||
<p aria-label={`${log.name} now`} className="mt-1 text-ink-100">
|
||||
|
|
@ -238,7 +238,7 @@ export function PilotLogbook({ logbook, state }: { logbook: Logbook; state: Play
|
|||
<section aria-label="Pilot logbook" className="space-y-3 text-sm">
|
||||
<div
|
||||
aria-label="Logbook totals"
|
||||
className="grid grid-cols-2 gap-x-3 gap-y-1 rounded-xl border border-cyan-400/40 bg-cyan-950/30 p-3 sm:grid-cols-4"
|
||||
className="grid grid-cols-2 gap-x-3 gap-y-1 rounded-xl border border-glass-line bg-white/5 p-3 sm:grid-cols-4"
|
||||
>
|
||||
<span>{totals.jobs} jobs</span>
|
||||
<span>{totals.deadheads} deadheads</span>
|
||||
|
|
@ -249,7 +249,7 @@ export function PilotLogbook({ logbook, state }: { logbook: Logbook; state: Play
|
|||
<span className={totals.net < 0 ? "text-rose-300" : "text-emerald-300"}>
|
||||
{formatCredits(totals.net)} net
|
||||
</span>
|
||||
<span className="text-violet-300">+{totals.xp} XP</span>
|
||||
<span className="text-ink-300">+{totals.xp} XP</span>
|
||||
</div>
|
||||
{logbook.pilots.length === 0 ? (
|
||||
<p className="text-ink-400">Nothing logged in this time.</p>
|
||||
|
|
@ -285,7 +285,7 @@ export function CatchingUp({ busy, delayMs = 500 }: { busy: boolean; delayMs?: n
|
|||
return (
|
||||
<p
|
||||
role="status"
|
||||
className="fixed top-3 left-1/2 z-40 -translate-x-1/2 rounded-full border border-cyan-400/50 bg-white/5 px-4 py-1.5 font-display text-sm text-ink-100 shadow-panel"
|
||||
className="fixed top-3 left-1/2 z-40 -translate-x-1/2 rounded-full border border-glass-line bg-white/5 px-4 py-1.5 font-display text-sm text-ink-100 shadow-panel"
|
||||
>
|
||||
Catching up on your fleet…
|
||||
</p>
|
||||
|
|
|
|||
|
|
@ -80,7 +80,7 @@ export function ServiceTag({ ship }: { ship: Ship }) {
|
|||
<p
|
||||
role="status"
|
||||
aria-label={`${ship.name} service`}
|
||||
className={`rounded-lg border px-3 py-1.5 text-sm ${warn ? "border-amber-400/40 bg-amber-950/30 text-ink-100" : "border-cyan-400/40 bg-cyan-950/30 text-ink-100"}`}
|
||||
className={`rounded-lg border px-3 py-1.5 text-sm ${warn ? "border-amber-400/40 bg-amber-950/30 text-ink-100" : "border-glass-line bg-white/5 text-ink-100"}`}
|
||||
>
|
||||
{tag}
|
||||
</p>
|
||||
|
|
|
|||
|
|
@ -22,8 +22,8 @@ function useViewportWidth(): number {
|
|||
|
||||
const TONES: Record<Toast["tone"], string> = {
|
||||
good: "border-emerald-400/40 text-emerald-50",
|
||||
info: "border-cyan-400/40 text-cyan-50",
|
||||
warn: "border-amber-400/50 text-amber-50",
|
||||
info: "border-glass-line text-ink-50",
|
||||
warn: "border-action/50 text-ink-50",
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -85,13 +85,13 @@ export function WelcomeCards({
|
|||
if (from - to > 50) advance();
|
||||
else if (to - from > 50 && index > 0) setIndex(index - 1);
|
||||
}}
|
||||
className="w-full max-w-md overflow-hidden rounded-t-2xl border border-amber-400/50 bg-white/5 p-6 pb-[max(1.5rem,env(safe-area-inset-bottom))] shadow-panel sm:rounded-2xl"
|
||||
className="w-full max-w-md overflow-hidden rounded-t-2xl border border-glass-line bg-space-850 p-6 pb-[max(1.5rem,env(safe-area-inset-bottom))] shadow-panel sm:rounded-2xl"
|
||||
>
|
||||
<p aria-live="polite" className="font-display text-xs font-semibold text-ink-300">
|
||||
{index + 1} of {cards.length}
|
||||
</p>
|
||||
<div key={index} data-testid="welcome-card" className={reduced ? "" : "animate-slide"}>
|
||||
<h2 id="welcome-title" className="mt-2 font-display text-2xl font-bold text-amber-300">
|
||||
<h2 id="welcome-title" className="mt-2 font-title text-lg leading-snug">
|
||||
{card.title}
|
||||
</h2>
|
||||
<p className="mt-3 text-ink-200">{welcomeBody(card.body)}</p>
|
||||
|
|
@ -100,7 +100,7 @@ export function WelcomeCards({
|
|||
{cards.map((_, i) => (
|
||||
<span
|
||||
key={i}
|
||||
className={`h-1.5 rounded-full ${i === index ? "w-5 bg-amber-300" : "w-1.5 bg-space-600"}`}
|
||||
className={`h-1.5 rounded-full ${i === index ? "w-5 bg-action" : "w-1.5 bg-white/25"}`}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -126,7 +126,7 @@ export function PanelHost({ children }: { children: ReactNode }) {
|
|||
"--sheet-h": `${dragPx ?? detentPx(detent, globalThis.innerHeight ?? 800)}px`,
|
||||
} as React.CSSProperties
|
||||
}
|
||||
className={`absolute inset-x-0 bottom-(--nav-h) z-10 flex h-(--sheet-h) flex-col rounded-t-3xl border-t border-glass-line bg-glass shadow-panel md:top-4 md:right-4 md:bottom-auto md:left-auto md:h-auto md:max-h-[calc(100%-2rem)] md:w-(--panel-w) md:rounded-3xl md:border md:backdrop-blur-xl ${
|
||||
className={`absolute inset-x-0 bottom-(--nav-h) z-10 flex h-(--sheet-h) flex-col rounded-t-3xl border-t border-glass-line bg-space-850/97 shadow-panel md:bg-glass md:top-4 md:right-4 md:bottom-auto md:left-auto md:h-auto md:max-h-[calc(100%-2rem)] md:w-(--panel-w) md:rounded-3xl md:border md:backdrop-blur-xl ${
|
||||
dragPx === null ? "transition-[height] duration-300 ease-out" : ""
|
||||
}`}
|
||||
>
|
||||
|
|
|
|||
|
|
@ -138,7 +138,7 @@ function ShipRow(props: {
|
|||
? `${locationName(dispatch.originId)} → ${locationName(dispatch.destinationId)}`
|
||||
: `At ${locationName(ship.locationId ?? "")}`}
|
||||
{" · "}
|
||||
<span className={pilotName ? "text-ink-300" : "text-amber-300"}>
|
||||
<span className={pilotName ? "text-ink-300" : "text-problem"}>
|
||||
{pilotName ?? "No pilot"}
|
||||
</span>
|
||||
</span>
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import { PlacesViews } from "../components/FleetViews";
|
||||
import { content } from "@deadhead/content";
|
||||
import type { Bay } from "@deadhead/schema";
|
||||
import { Link } from "react-router";
|
||||
|
|
@ -22,6 +23,7 @@ export function HQs() {
|
|||
icon="hq"
|
||||
subtitle={state.bays.length > 0 ? HQ_ALLOWS : undefined}
|
||||
/>
|
||||
<PlacesViews />
|
||||
{state.bays.length === 0 ? (
|
||||
<Panel tone="muted" className="space-y-3 text-sm">
|
||||
<p className="text-ink-200">You don't have an HQ yet.</p>
|
||||
|
|
@ -58,7 +60,7 @@ function HqCard({ bay }: { bay: Bay }) {
|
|||
);
|
||||
|
||||
return (
|
||||
<Panel as="li" tone="emerald" aria-label={`HQ at ${name}`} className="text-sm">
|
||||
<Panel as="li" aria-label={`HQ at ${name}`} className="text-sm">
|
||||
<div className="flex items-center gap-4">
|
||||
{location && (
|
||||
<Art
|
||||
|
|
|
|||
|
|
@ -96,7 +96,7 @@ export function JobsTable({
|
|||
New
|
||||
</Pill>
|
||||
)}
|
||||
<ClassChip contract={contract} />
|
||||
{contract.cargoTypeId !== "standard" && <ClassChip contract={contract} />}
|
||||
{contract.priority && contract.deliveryWindowGameHours !== null && (
|
||||
<PriorityChip windowHours={contract.deliveryWindowGameHours} />
|
||||
)}
|
||||
|
|
@ -132,7 +132,7 @@ export function JobsTable({
|
|||
<div className="hidden text-xs leading-snug text-ink-400 @2xl:block">
|
||||
Pays <span>{formatCredits(contract.payout)}</span> ·{" "}
|
||||
{formatMillionKm(distanceAt(contract.originId, contract.destinationId))} ·{" "}
|
||||
{requirements ? `Needs ${requirements}` : "No skills needed"} · expires in{" "}
|
||||
{requirements && `Needs ${requirements} · `}expires in{" "}
|
||||
<Countdown to={contract.expiresAt} done="expired" />
|
||||
</div>
|
||||
</td>
|
||||
|
|
|
|||
|
|
@ -175,7 +175,7 @@ function LocationBoard({
|
|||
{fresh.size > 0 && (
|
||||
<span
|
||||
role="status"
|
||||
className="ml-2 animate-rise rounded-full border border-cyan-400/50 bg-cyan-500/15 px-2 py-0.5 text-ink-100 normal-case"
|
||||
className="ml-2 animate-rise rounded-full border border-glass-line bg-white/5 px-2 py-0.5 text-ink-100 normal-case"
|
||||
>
|
||||
New contracts posted
|
||||
</span>
|
||||
|
|
@ -278,7 +278,6 @@ function NothingHere({
|
|||
key={ship.id}
|
||||
role="group"
|
||||
aria-label={`Nothing for ${ship.name}`}
|
||||
tone="cyan"
|
||||
className="text-sm"
|
||||
>
|
||||
<p className="flex items-center gap-2 text-ink-100">
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import { PlacesViews } from "../components/FleetViews";
|
||||
import { content, type Location } from "@deadhead/content";
|
||||
import { FuelPrice } from "../components/Fuel";
|
||||
import { Link } from "react-router";
|
||||
|
|
@ -27,7 +28,8 @@ export function Locations() {
|
|||
|
||||
return (
|
||||
<Screen>
|
||||
<ScreenHeader title="Places" eyebrow="Known space" icon="places" />
|
||||
<ScreenHeader title="Places" icon="places" />
|
||||
<PlacesViews />
|
||||
{lease.isError && (
|
||||
<p role="alert" className="text-sm text-rose-300">
|
||||
{errorMessage(lease.error)}
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ export function Logbook() {
|
|||
}
|
||||
|
||||
return (
|
||||
<Screen className="max-w-3xl">
|
||||
<Screen>
|
||||
<ScreenHeader title="Logbook" eyebrow="The last 7 days" icon="route" />
|
||||
<Panel className="flex flex-wrap items-end gap-3 text-sm" aria-label="Logbook filters">
|
||||
<label className="flex flex-col gap-1">
|
||||
|
|
|
|||
|
|
@ -30,7 +30,6 @@ export function Market() {
|
|||
<Screen>
|
||||
<ScreenHeader
|
||||
title="Shipyard"
|
||||
eyebrow="Shipyard"
|
||||
icon="market"
|
||||
subtitle="New ships are delivered with no pilot to one of your HQs."
|
||||
/>
|
||||
|
|
@ -53,17 +52,16 @@ export function Market() {
|
|||
const affordable = state.company.credits >= model.price;
|
||||
return (
|
||||
<Panel as="li" key={model.id} className="flex flex-col text-sm">
|
||||
<div className="relative -mx-4 -mt-4 grid h-40 place-items-center overflow-hidden rounded-t-xl bg-radial from-cyan-400/20 via-space-850/40 to-transparent to-75%">
|
||||
<div className="absolute inset-x-8 bottom-4 h-3 rounded-[50%] bg-cyan-300/15 blur-md" />
|
||||
<div className="relative -mt-1 grid h-32 place-items-center">
|
||||
<Art
|
||||
sprite={model.sprite}
|
||||
className="relative size-32 rotate-[30deg] drop-shadow-[0_10px_14px_rgb(0_0_0/0.8)]"
|
||||
className="relative size-28 drop-shadow-[0_10px_14px_rgb(0_0_0/0.8)]"
|
||||
/>
|
||||
</div>
|
||||
<div className="mt-2 flex items-baseline justify-between gap-2">
|
||||
<span className="font-display text-xl font-bold">{model.name}</span>
|
||||
<span className="text-lg font-semibold">{model.name}</span>
|
||||
<span
|
||||
className={`font-display text-base font-bold tabular-nums ${affordable ? "text-amber-300" : "text-ink-400"}`}
|
||||
className={`font-semibold tabular-nums ${affordable ? "text-ink-50" : "text-ink-300"}`}
|
||||
>
|
||||
{formatCredits(model.price)}
|
||||
</span>
|
||||
|
|
@ -94,6 +92,7 @@ export function Market() {
|
|||
<OwnedUpgraded modelId={model.id} />
|
||||
<Button
|
||||
aria-label={`Buy ${model.name}`}
|
||||
variant="secondary"
|
||||
block
|
||||
disabled={!affordable || state.bays.length === 0 || buy.isPending}
|
||||
onClick={() => setBuying(model)}
|
||||
|
|
@ -133,7 +132,7 @@ function Spec(props: { icon: IconName; label: string; value: string; share?: num
|
|||
{props.share !== undefined && (
|
||||
<div aria-hidden="true" className="mt-1 h-1 overflow-hidden rounded-full bg-black/25">
|
||||
<div
|
||||
className="h-full rounded-full bg-linear-to-r from-cyan-500 to-sky-300"
|
||||
className="h-full rounded-full bg-ink-300"
|
||||
style={{ width: `${Math.max(4, props.share * 100)}%` }}
|
||||
/>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -3,8 +3,12 @@ import { Icon, Screen, ScreenHeader, type IconName } from "../ui";
|
|||
|
||||
const ROWS: { to: string; title: string; detail: string; icon: IconName }[] = [
|
||||
{ to: "/market", title: "Shipyard", detail: "Compare and buy ships", icon: "market" },
|
||||
{ to: "/locations", title: "Places", detail: "Everywhere you can fly", icon: "places" },
|
||||
{ to: "/hqs", title: "HQs", detail: "Your bases and who's there", icon: "hq" },
|
||||
{
|
||||
to: "/locations",
|
||||
title: "Places & HQs",
|
||||
detail: "Where you can fly, and your bases",
|
||||
icon: "places",
|
||||
},
|
||||
{ to: "/logbook", title: "Logbook", detail: "Every job and refuel, 7 days", icon: "route" },
|
||||
{ to: "/settings", title: "Settings", detail: "Company, display and save", icon: "gear" },
|
||||
];
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ export function Settings() {
|
|||
const [howToPlay, setHowToPlay] = useState(false);
|
||||
|
||||
return (
|
||||
<Screen className="max-w-2xl">
|
||||
<Screen>
|
||||
<ScreenHeader title="Settings" eyebrow={state.company.name} icon="gear" />
|
||||
|
||||
<Section title="Company">
|
||||
|
|
|
|||
|
|
@ -22,27 +22,23 @@ export function StartScreen() {
|
|||
|
||||
return (
|
||||
<main className="relative flex min-h-dvh flex-col items-center justify-center gap-8 overflow-hidden p-6 text-center text-ink-50">
|
||||
<div aria-hidden="true" className="pointer-events-none absolute inset-0">
|
||||
<div
|
||||
aria-hidden="true"
|
||||
className="pointer-events-none absolute inset-0 overflow-hidden bg-[url(/assets/map-gen/bg.webp)] bg-cover bg-center"
|
||||
>
|
||||
<Art
|
||||
sprite="sun"
|
||||
className="absolute -top-24 -right-24 size-72 opacity-80 blur-[1px] sm:size-96"
|
||||
/>
|
||||
<Art sprite="body-earth" className="absolute bottom-[14%] -left-10 size-40 sm:size-56" />
|
||||
<Art
|
||||
sprite="body-moon"
|
||||
className="absolute bottom-[34%] left-[30%] size-10 sm:left-[18%]"
|
||||
sprite="body-earth"
|
||||
className="absolute -bottom-[82vmin] left-1/2 sm:-bottom-[96vmin] size-[120vmin] max-w-none -translate-x-1/2 drop-shadow-[0_-8px_60px_rgb(90_160_255/0.45)]"
|
||||
/>
|
||||
<Art
|
||||
sprite="ship-courier"
|
||||
className="absolute top-[22%] left-[12%] size-16 rotate-[60deg] drop-shadow-[0_0_10px_rgb(251_191_36/0.5)]"
|
||||
sprite="ship-clipper"
|
||||
className="absolute bottom-[20vmin] left-1/2 size-[22vmin] max-h-32 max-w-32 translate-x-16 sm:bottom-[10vmin] sm:translate-x-40 rotate-[34deg] drop-shadow-[0_8px_14px_rgb(0_0_0/0.8)]"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="relative animate-rise">
|
||||
<h1 className="bg-linear-to-b from-amber-100 via-amber-300 to-amber-600 bg-clip-text font-title text-3xl sm:text-5xl text-transparent drop-shadow-[0_0_24px_rgb(251_191_36/0.35)] sm:text-7xl">
|
||||
DEADHEAD
|
||||
</h1>
|
||||
<p className="mt-2 font-display text-sm text-ink-300">Space Freight Tycoon</p>
|
||||
<h1 className="font-title text-3xl sm:text-5xl">DEADHEAD</h1>
|
||||
<p className="mt-3 text-sm font-medium text-ink-200">Space Freight Tycoon</p>
|
||||
</div>
|
||||
<p className="relative max-w-sm animate-rise text-base text-ink-200">
|
||||
Fly company runs between Earth and the Moon, save up for your own ship, and build a freight
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ export function TutorialBoard() {
|
|||
Company runs in the loaner {loaner.name}. You keep a share of each payout.
|
||||
</p>
|
||||
{runInFlight && (
|
||||
<p className="flex items-center gap-2 rounded-lg border border-cyan-400/40 bg-cyan-950/50 px-3 py-2 text-sm text-ink-100">
|
||||
<p className="flex items-center gap-2 rounded-lg border border-glass-line bg-white/5 px-3 py-2 text-sm text-ink-100">
|
||||
<Icon name="send" className="size-4 shrink-0 text-ink-300" />
|
||||
Your run is in flight. Wait for it to land.
|
||||
</p>
|
||||
|
|
@ -105,13 +105,13 @@ export function TutorialBoard() {
|
|||
key={contract.id}
|
||||
data-suggested={suggested || undefined}
|
||||
data-scripted={scripted ? true : undefined}
|
||||
tone={scripted ? "fuchsia" : suggested ? "amber" : "default"}
|
||||
tone={scripted || suggested ? "amber" : "default"}
|
||||
className={`flex flex-col gap-2 ${suggested ? "shadow-glow-amber" : ""}`}
|
||||
>
|
||||
<div className="flex items-start justify-between gap-2">
|
||||
<span className="font-display font-bold">
|
||||
{scripted ? (
|
||||
<span className="text-fuchsia-200">{scripted.name}</span>
|
||||
<span className="text-ink-300">{scripted.name}</span>
|
||||
) : (
|
||||
<>
|
||||
{locationName(contract.originId)} → {locationName(contract.destinationId)}
|
||||
|
|
@ -129,7 +129,7 @@ export function TutorialBoard() {
|
|||
</span>
|
||||
</div>
|
||||
{scripted && (
|
||||
<p className="text-xs text-fuchsia-200">
|
||||
<p className="text-xs text-ink-300">
|
||||
{locationName(contract.originId)} → {locationName(contract.destinationId)} ·
|
||||
double pay, no questions asked
|
||||
</p>
|
||||
|
|
@ -160,7 +160,7 @@ export function TutorialBoard() {
|
|||
<dt className="font-display text-xs text-ink-400">XP</dt>
|
||||
<dd
|
||||
aria-label="XP"
|
||||
className="font-display text-base text-violet-300 tabular-nums"
|
||||
className="font-display text-base text-ink-300 tabular-nums"
|
||||
>
|
||||
+{xp}
|
||||
</dd>
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ export function Sheet({
|
|||
}) {
|
||||
return createPortal(
|
||||
<div
|
||||
className={`fixed inset-x-0 top-14 bottom-0 ${layer} flex items-end justify-center bg-space-950/70 sm:items-center sm:p-4 ${side ? "xl:pointer-events-none xl:top-4 xl:items-start xl:justify-end xl:bg-transparent xl:pr-[calc(45rem+2rem)]" : ""}`}
|
||||
className={`fixed inset-x-0 top-14 bottom-0 ${layer} flex items-end justify-center bg-space-950/70 sm:items-center sm:p-4 ${side ? "xl:pointer-events-none xl:top-20 xl:items-start xl:justify-end xl:bg-transparent xl:pr-[calc(45rem+2rem)]" : ""}`}
|
||||
>
|
||||
<div
|
||||
role="dialog"
|
||||
|
|
|
|||
|
|
@ -77,8 +77,7 @@ describe("app layout", () => {
|
|||
await screen.findByRole("heading", { level: 1, name: "More" });
|
||||
for (const [name, href] of [
|
||||
[/^Shipyard/, "/market"],
|
||||
[/^Places/, "/locations"],
|
||||
[/^HQs/, "/hqs"],
|
||||
[/^Places & HQs/, "/locations"],
|
||||
[/^Logbook/, "/logbook"],
|
||||
] as const) {
|
||||
expect(screen.getByRole("link", { name })).toHaveAttribute("href", href);
|
||||
|
|
|
|||
|
|
@ -159,10 +159,8 @@ describe("location contract boards", () => {
|
|||
const plain = screen.getByRole("row", { name: "Consumer Goods" });
|
||||
const special = screen.getByRole("row", { name: "Machine Parts" });
|
||||
// CR-007: good, class chip, shipper, mass and distance.
|
||||
expect(plain).toHaveTextContent("Standard");
|
||||
expect(plain).toHaveTextContent("Pacific Orbital Logistics");
|
||||
expect(plain).toHaveTextContent("50 t");
|
||||
expect(plain).toHaveTextContent("No skills needed");
|
||||
expect(plain).toHaveTextContent("expires in 30m 00s");
|
||||
expect(within(plain).queryByText("First contact")).not.toBeInTheDocument();
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue