From 2e91f3a1c1ac16d0fe6c527c793cea67dd981fc9 Mon Sep 17 00:00:00 2001 From: letieu Date: Wed, 10 Dec 2025 06:08:01 +0700 Subject: [PATCH] feat: implement theming system with persistence and add new themes --- index.css | 5 +- index.html | 25 +++++++-- index.js | 42 ++++++++++++-- installation.html | 109 +++++++++++++++++++++++++++++++++++- showcase.html | 19 ++++++- themes/ayu-dark.css | 25 +++++++++ themes/ayu-light.css | 25 +++++++++ themes/catppuccin-latte.css | 25 +++++++++ themes/catppuccin-mocha.css | 25 +++++++++ themes/default.css | 24 ++++++++ themes/dracula.css | 25 +++++++++ themes/gruvbox-dark.css | 25 +++++++++ themes/gruvbox-light.css | 25 +++++++++ themes/light.css | 24 ++++++++ themes/rose-pine-light.css | 25 +++++++++ themes/rose-pine.css | 25 +++++++++ 16 files changed, 457 insertions(+), 16 deletions(-) create mode 100644 themes/ayu-dark.css create mode 100644 themes/ayu-light.css create mode 100644 themes/catppuccin-latte.css create mode 100644 themes/catppuccin-mocha.css create mode 100644 themes/default.css create mode 100644 themes/dracula.css create mode 100644 themes/gruvbox-dark.css create mode 100644 themes/gruvbox-light.css create mode 100644 themes/light.css create mode 100644 themes/rose-pine-light.css create mode 100644 themes/rose-pine.css diff --git a/index.css b/index.css index 3035d1d..ca5ec03 100644 --- a/index.css +++ b/index.css @@ -835,7 +835,8 @@ ol.content li::before { } .progress::-webkit-progress-value { - background: var(--primary); + background: var. + --primary); } .progress::-moz-progress-bar { @@ -1221,4 +1222,4 @@ kbd { line-height: 1; padding: 2px 6px; white-space: nowrap; -} +} \ No newline at end of file diff --git a/index.html b/index.html index 4b023ae..d3085c9 100644 --- a/index.html +++ b/index.html @@ -6,16 +6,14 @@ terminal.css - Terminal CSS Component Library - + + - + @@ -28,7 +26,22 @@
dev@localhost:~/
-
v0.0.3
+
+ + +
diff --git a/index.js b/index.js index 8938b97..ed75e0e 100644 --- a/index.js +++ b/index.js @@ -69,10 +69,40 @@ function showToast(type, title, message, duration = 5000) { */ function dismissToast(closeButton) { const toast = closeButton.closest('.toast'); - toast.classList.add('is-dismissing'); - - // Remove from DOM after animation - setTimeout(() => { - toast.remove(); - }, 300); + if (toast) { + toast.classList.add('is-dismissing'); + + // Remove from DOM after animation + setTimeout(() => { + toast.remove(); + }, 300); + } } + +function initializeThemeSwitcher() { + const themeSelector = document.getElementById("theme-selector"); + const themeSwitcher = document.getElementById("theme-switcher"); + + if (!themeSwitcher) { + return; + } + + function applyTheme(theme) { + themeSwitcher.setAttribute("href", `themes/${theme}.css`); + localStorage.setItem("theme", theme); + if (themeSelector) { + themeSelector.value = theme; + } + } + + if (themeSelector) { + themeSelector.addEventListener("change", () => { + applyTheme(themeSelector.value); + }); + } + + const savedTheme = localStorage.getItem("theme") || "default"; + applyTheme(savedTheme); +} + +document.addEventListener("DOMContentLoaded", initializeThemeSwitcher); \ No newline at end of file diff --git a/installation.html b/installation.html index a4ed0ff..b2d6f41 100644 --- a/installation.html +++ b/installation.html @@ -7,6 +7,7 @@ + @@ -27,7 +28,22 @@
dev@localhost:~/tcss/installation
-
v0.0.3
+
+ + +
@@ -391,6 +407,97 @@ + +
+
+ 04. +

Theming

+
+ +
+

+ terminal.css includes a theming system that allows you to easily switch between different color schemes. The selected theme is persisted across pages using the browser's localStorage. +

+ +

How to use themes:

+
    +
  1. + Include the main index.css stylesheet and then a theme stylesheet in your <head> section. The theme stylesheet must have the ID theme-switcher. +
  2. +
+ +
+
+ <!-- In your <head> section --> +
+
+ <link rel="stylesheet" href="./index.css" /> +
+
+ <link rel="stylesheet" href="themes/default.css" id="theme-switcher" /> +
+
+ +

+ To enable theme switching and persistence, include the index.js script at the end of your <body> tag. This script contains the necessary logic to manage themes. +

+ +
+
+ <!-- Before closing </body> tag --> +
+
+ <script src="./index.js"></script> +
+
+ +

+ You can then add a theme selector dropdown to your HTML, like this: +

+ +
+
+ <select id="theme-selector" class="select"> +
+
+   <option value="default">Default</option> +
+
+   <option value="dracula">Dracula</option> +
+
+   <option value="light">Light</option> +
+
+ </select> +
+
+

+ The value attribute of each option should match the filename of the theme (e.g., default for themes/default.css). +

+
+
+
diff --git a/showcase.html b/showcase.html index 1c416f0..2bc6c5e 100644 --- a/showcase.html +++ b/showcase.html @@ -7,6 +7,7 @@ + @@ -59,8 +60,24 @@

Terminal-style components with Bulma naming conventions

-
+
Get Started +
+ + +
diff --git a/themes/ayu-dark.css b/themes/ayu-dark.css new file mode 100644 index 0000000..50f201f --- /dev/null +++ b/themes/ayu-dark.css @@ -0,0 +1,25 @@ +:root { + --terminal-bg: #0A0E14; + --terminal-fg: #B3B1AD; + + /* ANSI Palette */ + --terminal-black: #01060E; + --terminal-red: #FF3333; + --terminal-green: #BAE67E; + --terminal-yellow: #FFD580; + --terminal-blue: #73D0FF; + --terminal-magenta: #D4BFFF; + --terminal-cyan: #5FD7FF; + --terminal-white: #D9D7CE; + --terminal-purple: #D4BFFF; + + /* Semantic Colors */ + --primary: var(--terminal-blue); + --danger: var(--terminal-red); + --success: var(--terminal-green); + --warning: var(--terminal-yellow); + --info: var(--terminal-cyan); + --border-color: #393b44; + --surface: #1F2229; + --muted: #5C6773; +} diff --git a/themes/ayu-light.css b/themes/ayu-light.css new file mode 100644 index 0000000..57f2e92 --- /dev/null +++ b/themes/ayu-light.css @@ -0,0 +1,25 @@ +:root { + --terminal-bg: #fafafa; + --terminal-fg: #5c6773; + + /* ANSI Palette */ + --terminal-black: #f0f0f0; + --terminal-red: #f51818; + --terminal-green: #5e8504; + --terminal-yellow: #f2ae00; + --terminal-blue: #36a3d9; + --terminal-magenta: #a37acc; + --terminal-cyan: #4cbf99; + --terminal-white: #5c6773; + --terminal-purple: #a37acc; + + /* Semantic Colors */ + --primary: var(--terminal-blue); + --danger: var(--terminal-red); + --success: var(--terminal-green); + --warning: var(--terminal-yellow); + --info: var(--terminal-cyan); + --border-color: #e6e6e6; + --surface: #f5f5f5; + --muted: #8a9199; +} diff --git a/themes/catppuccin-latte.css b/themes/catppuccin-latte.css new file mode 100644 index 0000000..82eec54 --- /dev/null +++ b/themes/catppuccin-latte.css @@ -0,0 +1,25 @@ +:root { + --terminal-bg: #eff1f5; + --terminal-fg: #4c4f69; + + /* ANSI Palette */ + --terminal-black: #ccd0da; + --terminal-red: #d20f39; + --terminal-green: #40a02b; + --terminal-yellow: #df8e1d; + --terminal-blue: #1e66f5; + --terminal-magenta: #8839ef; + --terminal-cyan: #04a5e5; + --terminal-white: #4c4f69; + --terminal-purple: #8839ef; + + /* Semantic Colors */ + --primary: var(--terminal-blue); + --danger: var(--terminal-red); + --success: var(--terminal-green); + --warning: var(--terminal-yellow); + --info: var(--terminal-cyan); + --border-color: #bcc0cc; + --surface: #e6e9ef; + --muted: #acb0be; +} diff --git a/themes/catppuccin-mocha.css b/themes/catppuccin-mocha.css new file mode 100644 index 0000000..b1d33a4 --- /dev/null +++ b/themes/catppuccin-mocha.css @@ -0,0 +1,25 @@ +:root { + --terminal-bg: #1e1e2e; + --terminal-fg: #cdd6f4; + + /* ANSI Palette */ + --terminal-black: #45475a; + --terminal-red: #f38ba8; + --terminal-green: #a6e3a1; + --terminal-yellow: #f9e2af; + --terminal-blue: #89b4fa; + --terminal-magenta: #cba6f7; + --terminal-cyan: #89dceb; + --terminal-white: #bac2de; + --terminal-purple: #cba6f7; + + /* Semantic Colors */ + --primary: var(--terminal-blue); + --danger: var(--terminal-red); + --success: var(--terminal-green); + --warning: var(--terminal-yellow); + --info: var(--terminal-cyan); + --border-color: #585b70; + --surface: #313244; + --muted: #a6adc8; +} diff --git a/themes/default.css b/themes/default.css new file mode 100644 index 0000000..3c34944 --- /dev/null +++ b/themes/default.css @@ -0,0 +1,24 @@ +:root { + --terminal-bg: #050505; + --terminal-fg: #cccccc; + + /* ANSI Palette */ + --terminal-black: #000000; + --terminal-red: #ff5555; + --terminal-green: #50fa7b; + --terminal-yellow: #f1fa8c; + --terminal-blue: #bd93f9; + --terminal-magenta: #ff79c6; + --terminal-cyan: #8be9fd; + --terminal-white: #ffffff; + + /* Semantic Colors */ + --primary: var(--terminal-cyan); + --danger: var(--terminal-red); + --success: var(--terminal-green); + --warning: var(--terminal-yellow); + --info: var(--terminal-blue); + --border-color: #333333; + --surface: #000000; + --muted: #666666; +} diff --git a/themes/dracula.css b/themes/dracula.css new file mode 100644 index 0000000..6e90ec6 --- /dev/null +++ b/themes/dracula.css @@ -0,0 +1,25 @@ +:root { + --terminal-bg: #282a36; + --terminal-fg: #f8f8f2; + + /* ANSI Palette */ + --terminal-black: #000000; + --terminal-red: #ff5555; + --terminal-green: #50fa7b; + --terminal-yellow: #f1fa8c; + --terminal-blue: #bd93f9; + --terminal-magenta: #ff79c6; + --terminal-cyan: #8be9fd; + --terminal-white: #f8f8f2; + --terminal-purple: #bd93f9; + + /* Semantic Colors */ + --primary: var(--terminal-purple); + --danger: var(--terminal-red); + --success: var(--terminal-green); + --warning: var(--terminal-yellow); + --info: var(--terminal-cyan); + --border-color: #44475a; + --surface: #282a36; + --muted: #6272a4; +} diff --git a/themes/gruvbox-dark.css b/themes/gruvbox-dark.css new file mode 100644 index 0000000..4f5f389 --- /dev/null +++ b/themes/gruvbox-dark.css @@ -0,0 +1,25 @@ +:root { + --terminal-bg: #282828; + --terminal-fg: #ebdbb2; + + /* ANSI Palette */ + --terminal-black: #282828; + --terminal-red: #cc241d; + --terminal-green: #98971a; + --terminal-yellow: #d79921; + --terminal-blue: #458588; + --terminal-magenta: #b16286; + --terminal-cyan: #689d6a; + --terminal-white: #a89984; + --terminal-purple: #b16286; + + /* Semantic Colors */ + --primary: var(--terminal-blue); + --danger: var(--terminal-red); + --success: var(--terminal-green); + --warning: var(--terminal-yellow); + --info: var(--terminal-cyan); + --border-color: #504945; + --surface: #3c3836; + --muted: #928374; +} diff --git a/themes/gruvbox-light.css b/themes/gruvbox-light.css new file mode 100644 index 0000000..1b4eee6 --- /dev/null +++ b/themes/gruvbox-light.css @@ -0,0 +1,25 @@ +:root { + --terminal-bg: #fbf1c7; + --terminal-fg: #3c3836; + + /* ANSI Palette */ + --terminal-black: #fbf1c7; + --terminal-red: #9d0006; + --terminal-green: #79740e; + --terminal-yellow: #b57614; + --terminal-blue: #076678; + --terminal-magenta: #8f3f71; + --terminal-cyan: #427b58; + --terminal-white: #3c3836; + --terminal-purple: #8f3f71; + + /* Semantic Colors */ + --primary: var(--terminal-blue); + --danger: var(--terminal-red); + --success: var(--terminal-green); + --warning: var(--terminal-yellow); + --info: var(--terminal-cyan); + --border-color: #d5c4a1; + --surface: #ebdbb2; + --muted: #7c6f64; +} diff --git a/themes/light.css b/themes/light.css new file mode 100644 index 0000000..93f5eac --- /dev/null +++ b/themes/light.css @@ -0,0 +1,24 @@ +:root { + --terminal-bg: #f5f5f5; + --terminal-fg: #333333; + + /* ANSI Palette */ + --terminal-black: #000000; + --terminal-red: #dc3545; + --terminal-green: #28a745; + --terminal-yellow: #ffc107; + --terminal-blue: #007bff; + --terminal-magenta: #e83e8c; + --terminal-cyan: #17a2b8; + --terminal-white: #ffffff; + + /* Semantic Colors */ + --primary: var(--terminal-blue); + --danger: var(--terminal-red); + --success: var(--terminal-green); + --warning: var(--terminal-yellow); + --info: var(--terminal-cyan); + --border-color: #dddddd; + --surface: #ffffff; + --muted: #6c757d; +} diff --git a/themes/rose-pine-light.css b/themes/rose-pine-light.css new file mode 100644 index 0000000..81244c4 --- /dev/null +++ b/themes/rose-pine-light.css @@ -0,0 +1,25 @@ +:root { + --terminal-bg: #faf4ed; + --terminal-fg: #575279; + + /* ANSI Palette */ + --terminal-black: #f2e9de; + --terminal-red: #d7827e; + --terminal-green: #286983; + --terminal-yellow: #ea9d34; + --terminal-blue: #56949f; + --terminal-magenta: #907aa9; + --terminal-cyan: #d7827e; + --terminal-white: #575279; + --terminal-purple: #907aa9; + + /* Semantic Colors */ + --primary: var(--terminal-blue); + --danger: var(--terminal-red); + --success: var(--terminal-green); + --warning: var(--terminal-yellow); + --info: var(--terminal-cyan); + --border-color: #e4e2e0; + --surface: #fffaf3; + --muted: #9893a5; +} diff --git a/themes/rose-pine.css b/themes/rose-pine.css new file mode 100644 index 0000000..4e48e12 --- /dev/null +++ b/themes/rose-pine.css @@ -0,0 +1,25 @@ +:root { + --terminal-bg: #191724; + --terminal-fg: #e0def4; + + /* ANSI Palette */ + --terminal-black: #26233a; + --terminal-red: #eb6f92; + --terminal-green: #31748f; + --terminal-yellow: #f6c177; + --terminal-blue: #9ccfd8; + --terminal-magenta: #c4a7e7; + --terminal-cyan: #ebbcba; + --terminal-white: #e0def4; + --terminal-purple: #c4a7e7; + + /* Semantic Colors */ + --primary: var(--terminal-blue); + --danger: var(--terminal-red); + --success: var(--terminal-green); + --warning: var(--terminal-yellow); + --info: var(--terminal-cyan); + --border-color: #555169; + --surface: #1f1d2e; + --muted: #6e6a86; +}