JSFiddle - React, Tailwind, and code Playground

by Gwyn Milcote

HTML

<div id='tab-btns'>
    <div class='tab-btn active-tab' data-tab='1'>Characters</div>
    <div class='tab-btn' data-tab='2'>Skills</div>
    <div class='tab-btn' data-tab='3'>Items</div>
    <div class='tab-btn' data-tab='4'>Merchants</div>
    <div class='tab-btn' data-tab='5'>NPCs</div>
    <div class='tab-btn' data-tab='6'>Monsters</div>
    <div class='tab-btn' data-tab='7'>Maps</div>
    <div class='tab-btn' data-tab='8'>Events</div>
</div>
<div id='tab-content'>
    
    <div class='tab-content' id='tab-content-1' style='display: block;'>
        <h2>Characters</h2>
        <p>These characters are playable. The first is automatically present; the others can be recruited by finding them on the map and talking to them, like NPCs.</p>
        <div id='character-table'></div>
        
        <h2>Recruitment</h2>
        <p>If you skip a character, their NPC form will keep appearing again in later areas. If you recruit them later, they'll be at a higher level and with better equipment.</p>
        <div id='recruit-table'></div>
    </div>
    
    <div class='tab-content' id='tab-content-2'>
        <h2>Skills</h2>
        <p>When a character gains a level, they get a skill point, to spend on upgrading one skill. This will improve their battle performance or unlock an ability. Each character has several skills to choose from. A skill can be upgraded to level 15 at maximum.</p>
        <div id='skill-table'></div>
    </div>
    
    <div class='tab-content' id='tab-content-3'>
        <h2>Item types</h2>
        <p>Each item belongs to a type.</p>
        <div id='item-type-table'></div>
        
        <h2>Items</h2>
        <p>These items are listed on the Inventory page. Most can be used in or out of battle; a few are just key plot items. Some items can be bought from merchants, others are dropped by enemies. Most can be sold for money, and there's a limit to how many you can carry at once.</p>
        <div id='item-table'></div>
    </div>
    
    <div...

CSS

div, img, p, a, button, table, tr, th, td {
    box-sizing: border-box;
}

table {
    width: 100%;
    border-collapse: collapse;
}
table th {
    background-color: silver;
    border: 1px solid grey;
}
table td {
    padding: 5px;
    border: 1px solid silver;
}
table tr:nth-child(odd){
    background-color: #eee;
}


#tab-btns {
    position: relative;
    top: 1px;
    display: flex;
    flex-flow: row;
    justify-content: space-evenly;
}
#tab-btns .tab-btn {
    background-color: silver;
    border: 1px solid grey;
    border-bottom: none;
    border-radius: 5px 5px 0 0;
    padding: 5px;
    margin: 0 5px;
}
#tab-btns .tab-btn:hover {
    cursor: pointer;
    background-color: #eee;
}
#tab-btns .active-tab {
    background-color: #fff !important;
    border-bottom: 1px solid #fff !important;
}

#tab-content {
    background-color: #fff;
    border: 1px solid silver;
    padding: 10px;
    border-radius: 10px;
}
#tab-content .tab-content {
    display: none;
}


.space-between {
    display: flex;
    flex-flow: row;
    justify-content: space-between;
}

JavaScript

const db = {

    characters: [
        {
            id: 1, name: "Rohane",
            skills: [1,2,3,4,5,6,7],
            hpGain: 6,
            weaponType: 6, 
            armourType: 10,
            quotes: [
                "Justice prevails again!",
                "Out enemies fall before us!",
                "We emerge victorious!",
            ]
        },
        {
            id: 2, name: "Mipsy",
            skills: [8,9,10,11,12,13,14],
            hpGain: 4,
            weaponType: 7, 
            armourType: 11,
            quotes: [
                "The next time something bites me, it's going to get set on fire.",
                "Do we really have time for this?",
                "I wish I didn't need these stupid shoes!"
            ]
        },
        {
            id: 3, name: "Talinia",
            skills: [15,16,17,18,19,6,7],
            hpGain: 5,
            weaponType: 8, 
            armourType: 12,
            quotes: [
                "All too easy!",
                "It's all about the proper aim, baby.",
                "Back in my day, monsters were ten times as vicious!"
            ]
        },{
            id: 4, name: "Velm",
            skills: [20,21,22,23,24,13,14],
            hpGain: 4.5,
            weaponType: 9, 
            armourType: 13,
            quotes: [
                "Eat your vegetables.",
                "Fighting monsters is good exercise.",
                "Well, wasn't that exciting?",
                "Don't fidget. And get a haircut!"
            ]
        }
    ],

    // When a character joins party.
    // Can happen automatically, or after talking.
    // Same character may have multiple opportunities.
    // And join with different level, equipment.
    recruits: [
        { // Rohane, automatic.
            id: 1, character: 1,
            level: 1, exp: 0,
            weapon: 6, armour: 0
        },
        { // Mipsy in chapter 1.
            id: 2, character: 2,
            level: 12, exp:...