From 928e018fcd6c0e8180ba96afe933eb3397027f9d Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 24 Oct 2026 19:09:15 +0000 Subject: [PATCH] Fix map editor crash, readable radial menu, new lobby tokens start hidden Co-Authored-By: Claude Sonnet 5.5 Claude-Session: https://claude.ai/code/session_01HJhXuLD2Z6hv3Wqeq9UL9K --- frontend/src/Lobbies.jsx | 4 ++-- frontend/src/MapView.jsx | 2 +- frontend/src/styles.css | 10 ++++++++++ 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/frontend/src/Lobbies.jsx b/frontend/src/Lobbies.jsx index 2b6a4db..c992a1e 100644 --- a/frontend/src/Lobbies.jsx +++ b/frontend/src/Lobbies.jsx @@ -792,11 +792,11 @@ function LobbyView({ id, rules, user }) { const hp = n.hp > 0 ? n.hp : undefined const m = mapState.map setNpcPick(false) - send(`/api/lobbies/${id}/tokens`, 'POST', { name: n.name, npc_id: n.id, x: m.w / 2, y: m.h / 2, size: n.size || 1, color: '#c0392b', hp_max: hp }).then((r) => r.json()).then((d) => d.id && setMapSel(d.id)).catch(() => {}) + send(`/api/lobbies/${id}/tokens`, 'POST', { name: n.name, npc_id: n.id, x: m.w / 2, y: m.h / 2, size: n.size || 1, color: '#c0392b', hp_max: hp, hidden: true }).then((r) => r.json()).then((d) => d.id && setMapSel(d.id)).catch(() => {}) } const addToken = () => { const m = mapState.map, n = mapState.tokens.filter((t) => t.kind === 'npc').length + 1 - send(`/api/lobbies/${id}/tokens`, 'POST', { name: `Enemy ${n}`, x: m.w / 2, y: m.h / 2, size: 1, color: '#c0392b' }).then((r) => r.json()).then((d) => d.id && setMapSel(d.id)).catch(() => {}) + send(`/api/lobbies/${id}/tokens`, 'POST', { name: `Enemy ${n}`, x: m.w / 2, y: m.h / 2, size: 1, color: '#c0392b', hidden: true }).then((r) => r.json()).then((d) => d.id && setMapSel(d.id)).catch(() => {}) } if (err && !lobby) return

{err}

Back to all lobbies
diff --git a/frontend/src/MapView.jsx b/frontend/src/MapView.jsx index aa6d87b..a12cea8 100644 --- a/frontend/src/MapView.jsx +++ b/frontend/src/MapView.jsx @@ -329,12 +329,12 @@ export function MapEditor({ id, onClose }) { // the full-size image, loaded once for the editor const [image, setImage] = useState(null) useEffect(() => { if (m) setImage({ src: `/api/maps/${id}/image`, x: 0, y: 0, w: m.w, h: m.h }) }, [m?.id]) // eslint-disable-line + const [picker, setPicker] = useState(false) if (!m) return null const gridNum = Number(grid) >= 4 ? Number(grid) : m.grid const cur = tokens.find((t) => t.id === sel) const patch = (tid, p) => { setTokens((ts) => ts.map((t) => (t.id === tid ? { ...t, ...p } : t))); setDirty(true) } const addWalls = (list) => { setWalls((w) => [...w, ...list.map((x) => ({ id: uid(), ...x }))]); setDirty(true) } - const [picker, setPicker] = useState(false) const addNpc = (n) => { const k = tokens.length + 1 const t = { id: uid(), kind: 'npc', can_move: true, name: n.name, npc_id: n.id, portrait: n.portrait || '', x: m.w / 2 + (k % 5) * gridNum, y: m.h / 2 + (k % 3) * gridNum, size: n.size || 1, color: COLORS[0], hidden: false, hp_max: n.hp > 0 ? n.hp : null, hp: n.hp > 0 ? n.hp : null } diff --git a/frontend/src/styles.css b/frontend/src/styles.css index 99e6b82..ea4c2f7 100644 --- a/frontend/src/styles.css +++ b/frontend/src/styles.css @@ -595,3 +595,13 @@ textarea.pwrite:focus { box-shadow: 0 0 0 1px var(--pg); } .revealpanel { right: auto; left: .5rem; bottom: .5rem; top: auto; max-width: 18rem; display: grid; gap: .4rem; } .visiongroups { display: grid; gap: .4rem; } .vgrow { justify-content: space-between; } + +/* radial menu: always a dark disc with light text, readable on both themes */ +.radialbtn { background: #1b2116 !important; border: 2px solid #8fd44c !important; color: #fff !important; } +.radialbtn:hover:not(:disabled) { background: #2b3a1c !important; border-color: gold !important; } +.radialbtn:disabled { opacity: .55; } +.radialbtn .ri { font-size: 1.35rem; color: #fff; } +.radialbtn .rl { font-size: .62rem; font-weight: 700; color: #fff; text-shadow: 0 1px 1px #000; } +.radialbtn { width: 58px; height: 58px; left: -29px; top: -29px; } +.radialtitle { background: #000; color: #fff; font-weight: 700; font-size: .8rem; border: 1px solid #8fd44c; } +.radialbtn:disabled { opacity: .78; background: #262b22 !important; border-color: #5a634f !important; cursor: not-allowed; }