feedback7 UIBACK: a 设置 button left of 玩法说明 in the lobby's and the room's top bar (GitHub #238 by RushFTK) — ui/settings.js SettingsButton opens the same settings modal as the title screen and the match; no background-music option and no board-style option (the owner's decision of 2026-10-07: neither is official); test/ui/settings-entry.e2e.test.js; golden: unchanged (client only)

This commit is contained in:
sganggs committed 2026-10-08 19:09:55 +08:00
1 parent df540b6210
commit 911e4bff2b
6 files changed
+111 -2

No files matched your search

+16 -1
View File
@@ -3,10 +3,12 @@
// the settings modal — which also holds the language switch (ui/lang.js; kept apart in `sp.pref.lang`; under it a note
// while the current language's pack is a machine translation, `_meta.machineTranslated`) and the 快捷键
// section that rebinds the in-match shortcuts (the key map: ui/gameLogic/shortcuts.js; the community request
// 「快捷键可不可以自己设置」, the owner's decision of 2026-10-07).
// 「快捷键可不可以自己设置」, the owner's decision of 2026-10-07). The lobby and the room open it from a 设置 button next to
// 玩法说明 (SettingsButton, GitHub #238); the title screen and the match have their own gear.
import { useLayoutEffect, useState } from '../../vendor/hooks.module.js';
import { html, Modal, Button, Icon, MicroLabel } from './components.js';
import { GIcon } from './gameComponents.js';
import { createStore, useStore, loadPref, savePref } from '../store.js';
import { sanitizeSettings, HOTKEY_ACTIONS, DEFAULT_HOTKEYS, hotkeyLabel, rebindHotkey, isDefaultHotkeys, captureHotkey } from './gameLogic.js';
import { audio } from '../audio.js';
@@ -180,3 +182,16 @@ export function SettingsModal({ open, onClose }) {
</div>
<//>`;
}
/**
* The 设置 button of the lobby and the room (GitHub #238 — before it the settings were reachable only from the title
* screen and a running match): the twin of the 玩法说明 button (ui/guide.js GuideButton), with the settings modal behind it
* (mounted only while open). The same modal as the title screen's and the match's: nothing in it is match-only.
* @param {{ class?: string, size?: 'sm'|'md'|'lg'|'xl', variant?: string, label?: string }} props
*/
export function SettingsButton({ class: cls, size = 'sm', variant = 'ghost', label = t('设置') }) {
const [open, setOpen] = useState(false);
return html`<${Button} variant=${variant} size=${size} class=${cx('settings-btn', cls)} onClick=${() => setOpen(true)}
title=${t('设置')} aria-label=${t('设置')} data-testid="settings-btn"><${GIcon} name="gear" class="btn__icon" />${label}<//>
${open ? html`<${SettingsModal} open=${true} onClose=${() => setOpen(false)} />` : null}`;
}