diff --git a/administrator/components/com_users/forms/user.xml b/administrator/components/com_users/forms/user.xml index 1608607dc9554..9ed4ed6f24a8b 100644 --- a/administrator/components/com_users/forms/user.xml +++ b/administrator/components/com_users/forms/user.xml @@ -187,6 +187,19 @@ + + + + + + +
getTemplate(true)->params; +// Not all templates support a colorScheme +$colorSchemeSwitch = !!$tParams->get('colorScheme'); + // Load the Bootstrap Dropdown HTMLHelper::_('bootstrap.dropdown', '.dropdown-toggle'); ?>
diff --git a/build/media_source/plg_editors_codemirror/js/codemirror.es6.js b/build/media_source/plg_editors_codemirror/js/codemirror.es6.js index 0d06c56a85386..2fb8b5a8f4c26 100644 --- a/build/media_source/plg_editors_codemirror/js/codemirror.es6.js +++ b/build/media_source/plg_editors_codemirror/js/codemirror.es6.js @@ -105,8 +105,10 @@ const optionsToExtensions = async (options) => { readOnly.$j_name = 'readOnly'; extensions.push(readOnly.of(EditorState.readOnly.of(!!options.readOnly))); + // Check for a skin that suits best for the active color scheme // TODO: Use compartments to update on change of dark mode like: https://discuss.codemirror.net/t/dynamic-light-mode-dark-mode-how/4709 - if ('colorSchemeOs' in document.body.dataset && window.matchMedia('(prefers-color-scheme: dark)').matches) { + if (('colorSchemeOs' in document.documentElement.dataset && window.matchMedia('(prefers-color-scheme: dark)').matches) + || document.documentElement.dataset.colorScheme === 'dark') { extensions.push(oneDark); } diff --git a/build/media_source/plg_editors_tinymce/js/tinymce.es6.js b/build/media_source/plg_editors_tinymce/js/tinymce.es6.js index 235effdd9d785..4d00768df7079 100644 --- a/build/media_source/plg_editors_tinymce/js/tinymce.es6.js +++ b/build/media_source/plg_editors_tinymce/js/tinymce.es6.js @@ -155,17 +155,21 @@ Joomla.JoomlaTinyMCE = { options.target = element; } + // Check for a skin that suits best for the active color scheme const skinLight = options.skin_light; const skinDark = options.skin_dark; - - if ('colorSchemeOs' in document.body.dataset) { - options.skin = (window.matchMedia('(prefers-color-scheme: dark)').matches ? skinDark : skinLight); - } else { - options.skin = skinLight; - } - delete options.skin_light; delete options.skin_dark; + // Set light as default + options.skin = skinLight; + + // For templates with OS preferred color scheme + if ('colorSchemeOs' in document.documentElement.dataset) { + const mql = window.matchMedia('(prefers-color-scheme: dark)'); + options.skin = mql.matches ? skinDark : skinLight; + } else if (document.documentElement.dataset.colorScheme === 'dark') { + options.skin = skinDark; + } // Ensure tinymce is initialised in readonly mode if the textarea has readonly applied let readOnlyMode = false; diff --git a/build/media_source/templates/administrator/atum/js/template.es6.js b/build/media_source/templates/administrator/atum/js/template.es6.js index 23a4cb1b6086c..b8c4540863e26 100644 --- a/build/media_source/templates/administrator/atum/js/template.es6.js +++ b/build/media_source/templates/administrator/atum/js/template.es6.js @@ -218,7 +218,51 @@ function subheadScrolling() { } } +/** + * Watch for Dark mode changes + * + * @since __DEPLOY_VERSION__ + */ +function darkModeWatch() { + const docEl = document.documentElement; + // Update data-bs-theme when scheme has been changed + document.addEventListener('joomla:color-scheme-change', () => { + docEl.dataset.bsTheme = docEl.dataset.colorScheme; + }); + + // Look for User choose with data-color-scheme-switch button + const buttons = document.querySelectorAll('button[data-color-scheme-switch]'); + buttons.forEach((button) => { + button.addEventListener('click', (e) => { + e.preventDefault(); + const { colorScheme } = docEl.dataset; + const newScheme = colorScheme !== 'dark' ? 'dark' : 'light'; + docEl.dataset.colorScheme = newScheme; + document.cookie = `userColorScheme=${newScheme};`; + document.dispatchEvent(new CustomEvent('joomla:color-scheme-change', { bubbles: true })); + }); + }); + + // Look for data-color-scheme-os attribute + const { colorSchemeOs } = docEl.dataset; + if (colorSchemeOs === undefined) return; + // Watch on media changes + const mql = window.matchMedia('(prefers-color-scheme: dark)'); + const check = () => { + const newScheme = mql.matches ? 'dark' : 'light'; + // Check if theme already was set + if (docEl.dataset.colorScheme === newScheme) return; + docEl.dataset.colorScheme = newScheme; + // Store theme in cookies, so php will know the last choice + document.cookie = `osColorScheme=${newScheme};`; + document.dispatchEvent(new CustomEvent('joomla:color-scheme-change', { bubbles: true })); + }; + mql.addEventListener('change', check); + check(); +} + // Initialize +darkModeWatch(); headerItemsInDropdown(); reactToResize(); subheadScrolling(); diff --git a/build/media_source/templates/administrator/atum/scss/_variables.scss b/build/media_source/templates/administrator/atum/scss/_variables.scss index bf6b4ef4591a8..7125c202caf09 100644 --- a/build/media_source/templates/administrator/atum/scss/_variables.scss +++ b/build/media_source/templates/administrator/atum/scss/_variables.scss @@ -1,8 +1,8 @@ // Remove prefix added in BS5 for compat with Joomla beta's shipped with Betas $prefix: ""; -// Use dark mode conditionally based on media queries from the browser to match the desktop theme -$color-mode-type: media-query; +// Use dark mode conditionally based on data-bs-theme attribute +$color-mode-type: data; // Enable dark mode in J5.0 $enable-dark-mode: true; diff --git a/build/media_source/templates/administrator/atum/scss/blocks/_utilities.scss b/build/media_source/templates/administrator/atum/scss/blocks/_utilities.scss index 6374fab8596d0..897f75e30db0f 100644 --- a/build/media_source/templates/administrator/atum/scss/blocks/_utilities.scss +++ b/build/media_source/templates/administrator/atum/scss/blocks/_utilities.scss @@ -191,3 +191,15 @@ .editor-xtd-buttons .btn { margin-bottom: 5px; } + +// Visibility depend from ColorScheme +@include color-mode(dark) { + .d-dark-scheme-none { + display: none; + } +} +@include color-mode(light) { + .d-light-scheme-none { + display: none; + } +} diff --git a/components/com_users/forms/frontend.xml b/components/com_users/forms/frontend.xml index 68a200ea5c627..95a4ec7d3aff1 100644 --- a/components/com_users/forms/frontend.xml +++ b/components/com_users/forms/frontend.xml @@ -31,6 +31,19 @@ > + + + + + + +
diff --git a/installation/sql/mysql/base.sql b/installation/sql/mysql/base.sql index d6e168abcda62..871ae9ecf8e17 100644 --- a/installation/sql/mysql/base.sql +++ b/installation/sql/mysql/base.sql @@ -841,7 +841,7 @@ CREATE TABLE IF NOT EXISTS `#__template_styles` ( -- INSERT INTO `#__template_styles` (`id`, `template`, `client_id`, `home`, `title`, `inheritable`, `parent`, `params`) VALUES -(10, 'atum', 1, '1', 'Atum - Default', 1, '', '{"hue":"hsl(214, 63%, 20%)","bg-light":"#f0f4fb","text-dark":"#495057","text-light":"#ffffff","link-color":"#2a69b8","special-color":"#001b4c","monochrome":"0","loginLogo":"","loginLogoAlt":"","logoBrandLarge":"","logoBrandLargeAlt":"","logoBrandSmall":"","logoBrandSmallAlt":""}'), +(10, 'atum', 1, '1', 'Atum - Default', 1, '', '{"hue":"hsl(214, 63%, 20%)","bg-light":"#f0f4fb","text-dark":"#495057","text-light":"#ffffff","link-color":"#2a69b8","special-color":"#001b4c","colorScheme":"os","monochrome":"0","loginLogo":"","loginLogoAlt":"","logoBrandLarge":"","logoBrandLargeAlt":"","logoBrandSmall":"","logoBrandSmallAlt":""}'), (11, 'cassiopeia', 0, '1', 'Cassiopeia - Default', 1, '', '{"brand":"1","logoFile":"","siteTitle":"","siteDescription":"","useFontScheme":"0","colorName":"colors_standard","fluidContainer":"0","stickyHeader":0,"backTop":0}'); -- -------------------------------------------------------- diff --git a/installation/sql/postgresql/base.sql b/installation/sql/postgresql/base.sql index d8dcbde5ec80b..bb30f0950f263 100644 --- a/installation/sql/postgresql/base.sql +++ b/installation/sql/postgresql/base.sql @@ -856,7 +856,7 @@ CREATE INDEX "#__template_styles_idx_client_id_home" ON "#__template_styles" ("c -- Dumping data for table `#__template_styles` -- INSERT INTO "#__template_styles" ("id", "template", "client_id", "home", "title", "inheritable", "parent", "params") VALUES -(10, 'atum', 1, '1', 'Atum - Default', 1, '', '{"hue":"hsl(214, 63%, 20%)","bg-light":"#f0f4fb","text-dark":"#495057","text-light":"#ffffff","link-color":"#2a69b8","special-color":"#001b4c","monochrome":"0","loginLogo":"","loginLogoAlt":"","logoBrandLarge":"","logoBrandLargeAlt":"","logoBrandSmall":"","logoBrandSmallAlt":""}'), +(10, 'atum', 1, '1', 'Atum - Default', 1, '', '{"hue":"hsl(214, 63%, 20%)","bg-light":"#f0f4fb","text-dark":"#495057","text-light":"#ffffff","link-color":"#2a69b8","special-color":"#001b4c","colorScheme":"os","monochrome":"0","loginLogo":"","loginLogoAlt":"","logoBrandLarge":"","logoBrandLargeAlt":"","logoBrandSmall":"","logoBrandSmallAlt":""}'), (11, 'cassiopeia', 0, '1', 'Cassiopeia - Default', 1, '', '{"brand":"1","logoFile":"","siteTitle":"","siteDescription":"","useFontScheme":"0","colorName":"colors_standard","fluidContainer":"0","stickyHeader":0,"backTop":0}'); SELECT setval('#__template_styles_id_seq', 12, false); diff --git a/language/en-GB/com_users.ini b/language/en-GB/com_users.ini index 1e1d270d6d75d..6878e13fce773 100644 --- a/language/en-GB/com_users.ini +++ b/language/en-GB/com_users.ini @@ -145,6 +145,10 @@ COM_USERS_USER_BACKUPCODES="Backup Codes" COM_USERS_USER_BACKUPCODES_CAPTIVE_PROMPT="If you do not have access to your usual Multi-factor Authentication method use any of your Backup Codes in the field below. Please remember that this emergency backup code cannot be reused." COM_USERS_USER_BACKUPCODES_DESC="If you do not have access to your Multi-factor Authentication device you can use any of the following passwords instead of a regular security code. Each one of these emergency codes is immediately destroyed upon use. We recommend printing these codes out and keeping the printout in a safe and accessible location, eg your wallet or a safety deposit box." COM_USERS_USER_BLOCKED="This user is blocked. If this is an error, please contact an administrator." +COM_USERS_USER_COLORSCHEME_LABEL="Dark Mode" +COM_USERS_USER_COLORSCHEME_OPTION_DARK="Use Dark color scheme" +COM_USERS_USER_COLORSCHEME_OPTION_FOLLOW_OS="Follow OS settings" +COM_USERS_USER_COLORSCHEME_OPTION_LIGHT="Use Light color scheme" COM_USERS_USER_FIELD_BACKEND_LANGUAGE_LABEL="Backend Language" COM_USERS_USER_FIELD_BACKEND_TEMPLATE_LABEL="Backend Template Style" COM_USERS_USER_FIELD_EDITOR_LABEL="Editor"