HUDShell

HUDShell is the full-screen frame of a JARVIS app. It draws the complete backdrop and gives you slots for the top bar, the orb, your panels and the voice dock, layered in the right order. Start every app with it.

import { HUDShell } from 'jarvis-react-ui';

Starting an app

Wrap the app in JarvisProvider for sound and toasts, then render HUDShell as its root element and fill the slots.

import 'jarvis-react-ui/style.css';
import { createRoot } from 'react-dom/client';
import { JarvisProvider } from 'jarvis-react-ui';
import { App } from './App'; // renders <HUDShell ...> like the demo below

createRoot(document.getElementById('root') as HTMLElement).render(
    <JarvisProvider>
        <App />
    </JarvisProvider>,
);

The demo shows a typical App: a TopBar with a StatusBadge, a CssOrb, two panels and a StatusDock that share one AppOrbState. Click the microphone to switch between idle and listening. The demo shrinks the orb with scale-[0.6] to fit the frame; drop that class in a full-screen app.

import { useState } from 'react';
import {
    BrandMark,
    CssOrb,
    HUDShell,
    Metric,
    Panel,
    StatusBadge,
    StatusDock,
    TopBar,
} from 'jarvis-react-ui';
import type { AppOrbState } from 'jarvis-react-ui';

export default function AppShell() {
    const [state, setState] = useState<AppOrbState>('idle');

    return (
        <HUDShell
            topbar={<TopBar left={<BrandMark />} right={<StatusBadge />} />}
            orb={<CssOrb state={state} particles={false} className="scale-[0.6]" />}
            dock={
                <StatusDock
                    state={state}
                    onPTT={() => setState((s) => (s === 'idle' ? 'listening' : 'idle'))}
                />
            }
        >
            <div className="flex justify-between px-5 pt-16">
                <Panel title="Vitals" className="w-[180px]">
                    <Metric value={42} unit="%" />
                </Panel>
                <Panel title="Agenda" className="w-[180px]">
                    <span className="text-text-secondary">10:30 · Briefing</span>
                </Panel>
            </div>
        </HUDShell>
    );
}

Layers

HUDShell is a position: fixed; inset: 0 element. From back to front it renders:

Layer Rendered Toggle
Scene background always scene (grid, stars, scanlines)
Reactor glow by default reactor={false}
ViewportCorners by default viewportCorners={false}
orb slot, full-screen and click-through (z 0) when set —
children in a relative layer (z 10) when set —
dock slot, rendered as is (StatusDock is z 25) when set —
topbar slot (z 30) when set —

The children layer starts at the top of the screen, spans its width and is only as tall as its content. Lay out your panels inside it, or use WindowManager for draggable windows.

import { HUDShell, Panel } from 'jarvis-react-ui';

export default function Basic() {
    return (
        <HUDShell>
            <div className="p-6">
                <Panel title="Diagnostics" className="h-[120px] w-[280px]">
                    <span className="text-text-secondary">All subsystems nominal.</span>
                </Panel>
            </div>
        </HUDShell>
    );
}

scene switches off single Scene layers; the dark background, vignette, grain and horizon glow always stay. reactor and viewportCorners remove the glow and the corner marks.

import { HUDShell, Panel } from 'jarvis-react-ui';

export default function Layers() {
    return (
        <HUDShell
            scene={{ stars: false, scanlines: false }}
            reactor={false}
            viewportCorners={false}
        >
            <div className="p-6">
                <Panel title="Minimal" className="h-[120px] w-[280px]">
                    <span className="text-text-secondary">Grid only, no reactor or corners.</span>
                </Panel>
            </div>
        </HUDShell>
    );
}

Idle mode

idle dims and blurs every Panel inside children and fades the top bar, so only the orb remains in focus. The children layer becomes inert while idle: it is click-through, its controls leave the tab order and it is hidden from assistive technology. Entering and leaving idle both crossfade (instantly under prefers-reduced-motion). Use it when the assistant has been inactive for a while. The top bar stays interactive, which is where this demo puts the toggle.

import { useState } from 'react';
import { BrandMark, Button, HUDShell, Panel, TopBar } from 'jarvis-react-ui';

export default function Idle() {
    const [idle, setIdle] = useState(false);

    return (
        <HUDShell
            idle={idle}
            topbar={
                <TopBar
                    left={<BrandMark />}
                    right={
                        <Button size="sm" variant="ghost" onClick={() => setIdle((v) => !v)}>
                            {idle ? 'Wake' : 'Idle'}
                        </Button>
                    }
                />
            }
        >
            <div className="flex justify-center px-5 pt-20">
                <Panel title="Transcript" className="h-[140px] w-[300px]">
                    <span className="text-text-secondary">
                        {idle ? 'Panels are dimmed and click-through.' : 'Awaiting input.'}
                    </span>
                </Panel>
            </div>
        </HUDShell>
    );
}

Working state

Set working while a tool call runs. HUDShell adds the is-working class to its root, which draws an accent light trace sweeping along the top edge and a soft accent vignette breathing at the screen edges. Under prefers-reduced-motion both stay still: the trace becomes a static hairline across the top. The amber working look of the orb still comes from passing state="working" to the orb itself; you can target .hud-shell.is-working for further styles of your own.

import { useState } from 'react';
import { BrandMark, Button, HUDShell, Panel, TopBar } from 'jarvis-react-ui';

export default function Working() {
    const [working, setWorking] = useState(true);

    return (
        <HUDShell
            working={working}
            topbar={
                <TopBar
                    left={<BrandMark />}
                    right={
                        <Button size="sm" variant="ghost" onClick={() => setWorking((v) => !v)}>
                            {working ? 'Done' : 'Run tool'}
                        </Button>
                    }
                />
            }
        >
            <div className="flex justify-center px-5 pt-20">
                <Panel title="Tool call" className="h-[140px] w-[300px]">
                    <span className="text-text-secondary">
                        {working ? 'Fetching weather data...' : 'Idle.'}
                    </span>
                </Panel>
            </div>
        </HUDShell>
    );
}

Accessibility

  • HUDShell renders plain <div>s without landmark roles. Give your content its own structure, for example a <main> around the panels and a <nav> in the top bar.
  • The Scene, Reactor and ViewportCorners layers are aria-hidden and ignore pointer events; the orb layer ignores pointer events as well.
  • Idle mode sets inert on the children layer, so the dimmed panels cannot be clicked or focused and are hidden from assistive technology until idle is false again. The top bar, orb and dock slots stay interactive.
  • The working effect is decorative pseudo-element chrome and is not announced; pair it with a visible or live status (for example StatusDock).

API

Prop Type Default Description
children ReactNode Panels and windows; rendered in a relative layer above the orb (z-index 10).
className string Additional class names for the fixed, full-screen root <div>.
dock ReactNode Dock slot, typically a StatusDock; rendered as is, so it keeps its own fixed position.
idle boolean false Idle mode: dims and blurs the panels in children, makes them inert (click-through and removed from the tab order and accessibility tree) and fades the top bar. Entering and leaving idle both crossfade.
orb ReactNode Orb slot, typically a CssOrb or ThreeOrb; rendered in a full-screen, click-through layer behind the panels.
reactor boolean true Renders the Reactor glow at the bottom edge.
scene { grid?: boolean; stars?: boolean; scanlines?: boolean | undefined; } | undefined Optional layers of the background Scene; each one is on unless set to false.
style CSSProperties Inline styles for the root <div>; use it to inject CSS custom properties.
topbar ReactNode Top bar slot, typically a TopBar; rendered above everything else (z-index 30).
viewportCorners boolean true Renders the ViewportCorners marks in the four corners.
working boolean false Working mode for tool-call activity: adds the is-working class to the root, which draws an accent light trace sweeping along the top edge and a soft breathing accent vignette at the screen edges (static under prefers-reduced-motion).