You've already forked wp-bootstrap
v0.1.0 - Core Theme: patterns, dark mode, block styles, style variations
- Add 16 block patterns across 7 new categories (hero, features, CTA, testimonials, pricing, contact, text) - Add dark mode toggle with localStorage persistence and system preference detection (Bootstrap 5.3 data-bs-theme) - Register 17 custom block styles mapping Bootstrap components to WordPress blocks (cards, alerts, tables, buttons, etc.) - Add 4 style variations: Ocean, Forest, Sunset, Midnight - Add sidebar template part and "Blog with Sidebar" custom template - Add Inter and Lora variable fonts with fontFace declarations - Add Display font size (fluid 2.5rem-3.5rem) - Update translations (en_US .pot, de_CH .po) with all new strings - Bump version to 0.1.0 Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
74
src/js/dark-mode.js
Normal file
74
src/js/dark-mode.js
Normal file
@@ -0,0 +1,74 @@
|
||||
/**
|
||||
* WP Bootstrap Dark Mode Toggle
|
||||
*
|
||||
* Handles dark mode switching using Bootstrap 5.3's data-bs-theme attribute.
|
||||
* Respects prefers-color-scheme media query and persists choice in localStorage.
|
||||
*
|
||||
* @package WPBootstrap
|
||||
* @since 0.1.0
|
||||
*/
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
var STORAGE_KEY = 'wp-bootstrap-theme';
|
||||
var ATTR = 'data-bs-theme';
|
||||
|
||||
/**
|
||||
* Get the user's stored preference, or fall back to system preference.
|
||||
*
|
||||
* @return {string} 'dark' or 'light'
|
||||
*/
|
||||
function getPreferredTheme() {
|
||||
var stored = localStorage.getItem(STORAGE_KEY);
|
||||
if (stored) {
|
||||
return stored;
|
||||
}
|
||||
return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the theme to the document and update all toggle buttons.
|
||||
*
|
||||
* @param {string} theme - 'dark' or 'light'
|
||||
*/
|
||||
function setTheme(theme) {
|
||||
document.documentElement.setAttribute(ATTR, theme);
|
||||
|
||||
document.querySelectorAll('[data-bs-theme-toggle]').forEach(function (toggle) {
|
||||
var isDark = theme === 'dark';
|
||||
toggle.setAttribute('aria-label', isDark
|
||||
? (toggle.dataset.labelLight || 'Switch to light mode')
|
||||
: (toggle.dataset.labelDark || 'Switch to dark mode'));
|
||||
toggle.setAttribute('aria-pressed', String(isDark));
|
||||
|
||||
var sunIcon = toggle.querySelector('.wp-bootstrap-sun-icon');
|
||||
var moonIcon = toggle.querySelector('.wp-bootstrap-moon-icon');
|
||||
if (sunIcon) sunIcon.style.display = isDark ? 'inline-block' : 'none';
|
||||
if (moonIcon) moonIcon.style.display = isDark ? 'none' : 'inline-block';
|
||||
});
|
||||
}
|
||||
|
||||
// Apply theme immediately to prevent flash.
|
||||
setTheme(getPreferredTheme());
|
||||
|
||||
// When DOM is ready, re-apply for toggle buttons and attach event listeners.
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
setTheme(getPreferredTheme());
|
||||
|
||||
document.querySelectorAll('[data-bs-theme-toggle]').forEach(function (toggle) {
|
||||
toggle.addEventListener('click', function () {
|
||||
var currentTheme = document.documentElement.getAttribute(ATTR);
|
||||
var newTheme = currentTheme === 'dark' ? 'light' : 'dark';
|
||||
localStorage.setItem(STORAGE_KEY, newTheme);
|
||||
setTheme(newTheme);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// Listen for system preference changes when no stored preference exists.
|
||||
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', function (e) {
|
||||
if (!localStorage.getItem(STORAGE_KEY)) {
|
||||
setTheme(e.matches ? 'dark' : 'light');
|
||||
}
|
||||
});
|
||||
})();
|
||||
@@ -1,2 +1,59 @@
|
||||
// Custom theme styles
|
||||
// Add theme-specific styles here that go beyond Bootstrap defaults
|
||||
|
||||
// Dark mode toggle button
|
||||
.wp-bootstrap-dark-mode-toggle {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: none;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
padding: 0.375rem;
|
||||
color: currentColor;
|
||||
line-height: 1;
|
||||
transition: opacity 0.15s ease-in-out;
|
||||
|
||||
&:hover {
|
||||
opacity: 0.75;
|
||||
}
|
||||
|
||||
&:focus-visible {
|
||||
outline: 2px solid currentColor;
|
||||
outline-offset: 2px;
|
||||
border-radius: 0.25rem;
|
||||
}
|
||||
}
|
||||
|
||||
// Dark mode overrides for block styles with hardcoded colors
|
||||
[data-bs-theme="dark"] {
|
||||
.is-style-alert-info {
|
||||
background-color: #032830;
|
||||
border-color: #055160;
|
||||
color: #6edff6;
|
||||
}
|
||||
|
||||
.is-style-alert-success {
|
||||
background-color: #051b11;
|
||||
border-color: #0a3622;
|
||||
color: #75b798;
|
||||
}
|
||||
|
||||
.is-style-alert-warning {
|
||||
background-color: #332701;
|
||||
border-color: #664d03;
|
||||
color: #ffda6a;
|
||||
}
|
||||
|
||||
.is-style-alert-danger {
|
||||
background-color: #2c0b0e;
|
||||
border-color: #58151c;
|
||||
color: #ea868f;
|
||||
}
|
||||
|
||||
.is-style-card,
|
||||
.is-style-card-shadow {
|
||||
border-color: $gray-600;
|
||||
background: var(--bs-body-bg);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,6 +35,10 @@ $container-max-widths: (
|
||||
// Typography - using system fonts (matching theme.json)
|
||||
$font-family-sans-serif: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", "Liberation Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
|
||||
|
||||
// Additional font families
|
||||
$font-family-inter: Inter, system-ui, -apple-system, sans-serif;
|
||||
$font-family-serif: Lora, Georgia, "Times New Roman", serif;
|
||||
|
||||
// Enable dark mode
|
||||
$enable-dark-mode: true;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user