diff --git a/index.html b/index.html
index f40787d..8406a6b 100644
--- a/index.html
+++ b/index.html
@@ -72,22 +72,51 @@
-
Color Schema Presets
-
+
Color Schema Presets (light)
+
+
+
+
+
+
Color Schema Presets (dark)
+
+
+
+
-
Background
-
+
Background (dark)
+
-
Foreground
-
+
Foreground (dark)
+
-
Accent
-
+
Accent (dark)
+
+
+
+
diff --git a/modules/components.js b/modules/components.js
index 7544d48..bc030dc 100644
--- a/modules/components.js
+++ b/modules/components.js
@@ -13,13 +13,35 @@ export class Standalone {
}
updateVariables() {
+ // Get light theme values (use names without '-light' suffix for standalone)
+ const bgLight = this.formData.get("background-light") || defaultValues["background"];
+ const fgLight = this.formData.get("foreground-light") || defaultValues["foreground"];
+ const accentLight = this.formData.get("accent-light") || defaultValues["accent"];
+
+ // Get dark theme values
+ const bgDark = this.formData.get("background-dark") || bgLight; // Default dark to light if not provided
+ const fgDark = this.formData.get("foreground-dark") || fgLight;
+ const accentDark = this.formData.get("accent-dark") || accentLight;
+
+ // Construct the hybrid CSS variables block
const variables = `:root {
- --background: ${this.formData.get("background")};
- --foreground: ${this.formData.get("foreground")};
- --accent: ${this.formData.get("accent")};
+ --background: ${bgLight};
+ --foreground: ${fgLight};
+ --accent: ${accentLight};
--radius: ${defaultValues["radius"]};
--font-size: ${defaultValues["fontSize"]};
--line-height: ${defaultValues["lineHeight"]};
+}
+
+@media (prefers-color-scheme: dark) {
+ :root {
+ --background: ${bgDark};
+ --foreground: ${fgDark};
+ --accent: ${accentDark};
+ --radius: ${defaultValues["radius"]};
+ --font-size: ${defaultValues["fontSize"]};
+ --line-height: ${defaultValues["lineHeight"]};
+ }
}`;
this.styles = this.styles.replace(components.variables, variables.trim());
return this;
@@ -93,11 +115,31 @@ export class TerminalTheme {
}
updateVariables() {
+ // Get light theme values
+ const bgLight = this.formData.get("background-light") || defaultValues["background"];
+ const fgLight = this.formData.get("foreground-light") || defaultValues["foreground"];
+ const accentLight = this.formData.get("accent-light") || defaultValues["accent"];
+
+ // Get dark theme values
+ const bgDark = this.formData.get("background-dark") || bgLight; // Default dark to light if not provided
+ const fgDark = this.formData.get("foreground-dark") || fgLight;
+ const accentDark = this.formData.get("accent-dark") || accentLight;
+
+ // Construct the hybrid CSS variables block
const variables = `:root {
- --background: ${this.formData.get("background")};
- --foreground: ${this.formData.get("foreground")};
- --accent: ${this.formData.get("accent")};
+ --background: ${bgLight};
+ --foreground: ${fgLight};
+ --accent: ${accentLight};
+}
+
+@media (prefers-color-scheme: dark) {
+ :root {
+ --background: ${bgDark};
+ --foreground: ${fgDark};
+ --accent: ${accentDark};
+ }
}`;
+ // Replace the placeholder in the base styles
this.styles = this.styles.replace(components.variables, variables.trim());
return this;
}
diff --git a/modules/presets.js b/modules/presets.js
index 3e7d872..175b106 100644
--- a/modules/presets.js
+++ b/modules/presets.js
@@ -1,45 +1,89 @@
import { isDark } from "./helpers.js";
-export const presetsInput = document.querySelector("#presets");
+// Get references to both preset dropdowns
+const presetsInputLight = document.querySelector("#presets-light");
+const presetsInputDark = document.querySelector("#presets-dark");
+const colorInputsLight = {
+ background: document.querySelector('input[name="background-light"]'),
+ foreground: document.querySelector('input[name="foreground-light"]'),
+ accent: document.querySelector('input[name="accent-light"]'),
+};
+const colorInputsDark = {
+ background: document.querySelector('input[name="background-dark"]'),
+ foreground: document.querySelector('input[name="foreground-dark"]'),
+ accent: document.querySelector('input[name="accent-dark"]'),
+};
+
const res = await fetch("./presets.json");
const presets = await res.json();
-// At the moment it takes less than 1ms to create a grouped list of presets.
-// If it gets worse over time, I'll rewrite it.
-const presetsList = [];
-for (const [k, v] of Object.entries(presets)) {
- const entry = v;
- entry.name = k;
- presetsList.push(entry);
-}
+// Populate function
+function populatePresets(selectElement) {
+ // Add a default "Select Preset..." option
+ const defaultOption = new Option("Select Preset...", "");
+ defaultOption.disabled = true;
+ defaultOption.selected = true;
+ selectElement.add(defaultOption);
-const grouped = Object.groupBy(presetsList, ({ background }) => {
- return isDark(background) ? "Dark" : "Light";
-});
+ const presetsList = [];
+ for (const [k, v] of Object.entries(presets)) {
+ const entry = { ...v, name: k }; // Clone and add name
+ presetsList.push(entry);
+ }
-for (const [group, p] of Object.entries(grouped)) {
- const groupOption = new Option(group, group);
- groupOption.disabled = true;
- presetsInput.add(groupOption, undefined);
+ const grouped = Object.groupBy(presetsList, ({ background }) => {
+ return isDark(background) ? "Dark" : "Light";
+ });
- for (const v of p) {
- const option = new Option(v.name, v.name);
- presetsInput.add(option, undefined);
+ // Ensure consistent group order (Light first)
+ const groupOrder = ["Light", "Dark"];
+ for (const group of groupOrder) {
+ if (grouped[group]) {
+ const groupOption = new Option(group, group);
+ groupOption.disabled = true;
+ selectElement.add(groupOption, undefined);
+
+ for (const v of grouped[group]) {
+ const option = new Option(v.name, v.name);
+ selectElement.add(option, undefined);
+ }
+ }
}
}
-// -----------------------------------------------------------------------------
-const root = document.querySelector(":root");
-const settings = document.querySelectorAll("#settings input");
+// Populate both dropdowns
+populatePresets(presetsInputLight);
+populatePresets(presetsInputDark);
-presetsInput.addEventListener("change", e => {
- const preset = presets[e.currentTarget.value];
+// Event listener for light presets
+presetsInputLight.addEventListener("change", e => {
+ const presetName = e.currentTarget.value;
+ if (!presetName || !presets[presetName]) return; // Ignore if default or invalid
- for (const i of settings) {
- if (preset[i.name]) {
- i.value = preset[i.name];
- root.style.setProperty(`--${i.name}`, preset[i.name]);
- }
+ const preset = presets[presetName];
+ if (preset.background) colorInputsLight.background.value = preset.background;
+ if (preset.foreground) colorInputsLight.foreground.value = preset.foreground;
+ if (preset.accent) colorInputsLight.accent.value = preset.accent;
+
+ // Trigger live preview update (function defined in script.js)
+ if (window.updateLivePreview) {
+ window.updateLivePreview();
+ }
+});
+
+// Event listener for dark presets
+presetsInputDark.addEventListener("change", e => {
+ const presetName = e.currentTarget.value;
+ if (!presetName || !presets[presetName]) return; // Ignore if default or invalid
+
+ const preset = presets[presetName];
+ if (preset.background) colorInputsDark.background.value = preset.background;
+ if (preset.foreground) colorInputsDark.foreground.value = preset.foreground;
+ if (preset.accent) colorInputsDark.accent.value = preset.accent;
+
+ // Trigger live preview update (function defined in script.js)
+ if (window.updateLivePreview) {
+ window.updateLivePreview();
}
});
diff --git a/script.js b/script.js
index 6a8eff4..d40c2b0 100644
--- a/script.js
+++ b/script.js
@@ -7,18 +7,64 @@ import "./modules/presets.js";
// Init ------------------------------------------------------------------------
const root = document.querySelector(":root");
-const settings = document.querySelectorAll("#settings input");
-for (const i of settings) {
- if (defaultValues[i.name]) {
- i.value = defaultValues[i.name];
- }
+// Get references to all relevant inputs once
+const colorInputsLight = {
+ background: document.querySelector('input[name="background-light"]'),
+ foreground: document.querySelector('input[name="foreground-light"]'),
+ accent: document.querySelector('input[name="accent-light"]'),
+};
+const colorInputsDark = {
+ background: document.querySelector('input[name="background-dark"]'),
+ foreground: document.querySelector('input[name="foreground-dark"]'),
+ accent: document.querySelector('input[name="accent-dark"]'),
+};
+const previewThemeRadios = document.querySelectorAll('input[name="preview-theme"]');
+const headingStyleSelect = document.querySelector('select[name="headingStyle"]');
+const fontFamilySelect = document.querySelector('select[name="fontFamily"]');
+
+// Set initial default values for color inputs
+if (defaultValues["background"]) colorInputsLight.background.value = defaultValues["background"];
+if (defaultValues["foreground"]) colorInputsLight.foreground.value = defaultValues["foreground"];
+if (defaultValues["accent"]) colorInputsLight.accent.value = defaultValues["accent"];
+// Optionally set defaults for dark theme as well, or leave them empty/black/white
+// For now, let's mirror the light theme defaults initially
+if (defaultValues["background"]) colorInputsDark.background.value = defaultValues["background"];
+if (defaultValues["foreground"]) colorInputsDark.foreground.value = defaultValues["foreground"];
+if (defaultValues["accent"]) colorInputsDark.accent.value = defaultValues["accent"];
+
+// Set other defaults if they exist in defaultValues
+if (headingStyleSelect && defaultValues[headingStyleSelect.name]) {
+ headingStyleSelect.value = defaultValues[headingStyleSelect.name];
}
+if (fontFamilySelect && defaultValues[fontFamilySelect.name]) {
+ fontFamilySelect.value = defaultValues[fontFamilySelect.name];
+}
+
// -----------------------------------------------------------------------------
-function setVariable(variable, value) {
- root.style.setProperty(variable, value);
+// Live Preview Update Function
+function updateLivePreview() {
+ const selectedTheme = document.querySelector('input[name="preview-theme"]:checked').value;
+ let sourceInputs;
+
+ if (selectedTheme === 'dark') {
+ sourceInputs = colorInputsDark;
+ } else {
+ sourceInputs = colorInputsLight;
+ }
+
+ root.style.setProperty('--background', sourceInputs.background.value);
+ root.style.setProperty('--foreground', sourceInputs.foreground.value);
+ root.style.setProperty('--accent', sourceInputs.accent.value);
+
+ // Note: Other variables like --radius, --font-size, --line-height are not
+ // dynamically updated in this preview but will be included in the download.
+ // If previewing them is needed, this function would need expansion.
}
-window.setVariable = setVariable;
+window.updateLivePreview = updateLivePreview; // Make it globally accessible
+
+// Initial preview update on load
+updateLivePreview();
// Submit Download
const form = document.querySelector("#settings");