Zum Inhalt

src/ui/CinemaMode.tsx

import { type Component, createSignal, onCleanup, onMount } from 'solid-js';
import { presetState } from '~/stores/presetStore';
import { closePanel } from '~/stores/uiStore';

const HINT_VISIBLE_MS = 4000;
const HINT_FADE_MS = 800;

export const CinemaMode: Component = () => {
  // Show the exit hint at full opacity briefly, then fade out so it
  // stops competing with the visual. Re-shown on mouse move (below) so
  // a returning user can find it again without leaving cinema mode.
  const [hintVisible, setHintVisible] = createSignal(true);
  let hideTimer: ReturnType<typeof setTimeout> | null = null;

  const armHint = () => {
    setHintVisible(true);
    if (hideTimer !== null) clearTimeout(hideTimer);
    hideTimer = setTimeout(() => setHintVisible(false), HINT_VISIBLE_MS);
  };

  onMount(() => armHint());
  onCleanup(() => {
    if (hideTimer !== null) clearTimeout(hideTimer);
  });

  return (
    // biome-ignore lint/a11y/useKeyWithClickEvents: click-to-exit overlay — Escape key handled by useHotkeys
    <div
      style={{ position: 'absolute', inset: '0', 'z-index': '5' }}
      onClick={() => closePanel()}
      onMouseMove={armHint}
    >
      <div
        style={{
          position: 'absolute',
          top: '16px',
          right: '16px',
          padding: '7px 14px',
          background: 'color-mix(in oklab, var(--void-050) 65%, transparent)',
          border: '1px solid var(--phys-glass-border)',
          'backdrop-filter': 'blur(10px)',
          'border-radius': '999px',
          opacity: hintVisible() ? '0.92' : '0',
          transition: `opacity ${HINT_FADE_MS}ms ease-out`,
          'pointer-events': 'none',
        }}
      >
        <span
          class="phys-mono"
          style={{
            'font-size': '10px',
            color: 'var(--fg-primary)',
            'letter-spacing': '0.14em',
            'text-transform': 'uppercase',
          }}
        >
          Cinema · Esc or click to exit
        </span>
      </div>
      <div style={{ position: 'absolute', left: '24px', bottom: '24px', opacity: '0.4' }}>
        <span
          style={{
            'font-family': 'var(--font-display)',
            'font-size': '64px',
            'font-weight': '600',
            'letter-spacing': '-0.04em',
            'line-height': '1',
          }}
        >
          {presetState.current.name}
        </span>
      </div>
    </div>
  );
};