Lobby: chat at the right window edge, DM rolls hidden from players
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HJhXuLD2Z6hv3Wqeq9UL9K
This commit is contained in:
@@ -186,7 +186,7 @@ function Chat({ me, people, msgs, poll, id, to, setTo }) {
|
||||
const who = (m) => (
|
||||
<>
|
||||
<strong>{m.mine ? 'You' : m.from || '?'}</strong>
|
||||
{m.to && <em className="small whispertag"> {m.mine ? `to ${m.to}` : 'to you'} (private)</em>}
|
||||
{m.to && <em className="small whispertag"> {m.to === m.from ? '(only visible to you, the DM)' : m.mine ? `to ${m.to} (private)` : 'to you (private)'}</em>}
|
||||
</>
|
||||
)
|
||||
|
||||
@@ -241,7 +241,7 @@ function DieIcon({ sides }) {
|
||||
)
|
||||
}
|
||||
|
||||
function DiceBar({ id, to, poll }) {
|
||||
function DiceBar({ id, to, poll, isDm }) {
|
||||
const [count, setCount] = useState(1)
|
||||
const [busy, setBusy] = useState(false)
|
||||
const [err, setErr] = useState('')
|
||||
@@ -265,7 +265,7 @@ function DiceBar({ id, to, poll }) {
|
||||
<DieIcon sides={d} /><span>d{d}</span>
|
||||
</button>
|
||||
))}
|
||||
<span className={`small dicedest ${to ? 'priv' : 'muted'}`}>{to ? `Private: ${to}` : 'Public'}</span>
|
||||
<span className={`small dicedest ${to || isDm ? 'priv' : 'muted'}`}>{to ? `Private: ${to}` : isDm ? 'Hidden (only you)' : 'Public'}</span>
|
||||
{err && <span className="warn small">{err}</span>}
|
||||
</div>
|
||||
)
|
||||
@@ -297,7 +297,7 @@ function DiceTray({ rolls, me }) {
|
||||
const t = rollText(m)
|
||||
return (
|
||||
<div key={m.key} className="trayroll">
|
||||
<div className="small">{m.mine ? 'You' : m.from} rolled <strong>{t.dice}</strong>{m.to ? ` · private${m.mine ? ` to ${m.to}` : ''}` : ''}</div>
|
||||
<div className="small">{m.mine ? 'You' : m.from} rolled <strong>{t.dice}</strong>{m.to ? (m.to === m.from ? ' · only you' : ` · private${m.mine ? ` to ${m.to}` : ''}`) : ''}</div>
|
||||
<div className="trayrow">
|
||||
{m.roll.results.map((v, i) => <Die key={i} sides={m.roll.sides} value={v} delay={i * 120} />)}
|
||||
{t.n > 1 && <span className="traytotal">= {t.sum}</span>}
|
||||
@@ -461,7 +461,7 @@ function LobbyView({ id, rules, user, onOpen }) {
|
||||
</div>
|
||||
|
||||
<DiceTray rolls={tray} me={user} />
|
||||
<DiceBar id={id} to={dest} poll={feed.poll} />
|
||||
<DiceBar id={id} to={dest} poll={feed.poll} isDm={lobby.is_dm} />
|
||||
</section>
|
||||
)
|
||||
}
|
||||
|
||||
+14
-8
@@ -205,10 +205,11 @@ h2 + .charlist, .card + h2 { margin-top: 1.4rem; }
|
||||
.sheetview table { width: 100%; }
|
||||
@media (max-width: 760px) { .sheetcols { grid-template-columns: 1fr; } .chatform { flex-wrap: wrap; } .chatform select { width: 100%; } }
|
||||
|
||||
/* lobby desktop layout: main area left, chat column right, dice bar bottom centre */
|
||||
.lobbypage { max-width: 1500px; padding-bottom: 8rem; }
|
||||
.lobbygrid { display: grid; grid-template-columns: minmax(0, 1fr) 400px; gap: 1.4rem; align-items: start; }
|
||||
.lobbychat { position: sticky; top: 4.6rem; height: calc(100vh - 11rem); min-height: 22rem; padding: .7rem; display: flex; flex-direction: column; }
|
||||
/* lobby desktop layout: main area left, chat column fixed at the right edge of the window, dice bar bottom centre of the main area */
|
||||
:root { --chatw: 380px; --hdr: 3.7rem; }
|
||||
body:has(.lobbychat) main { max-width: none; margin: 0; padding-right: calc(var(--chatw) + 1.5rem); }
|
||||
.lobbypage { max-width: 1200px; margin: 0 auto; padding-bottom: 8rem; }
|
||||
.lobbychat { position: fixed; right: 0; top: var(--hdr); bottom: 0; width: var(--chatw); z-index: 10; border-radius: 0; border-width: 0 0 0 1px; padding: .8rem; display: flex; flex-direction: column; overflow: hidden; }
|
||||
.lobbychat .chatwrap { flex: 1; min-height: 0; grid-template-rows: minmax(0, 1fr) auto auto auto auto; }
|
||||
.lobbychat .chatbox { height: auto; min-height: 0; }
|
||||
.lobbychat .chatform { flex-wrap: wrap; }
|
||||
@@ -217,17 +218,17 @@ h2 + .charlist, .card + h2 { margin-top: 1.4rem; }
|
||||
.partygrid { grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); }
|
||||
.msg.rollmsg .rollres b { font-size: 1.05rem; color: var(--noxium); }
|
||||
.whispertag { color: #8a63c7; }
|
||||
@media (max-width: 1050px) { .lobbygrid { grid-template-columns: 1fr; } .lobbychat { position: static; height: 28rem; } }
|
||||
|
||||
.dicebar { position: fixed; bottom: 1rem; left: 50%; transform: translateX(-50%); z-index: 30; display: flex; align-items: center; gap: .35rem; flex-wrap: wrap; justify-content: center;
|
||||
max-width: calc(100vw - 1.5rem); background: var(--panel); border: 1px solid var(--line); border-radius: 999px; padding: .4rem .8rem; box-shadow: 0 6px 24px rgba(0, 0, 0, .22); }
|
||||
|
||||
.dicebar { position: fixed; bottom: 1rem; left: calc((100vw - var(--chatw)) / 2); transform: translateX(-50%); z-index: 30; display: flex; align-items: center; gap: .35rem; flex-wrap: wrap; justify-content: center;
|
||||
max-width: calc(100vw - var(--chatw) - 1.5rem); background: var(--panel); border: 1px solid var(--line); border-radius: 999px; padding: .4rem .8rem; box-shadow: 0 6px 24px rgba(0, 0, 0, .22); }
|
||||
.dicecount { display: flex; align-items: center; gap: .3rem; margin-right: .3rem; }
|
||||
.dicecount select { width: auto; padding: .25rem .4rem; }
|
||||
.diebtn { display: flex; flex-direction: column; align-items: center; gap: 0; padding: .2rem .5rem; border-radius: 12px; min-width: 3.1rem; font-size: .75rem; line-height: 1.1; }
|
||||
.diebtn:hover:not(:disabled) { border-color: var(--noxium); color: var(--noxium); }
|
||||
.dicedest { margin-left: .4rem; padding-left: .6rem; border-left: 1px solid var(--line); }
|
||||
.dicedest.priv { color: #8a63c7; font-weight: 600; }
|
||||
.dicetray { position: fixed; bottom: 5.4rem; left: 50%; transform: translateX(-50%); z-index: 29; display: grid; gap: .5rem; justify-items: center; pointer-events: none; }
|
||||
.dicetray { position: fixed; bottom: 5.4rem; left: calc((100vw - var(--chatw)) / 2); transform: translateX(-50%); z-index: 29; display: grid; gap: .5rem; justify-items: center; pointer-events: none; }
|
||||
.trayroll { background: var(--panel); border: 1px solid var(--line); border-radius: 14px; padding: .5rem .9rem; box-shadow: 0 6px 24px rgba(0, 0, 0, .25); animation: trayin .25s ease-out; }
|
||||
.trayrow { display: flex; align-items: center; gap: .5rem; margin-top: .3rem; flex-wrap: wrap; justify-content: center; max-width: 30rem; }
|
||||
.traytotal { font-weight: 700; font-size: 1.2rem; margin-left: .3rem; }
|
||||
@@ -245,3 +246,8 @@ h2 + .charlist, .card + h2 { margin-top: 1.4rem; }
|
||||
@keyframes land { 0% { transform: scale(1.35); } 100% { transform: scale(1); } }
|
||||
@keyframes trayin { from { opacity: 0; transform: translateY(14px); } to { opacity: 1; transform: none; } }
|
||||
@media (prefers-reduced-motion: reduce) { .die.rolling, .die.landed, .trayroll { animation: none; } }
|
||||
|
||||
@media (max-width: 1050px) { body:has(.lobbychat) main { max-width: 1280px; margin: 0 auto; padding-right: 1rem; } .lobbychat { position: static; width: auto; height: 28rem; border-width: 1px; border-radius: var(--radius); margin-top: 1rem; } .dicebar, .dicetray { left: 50%; } .dicebar { max-width: calc(100vw - 1.5rem); } }
|
||||
.lobbycard { align-content: start; }
|
||||
.lobbycard .chips { align-items: flex-start; align-content: flex-start; }
|
||||
.lobbycard .chip { align-self: flex-start; }
|
||||
|
||||
Reference in New Issue
Block a user