diff --git a/src/client/components/overviewButton.tsx b/src/client/components/overviewButton.tsx
index 934c98b..b4e5085 100644
--- a/src/client/components/overviewButton.tsx
+++ b/src/client/components/overviewButton.tsx
@@ -3,9 +3,8 @@
* above Settings (the harness's own foot layout: footer actions, then the
* settings row), mirroring the Settings trigger's geometry in both column
* widths. The button carries the plugin emblem and, on the wide
- * column, its label; a badge counts the sessions currently running (the one
- * glanceable live fact a footer can carry). Clicking opens the overview
- * overlay through the shared module store (overviewStore.ts).
+ * column, its label. Clicking opens the overview overlay through the shared
+ * module store (overviewStore.ts).
*
* The per-user `insightsEntry` preference takes the entry down (renders
* null) without unregistering the seat. The subscription fails open: an
@@ -15,7 +14,6 @@
import { useSyncExternalStore, type ReactElement } from 'react'
import { ContextIcon } from '../icon'
-import { runningCountOf, sessionsSnapshotOf } from '../overview'
import { overviewStore } from '../overviewStore'
import type { ContextSettings, InsightsEntry } from '../settings'
import type { ViewKit } from '../viewkit'
@@ -23,8 +21,6 @@ import type { ViewKit } from '../viewkit'
export interface OverviewButtonProps {
/** The footer-action owner share: false on the collapsed 56px rail (icon only). */
wide?: boolean
- /** The root standard kit's sessions seat (absent on a harness without it). */
- useSessions?: unknown
}
/** Stable subscription faces for the settings-less degrade (no re-subscribes). */
@@ -40,8 +36,6 @@ export function makeOverviewButton(kit: ViewKit, settings?: ContextSettings): (p
: (listener: () => void): (() => void) => settings.store.subscribe(listener)
const getEntry = settings === undefined ? entryShown : (): InsightsEntry => settings.insightsEntry()
return function OverviewButton(props: OverviewButtonProps): ReactElement | null {
- // The hook-level read (unconditional, guarded inside); the badge hides at 0.
- const running = runningCountOf(sessionsSnapshotOf(props))
// The entry toggle: subscribed, so a preference flip takes effect live.
const entry = useSyncExternalStore(subscribeEntry, getEntry)
if (entry === 'hide') return null
@@ -55,7 +49,6 @@ export function makeOverviewButton(kit: ViewKit, settings?: ContextSettings): (p
>
{props.wide === true && {t('ov.entry')}}
- {running > 0 && {running}}
)
}
diff --git a/src/client/overview.ts b/src/client/overview.ts
index c588214..6b1e39d 100644
--- a/src/client/overview.ts
+++ b/src/client/overview.ts
@@ -56,24 +56,6 @@ export function sessionsSnapshotOf(props: { useSessions?: unknown }): unknown {
}
}
-/** The running-session tally for the footer entry's badge (0 on any shape failure). */
-export function runningCountOf(snapshot: unknown): number {
- const state = asRecord(snapshot)
- if (state === null) return 0
- const byId = asRecord(state.byId)
- if (byId === null) return 0
- let count = 0
- try {
- for (const id of Object.keys(byId)) {
- const row = asRecord(byId[id])
- if (row !== null && row.running === true) count++
- }
- } catch {
- // A hostile row throwing on access stops the tally at what was counted.
- }
- return count
-}
-
/**
* The `useWorkspaces` standard prop read — same guarded-hook contract as
* {@link sessionsSnapshotOf}. The overview joins its session → workspace
diff --git a/src/client/styles/overview.css b/src/client/styles/overview.css
index 2d662ef..a6bbdbb 100644
--- a/src/client/styles/overview.css
+++ b/src/client/styles/overview.css
@@ -15,14 +15,12 @@
/* Geometry mirrors the harness's own Settings trigger (ui-settings-general's
.trigger): the 42px row, 12px radius, 14px/22px label, and its shared hover
fill, so the plugin entry reads as a native foot control, not a visitor. */
-.lc-ov-entry { position: relative; display: flex; align-items: center; gap: 8px; width: calc(100% + 4px); height: 42px; box-sizing: border-box; margin: 0 -2px; border: 0; padding: 0 10px 0 8px; overflow: hidden; background: transparent; border-radius: 12px; color: var(--dsw-alias-label-primary); font-family: inherit; font-size: 14px; line-height: 22px; cursor: pointer; }
+.lc-ov-entry { display: flex; align-items: center; gap: 8px; width: calc(100% + 4px); height: 42px; box-sizing: border-box; margin: 0 -2px; border: 0; padding: 0 10px 0 8px; overflow: hidden; background: transparent; border-radius: 12px; color: var(--dsw-alias-label-primary); font-family: inherit; font-size: 14px; line-height: 22px; cursor: pointer; }
.lc-ov-entry:hover { background: var(--dsw-alias-interactive-bg-hover); }
/* The collapsed rail takes the native foot controls' 36x36 circle, icon only. */
.lc-ov-entry-rail { flex: none; justify-content: center; gap: 0; width: 36px; height: 36px; margin: 0; padding: 0; border-radius: 50%; }
.lc-ov-entry-icon { flex: none; }
.lc-ov-entry-label { flex: 1 1 auto; min-width: 0; text-align: left; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
-/* The running-sessions badge: the footer's one live fact, pinned to the icon's corner in both column widths. */
-.lc-ov-badge { position: absolute; top: 1px; right: 4px; min-width: 15px; height: 15px; box-sizing: border-box; border-radius: 999px; background: var(--color-green-500); color: #fff; font-size: 9px; font-weight: 700; line-height: 1; display: flex; align-items: center; justify-content: center; padding: 0 4px; pointer-events: none; }
/* ---- the overlay chrome ---- */
/* The backdrop carries the `lc-ov` container: it spans the viewport exactly,
diff --git a/tests/client/components/overviewButton.spec.ts b/tests/client/components/overviewButton.spec.ts
index 6438154..f6f9d23 100644
--- a/tests/client/components/overviewButton.spec.ts
+++ b/tests/client/components/overviewButton.spec.ts
@@ -1,6 +1,6 @@
// The Context Dashboard's sidebar-foot entry (src/client/components/
-// overviewButton.tsx): wide/rail rendering, the running badge, the store
-// flip on click, and the per-user insights-entry toggle.
+// overviewButton.tsx): wide/rail rendering, the store flip on click, and the
+// per-user insights-entry toggle.
import { createElement as h, act } from 'react'
import assert from 'node:assert/strict'
@@ -17,9 +17,6 @@ afterEach(() => {
overviewStore.set(false)
})
-/** A useSessions stand-in over a static snapshot. */
-const useSessionsOf = (snapshot: unknown) => ((sel: (s: unknown) => T): T => sel(snapshot))
-
describe('OverviewButton', () => {
test('the wide column renders icon and label; the rail renders the icon alone', async () => {
const wide = await mount(h(Button, { wide: true }))
@@ -41,23 +38,6 @@ describe('OverviewButton', () => {
await bare.unmount()
})
- test('the badge counts running sessions and hides at zero', async () => {
- const running = useSessionsOf({ byId: { a: { running: true }, b: { running: false }, c: { running: true } } })
- const m = await mount(h(Button, { wide: true, useSessions: running }))
- assert.equal(query(m.container, '.lc-ov-badge').textContent, '2')
- await m.unmount()
-
- const idle = useSessionsOf({ byId: { a: { running: false } } })
- const calm = await mount(h(Button, { wide: true, useSessions: idle }))
- assert.equal(queryAll(calm.container, '.lc-ov-badge').length, 0)
- await calm.unmount()
-
- // No sessions seat at all: no badge, no throw.
- const seatless = await mount(h(Button, { wide: true }))
- assert.equal(queryAll(seatless.container, '.lc-ov-badge').length, 0)
- await seatless.unmount()
- })
-
test('clicking opens the overview through the shared store', async () => {
assert.equal(overviewStore.getSnapshot(), false)
const m = await mount(h(Button, { wide: true }))
diff --git a/tests/client/overview.spec.ts b/tests/client/overview.spec.ts
index 743a91d..bae2e81 100644
--- a/tests/client/overview.spec.ts
+++ b/tests/client/overview.spec.ts
@@ -19,7 +19,6 @@ import {
refreshSessions,
relativeTime,
rowsOfSnapshot,
- runningCountOf,
sessionGroupsOf,
sessionsSnapshotOf,
sortRows,
@@ -89,20 +88,6 @@ describe('sessionsSnapshotOf', () => {
})
})
-describe('runningCountOf', () => {
- test('unusable snapshots tally zero', () => {
- assert.equal(runningCountOf(null), 0)
- assert.equal(runningCountOf(7), 0)
- assert.equal(runningCountOf({ byId: 7 }), 0)
- })
-
- test('running rows tally; a hostile row stops the count at what was seen', () => {
- const hostile = new Proxy({}, { get: () => { throw new Error('boom') } })
- assert.equal(runningCountOf({ byId: { a: { running: true }, b: { running: false }, c: { running: true } } }), 2)
- assert.equal(runningCountOf({ byId: { a: { running: true }, x: hostile } }), 1)
- })
-})
-
describe('rowsOfSnapshot', () => {
test('unusable snapshots read null (the unavailable note, not an empty list)', () => {
assert.equal(rowsOfSnapshot(null), null)