chore: Fix useButtonType linter errors

This commit is contained in:
2026-06-28 12:39:34 -04:00
parent ce1f0fee41
commit b2bbad9c58

View File

@@ -329,7 +329,12 @@ export default function CharacterSheet() {
b: c.benefits, b: c.benefits,
s: c.skills, s: c.skills,
})), })),
oc: otherClasses.map((c) => ({ n: c.name, lv: c.level, b: c.benefits, s: c.skills })), oc: otherClasses.map((c) => ({
n: c.name,
lv: c.level,
b: c.benefits,
s: c.skills,
})),
sp: spells.map((s) => ({ sp: spells.map((s) => ({
n: s.name, n: s.name,
cl: s.spellClass, cl: s.spellClass,
@@ -612,7 +617,7 @@ export default function CharacterSheet() {
<div className="logo">Fabula Ultima</div> <div className="logo">Fabula Ultima</div>
<div className="tabs"> <div className="tabs">
{["main", "classes", "spells", "manage"].map((tab, i) => ( {["main", "classes", "spells", "manage"].map((tab, i) => (
<button <button type="button"
key={tab} key={tab}
className={`tab${activeTab === tab ? " active" : ""}`} className={`tab${activeTab === tab ? " active" : ""}`}
onClick={() => setActiveTab(tab)} onClick={() => setActiveTab(tab)}
@@ -625,10 +630,10 @@ export default function CharacterSheet() {
<span className={`save-status${saveStatus ? " show" : ""}`}> <span className={`save-status${saveStatus ? " show" : ""}`}>
Saved! Saved!
</span> </span>
<button className="btn-print" onClick={() => window.print()}> <button type="button" className="btn-print" onClick={() => window.print()}>
Print Print
</button> </button>
<button <button type="button"
className="btn-theme" className="btn-theme"
onClick={() => setTheme((t) => (t === "light" ? "dark" : "light"))} onClick={() => setTheme((t) => (t === "light" ? "dark" : "light"))}
> >
@@ -725,7 +730,7 @@ export default function CharacterSheet() {
<div className="level-display"> <div className="level-display">
<span className="level-num">{level}</span> <span className="level-num">{level}</span>
<span className="level-text">Character Level</span> <span className="level-text">Character Level</span>
<button <button type="button"
className="add-btn" className="add-btn"
style={{ style={{
marginTop: 10, marginTop: 10,
@@ -736,7 +741,7 @@ export default function CharacterSheet() {
> >
+ Level Up + Level Up
</button> </button>
<button <button type="button"
className="add-btn" className="add-btn"
style={{ style={{
marginTop: 4, marginTop: 4,
@@ -821,12 +826,14 @@ export default function CharacterSheet() {
<span className="icon"></span> Attributes <span className="icon"></span> Attributes
</div> </div>
<div className="attr-grid"> <div className="attr-grid">
{([ {(
[
{ label: "Dexterity", base: "dexBase", cur: "dexCur" }, { label: "Dexterity", base: "dexBase", cur: "dexCur" },
{ label: "Insight", base: "insBase", cur: "insCur" }, { label: "Insight", base: "insBase", cur: "insCur" },
{ label: "Might", base: "migBase", cur: "migCur" }, { label: "Might", base: "migBase", cur: "migCur" },
{ label: "Willpower", base: "wlpBase", cur: "wlpCur" }, { label: "Willpower", base: "wlpBase", cur: "wlpCur" },
] as const).map(({ label, base, cur }) => ( ] as const
).map(({ label, base, cur }) => (
<div key={label} className="attr-block"> <div key={label} className="attr-block">
<div className="attr-name">{label}</div> <div className="attr-name">{label}</div>
<div className="attr-inputs"> <div className="attr-inputs">
@@ -901,7 +908,7 @@ export default function CharacterSheet() {
{inCrisis && <div className="crisis-badge">CRISIS</div>} {inCrisis && <div className="crisis-badge">CRISIS</div>}
</div> </div>
</div> </div>
<button <button type="button"
className="add-btn" className="add-btn"
style={{ padding: "4px 8px" }} style={{ padding: "4px 8px" }}
onClick={calcHP} onClick={calcHP}
@@ -931,7 +938,7 @@ export default function CharacterSheet() {
/> />
</div> </div>
</div> </div>
<button <button type="button"
className="add-btn" className="add-btn"
style={{ padding: "4px 8px" }} style={{ padding: "4px 8px" }}
onClick={calcMP} onClick={calcMP}
@@ -1099,7 +1106,8 @@ export default function CharacterSheet() {
))} ))}
</div> </div>
<div style={{ marginTop: 14 }}> <div style={{ marginTop: 14 }}>
{([ {(
[
{ {
slot: "Accessory", slot: "Accessory",
name: "accName", name: "accName",
@@ -1128,7 +1136,8 @@ export default function CharacterSheet() {
namePh: "Weapon / shield", namePh: "Weapon / shield",
descPh: "Damage / effect", descPh: "Damage / effect",
}, },
] as const).map(({ slot, name, desc, namePh, descPh }) => ( ] as const
).map(({ slot, name, desc, namePh, descPh }) => (
<div key={slot} className="equip-row"> <div key={slot} className="equip-row">
<div className="equip-slot">{slot}</div> <div className="equip-slot">{slot}</div>
<div className="equip-fields"> <div className="equip-fields">
@@ -1160,26 +1169,47 @@ export default function CharacterSheet() {
placeholder="Items, notes, lore…" placeholder="Items, notes, lore…"
style={{ minHeight: 200 }} style={{ minHeight: 200 }}
/> />
<button <button type="button"
className="add-btn" className="add-btn"
style={{ marginTop: 8 }} style={{ marginTop: 8 }}
onClick={() => { setWeaponCategory("all"); setWeaponPickerOpen(true); }} onClick={() => {
setWeaponCategory("all");
setWeaponPickerOpen(true);
}}
> >
+ Add Equipment + Add Equipment
</button> </button>
{weaponPickerOpen && (() => { {weaponPickerOpen &&
(() => {
const allWeapons = (weaponsFile as WeaponsFile).weapons; const allWeapons = (weaponsFile as WeaponsFile).weapons;
const allArmorShields = (armorShieldsFile as ArmorShieldsFile).armor_shields; const allArmorShields = (armorShieldsFile as ArmorShieldsFile)
.armor_shields;
type PickerItem = type PickerItem =
| { kind: "weapon"; data: WeaponTemplate } | { kind: "weapon"; data: WeaponTemplate }
| { kind: "armor"; data: ArmorShieldTemplate }; | { kind: "armor"; data: ArmorShieldTemplate };
const allItems: PickerItem[] = [ const allItems: PickerItem[] = [
...allWeapons.map(w => ({ kind: "weapon" as const, data: w })), ...allWeapons.map((w) => ({
...allArmorShields.map(a => ({ kind: "armor" as const, data: a })), kind: "weapon" as const,
data: w,
})),
...allArmorShields.map((a) => ({
kind: "armor" as const,
data: a,
})),
]; ];
const categories = ["all", ...Array.from(new Set(allItems.map(i => i.data.category))).sort()]; const categories = [
const visible = weaponCategory === "all" ? allItems : allItems.filter(i => i.data.category === weaponCategory); "all",
...Array.from(
new Set(allItems.map((i) => i.data.category)),
).sort(),
];
const visible =
weaponCategory === "all"
? allItems
: allItems.filter(
(i) => i.data.category === weaponCategory,
);
const formatLine = (item: PickerItem) => { const formatLine = (item: PickerItem) => {
if (item.kind === "weapon") { if (item.kind === "weapon") {
const w = item.data; const w = item.data;
@@ -1191,18 +1221,41 @@ export default function CharacterSheet() {
} }
}; };
return ( return (
<div className="spell-picker-overlay" onClick={() => setWeaponPickerOpen(false)}> <div
<div className="spell-picker-modal" onClick={e => e.stopPropagation()}> className="spell-picker-overlay"
onClick={() => setWeaponPickerOpen(false)}
>
<div
className="spell-picker-modal"
onClick={(e) => e.stopPropagation()}
>
<div className="spell-picker-header"> <div className="spell-picker-header">
<span>Choose equipment</span> <span>Choose equipment</span>
<button className="spell-picker-close" onClick={() => setWeaponPickerOpen(false)}></button> <button type="button"
className="spell-picker-close"
onClick={() => setWeaponPickerOpen(false)}
>
</button>
</div> </div>
<div style={{ display: "flex", gap: 6, flexWrap: "wrap", padding: "8px 14px", borderBottom: "1px solid var(--border)" }}> <div
{categories.map(cat => ( style={{
<button display: "flex",
gap: 6,
flexWrap: "wrap",
padding: "8px 14px",
borderBottom: "1px solid var(--border)",
}}
>
{categories.map((cat) => (
<button type="button"
key={cat} key={cat}
className={`add-btn${weaponCategory === cat ? " active-filter" : ""}`} className={`add-btn${weaponCategory === cat ? " active-filter" : ""}`}
style={{ padding: "2px 8px", fontSize: "0.65rem", textTransform: "capitalize" }} style={{
padding: "2px 8px",
fontSize: "0.65rem",
textTransform: "capitalize",
}}
onClick={() => setWeaponCategory(cat)} onClick={() => setWeaponCategory(cat)}
> >
{cat} {cat}
@@ -1216,12 +1269,21 @@ export default function CharacterSheet() {
className="spell-picker-item" className="spell-picker-item"
onClick={() => { onClick={() => {
const line = formatLine(item); const line = formatLine(item);
f("backpack", fields.backpack ? fields.backpack + "\n" + line : line); f(
"backpack",
fields.backpack
? fields.backpack + "\n" + line
: line,
);
setWeaponPickerOpen(false); setWeaponPickerOpen(false);
}} }}
> >
<span className="spell-picker-name">{item.data.name}</span> <span className="spell-picker-name">
<span className="spell-picker-class">{item.data.category}</span> {item.data.name}
</span>
<span className="spell-picker-class">
{item.data.category}
</span>
</li> </li>
))} ))}
</ul> </ul>
@@ -1275,7 +1337,9 @@ export default function CharacterSheet() {
<textarea <textarea
placeholder="Skill information…" placeholder="Skill information…"
value={cls.skills || ""} value={cls.skills || ""}
ref={(el) => { if (el) autoResize(el); }} ref={(el) => {
if (el) autoResize(el);
}}
onInput={(e) => autoResize(e.currentTarget)} onInput={(e) => autoResize(e.currentTarget)}
onChange={(e) => onChange={(e) =>
setPrimaryClasses((prev) => setPrimaryClasses((prev) =>
@@ -1295,7 +1359,14 @@ export default function CharacterSheet() {
justifyContent: "space-between", justifyContent: "space-between",
}} }}
> >
<label style={{ display: "flex", alignItems: "center", gap: "6px", fontSize: "0.85em" }}> <label
style={{
display: "flex",
alignItems: "center",
gap: "6px",
fontSize: "0.85em",
}}
>
Level Level
<input <input
type="number" type="number"
@@ -1305,14 +1376,16 @@ export default function CharacterSheet() {
onChange={(e) => onChange={(e) =>
setPrimaryClasses((prev) => setPrimaryClasses((prev) =>
prev.map((c, i) => prev.map((c, i) =>
i === idx ? { ...c, level: Number(e.target.value) } : c, i === idx
? { ...c, level: Number(e.target.value) }
: c,
), ),
) )
} }
style={{ width: "50px" }} style={{ width: "50px" }}
/> />
</label> </label>
<button <button type="button"
className="spell-del-btn" className="spell-del-btn"
onClick={() => onClick={() =>
setPrimaryClasses((prev) => setPrimaryClasses((prev) =>
@@ -1325,7 +1398,7 @@ export default function CharacterSheet() {
</div> </div>
</div> </div>
))} ))}
<button <button type="button"
className="add-btn" className="add-btn"
disabled={primaryClasses.length >= 3} disabled={primaryClasses.length >= 3}
onClick={() => onClick={() =>
@@ -1393,7 +1466,14 @@ export default function CharacterSheet() {
justifyContent: "space-between", justifyContent: "space-between",
}} }}
> >
<label style={{ display: "flex", alignItems: "center", gap: "6px", fontSize: "0.85em" }}> <label
style={{
display: "flex",
alignItems: "center",
gap: "6px",
fontSize: "0.85em",
}}
>
Level Level
<input <input
type="number" type="number"
@@ -1403,14 +1483,16 @@ export default function CharacterSheet() {
onChange={(e) => onChange={(e) =>
setOtherClasses((prev) => setOtherClasses((prev) =>
prev.map((c, i) => prev.map((c, i) =>
i === idx ? { ...c, level: Number(e.target.value) } : c, i === idx
? { ...c, level: Number(e.target.value) }
: c,
), ),
) )
} }
style={{ width: "50px" }} style={{ width: "50px" }}
/> />
</label> </label>
<button <button type="button"
className="spell-del-btn" className="spell-del-btn"
onClick={() => onClick={() =>
setOtherClasses((prev) => setOtherClasses((prev) =>
@@ -1423,7 +1505,7 @@ export default function CharacterSheet() {
</div> </div>
</div> </div>
))} ))}
<button <button type="button"
className="add-btn" className="add-btn"
onClick={() => onClick={() =>
setOtherClasses((prev) => [ setOtherClasses((prev) => [
@@ -1496,7 +1578,9 @@ export default function CharacterSheet() {
onChange={(e) => onChange={(e) =>
setSpells((prev) => setSpells((prev) =>
prev.map((sp, j) => prev.map((sp, j) =>
j === i ? { ...sp, spellClass: e.target.value } : sp, j === i
? { ...sp, spellClass: e.target.value }
: sp,
), ),
) )
} }
@@ -1538,14 +1622,16 @@ export default function CharacterSheet() {
onChange={(e) => onChange={(e) =>
setSpells((prev) => setSpells((prev) =>
prev.map((sp, j) => prev.map((sp, j) =>
j === i ? { ...sp, duration: e.target.value } : sp, j === i
? { ...sp, duration: e.target.value }
: sp,
), ),
) )
} }
/> />
</td> </td>
<td className="spell-del-col"> <td className="spell-del-col">
<button <button type="button"
className="spell-del-btn" className="spell-del-btn"
onClick={() => onClick={() =>
setSpells((prev) => prev.filter((_, j) => j !== i)) setSpells((prev) => prev.filter((_, j) => j !== i))
@@ -1560,7 +1646,9 @@ export default function CharacterSheet() {
<textarea <textarea
placeholder="Notes / effect description…" placeholder="Notes / effect description…"
value={s.notes || ""} value={s.notes || ""}
ref={(el) => { if (el) autoResize(el); }} ref={(el) => {
if (el) autoResize(el);
}}
onInput={(e) => autoResize(e.currentTarget)} onInput={(e) => autoResize(e.currentTarget)}
onChange={(e) => onChange={(e) =>
setSpells((prev) => setSpells((prev) =>
@@ -1577,18 +1665,25 @@ export default function CharacterSheet() {
</tbody> </tbody>
</table> </table>
<div style={{ display: "flex", gap: 8, marginTop: 10 }}> <div style={{ display: "flex", gap: 8, marginTop: 10 }}>
<button <button type="button"
className="add-btn" className="add-btn"
onClick={() => onClick={() =>
setSpells((prev) => [ setSpells((prev) => [
...prev, ...prev,
{ name: "", spellClass: "", notes: "", mp: "", targets: "", duration: "" }, {
name: "",
spellClass: "",
notes: "",
mp: "",
targets: "",
duration: "",
},
]) ])
} }
> >
+ Add Spell / Arcana + Add Spell / Arcana
</button> </button>
<button <button type="button"
className="add-btn" className="add-btn"
onClick={() => setSpellPickerOpen(true)} onClick={() => setSpellPickerOpen(true)}
> >
@@ -1597,11 +1692,22 @@ export default function CharacterSheet() {
</div> </div>
{spellPickerOpen && ( {spellPickerOpen && (
<div className="spell-picker-overlay" onClick={() => setSpellPickerOpen(false)}> <div
<div className="spell-picker-modal" onClick={(e) => e.stopPropagation()}> className="spell-picker-overlay"
onClick={() => setSpellPickerOpen(false)}
>
<div
className="spell-picker-modal"
onClick={(e) => e.stopPropagation()}
>
<div className="spell-picker-header"> <div className="spell-picker-header">
<span>Choose a spell</span> <span>Choose a spell</span>
<button className="spell-picker-close" onClick={() => setSpellPickerOpen(false)}></button> <button type="button"
className="spell-picker-close"
onClick={() => setSpellPickerOpen(false)}
>
</button>
</div> </div>
<ul className="spell-picker-list"> <ul className="spell-picker-list">
{(spellsFile as SpellsFile).spells.map((t, i) => ( {(spellsFile as SpellsFile).spells.map((t, i) => (
@@ -1673,10 +1779,10 @@ export default function CharacterSheet() {
a previously saved sheet. a previously saved sheet.
</p> </p>
<div className="manage-btn-row"> <div className="manage-btn-row">
<button className="btn-save btn-lg" onClick={saveSheet}> <button type="button" className="btn-save btn-lg" onClick={saveSheet}>
✦ Save to Browser ✦ Save to Browser
</button> </button>
<button className="btn-load btn-lg" onClick={loadSheet}> <button type="button" className="btn-load btn-lg" onClick={loadSheet}>
↑ Load from Browser ↑ Load from Browser
</button> </button>
</div> </div>
@@ -1691,13 +1797,13 @@ export default function CharacterSheet() {
import from a previously exported file. import from a previously exported file.
</p> </p>
<div className="manage-btn-row"> <div className="manage-btn-row">
<button <button type="button"
className="btn-save btn-export btn-lg" className="btn-save btn-export btn-lg"
onClick={exportSheet} onClick={exportSheet}
> >
↓ Export JSON ↓ Export JSON
</button> </button>
<button <button type="button"
className="btn-load btn-import btn-lg" className="btn-load btn-import btn-lg"
onClick={() => { onClick={() => {
if (!importFileRef.current) return; if (!importFileRef.current) return;
@@ -1727,7 +1833,7 @@ export default function CharacterSheet() {
disabled for viewers. disabled for viewers.
</p> </p>
<div className="manage-btn-row"> <div className="manage-btn-row">
<button <button type="button"
className="btn-save btn-export btn-lg" className="btn-save btn-export btn-lg"
onClick={copyShareURL} onClick={copyShareURL}
> >