beginning of my ideases

This commit is contained in:
legop3
2026-05-21 01:57:59 -04:00
parent 8727555788
commit bfd1a94030
17 changed files with 90 additions and 48 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
+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-title" content="Roomba Rover" />
<title>Roomba Rover</title>
<script type="module" crossorigin src="/assets/index-DqqTkkpY.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-v8lmO81Z.css">
<script type="module" crossorigin src="/assets/index-4eskKUF4.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-B8wCAHw2.css">
</head>
<body>
<div id="root"></div>
@@ -127,8 +127,8 @@ export default function ButtonBoxPanel() {
return (
<section className="panel-section space-y-0.5 text-base">
<header className="panel-muted text-center text-sm">
<p>Button Box</p>
<header className="panel-title-row">
<p className="panel-title-text">Button Box</p>
</header>
<div className="grid grid-cols-4 gap-0.5">
{buttons.map((button) => {
+6
View File
@@ -16,6 +16,7 @@ export default function ChatPanel({
hideSpectatorNotice = false,
fillHeight = false,
allowSpectatorInput = false,
title = 'Chat',
}) {
const role = useSessionSelector((state) => state.session?.role || null);
const currentRoverId = useSessionSelector((state) => state.session?.assignment?.roverId || null);
@@ -106,6 +107,11 @@ export default function ChatPanel({
return (
<section className={`panel-section space-y-0.5 text-base ${fillHeight ? 'flex h-full flex-col overflow-hidden' : ''}`}>
{title ? (
<div className="panel-title-row">
<span className="panel-title-text">{title}</span>
</div>
) : null}
<div className={`surface overflow-y-auto space-y-0.5 px-0 ${listClass}`} ref={listRef}>
{sorted.length === 0 && typingRows.length === 0 ? (
<p className="text-sm text-slate-500">No messages yet.</p>
@@ -256,7 +256,7 @@ export default function HomeAssistantControls() {
if (!ha?.enabled) {
return (
<section className="panel-section space-y-0.5 text-sm text-slate-400">
<p className="text-slate-300">Room Controls</p>
<p className="panel-title-text">Room Controls</p>
<p className="text-slate-500">Not configured on the server.</p>
</section>
);
@@ -265,7 +265,7 @@ export default function HomeAssistantControls() {
if (entities.length === 0) {
return (
<section className="panel-section space-y-0.5 text-sm text-slate-400">
<p className="text-slate-300">Room Controls</p>
<p className="panel-title-text">Room Controls</p>
<p className="text-slate-500">No lights or switches configured.</p>
</section>
);
@@ -275,23 +275,25 @@ export default function HomeAssistantControls() {
return (
<section className="panel-section space-y-0.5 text-base">
<header className="flex items-center justify-between gap-0.5 text-sm text-slate-400">
<div className="flex items-center gap-0.5">
<p>Room Controls</p>
<span className="text-xs text-slate-500">{entities.length}</span>
{controlsLocked ? <StatusBadge label={lockState === 'off' ? 'Locked Off' : 'Locked On'} tone="warn" /> : null}
<div className="flex items-center gap-0.5 text-xs text-slate-300 background-black">
<header className="panel-title-row">
<div className="panel-title-left">
<p className="panel-title-text">Room Controls</p>
<span className="panel-title-meta">{entities.length}</span>
</div>
<div className="panel-title-right">
<div className="panel-title-actions">
<span className="flex items-center gap-0.5">
<span>On</span>
<span className="panel-title-meta">On</span>
{onKeyLabel ? <KeyPill label={onKeyLabel} /> : null}
</span>
<span className="flex items-center gap-0.5">
<span>Off</span>
<span className="panel-title-meta">Off</span>
{offKeyLabel ? <KeyPill label={offKeyLabel} /> : null}
</span>
</div>
</div>
{controlsLocked ? <StatusBadge label={lockState === 'off' ? 'Locked Off' : 'Locked On'} tone="warn" /> : null}
<StatusBadge label={connected ? 'Connected' : 'Offline'} tone={connected ? 'success' : 'warn'} />
</div>
</header>
{controlsLocked ? (
<p className="rounded border border-amber-600/60 bg-amber-900/40 px-1 py-0.5 text-xs text-amber-100">
@@ -319,5 +321,5 @@ export default function HomeAssistantControls() {
function KeyPill({ label }) {
if (!label) return null;
return <span className="rounded border border-white/40 px-1 text-[0.7rem] text-white">{label}</span>;
return <span className="rounded border border-slate-600 px-1 text-[0.65rem] text-slate-300">{label}</span>;
}
+3 -3
View File
@@ -9,9 +9,9 @@ export default function LogPanel() {
const rendered = useMemo(() => logs.slice().reverse(), [logs]);
return (
<div className="panel-section space-y-0.5 text-base">
<div className="flex items-center justify-between text-sm text-slate-400">
<span>Server logs</span>
<span>{logs.length}</span>
<div className="panel-title-row">
<span className="panel-title-text">Server logs</span>
<span className="panel-title-meta">{logs.length}</span>
</div>
<div className="surface h-64 overflow-y-auto font-mono text-xs">
{logs.length === 0 ? (
@@ -22,7 +22,9 @@ export default function OverseerPreferencePanel() {
return (
<section className="surface p-1 text-xs text-slate-200 text-center">
<div className="text-[0.65rem] text-slate-400">Overseer vote</div>
<div className="panel-title-row">
<span className="panel-title-text">Overseer vote</span>
</div>
<label
className={`flex items-center justify-center gap-1.5 rounded px-1 py-0.5 ${
enabled ? 'bg-emerald-600/80 text-emerald-50' : 'bg-slate-600/70 text-slate-100'
@@ -76,9 +76,9 @@ export default function RawUserPilePanel({
<div className={`space-y-0.5 ${fillHeight ? 'flex flex-1 min-h-0 flex-col' : ''}`}>
{!hideHeader && (
<div className={`flex items-center justify-between text-sm text-slate-400 ${compact ? 'text-xs' : ''}`}>
<span>Users</span>
<span className="text-xs text-slate-500">{sorted.length}</span>
<div className="panel-title-row">
<span className="panel-title-text">Users</span>
<span className="panel-title-meta">{sorted.length}</span>
</div>
)}
<div
@@ -151,9 +151,9 @@ export default function ReplaySourcesPanel({ panelId = 'replay-sources', fillHei
return (
<section className={`panel-section p-0.75 text-sm ${containerClass}`}>
<header className="panel-muted flex items-center justify-between text-xs">
<span>Replay Sources</span>
<span>{sources.length}</span>
<header className="panel-title-row">
<span className="panel-title-text">Replay Sources</span>
<span className="panel-title-meta">{sources.length}</span>
</header>
<div className={`grid gap-0.5 md:grid-cols-2 ${listWrapClass}`}>
<GroupList title="Rovers" items={grouped.rovers} selected={selected} onToggle={toggleKey} />
@@ -101,6 +101,7 @@ function DriveDockPanel() {
value={value}
min={min}
max={max}
label="Camera tilt"
disabled={cameraDisabled}
onChange={setServoAngle}
keyDownLabel={downLabel}
@@ -69,15 +69,15 @@ export default function RoomCameraPanel({
return (
<section className="panel-section space-y-0.5 text-base">
{!hideHeader && (
<header className="flex flex-wrap items-center justify-between gap-0.5 text-sm text-slate-400">
<div className="flex items-center gap-0.5">
<p>Room cameras</p>
<span className="text-xs text-slate-500">{cameras.length}</span>
<header className="panel-title-row">
<div className="panel-title-left">
<p className="panel-title-text">Room cameras</p>
<span className="panel-title-meta">{cameras.length}</span>
</div>
<div className="flex flex-wrap items-center gap-0.5 text-xs">
<div className="panel-title-right">
{showLayoutToggle && (
<div className="flex items-center gap-0.5">
<span className="text-slate-500">Layout:</span>
<div className="panel-title-actions">
<span className="panel-title-meta">Layout</span>
<div className="inline-flex overflow-hidden rounded border border-slate-700">
{ORIENTATIONS.map((option) => (
<button
@@ -97,7 +97,11 @@ export default function RoverQueuesPanel({ title = 'Rovers' }) {
return (
<div className="space-y-0.5 text-sm">
{title && <p className="text-sm text-slate-400">{title}</p>}
{title && (
<div className="panel-title-row">
<p className="panel-title-text">{title}</p>
</div>
)}
{rosterItems.length === 0 ? (
<p className="text-sm text-slate-500">No rovers registered.</p>
) : (
@@ -173,7 +173,7 @@ function SensorDetails({ sensors, dockState }) {
function DetailCard({ title, children }) {
return (
<div className="surface space-y-0.5 p-1 text-sm">
<div className="text-[0.8rem] uppercase tracking-wide text-slate-400">{title}</div>
<div className="panel-title-text">{title}</div>
<div className="space-y-0.5">{children}</div>
</div>
);
@@ -20,6 +20,9 @@ export function NicknameEntryPanel({ compact = false }) {
export function LinkButtonsPanel() {
return (
<section className="panel-section flex h-full min-h-0 flex-col gap-0.5 text-base">
<div className="panel-title-row">
<span className="panel-title-text">Socials</span>
</div>
<SocialButtonsGrid className="flex-1 min-h-0" />
</section>
);
+24
View File
@@ -71,6 +71,30 @@ body {
@apply text-sm text-slate-400 rounded-md;
}
.panel-title-row {
@apply flex items-center justify-between gap-0.5 rounded-md bg-slate-900 px-0.5 py-0.5 text-left;
}
.panel-title-text {
@apply text-[0.78rem] font-semibold tracking-normal text-slate-200 leading-none text-left;
}
.panel-title-meta {
@apply text-[0.68rem] font-medium tracking-normal text-slate-400 leading-none;
}
.panel-title-left {
@apply flex min-w-0 items-center gap-0.5;
}
.panel-title-right {
@apply flex flex-wrap items-center justify-end gap-0.5;
}
.panel-title-actions {
@apply flex items-center gap-0.5 text-[0.68rem] text-slate-400 leading-none;
}
.surface {
@apply bg-neutral-800 text-white px-0.5 py-0.5 rounded-md;
}