Files
typedserver/ts_swdash/sw-dash-styles.ts

495 lines
9.1 KiB
TypeScript

import { css } from './plugins.js';
import type { CSSResult } from './plugins.js';
/**
* Shared terminal-style theme for sw-dash components
*/
export const sharedStyles: CSSResult = css`
:host {
--sw-bg-dark: #0a0a0a;
--sw-bg-panel: #0d0d0d;
--sw-bg-header: #111;
--sw-bg-input: #1a1a1a;
--sw-border: #333;
--sw-border-active: #00ff00;
--sw-text-primary: #00ff00;
--sw-text-secondary: #888;
--sw-text-cyan: #00ffff;
--sw-text-warning: #ffff00;
--sw-text-error: #ff4444;
--sw-gauge-good: #00aa00;
--sw-gauge-warning: #aaaa00;
--sw-gauge-bad: #aa0000;
font-family: 'Courier New', Courier, monospace;
font-size: 14px;
line-height: 1.4;
color: var(--sw-text-primary);
}
`;
export const terminalStyles: CSSResult = css`
.terminal {
max-width: 1200px;
margin: 0 auto;
border: 1px solid var(--sw-border-active);
background: var(--sw-bg-panel);
box-shadow: 0 0 20px rgba(0, 255, 0, 0.1);
}
.header {
border-bottom: 1px solid var(--sw-border-active);
padding: 10px 15px;
display: flex;
justify-content: space-between;
align-items: center;
background: var(--sw-bg-header);
}
.title {
color: var(--sw-text-primary);
font-weight: bold;
font-size: 16px;
}
.uptime {
color: var(--sw-text-secondary);
}
.content {
padding: 15px;
min-height: 400px;
}
.footer {
border-top: 1px solid var(--sw-border-active);
padding: 10px 15px;
display: flex;
justify-content: space-between;
align-items: center;
background: var(--sw-bg-header);
font-size: 12px;
}
.refresh-info {
color: var(--sw-text-secondary);
}
.status {
display: flex;
align-items: center;
gap: 8px;
}
.status-dot {
width: 8px;
height: 8px;
border-radius: 50%;
background: var(--sw-text-primary);
animation: pulse 2s infinite;
}
.prompt {
color: var(--sw-text-primary);
}
.cursor {
display: inline-block;
width: 8px;
height: 14px;
background: var(--sw-text-primary);
animation: blink 1s step-end infinite;
vertical-align: middle;
margin-left: 2px;
}
@keyframes pulse {
0%, 100% { opacity: 1; }
50% { opacity: 0.5; }
}
@keyframes blink {
50% { opacity: 0; }
}
`;
export const navStyles: CSSResult = css`
.nav {
display: flex;
background: var(--sw-bg-header);
border-bottom: 1px solid var(--sw-border);
padding: 0 10px;
}
.nav-tab {
padding: 10px 20px;
cursor: pointer;
color: var(--sw-text-secondary);
border: none;
background: transparent;
font-family: inherit;
font-size: 13px;
transition: all 0.2s;
border-bottom: 2px solid transparent;
}
.nav-tab:hover {
color: var(--sw-text-primary);
}
.nav-tab.active {
color: var(--sw-text-primary);
border-bottom-color: var(--sw-text-primary);
background: var(--sw-bg-input);
}
.nav-tab .count {
background: var(--sw-border);
padding: 1px 6px;
border-radius: 8px;
font-size: 11px;
margin-left: 6px;
}
`;
export const panelStyles: CSSResult = css`
.grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(340px, 1fr));
gap: 15px;
}
.panel {
border: 1px solid var(--sw-border);
padding: 12px;
background: var(--sw-bg-dark);
}
.panel-title {
color: var(--sw-text-cyan);
font-weight: bold;
margin-bottom: 10px;
padding-bottom: 5px;
border-bottom: 1px dashed var(--sw-border);
}
.row {
display: flex;
justify-content: space-between;
padding: 3px 0;
}
.label {
color: var(--sw-text-secondary);
}
.value {
color: var(--sw-text-primary);
}
.value.warning {
color: var(--sw-text-warning);
}
.value.error {
color: var(--sw-text-error);
}
.value.success {
color: var(--sw-text-primary);
}
`;
export const gaugeStyles: CSSResult = css`
.gauge {
margin: 8px 0;
}
.gauge-bar {
height: 16px;
background: var(--sw-bg-input);
border: 1px solid var(--sw-border);
position: relative;
font-size: 12px;
}
.gauge-fill {
height: 100%;
transition: width 0.3s ease;
}
.gauge-fill.good {
background: var(--sw-gauge-good);
}
.gauge-fill.warning {
background: var(--sw-gauge-warning);
}
.gauge-fill.bad {
background: var(--sw-gauge-bad);
}
.gauge-text {
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
color: #fff;
font-weight: bold;
text-shadow: 1px 1px 2px #000;
}
`;
export const tableStyles: CSSResult = css`
.table-container {
overflow-x: auto;
}
.data-table {
width: 100%;
border-collapse: collapse;
font-size: 12px;
}
.data-table th,
.data-table td {
padding: 8px 10px;
text-align: left;
border-bottom: 1px solid var(--sw-border);
}
.data-table th {
background: var(--sw-bg-input);
color: var(--sw-text-cyan);
cursor: pointer;
user-select: none;
white-space: nowrap;
}
.data-table th:hover {
background: #252525;
}
.data-table th .sort-icon {
margin-left: 5px;
opacity: 0.5;
}
.data-table th.sorted .sort-icon {
opacity: 1;
color: var(--sw-text-primary);
}
.data-table tr:hover {
background: #151515;
}
.data-table td {
color: #ccc;
}
.data-table td.url {
max-width: 400px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.data-table td.num {
text-align: right;
color: var(--sw-text-primary);
}
.table-controls {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 10px;
gap: 10px;
}
.search-input {
background: var(--sw-bg-input);
border: 1px solid var(--sw-border);
color: var(--sw-text-primary);
padding: 6px 10px;
font-family: inherit;
font-size: 12px;
width: 250px;
}
.search-input:focus {
outline: none;
border-color: var(--sw-border-active);
}
.table-info {
color: var(--sw-text-secondary);
font-size: 12px;
}
.hit-rate-bar {
width: 60px;
height: 10px;
background: var(--sw-bg-input);
border: 1px solid var(--sw-border);
display: inline-block;
vertical-align: middle;
margin-right: 6px;
}
.hit-rate-fill {
height: 100%;
}
.hit-rate-fill.good {
background: var(--sw-gauge-good);
}
.hit-rate-fill.warning {
background: var(--sw-gauge-warning);
}
.hit-rate-fill.bad {
background: var(--sw-gauge-bad);
}
`;
export const buttonStyles: CSSResult = css`
.btn {
background: var(--sw-bg-input);
border: 1px solid var(--sw-border-active);
color: var(--sw-text-primary);
padding: 8px 16px;
cursor: pointer;
font-family: inherit;
font-size: 12px;
transition: all 0.2s ease;
}
.btn:hover {
background: var(--sw-text-primary);
color: #000;
}
.btn:disabled {
opacity: 0.5;
cursor: not-allowed;
}
.btn-row {
display: flex;
justify-content: flex-end;
margin-top: 10px;
}
`;
export const speedtestStyles: CSSResult = css`
.online-indicator {
display: flex;
align-items: center;
gap: 8px;
padding: 8px 0;
margin-bottom: 10px;
border-bottom: 1px dashed var(--sw-border);
}
.online-dot {
width: 12px;
height: 12px;
border-radius: 50%;
transition: background-color 0.3s ease;
}
.online-dot.online {
background: var(--sw-text-primary);
box-shadow: 0 0 8px rgba(0, 255, 0, 0.5);
}
.online-dot.offline {
background: var(--sw-text-error);
box-shadow: 0 0 8px rgba(255, 68, 68, 0.5);
}
.speed-bar {
height: 8px;
background: var(--sw-bg-input);
border: 1px solid var(--sw-border);
margin: 4px 0;
}
.speed-fill {
height: 100%;
background: var(--sw-gauge-good);
transition: width 0.5s ease;
}
/* Speedtest progress indicator */
.speedtest-progress {
padding: 10px 0;
}
.progress-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 8px;
}
.progress-phase {
color: var(--sw-text-cyan);
font-weight: bold;
animation: pulse 1s infinite;
}
.progress-time {
color: var(--sw-text-secondary);
font-size: 12px;
}
.progress-bar {
height: 20px;
background: var(--sw-bg-input);
border: 1px solid var(--sw-border);
position: relative;
overflow: hidden;
}
.progress-fill {
height: 100%;
background: linear-gradient(90deg, var(--sw-gauge-good), var(--sw-text-cyan));
transition: width 0.1s linear;
position: relative;
}
.progress-fill::after {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent);
animation: shimmer 1.5s infinite;
}
.progress-fill.complete {
background: var(--sw-text-primary);
}
.progress-fill.complete::after {
display: none;
}
@keyframes shimmer {
0% { transform: translateX(-100%); }
100% { transform: translateX(100%); }
}
@keyframes pulse {
0%, 100% { opacity: 1; }
50% { opacity: 0.6; }
}
`;