diff --git a/frontend/src/components/EntityCard.tsx b/frontend/src/components/EntityCard.tsx index 671586e..2e43f63 100644 --- a/frontend/src/components/EntityCard.tsx +++ b/frontend/src/components/EntityCard.tsx @@ -1,79 +1,104 @@ import { useTranslation } from 'react-i18next' import type { SpiritEntity } from '../lib/types' -import { GhostGlyph } from './GhostGlyph' export type EntityCardProps = { entity: SpiritEntity | null isNew: boolean + /** Whether the collapsible dossier body is expanded. */ + open: boolean + /** Toggle the collapsed/expanded state (ignored while there's no entity). */ + onToggleOpen: () => void } -const RARITY_CLASS: Record = { - common: 'rarity-common', - uncommon: 'rarity-uncommon', - rare: 'rarity-rare', - mythic: 'rarity-mythic', -} - -/** Occult dossier of the currently-summoned spirit, wax-seal vibe. */ -export function EntityCard({ entity, isNew }: EntityCardProps) { +/** + * Occult dossier of the currently-summoned spirit, wax-seal vibe. + * Styling (`.spirit-dossier` / `.dossier-*` / `.rarity-badge` / …) lives in + * SeancePage.css alongside the rest of the side column. + */ +export function EntityCard({ entity, isNew, open, onToggleOpen }: EntityCardProps) { const { t } = useTranslation() if (!entity) { return ( - + ) } return ( - + ) } diff --git a/frontend/src/components/TelemetryReadout.tsx b/frontend/src/components/TelemetryReadout.tsx index 6a3310e..5d476b6 100644 --- a/frontend/src/components/TelemetryReadout.tsx +++ b/frontend/src/components/TelemetryReadout.tsx @@ -1,28 +1,47 @@ import { useTranslation } from 'react-i18next' import type { Telemetry } from '../lib/types' -/** Flickering terminal readout of live wire telemetry. */ +/** + * Flickering terminal readout of live wire telemetry. + * Styling (`.panel-title` / `.telemetry-grid` / `.tel-row` / …) lives in + * SeancePage.css alongside the other mode-panel styles. + */ export function TelemetryReadout({ telemetry }: { telemetry: Telemetry | null }) { const { t } = useTranslation() - const rows: Array<[string, string]> = telemetry - ? [ - [t('seance.telemetry.jitter'), `${telemetry.jitter_bytes_per_s.toFixed(1)} ${t('seance.telemetry.units.bytes')}`], - [t('seance.telemetry.latencyVar'), `${telemetry.latency_variance_ms.toFixed(2)} ${t('seance.telemetry.units.ms')}`], - [t('seance.telemetry.latencyMean'), `${telemetry.latency_mean_ms.toFixed(2)} ${t('seance.telemetry.units.ms')}`], - [t('seance.telemetry.dns'), `${telemetry.dns_ms.toFixed(1)} ${t('seance.telemetry.units.ms')}`], - ] - : [] return ( -
-

{t('seance.telemetry.title')}

- {rows.length === 0 &&
— — —
} - {rows.map(([label, value]) => ( -
- {label} - {value} + <> +

{t('seance.telemetry.title')}

+ {telemetry ? ( +
+
+ {t('seance.telemetry.jitter')} + + {telemetry.jitter_bytes_per_s.toFixed(1)} {t('seance.telemetry.units.bytes')} + +
+
+ {t('seance.telemetry.latencyVar')} + + {telemetry.latency_variance_ms.toFixed(2)} {t('seance.telemetry.units.ms')} + +
+
+ {t('seance.telemetry.latencyMean')} + + {telemetry.latency_mean_ms.toFixed(1)} {t('seance.telemetry.units.ms')} + +
+
+ {t('seance.telemetry.dns')} + + {telemetry.dns_ms.toFixed(1)} {t('seance.telemetry.units.ms')} + +
- ))} -
+ ) : ( +

{t('common.loading')}

+ )} + ) } diff --git a/frontend/src/pages/SeancePage.tsx b/frontend/src/pages/SeancePage.tsx index b579388..500be59 100644 --- a/frontend/src/pages/SeancePage.tsx +++ b/frontend/src/pages/SeancePage.tsx @@ -22,6 +22,8 @@ import { PlanchetteBoard } from '../components/PlanchetteBoard' import { MatrixView } from '../components/MatrixView' import { GraphView } from '../components/GraphView' import { Transcript } from '../components/Transcript' +import { EntityCard } from '../components/EntityCard' +import { TelemetryReadout } from '../components/TelemetryReadout' import { PlanchetteMachine } from '../lib/planchette' import type { PlanchetteSnapshot } from '../lib/planchette' import { EvpListener } from '../lib/evp' @@ -335,90 +337,12 @@ function SeanceSession({ username }: { username: string }) {