add theme.js — shared design tokens module referenced by App.jsx
This commit is contained in:
+31
-32
@@ -125,13 +125,12 @@ function getBlockDisplayName(block) {
|
||||
const css = `
|
||||
@import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;700&family=Space+Grotesk:wght@300;400;500;600&display=swap');
|
||||
* { box-sizing: border-box; margin: 0; padding: 0; -webkit-tap-highlight-color: transparent; user-select: none; }
|
||||
html, body { height: 100%; overflow: hidden; background: ${T.bg}; }
|
||||
body { color: ${T.textPrimary}; font-family: 'Space Grotesk', sans-serif; }
|
||||
:root { --amber: ${T.amber}; --blue: ${T.blue}; --green: ${T.green}; }
|
||||
html, body { height: 100%; overflow: hidden; background: var(--bg); }
|
||||
body { color: var(--text-primary); font-family: 'Space Grotesk', sans-serif; }
|
||||
.mono { font-family: 'JetBrains Mono', monospace; }
|
||||
::-webkit-scrollbar { width: 4px; height: 4px; }
|
||||
::-webkit-scrollbar-track { background: ${T.panel}; }
|
||||
::-webkit-scrollbar-thumb { background: ${T.border}; border-radius: 2px; }
|
||||
::-webkit-scrollbar-track { background: var(--panel); }
|
||||
::-webkit-scrollbar-thumb { background: var(--border); border-radius: 2px; }
|
||||
|
||||
/* ── Knob ── */
|
||||
.knob-wrap { display: flex; flex-direction: column; align-items: center; gap: 4px; cursor: pointer; }
|
||||
@@ -141,21 +140,21 @@ const css = `
|
||||
box-shadow: 0 2px 8px rgba(0,0,0,.6), inset 0 1px 0 rgba(255,255,255,.07); }
|
||||
.knob-dot { position: absolute; width: 3px; border-radius: 2px; background: var(--amber);
|
||||
left: 50%; transform-origin: bottom center; box-shadow: 0 0 6px var(--amber); }
|
||||
.knob-label { font-size: 9px; color: ${T.textSec}; letter-spacing: .06em; text-transform: uppercase; text-align: center; }
|
||||
.knob-value { font-family: 'JetBrains Mono', monospace; font-size: 10px; color: ${T.amber}; }
|
||||
.knob-label { font-size: 9px; color: var(--text-sec); letter-spacing: .06em; text-transform: uppercase; text-align: center; }
|
||||
.knob-value { font-family: 'JetBrains Mono', monospace; font-size: 10px; color: var(--amber); }
|
||||
|
||||
/* ── Buttons ── */
|
||||
.btn { padding: 8px 14px; border-radius: 6px; font-size: 12px; font-weight: 600;
|
||||
letter-spacing: .04em; border: none; cursor: pointer; transition: all .12s; }
|
||||
.btn-primary { background: ${T.amber}; color: #000; }
|
||||
.btn-primary { background: var(--amber); color: #000; }
|
||||
.btn-primary:active { filter: brightness(.85); transform: scale(.97); }
|
||||
.btn-ghost { background: ${T.surface}; color: ${T.textPrimary}; border: 1px solid ${T.border}; }
|
||||
.btn-ghost:active { background: ${T.border}; }
|
||||
.btn-ghost { background: var(--surface); color: var(--text-primary); border: 1px solid var(--border); }
|
||||
.btn-ghost:active { background: var(--border); }
|
||||
.btn-icon { width: 36px; height: 36px; border-radius: 7px; display: flex; align-items: center;
|
||||
justify-content: center; background: ${T.surface}; border: 1px solid ${T.border}; cursor: pointer;
|
||||
justify-content: center; background: var(--surface); border: 1px solid var(--border); cursor: pointer;
|
||||
font-size: 15px; transition: all .12s; flex-shrink: 0; }
|
||||
.btn-icon:active { transform: scale(.93); }
|
||||
.btn-icon.active { background: rgba(232,160,48,.15); border-color: ${T.amber}; color: ${T.amber}; }
|
||||
.btn-icon.active { background: rgba(232,160,48,.15); border-color: var(--amber); color: var(--amber); }
|
||||
.btn:focus-visible { outline: 2px solid #3AB87A; outline-offset: 2px; }
|
||||
.btn-icon:focus-visible { outline: 2px solid #3AB87A; outline-offset: 2px; }
|
||||
|
||||
@@ -163,43 +162,43 @@ const css = `
|
||||
.badge { display: inline-flex; align-items: center; justify-content: center;
|
||||
padding: 2px 7px; border-radius: 4px; font-size: 10px; font-weight: 700;
|
||||
letter-spacing: .06em; text-transform: uppercase; }
|
||||
.badge-amber { background: rgba(232,160,48,.2); color: ${T.amber}; }
|
||||
.badge-green { background: rgba(58,184,122,.2); color: ${T.green}; }
|
||||
.badge-blue { background: rgba(74,139,200,.2); color: ${T.blue}; }
|
||||
.badge-amber { background: rgba(232,160,48,.2); color: var(--amber); }
|
||||
.badge-green { background: rgba(58,184,122,.2); color: var(--green); }
|
||||
.badge-blue { background: rgba(74,139,200,.2); color: var(--blue); }
|
||||
|
||||
/* ── Param slider ── */
|
||||
.param-panel { background: ${T.surface}; padding: 8px 12px 6px; border-top: 1px solid ${T.border}; flex-shrink: 0; }
|
||||
.param-panel { background: var(--surface); padding: 8px 12px 6px; border-top: 1px solid var(--border); flex-shrink: 0; }
|
||||
.param-panel-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 2px; }
|
||||
.param-panel-title { font-size: 10px; font-weight: 600; letter-spacing: .07em; text-transform: uppercase; color: ${T.textSec}; }
|
||||
.param-panel-title { font-size: 10px; font-weight: 600; letter-spacing: .07em; text-transform: uppercase; color: var(--text-sec); }
|
||||
.param-row { display: flex; flex-direction: column; gap: 1px; padding: 1px 0; }
|
||||
.param-header { display: flex; justify-content: space-between; align-items: center; }
|
||||
.param-label { font-size: 9px; font-weight: 500; text-transform: uppercase; letter-spacing: .06em; color: ${T.textSec}; }
|
||||
.param-label { font-size: 9px; font-weight: 500; text-transform: uppercase; letter-spacing: .06em; color: var(--text-sec); }
|
||||
.param-val { font-family: 'JetBrains Mono',monospace; font-size: 11px; font-weight: 600; }
|
||||
.param-track-wrap { position: relative; height: 30px; display: flex; align-items: center; cursor: pointer; touch-action: none; }
|
||||
.param-track { width: 100%; height: 6px; background: ${T.border}; border-radius: 3px; position: relative; overflow: hidden; }
|
||||
.param-track { width: 100%; height: 6px; background: var(--border); border-radius: 3px; position: relative; overflow: hidden; }
|
||||
.param-fill { height: 100%; border-radius: 3px; position: absolute; top: 0; left: 0; transition: width .04s; }
|
||||
.param-thumb { width: 22px; height: 22px; border-radius: 50%; position: absolute; top: 50%;
|
||||
transform: translate(-50%,-50%); box-shadow: 0 1px 6px rgba(0,0,0,.6); pointer-events: none;
|
||||
border: 3px solid ${T.bg}; }
|
||||
.param-btn { width: 28px; height: 28px; border-radius: 50%; border: 1px solid ${T.border};
|
||||
background: ${T.panel}; color: ${T.textPrimary}; font-size: 14px; font-weight: 700;
|
||||
border: 3px solid var(--bg); }
|
||||
.param-btn { width: 28px; height: 28px; border-radius: 50%; border: 1px solid var(--border);
|
||||
background: var(--panel); color: var(--text-primary); font-size: 14px; font-weight: 700;
|
||||
display: flex; align-items: center; justify-content: center; cursor: pointer; line-height: 1; }
|
||||
.param-btn:active { background: ${T.border}; transform: scale(.92); }
|
||||
.param-btn:active { background: var(--border); transform: scale(.92); }
|
||||
.param-knobs { display: flex; flex-wrap: wrap; gap: 10px; justify-content: center; padding: 4px 0; }
|
||||
|
||||
/* ── Screen header (overlays) ── */
|
||||
.screen-header { padding: 10px 14px 8px; display: flex; align-items: center;
|
||||
justify-content: space-between; border-bottom: 1px solid ${T.border}; }
|
||||
.screen-title { font-size: 12px; font-weight: 600; letter-spacing: .06em; text-transform: uppercase; color: ${T.textSec}; }
|
||||
justify-content: space-between; border-bottom: 1px solid var(--border); }
|
||||
.screen-title { font-size: 12px; font-weight: 600; letter-spacing: .06em; text-transform: uppercase; color: var(--text-sec); }
|
||||
.screen-body { flex: 1; overflow-y: auto; padding: 10px 12px; display: flex; flex-direction: column; gap: 10px; }
|
||||
|
||||
/* ── Preset sidebar chip ── */
|
||||
.preset-chip-s { width: 100%; padding: 7px 6px; border-radius: 5px; background: ${T.surface}; border: 1px solid ${T.border};
|
||||
.preset-chip-s { width: 100%; padding: 7px 6px; border-radius: 5px; background: var(--surface); border: 1px solid var(--border);
|
||||
display: flex; flex-direction: column; align-items: center; cursor: pointer; transition: all .12s; }
|
||||
.preset-chip-s.active { border-color: ${T.amber}; background: rgba(232,160,48,.08); }
|
||||
.preset-chip-s.active { border-color: var(--amber); background: rgba(232,160,48,.08); }
|
||||
.preset-chip-s:active { transform: scale(.96); }
|
||||
.preset-chip-s .pcs-num { font-family: 'JetBrains Mono',monospace; font-size: 14px; font-weight: 700; color: ${T.amber}; line-height: 1.1; }
|
||||
.preset-chip-s .pcs-name { font-size: 9px; color: ${T.textSec}; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 100%; text-align: center; line-height: 1.2; }
|
||||
.preset-chip-s .pcs-num { font-family: 'JetBrains Mono',monospace; font-size: 14px; font-weight: 700; color: var(--amber); line-height: 1.1; }
|
||||
.preset-chip-s .pcs-name { font-size: 9px; color: var(--text-sec); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 100%; text-align: center; line-height: 1.2; }
|
||||
.preset-chip-s .pcs-indicator { width: 4px; height: 4px; border-radius: 50%; margin-top: 3px; }
|
||||
|
||||
/* ── Preset row (captures) ── */
|
||||
@@ -207,9 +206,9 @@ const css = `
|
||||
border-radius: 6px; cursor: pointer; transition: background .12s; border: 1px solid transparent; }
|
||||
.preset-row:active, .preset-row.active { background: rgba(232,160,48,.08); border-color: rgba(232,160,48,.25); }
|
||||
.section-label { font-size: 10px; letter-spacing: .1em; text-transform: uppercase;
|
||||
color: ${T.textDim}; font-weight: 600; margin-bottom: 8px; }
|
||||
.card { background: ${T.panel}; border: 1px solid ${T.border}; border-radius: 8px; padding: 14px; }
|
||||
.card-sm { background: ${T.surface}; border: 1px solid ${T.border}; border-radius: 6px; padding: 10px; }
|
||||
color: var(--text-dim); font-weight: 600; margin-bottom: 8px; }
|
||||
.card { background: var(--panel); border: 1px solid var(--border); border-radius: 8px; padding: 14px; }
|
||||
.card-sm { background: var(--surface); border: 1px solid var(--border); border-radius: 6px; padding: 10px; }
|
||||
|
||||
/* ── Responsive: narrow screens ── */
|
||||
@media (max-width: 640px) {
|
||||
|
||||
+1
-17
@@ -1,21 +1,5 @@
|
||||
import { useState, useRef, useCallback, useMemo } from "react";
|
||||
|
||||
// ── Design tokens ──────────────────────────────────
|
||||
const T = {
|
||||
bg: "#0A0A0C",
|
||||
panel: "#141418",
|
||||
surface: "#1C1C22",
|
||||
border: "#2A2A32",
|
||||
amber: "#E8A030",
|
||||
amberDim: "#7A5218",
|
||||
blue: "#4A8BC8",
|
||||
blueDim: "#1E4060",
|
||||
green: "#3AB87A",
|
||||
red: "#E06060",
|
||||
textPrimary: "#F0EDE6",
|
||||
textSec: "#A0A0BC",
|
||||
textDim: "#7878A0",
|
||||
};
|
||||
import { T } from "./theme.js";
|
||||
|
||||
// ── Split type metadata ────────────────────────────
|
||||
const SPLIT_TYPES = {
|
||||
|
||||
+1
-17
@@ -1,21 +1,5 @@
|
||||
import { useState, useRef, useCallback, useMemo } from "react";
|
||||
|
||||
// ── Design tokens ──
|
||||
const T = {
|
||||
bg: "#0A0A0C",
|
||||
panel: "#141418",
|
||||
surface: "#1C1C22",
|
||||
border: "#2A2A32",
|
||||
amber: "#E8A030",
|
||||
amberDim: "#7A5218",
|
||||
blue: "#4A8BC8",
|
||||
blueDim: "#1E4060",
|
||||
green: "#3AB87A",
|
||||
red: "#E06060",
|
||||
textPrimary: "#F0EDE6",
|
||||
textSec: "#A0A0BC",
|
||||
textDim: "#7878A0",
|
||||
};
|
||||
import { T } from "./theme.js";
|
||||
|
||||
// ── Block param definitions (mirrored from App.jsx) ──
|
||||
const BLOCK_PARAMS = {
|
||||
|
||||
@@ -1,10 +1,5 @@
|
||||
import { useRef, useEffect } from "react";
|
||||
|
||||
const T = {
|
||||
bg: "#0A0A0C", panel: "#141418", surface: "#1C1C22", border: "#2A2A32",
|
||||
amber: "#E8A030", amberDim: "#7A5218", blue: "#4A8BC8", blueDim: "#1E4060",
|
||||
green: "#3AB87A", red: "#E06060", textPrimary: "#F0EDE6", textSec: "#A0A0BC", textDim: "#7878A0",
|
||||
};
|
||||
import { T } from "./theme.js";
|
||||
|
||||
const TYPE_COLORS = {
|
||||
overdrive: T.amber, drive: T.amber, distortion: T.red, fuzz: "#D060E0",
|
||||
|
||||
+1
-6
@@ -1,10 +1,5 @@
|
||||
import { useState, useRef, useCallback, useEffect } from "react";
|
||||
|
||||
const T = {
|
||||
bg: "#0A0A0C", panel: "#141418", surface: "#1C1C22", border: "#2A2A32",
|
||||
amber: "#E8A030", amberDim: "#7A5218", blue: "#4A8BC8", blueDim: "#1E4060",
|
||||
green: "#3AB87A", red: "#E06060", textPrimary: "#F0EDE6", textSec: "#A0A0BC", textDim: "#7878A0",
|
||||
};
|
||||
import { T } from "./theme.js";
|
||||
|
||||
// ── EQ Band definitions ──
|
||||
const EQ_BANDS = [
|
||||
|
||||
@@ -1,10 +1,5 @@
|
||||
import { useState, useCallback, useRef, useEffect, useMemo } from "react";
|
||||
|
||||
const T = {
|
||||
bg: "#0A0A0C", panel: "#141418", surface: "#1C1C22", border: "#2A2A32",
|
||||
amber: "#E8A030", amberDim: "#7A5218", blue: "#4A8BC8", blueDim: "#1E4060",
|
||||
green: "#3AB87A", red: "#E06060", textPrimary: "#F0EDE6", textSec: "#A0A0BC", textDim: "#7878A0",
|
||||
};
|
||||
import { useState, useRef, useEffect, useCallback, useMemo } from "react";
|
||||
import { T } from "./theme.js";
|
||||
|
||||
async function api(method, path, body) {
|
||||
const opts = { method, headers: { "Content-Type": "application/json" } };
|
||||
|
||||
+1
-6
@@ -1,10 +1,5 @@
|
||||
import { useRef, useEffect } from "react";
|
||||
|
||||
const T = {
|
||||
bg: "#0A0A0C", panel: "#141418", surface: "#1C1C22", border: "#2A2A32",
|
||||
amber: "#E8A030", amberDim: "#7A5218", blue: "#4A8BC8", blueDim: "#1E4060",
|
||||
green: "#3AB87A", red: "#E06060", textPrimary: "#F0EDE6", textSec: "#A0A0BC", textDim: "#7878A0",
|
||||
};
|
||||
import { T } from "./theme.js";
|
||||
|
||||
const MENU_ITEMS = [
|
||||
{ id: "save", label: "Save Preset", icon: "💾", desc: "Save current preset to bank" },
|
||||
|
||||
+1
-17
@@ -1,21 +1,5 @@
|
||||
import { useState, useEffect, useMemo, useCallback, useRef } from "react";
|
||||
|
||||
// ── Design tokens ──
|
||||
const T = {
|
||||
bg: "#0A0A0C",
|
||||
panel: "#141418",
|
||||
surface: "#1C1C22",
|
||||
border: "#2A2A32",
|
||||
amber: "#E8A030",
|
||||
amberDim: "#7A5218",
|
||||
blue: "#4A8BC8",
|
||||
blueDim: "#1E4060",
|
||||
green: "#3AB87A",
|
||||
red: "#E06060",
|
||||
textPrimary: "#F0EDE6",
|
||||
textSec: "#A0A0BC",
|
||||
textDim: "#7878A0",
|
||||
};
|
||||
import { T } from "./theme.js";
|
||||
|
||||
const IMG_PATH = (import.meta.env.BASE_URL || '/ui/') + 'img/';
|
||||
|
||||
|
||||
+1
-8
@@ -1,12 +1,5 @@
|
||||
import { useState, useEffect, useRef, useCallback } from "react";
|
||||
|
||||
// ── Design tokens (mirrored) ──────────────────────────────────
|
||||
const T = {
|
||||
bg: "#0A0A0C", panel: "#141418", surface: "#1C1C22", border: "#2A2A32",
|
||||
amber: "#E8A030", amberDim: "#7A5218", blue: "#4A8BC8",
|
||||
green: "#3AB87A", red: "#E06060", textPrimary: "#F0EDE6",
|
||||
textSec: "#A0A0BC", textDim: "#7878A0",
|
||||
};
|
||||
import { T } from "./theme.js";
|
||||
|
||||
// ── String labels matching _STRING_NAMES ──────────────────────
|
||||
const STRING_LABELS = [
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
/**
|
||||
* theme.js — Shared design tokens
|
||||
*
|
||||
* Single source of truth: CSS custom properties in index.css :root {}
|
||||
* This module reads them at load time so JS components use the same
|
||||
* values as the stylesheet. To theme the app, override the CSS vars.
|
||||
*/
|
||||
|
||||
function v(name) {
|
||||
return getComputedStyle(document.documentElement).getPropertyValue(name).trim();
|
||||
}
|
||||
|
||||
export const T = {
|
||||
bg: v('--bg'),
|
||||
panel: v('--panel'),
|
||||
surface: v('--surface'),
|
||||
border: v('--border'),
|
||||
amber: v('--amber'),
|
||||
amberDim: v('--amber-dim'),
|
||||
blue: v('--blue'),
|
||||
blueDim: v('--blue-dim'),
|
||||
green: v('--green'),
|
||||
red: v('--red'),
|
||||
textPrimary: v('--text-primary'),
|
||||
textSec: v('--text-sec'),
|
||||
textDim: v('--text-dim'),
|
||||
};
|
||||
Reference in New Issue
Block a user