Enter to submit.

This commit is contained in:
Greyson Parrelli
2026-07-25 23:13:40 -04:00
parent 0bf9712c5e
commit e3234b6f83
3 changed files with 31 additions and 52 deletions
+11 -39
View File
@@ -3,38 +3,6 @@ import { createPortal } from 'react-dom'
import type { Card } from '../types'
import { artFor, artUrlFor } from '../petArt'
// The suit's "hat" — the trade-in symbol printed on the real cards, tinted to
// the suit's colour. Drawn as a tiny sun-hat SVG so it scales crisply.
const SUIT_HAT: Record<string, { fill: string; band: string }> = {
red: { fill: '#e5563f', band: '#b62c1f' },
blue: { fill: '#4d8ce3', band: '#2b5fb0' },
yellow: { fill: '#f2c24d', band: '#d9992f' },
}
function SuitHat({ suit }: { suit: string }) {
const c = SUIT_HAT[suit] ?? SUIT_HAT.yellow
return (
<svg className="card-hat" viewBox="0 0 28 18" aria-hidden>
<path
d="M7 12.5 Q7 3.5 14 3.5 Q21 3.5 21 12.5 Z"
fill={c.fill}
stroke="rgba(50,25,8,.45)"
strokeWidth="1"
/>
<path d="M7.4 11 Q14 13 20.6 11 L20.6 12.6 Q14 14.6 7.4 12.6 Z" fill={c.band} />
<ellipse
cx="14"
cy="13.4"
rx="12.6"
ry="3.7"
fill={c.fill}
stroke="rgba(50,25,8,.45)"
strokeWidth="1"
/>
</svg>
)
}
// The tier shown as a die face (16 pips), like the real cards' corner marker.
const DIE_PIPS: Record<number, [number, number][]> = {
1: [[15, 15]],
@@ -57,21 +25,25 @@ function TierDie({ tier }: { tier: number }) {
)
}
// useFitText shrinks the effect text until it fits its band, so long abilities
// (and the smaller battle cards) render in full instead of being clipped by
// the fixed card height. It never grows past the CSS size, only shrinks toward
// a small floor, and re-fits when the band resizes (breakpoints, battle mode).
// useFitText shrinks text until it fits its box, so long abilities (and the
// smaller battle cards) render in full instead of being clipped by the fixed
// card height, and long single-line names shrink instead of wrapping. It
// checks both axes — the effect band wraps and overflows vertically, the
// (nowrap) name row overflows horizontally. It never grows past the CSS size,
// only shrinks toward a small floor, and re-fits when the box resizes
// (breakpoints, battle mode).
function useFitText(dep: unknown) {
const ref = useRef<HTMLDivElement>(null)
useLayoutEffect(() => {
const el = ref.current
if (!el) return
const overflows = () => el.scrollHeight > el.clientHeight || el.scrollWidth > el.clientWidth
const fit = () => {
el.style.fontSize = ''
let size = parseFloat(getComputedStyle(el).fontSize)
const min = 6
// Guard the loop; each step is 0.5px so ~40 covers any realistic band.
for (let i = 0; i < 40 && el.scrollHeight > el.clientHeight && size > min; i++) {
// Guard the loop; each step is 0.5px so ~40 covers any realistic box.
for (let i = 0; i < 40 && overflows() && size > min; i++) {
size = Math.max(min, size - 0.5)
el.style.fontSize = `${size}px`
}
@@ -284,7 +256,7 @@ export function CardView({
<div className="card-panel">
<div className="card-panel-head">
{card.suit ? (
<SuitHat suit={card.suit} />
<span className={`suit-dot card-suit suit-${card.suit}`} aria-hidden />
) : (
<span className="card-panel-slot" aria-hidden />
)}