Files
2026-05-27 23:29:53 +01:00

3.2 KiB

OpenSpec Change: enterprise-gaming-react-game-settings

  • Change ID: enterprise-gaming-react-game-settings
  • Package: @suaveplan/react-game-settings
  • Category: gaming/react
  • Target path: gaming/react/react-game-settings
  • Status: PROPOSED
  • Date: 2026-04-24
  • Reference spec: /mnt/s/web/suaveplan/enterprise/react-game-settings.md

Summary

Deliver @suaveplan/react-game-settings on the genesis branch from scratch at enterprise quality. The package is a headless React layer for player-configurable game settings. A SettingsManager holds typed settings categories (graphics, audio, controls, gameplay) with default values, dirty tracking, and localStorage persistence; useGameSettings() provides useSyncExternalStore access; typed components expose sliders, toggles, dropdowns, and keybind rows. Genesis adds Zod settings schemas, structured errors, and Storybook stories for all components.


Current-state audit (genesis)

Package does not exist on genesis yet — fresh build.


Available workspace deps on genesis

Package Role
@suaveplan/error (workspace:^) SettingsError
@suaveplan/controller (workspace:^) Keybind capture for controls settings
react (catalog:react) React 18
zod (catalog:forms) Settings schema validation

Public API surface

interface GameSettings {
  graphics: GraphicsSettings
  audio: AudioSettings
  controls: ControlsSettings
  gameplay: GameplaySettings
}

function createSettingsManager(defaults: GameSettings, options?: SettingsManagerOptions): SettingsManager

interface SettingsManager {
  getSnapshot(): GameSettings
  subscribe(cb: () => void): () => void
  update<K extends keyof GameSettings>(category: K, values: Partial<GameSettings[K]>): void
  reset(category?: keyof GameSettings): void
  save(): void
  load(): void
  readonly isDirty: boolean
}

function useGameSettings(): GameSettings & { update: SettingsManager['update']; isDirty: boolean }

// Components
function SettingsPanel(props: SettingsPanelProps): JSX.Element
function SettingsSlider(props: SettingsSliderProps): JSX.Element
function SettingsToggle(props: SettingsToggleProps): JSX.Element
function SettingsDropdown(props: SettingsDropdownProps): JSX.Element
function KeybindRow(props: KeybindRowProps): JSX.Element

File layout

gaming/react/react-game-settings/
  package.json
  tsconfig.json
  vitest.config.ts
  src/
    index.ts
    types/common.ts
    types/common.md
    state/
      settings-manager.ts
      settings-manager.md
      settings-manager.test.ts
    hooks/
      use-game-settings.ts
      use-game-settings.md
      use-game-settings.test.ts
    components/
      settings-panel/
        settings-panel.tsx + md + test + stories + index
      settings-slider/
        settings-slider.tsx + md + test + stories + index
      settings-toggle/
        settings-toggle.tsx + md + test + stories + index
      settings-dropdown/
        settings-dropdown.tsx + md + test + stories + index
      keybind-row/
        keybind-row.tsx + md + test + stories + index

Impact

Downstream: game apps use settings panel in pause menu. Prerequisites: @suaveplan/error, @suaveplan/controller, react, zod.