diff --git a/README.md b/README.md index f7ae954..ffe99ac 100644 --- a/README.md +++ b/README.md @@ -57,6 +57,7 @@ MokoCassiopeia is a modern, lightweight enhancement layer built on top of Joomla - **Dark Mode Support**: Built-in light/dark mode toggle with system preference detection - **Color Palettes**: Standard, Alternative, and Custom color schemes +- **Parameter-Based Colors**: Edit key brand colors directly in template settings (no CSS files required) - **Theme Persistence**: User preferences saved via localStorage - **Theme Control Options**: Switch, radio buttons, or hidden controls - **Auto Dark Mode**: Optional automatic dark mode based on time/system settings @@ -69,6 +70,7 @@ MokoCassiopeia is a modern, lightweight enhancement layer built on top of Joomla - **Font Options**: Local and web fonts (Roboto, Fira Sans, Noto Sans) - **Sticky Header**: Optional sticky navigation - **Back to Top**: Floating back-to-top button +- **400+ CSS Variables**: Complete control over colors, spacing, and styling ### Analytics & Tracking @@ -164,6 +166,22 @@ Access template configuration via **System → Site Templates → MokoCassiopeia - **Light Mode Palette**: Standard, Alternative, or Custom - **Dark Mode Palette**: Standard, Alternative, or Custom +**Custom Colors - Light Mode:** +- **Brand Primary Color**: Main brand color throughout the template +- **Accent Primary Color**: Accent color for highlights and interactive elements +- **Navigation Background**: Background color for the main navigation menu +- **Navigation Link Color**: Text color for navigation links +- **Body Background**: Main page background color +- **Body Text Color**: Default text color for body content +- **Link Color**: Color for regular hyperlinks +- **Link Hover Color**: Color for hyperlinks on hover +- **Bootstrap Primary Color**: Bootstrap primary color for buttons, alerts, and components + +**Custom Colors - Dark Mode:** +- Same 9 color options as Light Mode, but optimized for dark backgrounds + +> **Note**: Custom color parameters override values from color palette CSS files. Leave fields blank to use palette defaults. Changes apply immediately when you save the template. + **Typography:** - **Font Scheme**: Local (Roboto) or Web fonts (Fira Sans, Roboto+Noto Sans) diff --git a/docs/CLIENT_FORK_WORKFLOW.md b/docs/CLIENT_FORK_WORKFLOW.md index 131ceaf..beba3d3 100644 --- a/docs/CLIENT_FORK_WORKFLOW.md +++ b/docs/CLIENT_FORK_WORKFLOW.md @@ -195,6 +195,58 @@ After running the workflow or script, you should: --- +## Color Customization Methods + +You now have **two ways** to customize colors for your client fork: + +### Method 1: Parameter-Based Customization (Recommended for Simple Branding) + +**Best for**: Quick brand color changes without editing CSS files + +1. Log into Joomla admin +2. Navigate to System → Site Templates → MokoCassiopeia +3. Click on the template name to edit +4. Go to the "Theme" tab +5. Scroll to "Custom Colours - Light Mode" and "Custom Colours - Dark Mode" sections +6. Use the color pickers to set: + - Brand Primary Color + - Accent Primary Color + - Navigation Background & Link Color + - Body Background & Text Color + - Link & Link Hover Colors + - Bootstrap Primary Color +7. Save the template + +**Advantages**: +- ✅ No CSS files to edit +- ✅ Visual color picker interface +- ✅ Changes apply immediately +- ✅ Easy to revert by clearing the fields +- ✅ No file management required + +**Limitations**: +- Only 9 essential colors per theme can be customized +- For advanced customization, use Method 2 + +### Method 2: CSS File Customization (Advanced) + +**Best for**: Complete control over all 400+ CSS variables + +1. Edit `src/media/css/colors/light/colors_custom.css` +2. Edit `src/media/css/colors/dark/colors_custom.css` +3. Update any of the 400+ CSS variables +4. Commit and deploy the changes + +**Advantages**: +- ✅ Complete control over all variables +- ✅ Can customize spacing, borders, shadows, etc. +- ✅ Supports complex color schemes +- ✅ Version controlled with your fork + +**Note**: Parameter-based colors (Method 1) will override CSS file colors (Method 2) if both are set. + +--- + ## Troubleshooting ### Workflow Fails with "CONFIRM" Error diff --git a/src/language/en-GB/tpl_mokocassiopeia.ini b/src/language/en-GB/tpl_mokocassiopeia.ini index 0eb9c00..a323293 100644 --- a/src/language/en-GB/tpl_mokocassiopeia.ini +++ b/src/language/en-GB/tpl_mokocassiopeia.ini @@ -111,6 +111,51 @@ TPL_MOKO_THEME_FAB_ENABLED_DESC="Display a persistent, accessible theme toggle." TPL_MOKO_THEME_FAB_POS="Floating switch position" TPL_MOKO_THEME_FAB_POS_DESC="Screen corner for the toggle." +; ===== Custom colour parameters ===== +TPL_MOKOCASSIOPEIA_CUSTOM_COLORS_LIGHT_LABEL="Custom Colours - Light Mode" +TPL_MOKOCASSIOPEIA_CUSTOM_COLORS_DARK_LABEL="Custom Colours - Dark Mode" +TPL_MOKOCASSIOPEIA_CUSTOM_COLORS_DESC="Override CSS colour variables with custom values below. Leave blank to use theme defaults. These settings override values from colour palette files. Changes apply immediately when you save the template." + +; Light mode colour fields +TPL_MOKOCASSIOPEIA_LIGHT_COLOR_PRIMARY_LABEL="Brand Primary Colour" +TPL_MOKOCASSIOPEIA_LIGHT_COLOR_PRIMARY_DESC="Main brand colour used throughout the template (CSS variable: --color-primary)" +TPL_MOKOCASSIOPEIA_LIGHT_ACCENT_PRIMARY_LABEL="Accent Primary Colour" +TPL_MOKOCASSIOPEIA_LIGHT_ACCENT_PRIMARY_DESC="Primary accent colour for highlights and interactive elements (CSS variable: --accent-color-primary)" +TPL_MOKOCASSIOPEIA_LIGHT_NAV_BG_LABEL="Navigation Background" +TPL_MOKOCASSIOPEIA_LIGHT_NAV_BG_DESC="Background colour for the main navigation menu (CSS variable: --nav-bg-color)" +TPL_MOKOCASSIOPEIA_LIGHT_NAV_LINK_LABEL="Navigation Link Colour" +TPL_MOKOCASSIOPEIA_LIGHT_NAV_LINK_DESC="Text colour for navigation links (CSS variable: --mainmenu-nav-link-color)" +TPL_MOKOCASSIOPEIA_LIGHT_BODY_BG_LABEL="Body Background" +TPL_MOKOCASSIOPEIA_LIGHT_BODY_BG_DESC="Main page background colour (CSS variable: --body-bg)" +TPL_MOKOCASSIOPEIA_LIGHT_BODY_COLOR_LABEL="Body Text Colour" +TPL_MOKOCASSIOPEIA_LIGHT_BODY_COLOR_DESC="Default text colour for body content (CSS variable: --body-color)" +TPL_MOKOCASSIOPEIA_LIGHT_LINK_COLOR_LABEL="Link Colour" +TPL_MOKOCASSIOPEIA_LIGHT_LINK_COLOR_DESC="Colour for regular hyperlinks (CSS variable: --link-color)" +TPL_MOKOCASSIOPEIA_LIGHT_LINK_HOVER_LABEL="Link Hover Colour" +TPL_MOKOCASSIOPEIA_LIGHT_LINK_HOVER_DESC="Colour for hyperlinks on hover (CSS variable: --link-hover-color)" +TPL_MOKOCASSIOPEIA_LIGHT_BS_PRIMARY_LABEL="Bootstrap Primary Colour" +TPL_MOKOCASSIOPEIA_LIGHT_BS_PRIMARY_DESC="Bootstrap primary colour for buttons, alerts, and components (CSS variable: --primary)" + +; Dark mode colour fields +TPL_MOKOCASSIOPEIA_DARK_COLOR_PRIMARY_LABEL="Brand Primary Colour" +TPL_MOKOCASSIOPEIA_DARK_COLOR_PRIMARY_DESC="Main brand colour used throughout the template (CSS variable: --color-primary)" +TPL_MOKOCASSIOPEIA_DARK_ACCENT_PRIMARY_LABEL="Accent Primary Colour" +TPL_MOKOCASSIOPEIA_DARK_ACCENT_PRIMARY_DESC="Primary accent colour for highlights and interactive elements (CSS variable: --accent-color-primary)" +TPL_MOKOCASSIOPEIA_DARK_NAV_BG_LABEL="Navigation Background" +TPL_MOKOCASSIOPEIA_DARK_NAV_BG_DESC="Background colour for the main navigation menu (CSS variable: --nav-bg-color)" +TPL_MOKOCASSIOPEIA_DARK_NAV_LINK_LABEL="Navigation Link Colour" +TPL_MOKOCASSIOPEIA_DARK_NAV_LINK_DESC="Text colour for navigation links (CSS variable: --mainmenu-nav-link-color)" +TPL_MOKOCASSIOPEIA_DARK_BODY_BG_LABEL="Body Background" +TPL_MOKOCASSIOPEIA_DARK_BODY_BG_DESC="Main page background colour (CSS variable: --body-bg)" +TPL_MOKOCASSIOPEIA_DARK_BODY_COLOR_LABEL="Body Text Colour" +TPL_MOKOCASSIOPEIA_DARK_BODY_COLOR_DESC="Default text colour for body content (CSS variable: --body-color)" +TPL_MOKOCASSIOPEIA_DARK_LINK_COLOR_LABEL="Link Colour" +TPL_MOKOCASSIOPEIA_DARK_LINK_COLOR_DESC="Colour for regular hyperlinks (CSS variable: --link-color)" +TPL_MOKOCASSIOPEIA_DARK_LINK_HOVER_LABEL="Link Hover Colour" +TPL_MOKOCASSIOPEIA_DARK_LINK_HOVER_DESC="Colour for hyperlinks on hover (CSS variable: --link-hover-color)" +TPL_MOKOCASSIOPEIA_DARK_BS_PRIMARY_LABEL="Bootstrap Primary Colour" +TPL_MOKOCASSIOPEIA_DARK_BS_PRIMARY_DESC="Bootstrap primary colour for buttons, alerts, and components (CSS variable: --primary)" + ; ===== Misc ===== MOD_BREADCRUMBS_HERE="YOU ARE HERE:" diff --git a/src/language/en-US/tpl_mokocassiopeia.ini b/src/language/en-US/tpl_mokocassiopeia.ini index 4c12993..01a3bdb 100644 --- a/src/language/en-US/tpl_mokocassiopeia.ini +++ b/src/language/en-US/tpl_mokocassiopeia.ini @@ -111,6 +111,51 @@ TPL_MOKO_THEME_FAB_ENABLED_DESC="Display a persistent, accessible theme toggle." TPL_MOKO_THEME_FAB_POS="Floating switch position" TPL_MOKO_THEME_FAB_POS_DESC="Screen corner for the toggle." +; ===== Custom color parameters ===== +TPL_MOKOCASSIOPEIA_CUSTOM_COLORS_LIGHT_LABEL="Custom Colors - Light Mode" +TPL_MOKOCASSIOPEIA_CUSTOM_COLORS_DARK_LABEL="Custom Colors - Dark Mode" +TPL_MOKOCASSIOPEIA_CUSTOM_COLORS_DESC="Override CSS color variables with custom values below. Leave blank to use theme defaults. These settings override values from color palette files. Changes apply immediately when you save the template." + +; Light mode color fields +TPL_MOKOCASSIOPEIA_LIGHT_COLOR_PRIMARY_LABEL="Brand Primary Color" +TPL_MOKOCASSIOPEIA_LIGHT_COLOR_PRIMARY_DESC="Main brand color used throughout the template (CSS variable: --color-primary)" +TPL_MOKOCASSIOPEIA_LIGHT_ACCENT_PRIMARY_LABEL="Accent Primary Color" +TPL_MOKOCASSIOPEIA_LIGHT_ACCENT_PRIMARY_DESC="Primary accent color for highlights and interactive elements (CSS variable: --accent-color-primary)" +TPL_MOKOCASSIOPEIA_LIGHT_NAV_BG_LABEL="Navigation Background" +TPL_MOKOCASSIOPEIA_LIGHT_NAV_BG_DESC="Background color for the main navigation menu (CSS variable: --nav-bg-color)" +TPL_MOKOCASSIOPEIA_LIGHT_NAV_LINK_LABEL="Navigation Link Color" +TPL_MOKOCASSIOPEIA_LIGHT_NAV_LINK_DESC="Text color for navigation links (CSS variable: --mainmenu-nav-link-color)" +TPL_MOKOCASSIOPEIA_LIGHT_BODY_BG_LABEL="Body Background" +TPL_MOKOCASSIOPEIA_LIGHT_BODY_BG_DESC="Main page background color (CSS variable: --body-bg)" +TPL_MOKOCASSIOPEIA_LIGHT_BODY_COLOR_LABEL="Body Text Color" +TPL_MOKOCASSIOPEIA_LIGHT_BODY_COLOR_DESC="Default text color for body content (CSS variable: --body-color)" +TPL_MOKOCASSIOPEIA_LIGHT_LINK_COLOR_LABEL="Link Color" +TPL_MOKOCASSIOPEIA_LIGHT_LINK_COLOR_DESC="Color for regular hyperlinks (CSS variable: --link-color)" +TPL_MOKOCASSIOPEIA_LIGHT_LINK_HOVER_LABEL="Link Hover Color" +TPL_MOKOCASSIOPEIA_LIGHT_LINK_HOVER_DESC="Color for hyperlinks on hover (CSS variable: --link-hover-color)" +TPL_MOKOCASSIOPEIA_LIGHT_BS_PRIMARY_LABEL="Bootstrap Primary Color" +TPL_MOKOCASSIOPEIA_LIGHT_BS_PRIMARY_DESC="Bootstrap primary color for buttons, alerts, and components (CSS variable: --primary)" + +; Dark mode color fields +TPL_MOKOCASSIOPEIA_DARK_COLOR_PRIMARY_LABEL="Brand Primary Color" +TPL_MOKOCASSIOPEIA_DARK_COLOR_PRIMARY_DESC="Main brand color used throughout the template (CSS variable: --color-primary)" +TPL_MOKOCASSIOPEIA_DARK_ACCENT_PRIMARY_LABEL="Accent Primary Color" +TPL_MOKOCASSIOPEIA_DARK_ACCENT_PRIMARY_DESC="Primary accent color for highlights and interactive elements (CSS variable: --accent-color-primary)" +TPL_MOKOCASSIOPEIA_DARK_NAV_BG_LABEL="Navigation Background" +TPL_MOKOCASSIOPEIA_DARK_NAV_BG_DESC="Background color for the main navigation menu (CSS variable: --nav-bg-color)" +TPL_MOKOCASSIOPEIA_DARK_NAV_LINK_LABEL="Navigation Link Color" +TPL_MOKOCASSIOPEIA_DARK_NAV_LINK_DESC="Text color for navigation links (CSS variable: --mainmenu-nav-link-color)" +TPL_MOKOCASSIOPEIA_DARK_BODY_BG_LABEL="Body Background" +TPL_MOKOCASSIOPEIA_DARK_BODY_BG_DESC="Main page background color (CSS variable: --body-bg)" +TPL_MOKOCASSIOPEIA_DARK_BODY_COLOR_LABEL="Body Text Color" +TPL_MOKOCASSIOPEIA_DARK_BODY_COLOR_DESC="Default text color for body content (CSS variable: --body-color)" +TPL_MOKOCASSIOPEIA_DARK_LINK_COLOR_LABEL="Link Color" +TPL_MOKOCASSIOPEIA_DARK_LINK_COLOR_DESC="Color for regular hyperlinks (CSS variable: --link-color)" +TPL_MOKOCASSIOPEIA_DARK_LINK_HOVER_LABEL="Link Hover Color" +TPL_MOKOCASSIOPEIA_DARK_LINK_HOVER_DESC="Color for hyperlinks on hover (CSS variable: --link-hover-color)" +TPL_MOKOCASSIOPEIA_DARK_BS_PRIMARY_LABEL="Bootstrap Primary Color" +TPL_MOKOCASSIOPEIA_DARK_BS_PRIMARY_DESC="Bootstrap primary color for buttons, alerts, and components (CSS variable: --primary)" + ; ===== Misc ===== MOD_BREADCRUMBS_HERE="YOU ARE HERE:" diff --git a/src/templates/index.php b/src/templates/index.php index 795669a..a4152b8 100644 --- a/src/templates/index.php +++ b/src/templates/index.php @@ -118,6 +118,112 @@ try { $wa->registerAndUseStyle('template.dark.dynamic', $templatePath . '/css/colors/dark/' . $colorDarkKey . '.css'); } +// Custom color parameters - generate inline CSS for color overrides +$customColorCSS = ''; + +/** + * Helper function to sanitize color values for CSS + * Accepts hex, rgb, rgba, hsl, hsla, and named colors + * + * Note: This function validates format but not value ranges (e.g., RGB 0-255). + * CSS will automatically clamp out-of-range values, so strict range validation + * is not necessary for security purposes. + * + * @param string $color The color value to sanitize + * @return string|null Sanitized color or null if invalid format + */ +$sanitizeColor = function($color) { + $color = trim($color); + if (empty($color)) { + return null; + } + + // Allow hex colors (#fff, #ffffff, #ffffffff) + if (preg_match('/^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$/', $color)) { + return strtolower($color); + } + + // Allow rgb/rgba + if (preg_match('/^rgba?\s*\(\s*\d{1,3}\s*,\s*\d{1,3}\s*,\s*\d{1,3}(\s*,\s*[\d.]+)?\s*\)$/i', $color)) { + return strtolower($color); + } + + // Allow hsl/hsla + if (preg_match('/^hsla?\s*\(\s*\d{1,3}\s*,\s*\d{1,3}%\s*,\s*\d{1,3}%(\s*,\s*[\d.]+)?\s*\)$/i', $color)) { + return strtolower($color); + } + + // Allow named colors (common CSS color names) + $namedColors = [ + 'transparent', 'black', 'white', 'red', 'green', 'blue', 'yellow', 'cyan', 'magenta', + 'gray', 'grey', 'silver', 'navy', 'teal', 'aqua', 'lime', 'olive', 'maroon', 'purple', 'fuchsia', + 'orange', 'pink', 'brown', 'gold', 'coral', 'crimson', 'indigo', 'violet', 'tan', 'khaki', + 'salmon', 'tomato', 'orchid', 'plum', 'lavender', 'ivory', 'beige', 'wheat', 'azure', 'snow' + ]; + if (in_array(strtolower($color), $namedColors, true)) { + return strtolower($color); + } + + return null; +}; + +/** + * Helper function to generate CSS overrides for a theme + * @param array $colorMap Array mapping parameter names to CSS variables + * @param string $theme Theme name ('light' or 'dark') + * @return string CSS rules or empty string + */ +$generateThemeCSS = function($colorMap, $theme) use ($sanitizeColor) { + $overrides = []; + foreach ($colorMap as $param => $cssVar) { + $value = $this->params->get($param, ''); + $sanitized = $sanitizeColor($value); + if ($sanitized !== null) { + $overrides[] = "\t" . $cssVar . ': ' . $sanitized . ';'; + } + } + + if (!empty($overrides)) { + return ":root[data-bs-theme='" . $theme . "'] {\n" . implode("\n", $overrides) . "\n}\n"; + } + + return ''; +}; + +// Define color mappings for light and dark modes +$lightColors = [ + 'light_color_primary' => '--color-primary', + 'light_accent_primary' => '--accent-color-primary', + 'light_nav_bg' => '--nav-bg-color', + 'light_nav_link' => '--mainmenu-nav-link-color', + 'light_body_bg' => '--body-bg', + 'light_body_color' => '--body-color', + 'light_link_color' => '--link-color', + 'light_link_hover' => '--link-hover-color', + 'light_bootstrap_primary' => '--primary', +]; + +$darkColors = [ + 'dark_color_primary' => '--color-primary', + 'dark_accent_primary' => '--accent-color-primary', + 'dark_nav_bg' => '--nav-bg-color', + 'dark_nav_link' => '--mainmenu-nav-link-color', + 'dark_body_bg' => '--body-bg', + 'dark_body_color' => '--body-color', + 'dark_link_color' => '--link-color', + 'dark_link_hover' => '--link-hover-color', + 'dark_bootstrap_primary' => '--primary', +]; + +// Generate CSS for both themes +$customColorCSS .= $generateThemeCSS($lightColors, 'light'); +$customColorCSS .= $generateThemeCSS($darkColors, 'dark'); + +// Add custom color CSS to document if any overrides are defined +if (!empty($customColorCSS)) { + $wa->addInlineStyle($customColorCSS); +} + // Scripts $wa->useScript('template.js'); diff --git a/src/templates/templateDetails.xml b/src/templates/templateDetails.xml index 646857b..27ebbbf 100644 --- a/src/templates/templateDetails.xml +++ b/src/templates/templateDetails.xml @@ -198,6 +198,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + +