anvilsign in

collin/mahjong

1import type { Prefs } from '../game/prefs';
2import { enterFullscreen, exitFullscreen, fullscreenSupported, useFullscreen } from './fullscreen';
3import { useT } from './lang';
4
5interface Props {
6 prefs: Prefs;
7 onPrefs: (p: Prefs) => void;
8 /** Icon only, for the cramped row of controls in the middle of the table. */
9 compact?: boolean;
10}
11
12/* Corner brackets rather than a glyph: this has to read on whatever font a
13 phone happens to have, and the symbols for it are thin on the ground. */
14const Corners = ({ out }: { out: boolean }) => (
15 <svg
16 className="fs-icon"
17 viewBox="0 0 20 20"
18 width="15"
19 height="15"
20 aria-hidden
21 fill="none"
22 stroke="currentColor"
23 strokeWidth="2"
24 strokeLinecap="round"
25 strokeLinejoin="round"
26 >
27 {out ? (
28 <path d="M2 7V2h5M13 2h5v5M18 13v5h-5M7 18H2v-5" />
29 ) : (
30 <path d="M7 2v5H2M18 7h-5V2M13 18v-5h5M2 13h5v5" />
31 )}
32 </svg>
33);
34
35/**
36 * Takes the screen and gives it back — and remembers which the player wanted.
37 * The browser drops fullscreen on every reload, and this game is built to be
38 * put down and resumed, so without that memory you would be reaching for this
39 * button every single time.
40 */
41export function FullscreenToggle({ prefs, onPrefs, compact }: Props) {
42 const t = useT();
43 const active = useFullscreen();
44 if (!fullscreenSupported()) return null;
45
46 return (
47 <button
48 className={`btn ghost pill fs-toggle ${compact ? 'compact' : ''} ${active ? 'on' : ''}`}
49 aria-pressed={active}
50 onClick={() => {
51 // Made here, inside the click: the same call from an effect is refused.
52 if (active) exitFullscreen();
53 else enterFullscreen();
54 onPrefs({ ...prefs, fullscreen: !active });
55 }}
56 >
57 <Corners out={!active} />
58 {!compact && (
59 <span>{active ? t('離開全螢幕', 'Exit full screen') : t('全螢幕', 'Full screen')}</span>
60 )}
61 </button>
62 );
63}