Обновил дизайн статусов и добавил адаптивный сайдбар
parent
eaf706ddfe
commit
750f06a4e5
|
|
@ -14,7 +14,7 @@ const PrometheusChart = ({ metricName }) => {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const fetchData = async () => {
|
const fetchData = async () => {
|
||||||
try {
|
try {
|
||||||
const response = await axios.get(`http://192.168.2.39:3000/metrics?metric=zvks_apiforsnmp_ifOutUnicastPacket1`);
|
const response = await axios.get(`http://192.168.2.39:3000/metrics?metric=zvks_apiforsnmp_cpurawsystem`);
|
||||||
const result = response.data;
|
const result = response.data;
|
||||||
|
|
||||||
// Проверяем структуру данных
|
// Проверяем структуру данных
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import React, { useState, useEffect } from "react";
|
import React, { useState, useEffect, useRef } from "react";
|
||||||
import SidebarMenu from "./SidebarMenu";
|
import SidebarMenu from "./SidebarMenu";
|
||||||
import TreeChart from "../TreeChart/TreeChart";
|
import TreeChart from "../TreeChart/TreeChart";
|
||||||
import "../../Style/Dashboard.css";
|
import "../../Style/Dashboard.css";
|
||||||
|
|
@ -14,8 +14,11 @@ const Dashboard = () => {
|
||||||
const [activeTab, setActiveTab] = useState("Главная");
|
const [activeTab, setActiveTab] = useState("Главная");
|
||||||
const [tabContent, setTabContent] = useState({});
|
const [tabContent, setTabContent] = useState({});
|
||||||
const [treeData, setTreeData] = useState(menuData); // Загружаем меню в state
|
const [treeData, setTreeData] = useState(menuData); // Загружаем меню в state
|
||||||
|
const [sidebarWidth, setSidebarWidth] = useState(250); // Начальная ширина сайдбара
|
||||||
|
const [isResizing, setIsResizing] = useState(false); // Состояние перетаскивания
|
||||||
|
const sidebarRef = useRef(null); // Референс на сайдбар
|
||||||
|
|
||||||
// Обновление treeData каждые 10 секунд
|
// Обновление treeData каждые 30 секунд
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setTabContent(tabContentData);
|
setTabContent(tabContentData);
|
||||||
|
|
||||||
|
|
@ -25,11 +28,48 @@ const Dashboard = () => {
|
||||||
updateStatuses(updatedData); // Обновляем статусы
|
updateStatuses(updatedData); // Обновляем статусы
|
||||||
return updatedData;
|
return updatedData;
|
||||||
});
|
});
|
||||||
}, 10000);
|
}, 30000);
|
||||||
|
|
||||||
return () => clearInterval(interval);
|
return () => clearInterval(interval);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
// Обработчик начала перетаскивания
|
||||||
|
const startResizing = (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
setIsResizing(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Обработчик движения мыши
|
||||||
|
const resize = (e) => {
|
||||||
|
if (isResizing) {
|
||||||
|
const newWidth = e.clientX; // Новая ширина сайдбара
|
||||||
|
if (newWidth > 100 && newWidth < 400) { // Ограничиваем минимальную и максимальную ширину
|
||||||
|
setSidebarWidth(newWidth);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Обработчик окончания перетаскивания
|
||||||
|
const stopResizing = () => {
|
||||||
|
setIsResizing(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Добавляем обработчики событий
|
||||||
|
useEffect(() => {
|
||||||
|
const handleMouseMove = (e) => resize(e);
|
||||||
|
const handleMouseUp = () => stopResizing();
|
||||||
|
|
||||||
|
if (isResizing) {
|
||||||
|
window.addEventListener("mousemove", handleMouseMove);
|
||||||
|
window.addEventListener("mouseup", handleMouseUp);
|
||||||
|
}
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
window.removeEventListener("mousemove", handleMouseMove);
|
||||||
|
window.removeEventListener("mouseup", handleMouseUp);
|
||||||
|
};
|
||||||
|
}, [isResizing]);
|
||||||
|
|
||||||
const handleOpenTab = (id, title) => {
|
const handleOpenTab = (id, title) => {
|
||||||
if (!tabs.some((tab) => tab.id === id)) {
|
if (!tabs.some((tab) => tab.id === id)) {
|
||||||
setTabs([...tabs, { id, title }]);
|
setTabs([...tabs, { id, title }]);
|
||||||
|
|
@ -51,7 +91,8 @@ const Dashboard = () => {
|
||||||
<div>
|
<div>
|
||||||
<h2>Общий мониторинг</h2>
|
<h2>Общий мониторинг</h2>
|
||||||
<ErrorIndicator />
|
<ErrorIndicator />
|
||||||
<TreeTable data={treeData.items} /> {/* Теперь используем актуальные данные */}
|
<TreeTable data={treeData.items} /> {/* Используем актуальные данные */}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
} else if (activeTab === "Визуализация") {
|
} else if (activeTab === "Визуализация") {
|
||||||
|
|
@ -64,8 +105,20 @@ const Dashboard = () => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="dashboard-container">
|
<div className="dashboard-container">
|
||||||
<SidebarMenu data={treeData} onOpenTab={handleOpenTab} /> {/* Передаём обновлённые данные */}
|
<div
|
||||||
<div className="main-content">
|
className="sidebar"
|
||||||
|
ref={sidebarRef}
|
||||||
|
style={{ width: sidebarWidth }} // Динамическая ширина сайдбара
|
||||||
|
>
|
||||||
|
<SidebarMenu data={treeData} onOpenTab={handleOpenTab} sidebarWidth={sidebarWidth} />
|
||||||
|
{/* Элемент для перетаскивания */}
|
||||||
|
<div
|
||||||
|
className="sidebar-resizer"
|
||||||
|
onMouseDown={startResizing}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="main-content" style={{ marginLeft: sidebarWidth }}>
|
||||||
<Tabs
|
<Tabs
|
||||||
tabs={tabs}
|
tabs={tabs}
|
||||||
activeTab={activeTab}
|
activeTab={activeTab}
|
||||||
|
|
|
||||||
|
|
@ -2,10 +2,10 @@ import React, { useState } from "react";
|
||||||
import "../../Style/SidebarMenu.css";
|
import "../../Style/SidebarMenu.css";
|
||||||
import { getStatusColor } from "../TreeChart/dataUtils"; // Импортируем только нужную функцию
|
import { getStatusColor } from "../TreeChart/dataUtils"; // Импортируем только нужную функцию
|
||||||
|
|
||||||
const MenuItem = ({ item, onSelectItem }) => {
|
const MenuItem = ({ item, onSelectItem, sidebarWidth }) => {
|
||||||
const [isOpen, setIsOpen] = useState(false);
|
const [isOpen, setIsOpen] = useState(false);
|
||||||
const hasChildren = Array.isArray(item.items) && item.items.length > 0;
|
const hasChildren = Array.isArray(item.items) && item.items.length > 0;
|
||||||
const backgroundColor = getStatusColor(item.status);
|
const statusColor = getStatusColor(item.status);
|
||||||
|
|
||||||
const handleClick = () => {
|
const handleClick = () => {
|
||||||
if (hasChildren) {
|
if (hasChildren) {
|
||||||
|
|
@ -16,15 +16,20 @@ const MenuItem = ({ item, onSelectItem }) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="menu-item">
|
<div className="menu-item" style={{ width: sidebarWidth - 20 }}> {/* Динамическая ширина */}
|
||||||
<div onClick={handleClick} className="menu-item-header" style={{ backgroundColor }}>
|
<div onClick={handleClick} className="menu-item-header">
|
||||||
|
{/* Круглый индикатор статуса */}
|
||||||
|
<div
|
||||||
|
className={`status-indicator ${statusColor === "red" ? "blinking" : ""}`}
|
||||||
|
style={{ backgroundColor: statusColor }}
|
||||||
|
/>
|
||||||
<span>{item.title}</span>
|
<span>{item.title}</span>
|
||||||
{hasChildren && <span>{isOpen ? "▲" : "▼"}</span>}
|
{hasChildren && <span>{isOpen ? "▲" : "▼"}</span>}
|
||||||
</div>
|
</div>
|
||||||
{isOpen && hasChildren && (
|
{isOpen && hasChildren && (
|
||||||
<div className="submenu">
|
<div className="submenu">
|
||||||
{item.items.map((child, index) => (
|
{item.items.map((child, index) => (
|
||||||
<MenuItem key={index} item={child} onSelectItem={onSelectItem} />
|
<MenuItem key={index} item={child} onSelectItem={onSelectItem} sidebarWidth={sidebarWidth} />
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
@ -32,15 +37,21 @@ const MenuItem = ({ item, onSelectItem }) => {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
function SidebarMenu({ data, onOpenTab }) { // Теперь получаем `data` из пропсов
|
function SidebarMenu({ data, onOpenTab, sidebarWidth }) {
|
||||||
const handleSelectItem = (item) => {
|
const handleSelectItem = (item) => {
|
||||||
onOpenTab(item.id, item.title);
|
onOpenTab(item.id, item.title);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="sidebar">
|
<div className="sidebar">
|
||||||
<h2 className="sidebar-title">Меню</h2>
|
<div className="sidebar-content" style={{ width: sidebarWidth }}> {/* Динамическая ширина */}
|
||||||
<MenuItem item={data} onSelectItem={handleSelectItem} />
|
<h2 className="sidebar-title">Меню</h2>
|
||||||
|
<MenuItem item={data} onSelectItem={handleSelectItem} sidebarWidth={sidebarWidth} />
|
||||||
|
</div>
|
||||||
|
<div className="sidebar-footer" style={{ width: sidebarWidth }}> {/* Динамическая ширина */}
|
||||||
|
<h2 className="help">Помощь</h2>
|
||||||
|
<h2 className="settings">Настройка</h2>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
// Функция для генерации случайных статусов
|
// Функция для генерации случайных статусов
|
||||||
const getRandomStatus = () => {
|
const getRandomStatus = () => {
|
||||||
const statuses = [
|
const statuses = [
|
||||||
"green", "green", "green", "green", "green", "green", "green", // 7/10 chance
|
...Array(90).fill("green"), // 63/70 chance (примерно 90%)
|
||||||
"yellow", // 1/10 chance
|
...Array(6).fill("yellow"), // 1/70 chance (примерно 1.43%)
|
||||||
"orange", // 1/10 chance
|
...Array(3).fill("orange"), // 1/70 chance (примерно 1.43%)
|
||||||
"red", // 1/10 chance
|
...Array(1).fill("red"), // 1/70 chance (примерно 1.43%)
|
||||||
];
|
];
|
||||||
return statuses[Math.floor(Math.random() * statuses.length)];
|
return statuses[Math.floor(Math.random() * statuses.length)];
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,21 +1,56 @@
|
||||||
|
/* Основной контейнер */
|
||||||
.dashboard-container {
|
.dashboard-container {
|
||||||
display: flex;
|
display: flex;
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
width: 100vw;
|
width: 98vw;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
/* Запрещаем появление скролла */
|
margin-left: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Сайдбар */
|
||||||
|
.sidebar {
|
||||||
|
height: 100vh;
|
||||||
|
background-color: #3d74c7;
|
||||||
|
color: white;
|
||||||
|
position: fixed;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
z-index: 999;
|
||||||
|
overflow: hidden;
|
||||||
|
transition: width 0.2s ease;
|
||||||
|
/* Плавное изменение ширины */
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Элемент для перетаскивания */
|
||||||
|
.sidebar-resizer {
|
||||||
|
width: 5px;
|
||||||
|
/* Ширина элемента перетаскивания */
|
||||||
|
height: 100%;
|
||||||
|
background-color: rgba(255, 255, 255, 0.1);
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
top: 0;
|
||||||
|
cursor: ew-resize;
|
||||||
|
/* Курсор "изменить размер" */
|
||||||
|
transition: background-color 0.2s ease;
|
||||||
|
z-index: 1000;
|
||||||
|
/* Убедимся, что элемент поверх других */
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar-resizer:hover {
|
||||||
|
background-color: rgba(255, 255, 255, 0.3);
|
||||||
|
/* Эффект при наведении */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Основной контент */
|
||||||
.main-content {
|
.main-content {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
min-width: 400px;
|
|
||||||
max-width: calc(100vw - 250px);
|
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
box-sizing: border-box;
|
margin-left: 50px;
|
||||||
overflow-y: auto;
|
transition: margin-left 0.2s ease;
|
||||||
/* Добавляем вертикальную прокрутку */
|
/* Плавное изменение отступа */
|
||||||
height: 100vh;
|
|
||||||
/* Ограничиваем высоту */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Контент */
|
/* Контент */
|
||||||
|
|
@ -26,19 +61,7 @@
|
||||||
box-shadow: 0 2px 5px rgba(29, 1, 1, 0.521);
|
box-shadow: 0 2px 5px rgba(29, 1, 1, 0.521);
|
||||||
}
|
}
|
||||||
|
|
||||||
.default-content {
|
/* Заголовки */
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
gap: 50px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tab-content {
|
|
||||||
background-color: #fff;
|
|
||||||
padding: 20px;
|
|
||||||
border-radius: 10px;
|
|
||||||
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
|
|
||||||
}
|
|
||||||
|
|
||||||
h2 {
|
h2 {
|
||||||
color: #444;
|
color: #444;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,71 +1,124 @@
|
||||||
/* Боковое меню */
|
/* Боковое меню */
|
||||||
.sidebar {
|
.sidebar {
|
||||||
width: 270px;
|
|
||||||
background-color: #3d74c7;
|
|
||||||
padding: 20px;
|
|
||||||
box-sizing: border-box;
|
|
||||||
border-right: 1px solid white;
|
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
/* Занимает всю высоту экрана */
|
background-color: #3d74c7;
|
||||||
overflow-y: auto;
|
color: white;
|
||||||
/* Прокрутка внутри меню, если контент не помещается */
|
position: fixed;
|
||||||
position: sticky;
|
left: 0;
|
||||||
/* Фиксируем меню */
|
|
||||||
top: 0;
|
top: 0;
|
||||||
/* Прилипаем к верху */
|
z-index: 999;
|
||||||
|
overflow: hidden;
|
||||||
|
transition: width 0.2s ease;
|
||||||
|
/* Плавное изменение ширины */
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Контейнер для основного контента меню */
|
||||||
|
.sidebar-content {
|
||||||
|
flex: 1;
|
||||||
|
overflow-y: auto;
|
||||||
|
/* Вертикальная прокрутка */
|
||||||
|
overflow-x: hidden;
|
||||||
|
/* Убираем горизонтальную прокрутку */
|
||||||
|
padding-bottom: 20px;
|
||||||
|
/* Отступ для "Помощи" и "Настроек" */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Заголовок меню */
|
||||||
.sidebar-title {
|
.sidebar-title {
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
color: white;
|
color: white;
|
||||||
|
padding: 10px;
|
||||||
|
/* Добавляем отступы */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Элементы меню */
|
||||||
.menu-item {
|
.menu-item {
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
color: white;
|
color: white;
|
||||||
}
|
width: 100%;
|
||||||
|
/* Ширина на всю ширину сайдбара */
|
||||||
h2 {
|
|
||||||
color: white
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.menu-item-header {
|
.menu-item-header {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
/* Выравниваем элементы по центру */
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
background-color: #3d74c7;
|
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
border: 1px solid white;
|
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: background-color 0.3s ease;
|
transition: background-color 0.3s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
.menu-item-header:hover {
|
.menu-item-header:hover {
|
||||||
background-color: #195fc9;
|
background-color: rgba(255, 255, 255, 0.1);
|
||||||
|
/* Легкий эффект при наведении */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Круглый индикатор статуса */
|
||||||
|
.status-indicator {
|
||||||
|
width: 10px;
|
||||||
|
height: 10px;
|
||||||
|
border-radius: 50%;
|
||||||
|
/* Делаем круглым */
|
||||||
|
margin-right: 10px;
|
||||||
|
/* Отступ от текста */
|
||||||
|
flex-shrink: 0;
|
||||||
|
/* Запрещаем сжатие */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Анимация мигания для красного индикатора */
|
||||||
|
@keyframes blink {
|
||||||
|
0% {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Полная видимость */
|
||||||
|
50% {
|
||||||
|
opacity: 0.3;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Полупрозрачность */
|
||||||
|
100% {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Полная видимость */
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-indicator.blinking {
|
||||||
|
animation: blink 1s infinite;
|
||||||
|
/* Бесконечная анимация с интервалом 1 секунда */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Подменю */
|
||||||
.submenu {
|
.submenu {
|
||||||
margin-left: 20px;
|
margin-left: 20px;
|
||||||
margin-top: 10px;
|
margin-top: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.tabs-container {
|
/* Футер сайдбара */
|
||||||
margin-top: 20px;
|
.sidebar-footer {
|
||||||
}
|
|
||||||
|
|
||||||
.tab {
|
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
background-color: #3d74c7;
|
background-color: #3d74c7;
|
||||||
border: 1px solid white;
|
text-align: center;
|
||||||
border-radius: 5px;
|
border-top: 1px solid rgba(255, 255, 255, 0.1);
|
||||||
margin-bottom: 5px;
|
/* Разделительная линия */
|
||||||
cursor: pointer;
|
flex-shrink: 0;
|
||||||
transition: background-color 0.3s ease;
|
/* Запрещаем сжатие */
|
||||||
|
width: 100%;
|
||||||
|
/* Ширина на всю ширину сайдбара */
|
||||||
}
|
}
|
||||||
|
|
||||||
.tab:hover {
|
.help,
|
||||||
background-color: #3d74c7;
|
.settings {
|
||||||
|
color: white;
|
||||||
|
margin: 5px 0;
|
||||||
|
/* Отступы между элементами */
|
||||||
|
overflow-x: hidden;
|
||||||
|
/* Убираем горизонтальную прокрутку */
|
||||||
|
text-align: left;
|
||||||
}
|
}
|
||||||
|
|
@ -1,43 +1,72 @@
|
||||||
/* src/Style/common.css */
|
/* src/Style/common.css */
|
||||||
/* Вкладки */
|
|
||||||
|
/* Контейнер для вкладок */
|
||||||
.tabs {
|
.tabs {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 5px;
|
gap: 5px;
|
||||||
|
/* Расстояние между вкладками */
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
background-color: #3d74c7;
|
background-color: #3d74c7;
|
||||||
|
/* Цвет фона */
|
||||||
border-bottom: 2px solid #195fc9;
|
border-bottom: 2px solid #195fc9;
|
||||||
|
/* Линия под вкладками */
|
||||||
overflow-x: auto;
|
overflow-x: auto;
|
||||||
|
/* Прокрутка, если вкладок много */
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
|
/* Скругление углов */
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
|
/* Запрет переноса текста */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Стили для отдельной вкладки */
|
||||||
.tab {
|
.tab {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
background-color: #3d74c7;
|
background-color: #3d74c7;
|
||||||
|
/* Цвет фона вкладки */
|
||||||
color: white;
|
color: white;
|
||||||
padding: 5px 10px;
|
/* Цвет текста */
|
||||||
|
padding: 5px 15px;
|
||||||
|
/* Отступы внутри вкладки */
|
||||||
border-radius: 5px 5px 0 0;
|
border-radius: 5px 5px 0 0;
|
||||||
|
/* Скругление углов */
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
max-width: 250px;
|
/* Курсор при наведении */
|
||||||
min-width: 100px;
|
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
position: relative;
|
/* Запрет сжатия */
|
||||||
|
transition: background-color 0.3s ease;
|
||||||
|
/* Плавное изменение цвета */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Активная вкладка */
|
||||||
.tab.active {
|
.tab.active {
|
||||||
background-color: #195fc9;
|
background-color: #195fc9;
|
||||||
|
/* Цвет фона активной вкладки */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Кнопка закрытия вкладки */
|
||||||
.close-tab {
|
.close-tab {
|
||||||
background: none;
|
background: none;
|
||||||
border: none;
|
border: none;
|
||||||
|
color: white;
|
||||||
|
/* Цвет крестика */
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
|
margin-left: 10px;
|
||||||
|
/* Отступ от текста */
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
transition: color 0.3s ease;
|
||||||
|
/* Плавное изменение цвета */
|
||||||
}
|
}
|
||||||
|
|
||||||
.error {
|
/* Эффект при наведении на кнопку закрытия */
|
||||||
color: red;
|
.close-tab:hover {
|
||||||
margin-bottom: 10px;
|
color: #ff6b6b;
|
||||||
|
/* Цвет крестика при наведении */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Эффект при наведении на вкладку */
|
||||||
|
.tab:hover {
|
||||||
|
background-color: #195fc9;
|
||||||
|
/* Цвет фона при наведении */
|
||||||
}
|
}
|
||||||
Loading…
Reference in New Issue