mirror of
https://github.com/phranck/TUIkit.git
synced 2026-06-20 09:54:37 +00:00
- Generate cropped favicon from tuikit-logo.png (transparent edges removed) - Add multi-size favicons (16, 32, 192, 512px + .ico) - Update metadata.icons in layout.tsx with proper sizes - Add global 't' keydown listener in ThemeProvider to cycle themes - Fix TUIKit → TUIkit typo in palette-preview.html
578 lines
16 KiB
HTML
578 lines
16 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>TUIkit Palette Preview</title>
|
|
<style>
|
|
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
|
|
|
|
:root {
|
|
--page-bg: #0a0a0a;
|
|
--page-fg: #999;
|
|
--page-fg-bright: #ccc;
|
|
--page-border: #222;
|
|
--card-radius: 10px;
|
|
}
|
|
|
|
body {
|
|
background: var(--page-bg);
|
|
color: var(--page-fg);
|
|
font-family: -apple-system, BlinkMacSystemFont, "SF Pro Text", "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
|
|
font-size: 18px;
|
|
line-height: 1.6;
|
|
padding: 48px 32px 100px;
|
|
max-width: 1600px;
|
|
margin: 0 auto;
|
|
}
|
|
|
|
h1 {
|
|
font-size: 44px;
|
|
font-weight: 700;
|
|
color: var(--page-fg-bright);
|
|
margin-bottom: 8px;
|
|
letter-spacing: -0.5px;
|
|
}
|
|
|
|
.subtitle {
|
|
font-size: 20px;
|
|
color: #666;
|
|
margin-bottom: 56px;
|
|
}
|
|
|
|
h2 {
|
|
font-size: 30px;
|
|
font-weight: 600;
|
|
color: var(--page-fg-bright);
|
|
margin: 56px 0 28px;
|
|
padding-bottom: 14px;
|
|
border-bottom: 1px solid var(--page-border);
|
|
letter-spacing: -0.3px;
|
|
}
|
|
|
|
.palette-grid {
|
|
display: grid;
|
|
grid-template-columns: repeat(2, 1fr);
|
|
gap: 32px;
|
|
}
|
|
|
|
.palette-card {
|
|
border: 1px solid var(--page-border);
|
|
border-radius: var(--card-radius);
|
|
overflow: hidden;
|
|
background: #0e0e0e;
|
|
}
|
|
|
|
.palette-header {
|
|
padding: 24px 28px 20px;
|
|
border-bottom: 1px solid var(--page-border);
|
|
}
|
|
|
|
.palette-name {
|
|
font-size: 28px;
|
|
font-weight: 700;
|
|
margin-bottom: 6px;
|
|
letter-spacing: -0.3px;
|
|
}
|
|
|
|
.palette-desc {
|
|
font-size: 16px;
|
|
color: #666;
|
|
font-style: italic;
|
|
}
|
|
|
|
.palette-body {
|
|
padding: 24px 28px;
|
|
}
|
|
|
|
/* Color swatches */
|
|
.swatch-section {
|
|
margin-bottom: 22px;
|
|
}
|
|
|
|
.swatch-section-title {
|
|
font-size: 13px;
|
|
font-weight: 600;
|
|
text-transform: uppercase;
|
|
letter-spacing: 1.2px;
|
|
color: #555;
|
|
margin-bottom: 10px;
|
|
}
|
|
|
|
.swatch-row {
|
|
display: grid;
|
|
grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));
|
|
gap: 10px;
|
|
}
|
|
|
|
.swatch {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
gap: 5px;
|
|
}
|
|
|
|
.swatch-color {
|
|
width: 100%;
|
|
height: 40px;
|
|
border-radius: 6px;
|
|
border: 1px solid rgba(255,255,255,0.06);
|
|
}
|
|
|
|
.swatch-label {
|
|
font-size: 13px;
|
|
font-weight: 500;
|
|
color: #555;
|
|
text-align: center;
|
|
line-height: 1.3;
|
|
word-break: break-word;
|
|
}
|
|
|
|
.swatch-hex {
|
|
font-family: "SF Mono", "Fira Code", "Cascadia Code", "JetBrains Mono", Menlo, Monaco, "Courier New", monospace;
|
|
font-size: 12px;
|
|
color: #444;
|
|
text-align: center;
|
|
}
|
|
|
|
|
|
|
|
/* Existing palette section - more compact */
|
|
.existing-grid {
|
|
display: grid;
|
|
grid-template-columns: repeat(auto-fill, minmax(min(100%, 360px), 1fr));
|
|
gap: 20px;
|
|
}
|
|
|
|
.existing-card {
|
|
border: 1px solid var(--page-border);
|
|
border-radius: 8px;
|
|
overflow: hidden;
|
|
background: #0e0e0e;
|
|
padding: 20px 24px;
|
|
}
|
|
|
|
.existing-name {
|
|
font-size: 22px;
|
|
font-weight: 700;
|
|
margin-bottom: 14px;
|
|
}
|
|
|
|
.existing-swatches {
|
|
display: grid;
|
|
grid-template-columns: repeat(auto-fill, minmax(40px, 1fr));
|
|
gap: 6px;
|
|
}
|
|
|
|
.existing-swatch {
|
|
width: 100%;
|
|
height: 30px;
|
|
border-radius: 5px;
|
|
border: 1px solid rgba(255,255,255,0.06);
|
|
}
|
|
|
|
/* Hue distribution bar */
|
|
.hue-wheel {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 20px;
|
|
margin: 28px 0 40px;
|
|
padding: 20px 24px;
|
|
background: #0e0e0e;
|
|
border: 1px solid var(--page-border);
|
|
border-radius: 10px;
|
|
}
|
|
|
|
.hue-bar {
|
|
flex: 1;
|
|
height: 16px;
|
|
border-radius: 8px;
|
|
position: relative;
|
|
background: linear-gradient(to right,
|
|
hsl(0,80%,50%), hsl(30,80%,50%), hsl(60,80%,50%),
|
|
hsl(90,80%,50%), hsl(120,80%,50%), hsl(150,80%,50%),
|
|
hsl(180,80%,50%), hsl(210,80%,50%), hsl(240,80%,50%),
|
|
hsl(270,80%,50%), hsl(300,80%,50%), hsl(330,80%,50%),
|
|
hsl(360,80%,50%)
|
|
);
|
|
}
|
|
|
|
.hue-marker {
|
|
position: absolute;
|
|
top: -4px;
|
|
width: 3px;
|
|
height: 20px;
|
|
border-radius: 2px;
|
|
transform: translateX(-50%);
|
|
}
|
|
|
|
.hue-marker-existing {
|
|
background: rgba(255,255,255,0.5);
|
|
border: 1px solid rgba(255,255,255,0.2);
|
|
}
|
|
|
|
.hue-marker-new {
|
|
background: #fff;
|
|
border: 2px solid #fff;
|
|
box-shadow: 0 0 6px rgba(255,255,255,0.5);
|
|
height: 22px;
|
|
top: -5px;
|
|
}
|
|
|
|
.hue-legend {
|
|
font-size: 14px;
|
|
color: #555;
|
|
display: flex;
|
|
gap: 18px;
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
.hue-legend span {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 4px;
|
|
}
|
|
|
|
.hue-legend-mark {
|
|
display: inline-block;
|
|
width: 12px;
|
|
height: 3px;
|
|
border-radius: 2px;
|
|
}
|
|
|
|
/* ── Responsive ──────────────────────────────────────────────────── */
|
|
|
|
@media (max-width: 900px) {
|
|
.palette-grid { grid-template-columns: 1fr; }
|
|
}
|
|
|
|
@media (max-width: 768px) {
|
|
body { padding: 24px 16px 60px; font-size: 16px; }
|
|
h1 { font-size: 32px; }
|
|
h2 { font-size: 24px; margin: 40px 0 20px; }
|
|
.subtitle { font-size: 17px; margin-bottom: 36px; }
|
|
.palette-header { padding: 18px 20px 14px; }
|
|
.palette-name { font-size: 22px; }
|
|
.palette-body { padding: 18px 20px; }
|
|
.hue-wheel { flex-direction: column; gap: 12px; padding: 16px; }
|
|
.hue-bar { width: 100%; height: 16px; flex: none; }
|
|
.hue-legend { justify-content: center; }
|
|
}
|
|
|
|
@media (max-width: 480px) {
|
|
body { padding: 16px 12px 40px; }
|
|
h1 { font-size: 26px; }
|
|
.swatch-row { grid-template-columns: repeat(auto-fill, minmax(60px, 1fr)); }
|
|
.swatch-color { height: 32px; }
|
|
.existing-grid { grid-template-columns: 1fr; }
|
|
}
|
|
|
|
</style>
|
|
</head>
|
|
<body>
|
|
|
|
<h1>TUIkit Color Palettes</h1>
|
|
<p class="subtitle">5 proposed palettes with Palette (13) + BlockPalette (3) properties — plus existing palettes for reference</p>
|
|
|
|
<!-- Hue distribution visualization -->
|
|
<div class="hue-wheel">
|
|
<div class="hue-bar">
|
|
<!-- Existing palettes -->
|
|
<div class="hue-marker hue-marker-existing" style="left: 0%;" title="Red (0°)"></div>
|
|
<div class="hue-marker hue-marker-existing" style="left: 8.3%;" title="Amber (30°)"></div>
|
|
<div class="hue-marker hue-marker-existing" style="left: 33.3%;" title="Green (120°)"></div>
|
|
<div class="hue-marker hue-marker-existing" style="left: 58.3%;" title="Blue (210°)"></div>
|
|
<div class="hue-marker hue-marker-existing" style="left: 75%;" title="Violet (270°)"></div>
|
|
<!-- New palettes -->
|
|
<div class="hue-marker hue-marker-new" style="left: 4.2%;" title="Coral (15°)"></div>
|
|
<div class="hue-marker hue-marker-new" style="left: 12.5%;" title="Gold (45°)"></div>
|
|
<div class="hue-marker hue-marker-new" style="left: 50%;" title="Teal (180°)"></div>
|
|
<div class="hue-marker hue-marker-new" style="left: 54.2%;" title="Frost (195°)"></div>
|
|
<div class="hue-marker hue-marker-new" style="left: 88.9%;" title="Magenta (320°)"></div>
|
|
</div>
|
|
<div class="hue-legend">
|
|
<span><span class="hue-legend-mark" style="background: rgba(255,255,255,0.4);"></span>Existing</span>
|
|
<span><span class="hue-legend-mark" style="background: #fff; box-shadow: 0 0 4px rgba(255,255,255,0.5);"></span>New</span>
|
|
</div>
|
|
</div>
|
|
|
|
<h2>New Palettes</h2>
|
|
|
|
<div class="palette-grid" id="new-palettes"></div>
|
|
|
|
<h2>Existing Palettes</h2>
|
|
|
|
<div class="existing-grid" id="existing-palettes"></div>
|
|
|
|
<script>
|
|
// ── Palette Definitions ──────────────────────────────────────────────
|
|
|
|
const newPalettes = [
|
|
{
|
|
name: "Teal",
|
|
desc: "Inspired by LCARS (Star Trek) terminal displays, teal control panels, and bridge consoles.",
|
|
colors: {
|
|
background: "#060A0A",
|
|
foreground: "#00DDC0",
|
|
foregroundSecondary: "#00AA94",
|
|
foregroundTertiary: "#007A6B",
|
|
accent: "#33FFE0",
|
|
success: "#33FFAA",
|
|
warning: "#CCFF66",
|
|
error: "#FF6633",
|
|
info: "#66FFEE",
|
|
border: "#2D5A55",
|
|
statusBarBackground: "#0D1E1D",
|
|
appHeaderBackground: "#0A1B1C",
|
|
overlayBackground: "#060A0A",
|
|
surfaceBackground: "#0E2526",
|
|
surfaceHeaderBackground: "#0A1B1C",
|
|
elevatedBackground: "#144542",
|
|
}
|
|
},
|
|
{
|
|
name: "Magenta",
|
|
desc: "Synthwave neon glow \u2014 inspired by 80s arcade cabinets, retrowave, and cyberpunk HUDs.",
|
|
colors: {
|
|
background: "#0A060A",
|
|
foreground: "#FF44CC",
|
|
foregroundSecondary: "#CC33A3",
|
|
foregroundTertiary: "#8F2472",
|
|
accent: "#FF77DD",
|
|
success: "#FF88DD",
|
|
warning: "#FFAA77",
|
|
error: "#FF6633",
|
|
info: "#FF99EE",
|
|
border: "#5A2D50",
|
|
statusBarBackground: "#180D19",
|
|
appHeaderBackground: "#1C0E1E",
|
|
overlayBackground: "#0A060A",
|
|
surfaceBackground: "#251428",
|
|
surfaceHeaderBackground: "#1C0E1E",
|
|
elevatedBackground: "#3A1D3A",
|
|
}
|
|
},
|
|
{
|
|
name: "Gold",
|
|
desc: "Warm brass instrument panels, steampunk gauges, and luxury cockpit displays.",
|
|
colors: {
|
|
background: "#0A0906",
|
|
foreground: "#DDAA22",
|
|
foregroundSecondary: "#BB8E1A",
|
|
foregroundTertiary: "#8A6814",
|
|
accent: "#FFCC44",
|
|
success: "#DDCC44",
|
|
warning: "#FFE066",
|
|
error: "#FF6633",
|
|
info: "#EEBB55",
|
|
border: "#5A4D2D",
|
|
statusBarBackground: "#191508",
|
|
appHeaderBackground: "#1C170A",
|
|
overlayBackground: "#0A0906",
|
|
surfaceBackground: "#261F0E",
|
|
surfaceHeaderBackground: "#1C170A",
|
|
elevatedBackground: "#3A3018",
|
|
}
|
|
},
|
|
{
|
|
name: "Coral",
|
|
desc: "Warm sunset terminals \u2014 inspired by sodium-vapor streetlights and desert radar stations.",
|
|
colors: {
|
|
background: "#0A0706",
|
|
foreground: "#FF7744",
|
|
foregroundSecondary: "#CC5E36",
|
|
foregroundTertiary: "#8F4226",
|
|
accent: "#FF9966",
|
|
success: "#FFAA77",
|
|
warning: "#FFCC66",
|
|
error: "#FF4433",
|
|
info: "#FFBB88",
|
|
border: "#5A3A2D",
|
|
statusBarBackground: "#190F0A",
|
|
appHeaderBackground: "#1E100C",
|
|
overlayBackground: "#0A0706",
|
|
surfaceBackground: "#281710",
|
|
surfaceHeaderBackground: "#1E100C",
|
|
elevatedBackground: "#3A2418",
|
|
}
|
|
},
|
|
{
|
|
name: "Frost",
|
|
desc: "Arctic cryogenic readouts \u2014 inspired by ice-blue instrument clusters and polar research stations.",
|
|
colors: {
|
|
background: "#060809",
|
|
foreground: "#88DDFF",
|
|
foregroundSecondary: "#66AACC",
|
|
foregroundTertiary: "#4A7A99",
|
|
accent: "#AAEEFF",
|
|
success: "#88EEBB",
|
|
warning: "#CCDDAA",
|
|
error: "#FF6633",
|
|
info: "#BBEEFF",
|
|
border: "#2D4A5A",
|
|
statusBarBackground: "#0D1720",
|
|
appHeaderBackground: "#0A151E",
|
|
overlayBackground: "#060809",
|
|
surfaceBackground: "#0E1D28",
|
|
surfaceHeaderBackground: "#0A151E",
|
|
elevatedBackground: "#142D3E",
|
|
}
|
|
},
|
|
];
|
|
|
|
const existingPalettes = [
|
|
{
|
|
name: "Green",
|
|
desc: "P1 phosphor",
|
|
fg: "#33FF33",
|
|
colors: ["#060A07",
|
|
"#33FF33","#27C227","#1F8F1F",
|
|
"#66FF66",
|
|
"#33FF33","#CCFF33","#FF6633","#33FFCC",
|
|
"#2D5A2D",
|
|
"#0F2215","#0A1B13","#060A07"]
|
|
},
|
|
{
|
|
name: "Amber",
|
|
desc: "P3 phosphor",
|
|
fg: "#FFAA00",
|
|
colors: ["#0A0706",
|
|
"#FFAA00","#CC8800","#8F6600",
|
|
"#FFCC33",
|
|
"#FFCC00","#FFE066","#FF6633","#FFD966",
|
|
"#5A4A2D",
|
|
"#191613","#1E110E","#0A0706"]
|
|
},
|
|
{
|
|
name: "Red",
|
|
desc: "Military",
|
|
fg: "#FF4444",
|
|
colors: ["#0A0606",
|
|
"#FF4444","#CC3333","#8F2222",
|
|
"#FF6666",
|
|
"#FF8080","#FFAA66","#FFFFFF","#FF9999",
|
|
"#5A2D2D",
|
|
"#191313","#1E0F10","#0A0606"]
|
|
},
|
|
{
|
|
name: "Violet",
|
|
desc: "Sci-fi",
|
|
fg: "#B275EF",
|
|
colors: ["#070509",
|
|
"#B275EF","#8C3BDC","#6528A3",
|
|
"#C697F6",
|
|
"#E4A567","#EF75B2","#A5F159","#7CB2E8",
|
|
"#3F2659",
|
|
"#140D1B","#110B18","#070509"]
|
|
},
|
|
{
|
|
name: "Blue",
|
|
desc: "VFD",
|
|
fg: "#00AAFF",
|
|
colors: ["#060708",
|
|
"#00AAFF","#0088CC","#006699",
|
|
"#33BBFF",
|
|
"#33CCFF","#66CCFF","#FF6633","#99DDFF",
|
|
"#2D4A5A",
|
|
"#0F1822","#0A121C","#060708"]
|
|
},
|
|
{
|
|
name: "White",
|
|
desc: "P4 phosphor",
|
|
fg: "#E8E8E8",
|
|
colors: ["#06070A",
|
|
"#E8E8E8","#B0B0B0","#787878",
|
|
"#FFFFFF",
|
|
"#C0FFC0","#FFE0A0","#FFA0A0","#A0D0FF",
|
|
"#484848",
|
|
"#131619","#0D131D","#06070A"]
|
|
},
|
|
];
|
|
|
|
const colorLabels = [
|
|
"background",
|
|
"foreground","foregroundSecondary","foregroundTertiary",
|
|
"accent",
|
|
"success","warning","error","info",
|
|
"border",
|
|
"statusBarBackground","appHeaderBackground","overlayBackground",
|
|
"surfaceBackground","surfaceHeaderBackground","elevatedBackground"
|
|
];
|
|
|
|
const swatchGroups = [
|
|
{ title: "Palette — Backgrounds", keys: ["background","statusBarBackground","appHeaderBackground","overlayBackground"] },
|
|
{ title: "Palette — Foregrounds", keys: ["foreground","foregroundSecondary","foregroundTertiary"] },
|
|
{ title: "Palette — Accent", keys: ["accent"] },
|
|
{ title: "Palette — Semantic", keys: ["success","warning","error","info"] },
|
|
{ title: "Palette — UI Elements", keys: ["border"] },
|
|
{ title: "BlockPalette — Surfaces", keys: ["surfaceBackground","surfaceHeaderBackground","elevatedBackground"] },
|
|
];
|
|
|
|
function camelToLabel(key) {
|
|
return key.replace(/([A-Z])/g, " $1").toLowerCase();
|
|
}
|
|
|
|
function createSwatch(color, label) {
|
|
return `<div class="swatch">
|
|
<div class="swatch-color" style="background:${color}"></div>
|
|
<div class="swatch-label">${label}</div>
|
|
<div class="swatch-hex">${color.toUpperCase()}</div>
|
|
</div>`;
|
|
}
|
|
|
|
function renderNewPalettes() {
|
|
const container = document.getElementById("new-palettes");
|
|
let html = "";
|
|
|
|
for (const palette of newPalettes) {
|
|
let swatchesHtml = "";
|
|
for (const group of swatchGroups) {
|
|
let row = "";
|
|
for (const key of group.keys) {
|
|
row += createSwatch(palette.colors[key], camelToLabel(key));
|
|
}
|
|
swatchesHtml += `<div class="swatch-section">
|
|
<div class="swatch-section-title">${group.title}</div>
|
|
<div class="swatch-row">${row}</div>
|
|
</div>`;
|
|
}
|
|
|
|
html += `<div class="palette-card">
|
|
<div class="palette-header">
|
|
<div class="palette-name" style="color:${palette.colors.foreground}">${palette.name}</div>
|
|
<div class="palette-desc">${palette.desc}</div>
|
|
</div>
|
|
<div class="palette-body">
|
|
${swatchesHtml}
|
|
</div>
|
|
</div>`;
|
|
}
|
|
|
|
container.innerHTML = html;
|
|
}
|
|
|
|
function renderExistingPalettes() {
|
|
const container = document.getElementById("existing-palettes");
|
|
let html = "";
|
|
|
|
for (const palette of existingPalettes) {
|
|
let swatches = "";
|
|
for (const color of palette.colors) {
|
|
swatches += `<div class="existing-swatch" style="background:${color}" title="${color}"></div>`;
|
|
}
|
|
|
|
html += `<div class="existing-card">
|
|
<div class="existing-name" style="color:${palette.fg}">${palette.name} <span style="color:#555;font-weight:400;font-size:16px">${palette.desc}</span></div>
|
|
<div class="existing-swatches">${swatches}</div>
|
|
</div>`;
|
|
}
|
|
|
|
container.innerHTML = html;
|
|
}
|
|
|
|
renderNewPalettes();
|
|
renderExistingPalettes();
|
|
</script>
|
|
</body>
|
|
</html>
|