better big button

This commit is contained in:
legop3
2026-01-15 18:43:46 -05:00
parent 705b38ea7b
commit e34d838d41
7 changed files with 169 additions and 133 deletions
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+2 -2
View File
@@ -11,8 +11,8 @@
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" /> <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
<meta name="apple-mobile-web-app-title" content="Multi Roomba Rover" /> <meta name="apple-mobile-web-app-title" content="Multi Roomba Rover" />
<title>Multi Roomba Rover</title> <title>Multi Roomba Rover</title>
<script type="module" crossorigin src="/assets/index-CJBHX9So.js"></script> <script type="module" crossorigin src="/assets/index-ZuH-jWBy.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-D46FE2Sk.css"> <link rel="stylesheet" crossorigin href="/assets/index-hvTkRjRF.css">
</head> </head>
<body> <body>
<div id="root"></div> <div id="root"></div>
+9 -2
View File
@@ -1,6 +1,7 @@
import { useCallback, useEffect, useMemo, useState } from 'react'; import { useCallback, useEffect, useMemo, useState } from 'react';
import TelemetryPanel from './components/TelemetryPanel.jsx'; import TelemetryPanel from './components/TelemetryPanel.jsx';
import ControlSummary, { RoverRosterPanel } from './components/ControlSummary.jsx'; import ControlSummary, { RoverRosterPanel } from './components/ControlSummary.jsx';
import ReplaySourcesPanel from './components/ReplaySourcesPanel.jsx';
import AlertFeed from './components/AlertFeed.jsx'; import AlertFeed from './components/AlertFeed.jsx';
import MobileControls, { import MobileControls, {
MobileLandscapeAuxColumn, MobileLandscapeAuxColumn,
@@ -128,7 +129,10 @@ function MobilePortraitLayout({ onOpenHelpOverlay }) {
<div className="flex flex-col gap-0.5"> <div className="flex flex-col gap-0.5">
<DriverVideoPanel layoutFormat="mobile-portrait" /> <DriverVideoPanel layoutFormat="mobile-portrait" />
<MobileControls /> <MobileControls />
<RoverRosterPanel /> <div className="grid gap-0.5 grid-cols-[minmax(0,1fr)_minmax(0,1.4fr)]">
<ReplaySourcesPanel panelId="replay-sources-mobile-portrait" />
<RoverRosterPanel />
</div>
{/* <ControlSummary /> */} {/* <ControlSummary /> */}
<MobileFeatureTabs <MobileFeatureTabs
layout="mobile-portrait" layout="mobile-portrait"
@@ -146,7 +150,10 @@ function MobileLandscapeLayout({ onOpenHelpOverlay }) {
<MobileLandscapeAuxColumn /> <MobileLandscapeAuxColumn />
<div> <div>
<DriverVideoPanel layoutFormat="mobile-landscape" /> <DriverVideoPanel layoutFormat="mobile-landscape" />
<RoverRosterPanel /> <div className="grid gap-0.5 grid-cols-[minmax(0,1fr)_minmax(0,1.4fr)]">
<ReplaySourcesPanel panelId="replay-sources-mobile-landscape" />
<RoverRosterPanel />
</div>
{/* <TelemetryPanel /> */} {/* <TelemetryPanel /> */}
</div> </div>
<MobileLandscapeControlColumn /> <MobileLandscapeControlColumn />
+38 -9
View File
@@ -24,7 +24,7 @@ export function useDriveDockState(roverId) {
function StatusPill({ label, active }) { function StatusPill({ label, active }) {
return ( return (
<span <span
className={`rounded px-1.5 py-0.5 text-[0.75rem] font-semibold ${ className={`rounded-xl px-1.5 py-0.5 text-[0.75rem] font-semibold ${
active ? 'bg-emerald-600 text-white' : 'bg-red-600 text-white' active ? 'bg-emerald-600 text-white' : 'bg-red-600 text-white'
}`} }`}
> >
@@ -38,6 +38,22 @@ function KeyPill({ label }) {
return <span className="rounded border border-white/40 px-1 text-[0.7rem] text-white">{label}</span>; return <span className="rounded border border-white/40 px-1 text-[0.7rem] text-white">{label}</span>;
} }
function ActionPill({ label, tone }) {
const toneClasses =
tone === 'emerald'
? 'border-emerald-200/70 bg-emerald-600/70 text-emerald-50'
: tone === 'amber'
? 'border-amber-200/70 bg-amber-600/70 text-amber-50'
: 'border-indigo-200/70 bg-indigo-600/70 text-indigo-50';
return (
<span
className={`rounded-full border px-0.5 py-0.15 text-[0.7rem] font-semibold ${toneClasses}`}
>
{label}
</span>
);
}
function DockModal({ instructions, onConfirm, onCancel, pending }) { function DockModal({ instructions, onConfirm, onCancel, pending }) {
return ( return (
<div className="fixed inset-0 z-40 flex items-center justify-center bg-black/70 p-1"> <div className="fixed inset-0 z-40 flex items-center justify-center bg-black/70 p-1">
@@ -149,7 +165,17 @@ export default function DriveDockAction({ layout = 'desktop', expand = false, dr
}; };
const baseCardClasses = const baseCardClasses =
'flex w-full flex-col gap-0.5 border border-slate-700 px-0.75 py-0.75 text-slate-100 shadow'; 'flex w-full flex-col gap-0.5 overflow-hidden rounded-xl border-2 px-0.75 py-0.75 text-slate-100 shadow-md transition hover:-translate-y-0.5 hover:shadow-xl focus-visible:outline-none focus-visible:ring-2 disabled:cursor-not-allowed disabled:opacity-60';
const ctaText = 'text-center';
const ctaLayout = 'items-center justify-between';
const ctaTextAndLayout = `${ctaText} ${ctaLayout}`;
const ctaSize = isMobile ? 'text-sm font-semibold' : '';
const emeraldCta =
'border-emerald-300/70 bg-emerald-800 text-emerald-50 hover:bg-emerald-700 focus-visible:ring-emerald-300';
const amberCta =
'border-amber-300/70 bg-amber-900 text-amber-50 hover:bg-amber-800 focus-visible:ring-amber-300';
const indigoCta =
'border-indigo-300/70 bg-indigo-900 text-indigo-50 hover:bg-indigo-800 focus-visible:ring-indigo-300';
const filledHeight = expand ? 'h-full flex-1' : ''; const filledHeight = expand ? 'h-full flex-1' : '';
if (!driving && !dockingInProgress) { if (!driving && !dockingInProgress) {
@@ -158,12 +184,13 @@ export default function DriveDockAction({ layout = 'desktop', expand = false, dr
type="button" type="button"
onClick={handleStartDrive} onClick={handleStartDrive}
disabled={driveDisabled} disabled={driveDisabled}
className={`${baseCardClasses} ${filledHeight} items-center justify-between bg-emerald-800 hover:bg-emerald-700 text-center transition disabled:cursor-not-allowed disabled:opacity-60`} className={`${baseCardClasses} ${filledHeight} ${ctaTextAndLayout} ${ctaSize} ${emeraldCta}`}
> >
<div className="space-y-0.25 w-full"> <div className="space-y-0.25 w-full">
<div className="flex items-center justify-center gap-0.5"> <div className="flex flex-wrap items-center justify-center gap-0.5">
<span className="text-base font-semibold text-emerald-50">Start Driving</span> <span className="text-base font-semibold text-emerald-50">Start Driving</span>
{!isMobile && driveKeyLabel ? <KeyPill label={driveKeyLabel} /> : null} {!isMobile && driveKeyLabel ? <KeyPill label={driveKeyLabel} /> : null}
{!isMobile ? <ActionPill label="Click to start" tone="emerald" /> : null}
</div> </div>
<p className="text-sm text-emerald-50/90">{startDriveInstructions.summary}</p> <p className="text-sm text-emerald-50/90">{startDriveInstructions.summary}</p>
<StepList steps={startDriveInstructions.steps} tone="emerald" /> <StepList steps={startDriveInstructions.steps} tone="emerald" />
@@ -188,11 +215,12 @@ export default function DriveDockAction({ layout = 'desktop', expand = false, dr
type="button" type="button"
disabled={driveDisabled} disabled={driveDisabled}
onClick={handleReturnToDrive} onClick={handleReturnToDrive}
className={`${baseCardClasses} ${filledHeight} items-center bg-amber-900 text-center transition hover:bg-amber-800 disabled:cursor-not-allowed disabled:opacity-50`} className={`${baseCardClasses} ${filledHeight} ${ctaTextAndLayout} ${ctaSize} ${amberCta}`}
> >
<div className="space-y-0.25 w-full"> <div className="space-y-0.25 w-full">
<div className="flex items-center justify-center gap-0.5"> <div className="flex flex-wrap items-center justify-center gap-0.5">
<span className="text-base font-semibold text-amber-50">Docking in Progress</span> <span className="text-base font-semibold text-amber-50">Docking in Progress</span>
{!isMobile ? <ActionPill label="Click to return to driving mode" tone="amber" /> : null}
</div> </div>
<p className="text-sm text-amber-50/90">{inProgressCopy.summary}</p> <p className="text-sm text-amber-50/90">{inProgressCopy.summary}</p>
</div> </div>
@@ -213,13 +241,14 @@ export default function DriveDockAction({ layout = 'desktop', expand = false, dr
onClick={handleOpenDock} onClick={handleOpenDock}
className={ className={
isMobile isMobile
? 'flex w-full items-center justify-center border border-slate-700 bg-indigo-900 px-0.75 py-0.75 text-sm font-semibold text-indigo-50 shadow transition hover:bg-indigo-800 disabled:cursor-not-allowed disabled:opacity-50' ? `flex w-full items-center justify-center ${baseCardClasses} ${ctaTextAndLayout} ${ctaSize} ${indigoCta}`
: `${baseCardClasses} ${filledHeight} items-center bg-indigo-900 text-center transition hover:bg-indigo-800 disabled:cursor-not-allowed disabled:opacity-50` : `${baseCardClasses} ${filledHeight} ${ctaTextAndLayout} ${ctaSize} ${indigoCta}`
} }
> >
<div className="flex items-center justify-center gap-0.5 w-full"> <div className="flex flex-wrap items-center justify-center gap-0.5 w-full">
<span className="text-base font-semibold text-indigo-50">Dock and Charge</span> <span className="text-base font-semibold text-indigo-50">Dock and Charge</span>
{!isMobile && dockKeyLabel ? <KeyPill label={dockKeyLabel} /> : null} {!isMobile && dockKeyLabel ? <KeyPill label={dockKeyLabel} /> : null}
{!isMobile ? <ActionPill label="Click to begin docking" tone="indigo" /> : null}
</div> </div>
{!isMobile && ( {!isMobile && (
<> <>