Skip to content

Commit 82c99e7

Browse files
daniel-monroeclaude
andcommitted
Maia3 paper, team update, copyright, lint setup, zoom/layout fixes
- Add Maia3 Chessformer paper card on the home page - Add Daniel Monroe to the contributors team - Update copyright to 2026 - Fix ESLint on Windows: Prettier endOfLine "auto", ignore Next.js- generated next-env.d.ts, plus prettier-plugin-tailwindcss class ordering in candidates.tsx - Fix layout shifts and drag-piece offset at non-100% browser zoom in play mode: pin the left sidebar to a constant size, allow the FEN/PGN containers to shrink below their content width so the FEN string no longer pushes the board horizontally, manual scroll in the moves panel to avoid scrollIntoView propagating to the document body Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
1 parent 3ba7d91 commit 82c99e7

11 files changed

Lines changed: 105 additions & 63 deletions

File tree

.eslintignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Auto-generated by Next.js — should not be linted or hand-edited
2+
next-env.d.ts
3+
.next/

.prettierrc.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,6 @@
22
"semi": false,
33
"singleQuote": true,
44
"tabWidth": 2,
5+
"endOfLine": "auto",
56
"plugins": ["prettier-plugin-tailwindcss"]
67
}

next-env.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
/// <reference types="next" />
22
/// <reference types="next/image-types/global" />
3+
/// <reference path="./.next/types/routes.d.ts" />
34

45
// NOTE: This file should not be edited
56
// see https://nextjs.org/docs/pages/api-reference/config/typescript for more information.

public/assets/papers/maia3.jpg

318 KB
Loading

public/assets/team/daniel.png

138 KB
Loading

src/components/Board/GameplayInterface.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ export const GameplayInterface: React.FC<React.PropsWithChildren<Props>> = (
161161
<>
162162
<div className="flex h-full flex-1 flex-col justify-center gap-1 py-2 md:py-4">
163163
<div className="mx-auto mt-2 flex w-[90%] flex-row items-start justify-between gap-3">
164-
<div className="flex h-[75vh] min-w-[16rem] max-w-[22rem] flex-shrink-0 flex-col">
164+
<div className="flex h-[75vh] max-h-[75vh] min-h-[75vh] w-[22rem] min-w-[22rem] max-w-[22rem] flex-shrink-0 flex-col overflow-hidden">
165165
<div className="flex h-full w-full flex-col overflow-hidden rounded-md border border-glass-border bg-glass backdrop-blur-md">
166166
<GameInfo
167167
icon="swords"
@@ -219,7 +219,7 @@ export const GameplayInterface: React.FC<React.PropsWithChildren<Props>> = (
219219
/>
220220
) : null}
221221
</div>
222-
<div className="flex h-[75vh] min-w-[18rem] flex-grow flex-col gap-2">
222+
<div className="flex h-[75vh] min-w-0 flex-grow basis-[18rem] flex-col gap-2 overflow-hidden">
223223
{timeControl != 'unlimited' ? (
224224
<GameClock
225225
player={orientation == 'white' ? 'black' : 'white'}

src/components/Board/MovesContainer.tsx

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -162,11 +162,36 @@ export const MovesContainer: React.FC<
162162
])
163163

164164
useEffect(() => {
165-
if (currentMoveRef.current && containerRef.current) {
166-
currentMoveRef.current.scrollIntoView({
165+
const move = currentMoveRef.current
166+
const container = containerRef.current
167+
if (!move || !container) return
168+
169+
// scrollIntoView walks every scrollable ancestor up to the document body,
170+
// so it can shift the whole page if the moves panel sits near a viewport
171+
// edge. Scroll the moves panel directly instead, leaving everything above
172+
// it alone.
173+
const moveRect = move.getBoundingClientRect()
174+
const containerRect = container.getBoundingClientRect()
175+
176+
let topDelta = 0
177+
if (moveRect.top < containerRect.top) {
178+
topDelta = moveRect.top - containerRect.top
179+
} else if (moveRect.bottom > containerRect.bottom) {
180+
topDelta = moveRect.bottom - containerRect.bottom
181+
}
182+
183+
let leftDelta = 0
184+
if (moveRect.left < containerRect.left) {
185+
leftDelta = moveRect.left - containerRect.left
186+
} else if (moveRect.right > containerRect.right) {
187+
leftDelta = moveRect.right - containerRect.right
188+
}
189+
190+
if (topDelta !== 0 || leftDelta !== 0) {
191+
container.scrollTo({
192+
top: container.scrollTop + topDelta,
193+
left: container.scrollLeft + leftDelta,
167194
behavior: 'smooth',
168-
block: 'nearest',
169-
inline: 'nearest',
170195
})
171196
}
172197
}, [controller.currentNode])

src/components/Common/ExportGame.tsx

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -98,8 +98,8 @@ export const ExportGame: React.FC<Props> = (props) => {
9898
}
9999

100100
return (
101-
<div className="flex w-full flex-col gap-2">
102-
<div className="flex w-full flex-col gap-0.5">
101+
<div className="flex w-full min-w-0 flex-col gap-2 overflow-hidden">
102+
<div className="flex w-full min-w-0 flex-col gap-0.5">
103103
<div className="flex w-full items-center justify-between">
104104
<p className="select-none text-xs font-semibold tracking-wider text-secondary">
105105
FEN
@@ -117,14 +117,14 @@ export const ExportGame: React.FC<Props> = (props) => {
117117
role="button"
118118
tabIndex={0}
119119
onClick={() => copy(fen)}
120-
className="border-1 group flex w-full cursor-pointer overflow-x-hidden rounded border border-white/5 p-1"
120+
className="border-1 group flex w-full min-w-0 cursor-pointer overflow-x-hidden rounded border border-white/5 p-1"
121121
>
122-
<p className="whitespace-nowrap text-xxs text-secondary group-hover:text-secondary/80">
122+
<p className="min-w-0 overflow-hidden whitespace-nowrap text-xxs text-secondary group-hover:text-secondary/80">
123123
{fen}
124124
</p>
125125
</div>
126126
</div>
127-
<div className="flex w-full flex-col gap-0.5">
127+
<div className="flex w-full min-w-0 flex-col gap-0.5">
128128
<div className="flex w-full items-center justify-between">
129129
<div className="flex w-full items-center">
130130
<p className="select-none text-xs font-semibold tracking-wider text-secondary">
@@ -144,7 +144,7 @@ export const ExportGame: React.FC<Props> = (props) => {
144144
role="button"
145145
tabIndex={0}
146146
onClick={() => copy(pgn)}
147-
className="group flex w-full cursor-pointer overflow-x-hidden overflow-y-scroll rounded border border-white/5 p-1"
147+
className="group flex h-40 max-h-40 min-h-40 w-full min-w-0 cursor-pointer overflow-x-hidden overflow-y-scroll rounded border border-white/5 p-1"
148148
>
149149
<p className="whitespace-pre-wrap text-xxs text-secondary group-hover:text-secondary/80">
150150
{pgn}

src/components/Common/Footer.tsx

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,30 +18,38 @@ export const Footer: React.FC = () => {
1818
title: 'Research',
1919
links: [
2020
{
21-
href: 'https://arxiv.org/abs/2006.01855',
22-
text: "Maia Paper (KDD '20)",
21+
href: 'https://arxiv.org/abs/2605.19091',
22+
text: "Maia-3 Paper (ICLR '26)",
2323
},
2424
{
2525
href: 'https://www.cs.toronto.edu/~ashton/pubs/maia2-neurips2024.pdf',
2626
text: "Maia-2 Paper (NeurIPS '24)",
2727
},
28+
{
29+
href: 'https://arxiv.org/abs/2006.01855',
30+
text: "Maia Paper (KDD '20)",
31+
},
2832
{
2933
href: 'https://csslab.cs.toronto.edu/research/',
3034
text: 'CSSLab Research',
3135
},
3236
],
3337
},
3438
{
35-
title: 'Opensource',
39+
title: 'Open-Source',
3640
links: [
3741
{
38-
href: 'https://github.com/CSSLab/maia-chess',
39-
text: 'Maia Model',
42+
href: 'https://github.com/CSSLab/maia3',
43+
text: 'Maia-3 Model',
4044
},
4145
{
4246
href: 'https://github.com/CSSLab/maia2',
4347
text: 'Maia-2 Model',
4448
},
49+
{
50+
href: 'https://github.com/CSSLab/maia-chess',
51+
text: 'Maia Model',
52+
},
4553
{
4654
href: 'https://github.com/csslab/maia-platform-frontend',
4755
text: 'Maia Web Platform',
@@ -153,7 +161,7 @@ export const Footer: React.FC = () => {
153161
</div>
154162
</div>
155163
<p className="text-left text-sm text-secondary md:text-center md:text-xs">
156-
© 2025 Maia Chess. All rights reserved.
164+
© 2026 Maia Chess. All rights reserved.
157165
</p>
158166
</div>
159167
</div>

src/components/Home/AboutMaia.tsx

Lines changed: 47 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,14 @@ const teamMembers = [
4242
role: 'Model Developer',
4343
github: 'lilv98',
4444
},
45+
{
46+
image: '/assets/team/daniel.png',
47+
name: 'Daniel Monroe',
48+
website: 'https://daniel-monroe.github.io/',
49+
institution: 'University of Toronto',
50+
role: 'Model Developer',
51+
github: 'daniel-monroe',
52+
},
4553
{
4654
image: '/assets/team/kevin.jpg',
4755
name: 'Kevin Thomas',
@@ -75,19 +83,44 @@ const teamMembers = [
7583
},
7684
]
7785

78-
const researchPapers = {
86+
interface Paper {
87+
title: string
88+
link: string
89+
description: string
90+
image?: string
91+
shortName?: string
92+
}
93+
94+
const researchPapers: {
95+
maia1: Paper
96+
maia2: Paper
97+
maia3: Paper
98+
others: Paper[]
99+
} = {
79100
maia1: {
80101
title:
81102
'Aligning Superhuman AI with Human Behavior: Chess as a Model System',
82103
link: 'https://www.cs.toronto.edu/~ashton/pubs/maia-kdd2020.pdf',
83104
description:
84105
'This paper introduces Maia, a chess engine trained to imitate real human moves at different rating levels. Instead of always picking the best move, Maia predicts what a human player of a given skill would actually play. This makes it ideal for training, game analysis, and even coaching, as it helps players learn from realistic decisions rather than computer perfection. It was the first AI to prioritize human-likeness over engine strength, making it a powerful tool for improvement.',
106+
image: 'maia1',
107+
shortName: 'Maia 1',
85108
},
86109
maia2: {
87110
title: 'Maia‑2: A Unified Model for Human‑AI Alignment in Chess',
88111
link: 'https://www.cs.toronto.edu/~ashton/pubs/maia2-neurips2024.pdf',
89112
description:
90113
"Maia‑2 is the evolution of Maia into a single model that can simulate any skill level in chess. Instead of using separate models for different ratings, it understands and adapts to your level in real time. Whether you're a beginner or a master, Maia‑2 predicts the moves players like you would actually make. It's built to feel human, teach naturally, and support personalized analysis without needing to toggle between bots.",
114+
image: 'maia2',
115+
shortName: 'Maia 2',
116+
},
117+
maia3: {
118+
title: 'Chessformer: A Unified Architecture for Chess Modeling',
119+
link: 'https://arxiv.org/abs/2605.19091',
120+
description:
121+
'Introduces Chessformer, a transformer-based architecture that unifies chess modeling to capture how human players make decisions across a wide range of skill levels.',
122+
image: 'maia3',
123+
shortName: 'Maia 3',
91124
},
92125
others: [
93126
{
@@ -125,7 +158,7 @@ const PaperCard = ({
125158
featured = false,
126159
className = '',
127160
}: {
128-
paper: typeof researchPapers.maia1
161+
paper: Paper
129162
featured?: boolean
130163
className?: string
131164
}) => (
@@ -146,7 +179,7 @@ const PaperCard = ({
146179
{featured && (
147180
<div className="aspect-[4/3] w-full overflow-hidden">
148181
<img
149-
src={`/assets/papers/${paper.title.includes('Maia‑2') ? 'maia2' : 'maia1'}.jpg`}
182+
src={`/assets/papers/${paper.image}.jpg`}
150183
alt={`${paper.title} paper preview`}
151184
className="h-full w-full object-cover object-top"
152185
/>
@@ -172,7 +205,7 @@ const PaperCard = ({
172205
rel="noreferrer"
173206
className="inline-flex w-full items-center justify-center bg-human-4/80 px-5 py-3 font-medium text-primary transition duration-200 hover:bg-human-4"
174207
>
175-
Read {paper.title.includes('Maia‑2') ? 'Maia 2' : 'Maia 1'} Paper
208+
Read {paper.shortName} Paper
176209
</a>
177210
)}
178211
</div>
@@ -248,46 +281,17 @@ export const AboutMaia = () => {
248281
</div>
249282
</div>
250283
<div className="mx-auto max-w-[95%] px-2 pt-16 md:max-w-[90%] md:px-4">
251-
{/* Layout for screens < 1280px */}
252-
<div className="xl:hidden">
253-
{/* Featured papers in a row */}
254-
<div className="mb-6 grid grid-rows-2 gap-6 md:grid-cols-2 md:grid-rows-none">
255-
<PaperCard
256-
paper={researchPapers.maia1}
257-
featured={true}
258-
className=""
259-
/>
260-
<PaperCard
261-
paper={researchPapers.maia2}
262-
featured={true}
263-
className=""
264-
/>
265-
</div>
266-
{/* Other papers in a row */}
267-
<div className="grid grid-rows-2 gap-4 sm:grid-cols-4 sm:grid-rows-none">
268-
{researchPapers.others.map((paper, index) => (
269-
<PaperCard key={index} paper={paper} className="flex-1" />
270-
))}
271-
</div>
284+
{/* Featured papers */}
285+
<div className="mb-6 grid gap-6 md:grid-cols-3">
286+
<PaperCard paper={researchPapers.maia1} featured={true} />
287+
<PaperCard paper={researchPapers.maia2} featured={true} />
288+
<PaperCard paper={researchPapers.maia3} featured={true} />
272289
</div>
273-
274-
{/* Layout for screens >= 1280px (original layout) */}
275-
<div className="hidden xl:grid xl:grid-cols-3 xl:gap-6">
276-
<PaperCard
277-
paper={researchPapers.maia1}
278-
featured={true}
279-
className=""
280-
/>
281-
<PaperCard
282-
paper={researchPapers.maia2}
283-
featured={true}
284-
className=""
285-
/>
286-
<div className="flex flex-col gap-4">
287-
{researchPapers.others.map((paper, index) => (
288-
<PaperCard key={index} paper={paper} className="flex-1" />
289-
))}
290-
</div>
290+
{/* Other papers in two columns */}
291+
<div className="grid gap-4 sm:grid-cols-2">
292+
{researchPapers.others.map((paper, index) => (
293+
<PaperCard key={index} paper={paper} />
294+
))}
291295
</div>
292296
</div>
293297
</section>

0 commit comments

Comments
 (0)