最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Trying to develop tabbed UI, but buttons are only visible on page load - Stack Overflow

programmeradmin4浏览0评论

Here is my code:

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>My API App</title>
    <link rel="stylesheet" href="style.css">
    <link href="/[email protected]/dist/tailwind.min.css" rel="stylesheet">
    <script src="/[email protected]/dist/cross-fetch.js"></script>
    <script src=".js"></script>
    <script type="importmap">
        {
          "imports": {
            "react": ";,
            "react-dom/client": ";,
            "react/jsx-runtime": ";,
            "sql.js": "/node_modules/sql.js/dist/sql-wasm.js"
          }
        }
    </script>
    <link rel="stylesheet" href="style.css">
</head>
<body>
    <div class="container mx-auto p-4">
        <h1 class="text-2xl font-bold mb-6">Boxergy API App</h1>

        <!-- Tabs Container -->
        <div class="mb-8">
            <!-- Tab Navigation -->
            <div class="flex border-b border-gray-200">
                <button class="py-2 px-4 font-medium text-blue-600 border-b-2 border-blue-600 tab-button active" data-tab="givenergy">
                    GivEnergy System
                </button>
                <button class="py-2 px-4 font-medium text-gray-500 hover:text-blue-600 tab-button" data-tab="alphaess">
                    AlphaESS System
                </button>
            </div>

            <!-- Tab Content -->
            <div class="bg-white rounded-lg shadow-md mt-1">
                <!-- GivEnergy Tab -->
                <div id="givenergy-tab" class="tab-content active p-4">
                    <div class="mb-6 border-b pb-6">
                        <h2 class="text-xl font-bold mb-4">System Data</h2>
                        <input type="text" id="serial-givenergy-data" placeholder="GivEnergy Serial Number" class="w-full p-2 border rounded mb-2">
                        <button id="fetch-givenergy-data-button" class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded w-full mb-4">
                            Fetch GivEnergy System Data
                        </button>
                        <div id="givenergy-system-output" class="mt-4 p-3 bg-gray-100 rounded overflow-auto max-h-96"></div>
                    </div>

                    <div>
                        <h2 class="text-xl font-bold mb-4">System Events</h2>
                        <input type="text" id="serial-givenergy-events" placeholder="GivEnergy Serial Number" class="w-full p-2 border rounded mb-2">
                        <button id="fetch-givenergy-events-button" class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded w-full mb-4">
                            Fetch GivEnergy Events
                        </button>
                        <div id="givenergy-events-output" class="mt-4 p-3 bg-gray-100 rounded overflow-auto max-h-96"></div>
                        <canvas id="givenergyChart" class="mt-4 h-64"></canvas>
                    </div>
                </div>

                <!-- AlphaESS Tab -->
                <div id="alphaess-tab" class="tab-content hidden p-4">
                    <div class="mb-6 border-b pb-6">
                        <h2 class="text-xl font-bold mb-4">System Data</h2>
                        <input type="text" id="serial-alphaess-data" placeholder="AlphaESS Serial Number" class="w-full p-2 border rounded mb-2">
                        <button id="fetch-alphaess-data-button" class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded w-full mb-4">
                            Fetch AlphaESS System Data
                        </button>
                        <div id="alphaess-system-output" class="mt-4 p-3 bg-gray-100 rounded overflow-auto max-h-96"></div>
                    </div>

                    <div>
                        <h2 class="text-xl font-bold mb-4">Historical Data</h2>
                        <input type="text" id="serial-alphaess-historical" placeholder="AlphaESS Serial Number" class="w-full p-2 border rounded mb-2">
                        <div class="grid grid-cols-2 gap-2 mb-2">
                            <div>
                                <label class="block text-sm">Start Time:</label>
                                <input type="datetime-local" id="alphaess-start-time" class="w-full p-2 border rounded">
                            </div>
                            <div>
                                <label class="block text-sm">End Time:</label>
                                <input type="datetime-local" id="alphaess-end-time" class="w-full p-2 border rounded">
                            </div>
                        </div>
                        <button id="fetch-alphaess-historical-button" class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded w-full mb-4">
                            Fetch AlphaESS Historical Data
                        </button>
                        <div id="alphaess-historical-output" class="mt-4 p-3 bg-gray-100 rounded overflow-auto max-h-96"></div>
                        <div id="alphaess-power-flow-container" class="mt-4"></div>
                    </div>
                </div>
            </div>
        </div>
    </div>

    <div id="root"></div>
    <script src="bundle.js" type="module"></script>
    <script src="client.js"></script>
    <script src="alphaess-fetcher.js"></script>

    <!-- Tab Functionality Script -->
    <script>
        document.addEventListener('DOMContentLoaded', function () {
            const tabButtons = document.querySelectorAll('.tab-button');
            const tabContents = document.querySelectorAll('.tab-content');

            tabButtons.forEach(button => {
                button.addEventListener('click', function () {
                    const tabId = this.getAttribute('data-tab');

                    tabButtons.forEach(btn => {
                        btn.classList.remove('active', 'text-blue-600', 'border-b-2', 'border-blue-600');
                        btn.classList.add('text-gray-500');
                    });

                    tabContents.forEach(content => {
                        content.style.display = 'none';
                        content.classList.remove('active');
                    });

                    this.classList.add('active', 'text-blue-600', 'border-b-2', 'border-blue-600');
                    this.classList.remove('text-gray-500');

                    const activeContent = document.getElementById(`${tabId}-tab`);
                    activeContent.style.display = 'block';
                    activeContent.classList.add('active');

                    const buttons = activeContent.querySelectorAll('button');
                    buttons.forEach(btn => {
                        btn.style.display = 'inline-block';
                        btn.style.visibility = 'visible';
                    });

                    const inputs = activeContent.querySelectorAll('input');
                    inputs.forEach(input => {
                        input.style.display = 'block';
                        input.style.visibility = 'visible';
                    });
                });
            });
        });
    </script>
</body>
</html>

style.css

@tailwind base;
@tailwind components;
@tailwind utilities;

/* Reset some default browser styles */
* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

body {
    font-family: 'Arial', sans-serif;
    background-color: #f4f4f4;
    color: #333;
    line-height: 1.6;
    padding: 20px;
}

.container {
    max-width: 1200px;
    margin: 0 auto;
    padding: 20px;
    background: #fff;
    box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
    border-radius: 8px;
}

h1, h2, h3 {
    margin-bottom: 20px;
    color: #444;
}

button {
    display: inline-block;
    background: #007bff;
    color: #fff;
    border: none;
    padding: 10px 20px;
    margin: 10px 0;
    border-radius: 5px;
    cursor: pointer;
    transition: background 0.3s ease;
}

    button:hover {
        background: #0056b3;
    }

input[type="text"] {
    width: 100%;
    padding: 10px;
    margin: 10px 0;
    border: 1px solid #ccc;
    border-radius: 5px;
}

#root {
    margin-top: 20px;
}

#givenergyChart {
    margin-top: 20px;
}

.output {
    background: #f9f9f9;
    padding: 10px;
    border: 1px solid #ddd;
    border-radius: 5px;
    margin-top: 10px;
    white-space: pre-wrap;
}

input[type="text"] {
    width: 20%;
}

.api-section {
    margin-bottom: 30px;
    padding: 15px;
    border: 1px solid #ddd;
    border-radius: 5px;
    background-color: #f9f9f9;
}

.datetime-inputs {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
    margin: 10px 0;
}

    .datetime-inputs label {
        display: flex;
        flex-direction: column;
        font-size: 14px;
    }

    .datetime-inputs input {
        padding: 8px;
        border: 1px solid #ccc;
        border-radius: 4px;
    }

.error {
    color: #d9534f;
    font-weight: bold;
}

/* Fix button display issues */
button {
    display: inline-block !important;
    visibility: visible !important;
    opacity: 1 !important;
}

/* Fix input field display issues */
input[type="text"],
input[type="datetime-local"] {
    display: block !important;
    visibility: visible !important;
    opacity: 1 !important;
}

/* Ensure tab content is displayed properly */
.tab-content.active {
    display: block !important;
    visibility: visible !important;
    opacity: 1 !important;
}

/* Fix the tab buttons */
.tab-button {
    display: inline-block !important;
    visibility: visible !important;
    opacity: 1 !important;
}

tailwind.config.js

/** @type {import('tailwindcss').Config} */
module.exports = {
    content: [
        "./src/**/*.{js,jsx,ts,tsx}",
    ],
    theme: {
        extend: {},
    },
    plugins: [],
}

postcss.config.js

module.exports = {
    plugins: {
        tailwindcss: {},
        autoprefixer: {},
    },
}

package.json

{
    "name": "givenergy-app",
    "version": "1.0.0",
    "main": "dist/server.js",
    "type": "module",
    "scripts": {
        "test": "echo \"Error: no test specified\" && exit 1",
        "build:client": "node build-client.js",
        "build:server": "tsc --build",
        "build": "npm run build:server && npm run build:client && copyfiles -u 1 public/**/* src/index.html dist && copyfiles -u 3 node_modules/sql.js/dist/* public/js/sql.js/",
        "clean": "tsc --build --clean",
        "start": "node dist/server.js",
        "dev": "ts-node src/server.ts"
    },
    "keywords": [],
    "author": "",
    "license": "ISC",
    "description": "",
    "devDependencies": {
        "@eslint/js": "^9.20.0",
        "@types/axios": "^0.14.4",
        "@types/cors": "^2.8.17",
        "@types/express": "^5.0.0",
        "@types/node": "^22.13.1",
        "@types/react": "^18.0.0",
        "@types/react-dom": "^18.0.0",
        "@types/sql.js": "^1.4.9",
        "@typescript-eslint/eslint-plugin": "^8.24.0",
        "@typescript-eslint/parser": "^8.24.0",
        "autoprefixer": "^10.4.21",
        "copyfiles": "^2.4.1",
        "eslint": "^9.20.1",
        "postcss": "^8.5.3",
        "tailwindcss": "^4.0.14",
        "ts-node": "^10.9.2",
        "typescript": "^5.7.3"
    },
    "dependencies": {
        "axios": "^1.7.9",
        "cors": "^2.8.5",
        "cross-fetch": "^4.1.0",
        "esbuild": "^0.25.0",
        "express": "^4.21.2",
        "lucide-react": "^0.477.0",
        "node-fetch": "^3.3.2",
        "node-polyfill-webpack-plugin": "^4.1.0",
        "react": "^19.0.0",
        "react-dom": "^19.0.0",
        "sequelize": "^6.37.5",
        "sql.js": "^1.12.0",
        "sqlite": "^5.1.1",
        "sqlite3": "^5.1.7"
    }
}

When I refresh the page, the buttons momentarily appear, but then immediately disappear. When I am in the GivEnergy tab, and hover over the 'Alpha ESS system' button the button text is visible, but oddly enough the reverse is not true, i.e. the 'GivEnergy system' button text is never visible under any circumstances. Please note I am not at all sure if Tailwind is correctly installed. In Visual Studio I am seeing the warning '"tailwind" is not a known '@' directive.' for all the lines starting @tailwind in styles.css. I did spend good deal of time trying to troubleshoot the Tailwind install including checking the relevant Windows environment variable was entered correctly and numerous terminal commands, but without success.

Can anyone help please? I have tried several AIs but none have been able to solve the problem and in fact their suggestions only made mattes worse. Thanks in advance.

Edit: does this throw any light on things? I'm a bit perplexed that I'm seeing .tab-button.active when there is no such setting in style.css?

enter image description here

Edit2:

I have managed to get the text on the Alpha ESS button visible by changing white to grey in the tab button settings:

/* eslint-env browser */
/* global HTMLElement */

/// <reference types="react" />
/// <reference types="react-dom" />
/// <reference lib="dom" />

import React from 'react';
import ReactDOM from 'react-dom/client';
import { InverterDashboard } from './components/InverterDisplay/GivEnergyInverterDashboard.js';
import { InverterDisplay } from './components/InverterDisplay/GivEnergyInverterDisplay.js';
import { AlphaEssDisplay } from './components/InverterDisplay/AlphaEssDisplay.js';

console.log("Root component rendering...");

const App = () => {
    const [view, setView] = React.useState<'list' | 'dashboard' | 'alphaess'>('dashboard');

    return (
        <div className="app-container">
            <header className="app-header">
                <h1>Solar Inverter Monitoring System</h1>
                <div className="view-tabs">
                    <button
                        className={`tab-button ${view === 'list' ? 'active' : ''}`}
                        onClick={() => setView('list')}
                    >
                        GivEnergy Inverter List
                    </button>
                    <button
                        className={`tab-button ${view === 'dashboard' ? 'active' : ''}`}
                        onClick={() => setView('dashboard')}
                    >
                        GivEnergy Dashboard
                    </button>
                    <button
                        className={`tab-button ${view === 'alphaess' ? 'active' : ''}`}
                        onClick={() => setView('alphaess')}
                    >
                        AlphaESS Inverters
                    </button>
                </div>
            </header>

            <main className="app-content">
                {view === 'list' ? (
                    <InverterDisplay />
                ) : view === 'dashboard' ? (
                    <InverterDashboard />
                ) : (
                    <AlphaEssDisplay />
                )}
            </main>

            <style>{`
        .app-container {
          font-family: Arial, sans-serif;
          max-width: 1200px;
          margin: 0 auto;
          padding: 20px;
          background-color: #f5f7f9;
          min-height: 100vh;
          box-sizing: border-box;
        }
        
        .app-header {
          background-color: #2c3e50;
          color: white;
          padding: 15px 20px;
          border-radius: 8px;
          margin-bottom: 20px;
          box-shadow: 0 2px 5px rgba(0,0,0,0.1);
          display: flex;
          flex-direction: column;
        }
        
        @media (min-width: 768px) {
          .app-header {
            flex-direction: row;
            justify-content: space-between;
            align-items: center;
          }
        }
        
        .app-header h1 {
          margin: 0;
          font-size: 24px;
          margin-bottom: 10px;
          color: #ffffff;
          text-shadow: 1px 1px 2px rgba(0,0,0,0.5);
        }
        
        @media (min-width: 768px) {
          .app-header h1 {
            margin-bottom: 0;
          }
        }
        
        .view-tabs {
          display: flex;
          gap: 10px;
        }
        
        .tab-button {
          background-color: rgba(255, 255, 255, 0.1);
          color: grey; // <- I changed this
          border: none;
          padding: 8px 16px;
          border-radius: 4px;
          cursor: pointer;
          transition: background-color 0.2s;
        }
        
        .tab-button:hover {
          background-color: rgba(255, 255, 255, 0.2);
        }
        
        .tab-button.active {
          background-color: rgba(255, 255, 255, 0.3);
          font-weight: bold;
        }
        
        .app-content {
          background-color: white;
          border-radius: 8px;
          box-shadow: 0 2px 8px rgba(0,0,0,0.1);
          padding: 20px;
        }
      `}</style>
        </div>
    );
};

const root = ReactDOM.createRoot(document.getElementById('root') as HTMLElement);
root.render(<App />);
发布评论

评论列表(0)

  1. 暂无评论