From 3f12aed75abd78c3a92f9b67f779706c4e6e2ddb Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 30 Sep 2026 22:40:04 +0000 Subject: [PATCH] chess: pieces in text presentation, white outlined --- src/apps/chess/__tests__/rules.test.ts | 14 ++++++++++++++ src/apps/chess/components/ChessTable.module.css | 3 ++- src/apps/chess/rules.ts | 6 ++++-- 3 files changed, 20 insertions(+), 3 deletions(-) diff --git a/src/apps/chess/__tests__/rules.test.ts b/src/apps/chess/__tests__/rules.test.ts index 4ebaaaa..3d4987f 100644 --- a/src/apps/chess/__tests__/rules.test.ts +++ b/src/apps/chess/__tests__/rules.test.ts @@ -1,5 +1,6 @@ import { describe, expect, it } from 'vitest' import { + glyph, describeResult, formatClock, lastMoveSquares, @@ -88,6 +89,19 @@ describe('formatClock', () => { }) }) +describe('glyph', () => { + // U+265F is an emoji: without the text selector, phones draw the pawn + // as a black emoji whatever its side's color. + it('asks for text presentation, so CSS colors every piece', () => { + for (const piece of 'KQRBNPkqrbnp') expect(glyph(piece).endsWith('\uFE0E')).toBe(true) + }) + + it('draws both sides with the filled glyph', () => { + expect(glyph('P')).toBe(glyph('p')) + expect(glyph('K')).toBe('♚\uFE0E') + }) +}) + describe('pieceName', () => { it('names a piece by its color and kind', () => { expect(pieceName('K')).toBe('white king') diff --git a/src/apps/chess/components/ChessTable.module.css b/src/apps/chess/components/ChessTable.module.css index bce54b0..97a58f4 100644 --- a/src/apps/chess/components/ChessTable.module.css +++ b/src/apps/chess/components/ChessTable.module.css @@ -138,7 +138,8 @@ .whitePiece { color: #fff; - text-shadow: 0 0 2px #000, 0 0 1px #000; + -webkit-text-stroke: 0.04em #000; + paint-order: stroke fill; } .blackPiece { diff --git a/src/apps/chess/rules.ts b/src/apps/chess/rules.ts index c9cc3c8..78a49a7 100644 --- a/src/apps/chess/rules.ts +++ b/src/apps/chess/rules.ts @@ -86,11 +86,13 @@ export function pieceName(piece: string): string { } // Filled glyphs for both sides, told apart by color, so neither side's -// pieces read as outlines. +// pieces read as outlines. U+FE0E asks for text presentation: ♟ is also +// an emoji, which phones draw black whatever the CSS color says. const GLYPHS: Record = { k: '♚', q: '♛', r: '♜', b: '♝', n: '♞', p: '♟' } export function glyph(piece: string): string { - return GLYPHS[piece.toLowerCase()] ?? '' + const shape = GLYPHS[piece.toLowerCase()] + return shape === undefined ? '' : `${shape}\uFE0E` } const WON_BY: Record = {