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