+
= ({
role="button"
tabIndex={0}
onClick={() => copy(pgn)}
- className="border-1 group flex cursor-pointer overflow-x-hidden rounded border border-white/5 bg-background-1/50 px-4 py-2"
+ className="group flex max-h-32 w-full cursor-pointer overflow-x-hidden overflow-y-scroll rounded border border-white/5 bg-background-1/50 p-3"
>
{pgn}
diff --git a/src/components/Misc/GameInfo.tsx b/src/components/Misc/GameInfo.tsx
index 56aee110..35b685e2 100644
--- a/src/components/Misc/GameInfo.tsx
+++ b/src/components/Misc/GameInfo.tsx
@@ -1,13 +1,17 @@
-import { useContext } from 'react'
-
-import { ModalContext } from 'src/contexts'
-import { InstructionsType } from 'src/components'
+import { useTour } from 'src/contexts'
+import { InstructionsType } from 'src/types'
+import { tourConfigs } from 'src/config/tours'
interface Props {
icon: string
title: string
type: InstructionsType
children: React.ReactNode
+ currentMaiaModel?: string
+ setCurrentMaiaModel?: (model: string) => void
+ MAIA_MODELS?: string[]
+ showGameListButton?: boolean
+ onGameListClick?: () => void
}
export const GameInfo: React.FC = ({
@@ -15,23 +19,82 @@ export const GameInfo: React.FC = ({
title,
type,
children,
+ currentMaiaModel,
+ setCurrentMaiaModel,
+ MAIA_MODELS,
+ showGameListButton,
+ onGameListClick,
}: Props) => {
- const { setInstructionsModalProps } = useContext(ModalContext)
+ const { startTour } = useTour()
+
return (
-
+
{icon}
{title}
+ {currentMaiaModel && setCurrentMaiaModel && (
+
+ using
+
+
+
+ arrow_drop_down
+
+
+
+ )}
+
+
+ {showGameListButton && (
+
+ )}
+
-
{children}
diff --git a/src/components/Misc/InstructionsModal.tsx b/src/components/Misc/InstructionsModal.tsx
deleted file mode 100644
index 696ac37d..00000000
--- a/src/components/Misc/InstructionsModal.tsx
+++ /dev/null
@@ -1,90 +0,0 @@
-import { useContext } from 'react'
-import { AnimatePresence } from 'framer-motion'
-
-import { ModalContext } from 'src/contexts'
-import { CloseIcon } from 'src/components/Icons/icons'
-import { Markdown, ModalContainer } from 'src/components'
-
-export type InstructionsType =
- | 'againstMaia'
- | 'handAndBrain'
- | 'analysis'
- | 'train'
- | 'turing'
-
-const titles = {
- againstMaia: 'Play Maia',
- handAndBrain: 'Play Hand and Brain',
- analysis: 'Analysis',
- train: 'Training',
- turing: 'Bot or Not',
-}
-
-// const placeholder = `Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum eget velit volutpat, efficitur velit sed, volutpat orci. Pellentesque magna libero, commodo a neque a, interdum fringilla lacus. Nulla bibendum scelerisque dignissim. Sed non mi ac ligula laoreet euismod in ut diam. Maecenas nunc dolor, congue et nisl a, placerat dignissim urna. Mauris pretium quis ante a tristique. Duis vulputate leo ac erat mollis finibus. Fusce leo neque, auctor a dignissim non, tristique quis tortor. Aenean faucibus lacus turpis, eget bibendum sem maximus vitae.`
-
-const analysisModalText = `This is the Analysis page, where you can analyze both your own Lichess games and World Championship matches with Maia and Stockfish. Combining Maia analysis with Stockfish analysis gives you a more human-centered way to think about chess. For example, it can help you differentiate strong, findable moves from strong but impossible-to-find "engine" moves. It can also highlight tempting blunders that humans are likely to play. The movemap in the top-right visualizes all legal moves on a plane, where Stockfish-measured quality is on the x-axis and Maia probability is on the y-axis. Strong, findable moves are in the top right, "engine" moves are in the bottom right, and tempting blunders are in the top left. You can navigate to different games in the games panel, and you can play a position against Maia with the "Continue against Maia" button. Happy analyzing, and let us know if you find any bugs or want to see any improvements!`
-
-const turingModalText = `Welcome to Bot-or-not, a fun Turing game where you see if you can tell human from machine. You will be shown games where one player is a human and the other player is a bot, and your job is to pick which side is the bot. You can browse the game in its entirety, and along with your guess you can submit an optional explanation of your reasoning. You will get a rating based on your accuracy, and you can see how you compare to other players on the leaderboard. Bots will also get ratings based on how often they trick humans. Have fun!`
-
-const handAndBrainModalText = `Here you can play Hand and Brain with Maia. In Hand and Brain chess, one player is the "brain" and decides which piece type to move (e.g. "pawn" or "rook") and the other player is the "hand" and chooses which move to make with that piece type (e.g. rook to c7). You can play as either the hand or the brain, and Maia will be your partner and play the other role. You will play against a team of Maias paired up with each other (one Maia will be the brain, and the other Maia will randomly decide which move to play, according to how often a human would play that move). You can also choose the level of Maia's play, from 1100 to 1900, for both your partner Maia and the opponent Maias. You will get both a Hand rating and a Brain rating based on your play. Have fun!`
-
-const againstMaiaModalText = `Here you can play against Maia, our human-like chess engine. Maia is trained to play like a human at a specific skill level. You can choose the level of Maia's play, from 1100 to 1900, and you can also choose the time control of the game. You can also choose to play from a specific starting position, for example to practice a specific opening. You will get a Maia rating based on your play. Have fun!`
-
-const trainModalText = `Here you can solve Maia-inspired tactics puzzles. Once you either correctly solve the puzzle or choose to give up, you will unlock the movemap that shows all legal moves in the position on the Stockfish-Maia plane. You will get a tactics rating based on your attempts. Have fun!`
-
-const content = {
- againstMaia: againstMaiaModalText,
- handAndBrain: handAndBrainModalText,
- analysis: analysisModalText,
- train: trainModalText,
- turing: turingModalText,
-}
-
-export interface Props {
- instructionsType: InstructionsType
-}
-
-export const InstructionsModal: React.FC
= ({
- instructionsType,
-}: Props) => {
- const {
- openedModals,
- setOpenedModals,
- setInstructionsModalProps: setInstructionsModalProps,
- } = useContext(ModalContext)
-
- const dismiss = () => {
- setInstructionsModalProps(undefined)
- setOpenedModals({ ...openedModals, [instructionsType]: true })
- }
-
- return (
-
-
-
-
-
- {titles[instructionsType]}
-
-
-
{content[instructionsType]}
-
-
-
-
-
-
-
- )
-}
diff --git a/src/components/Misc/ModalContainer.tsx b/src/components/Misc/ModalContainer.tsx
index c2485eb5..4cdec58c 100644
--- a/src/components/Misc/ModalContainer.tsx
+++ b/src/components/Misc/ModalContainer.tsx
@@ -1,4 +1,5 @@
import { motion } from 'framer-motion'
+import { useEffect } from 'react'
interface Props {
dismiss: () => void
@@ -11,6 +12,14 @@ export const ModalContainer: React.FC = ({
dismiss,
className,
}: Props) => {
+ // Prevent background scrolling when modal is open
+ useEffect(() => {
+ document.body.style.overflow = 'hidden'
+ return () => {
+ document.body.style.overflow = 'unset'
+ }
+ }, [])
+
return (
// Modal always has dismiss button so not required for a11y
// eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions
@@ -28,7 +37,7 @@ export const ModalContainer: React.FC = ({
animate={{ y: 0, opacity: 1 }}
exit={{ y: 100, opacity: 0 }}
transition={{ duration: 0.2, type: 'tween' }}
- className="max-w-[100vw] rounded bg-backdrop p-8"
+ className="max-w-[100vw] rounded"
onClick={(e: React.MouseEvent) => e.stopPropagation()}
>
{children}
diff --git a/src/components/Misc/PlaySetupModal.tsx b/src/components/Misc/PlaySetupModal.tsx
index cf6f4893..6522a552 100644
--- a/src/components/Misc/PlaySetupModal.tsx
+++ b/src/components/Misc/PlaySetupModal.tsx
@@ -1,4 +1,6 @@
import Image from 'next/image'
+import { Chess } from 'chess.ts'
+import toast from 'react-hot-toast'
import { useRouter } from 'next/router'
import { AnimatePresence } from 'framer-motion'
import { useCallback, useContext, useState } from 'react'
@@ -40,12 +42,18 @@ function OptionSelect({
onChange,
}: OptionSelectProps) {
return (
-
+
{options.map((option, index) => {
return (