Character section rollup: clickable title, count, persisted collapse
Match campaigns rollup pattern. Title button toggles collapse (chevron left, like campaigns). Character count in header. Collapse state persisted to localStorage key ttrpg.charactersCollapsed.
This commit is contained in:
+14
-8
@@ -5,7 +5,7 @@ import {
|
||||
PlusCircle, Users, Swords, Trash2, Eye, Edit3, Save, XCircle, ChevronsUpDown,
|
||||
UserCheck, UserX, HeartCrack, HeartPulse, Zap, EyeOff, ExternalLink, AlertTriangle,
|
||||
Play as PlayIcon, Pause as PauseIcon, SkipForward as SkipForwardIcon,
|
||||
StopCircle as StopCircleIcon, Users2, Dices, ChevronUp, ChevronDown, ScrollText,
|
||||
StopCircle as StopCircleIcon, Users2, Dices, ChevronDown, ScrollText,
|
||||
Maximize2, Minimize2, Moon, Coffee, Clock, ChevronRight, X,
|
||||
Undo2, Redo2, Crosshair
|
||||
} from 'lucide-react';
|
||||
@@ -682,7 +682,14 @@ function CharacterManager({ campaignId, campaignCharacters }) {
|
||||
const [editingCharacter, setEditingCharacter] = useState(null);
|
||||
const [showDeleteConfirm, setShowDeleteConfirm] = useState(false);
|
||||
const [itemToDelete, setItemToDelete] = useState(null);
|
||||
const [isOpen, setIsOpen] = useState(true);
|
||||
const [isOpen, setIsOpen] = useState(() => {
|
||||
try { return localStorage.getItem('ttrpg.charactersCollapsed') !== 'true'; }
|
||||
catch { return true; }
|
||||
});
|
||||
useEffect(() => {
|
||||
try { localStorage.setItem('ttrpg.charactersCollapsed', String(!isOpen)); }
|
||||
catch {}
|
||||
}, [isOpen]);
|
||||
|
||||
const handleAddCharacter = async () => {
|
||||
if (!db || !characterName.trim() || !campaignId) return;
|
||||
@@ -769,15 +776,14 @@ function CharacterManager({ campaignId, campaignCharacters }) {
|
||||
<>
|
||||
<div className="p-4 bg-stone-900 rounded-lg shadow">
|
||||
<div className="flex justify-between items-center mb-3">
|
||||
<h3 className="text-xl font-semibold text-amber-300 font-cinzel tracking-wide flex items-center">
|
||||
<Users size={24} className="mr-2" /> Campaign Characters
|
||||
</h3>
|
||||
<button
|
||||
onClick={() => setIsOpen(!isOpen)}
|
||||
className="p-1 text-stone-400 hover:text-stone-200"
|
||||
aria-label={isOpen ? "Collapse" : "Expand"}
|
||||
className="flex items-center text-xl font-semibold text-amber-300 font-cinzel tracking-wide hover:text-amber-200 transition-colors"
|
||||
aria-expanded={isOpen}
|
||||
>
|
||||
{isOpen ? <ChevronUp size={20} /> : <ChevronDown size={20} />}
|
||||
{isOpen ? <ChevronDown size={20} className="mr-1" /> : <ChevronRight size={20} className="mr-1" />}
|
||||
<Users size={24} className="mr-2" /> Campaign Characters
|
||||
<span className="text-sm font-normal text-stone-400 ml-1">({campaignCharacters.length})</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user