diff --git a/src/openforms/js/components/admin/form_design/Editor.js b/src/openforms/js/components/admin/form_design/Editor.js index 3ae90687d2..20606f58b4 100644 --- a/src/openforms/js/components/admin/form_design/Editor.js +++ b/src/openforms/js/components/admin/form_design/Editor.js @@ -9,6 +9,9 @@ const TinyMCEEditor = ({content, onEditorChange}) => { const editorRef = useRef(null); const tinyMceUrl = useContext(TinyMceContext); const intl = useIntl(); + // TODO Django 4.2: use explicit theme names rather than the media query approach: + // https://github.com/django/django/blob/main/django/contrib/admin/static/admin/css/dark_mode.css#L36 + const useDarkMode = window.matchMedia('(prefers-color-scheme: dark)').matches; return ( <> @@ -16,7 +19,12 @@ const TinyMCEEditor = ({content, onEditorChange}) => { tinymceScriptSrc={tinyMceUrl} onInit={(evt, editor) => (editorRef.current = editor)} value={content} - init={{...tinyMceConfig, language: intl.locale}} + init={{ + ...tinyMceConfig, + language: intl.locale, + skin: useDarkMode ? 'oxide-dark' : 'oxide', + content_css: useDarkMode ? 'dark' : 'default', + }} onEditorChange={onEditorChange} /> diff --git a/src/openforms/js/components/form/textfield.js b/src/openforms/js/components/form/textfield.js index e771302b27..3a41991c12 100644 --- a/src/openforms/js/components/form/textfield.js +++ b/src/openforms/js/components/form/textfield.js @@ -1,5 +1,4 @@ import {Formio} from 'react-formio'; - import {DEFAULT_TEXT_TABS} from './edit/tabs'; class TextField extends Formio.Components.components.textfield { diff --git a/src/openforms/js/index.js b/src/openforms/js/index.js index f881ac852c..9738775e6d 100644 --- a/src/openforms/js/index.js +++ b/src/openforms/js/index.js @@ -1,5 +1,5 @@ import {Formio} from 'react-formio'; - +import './initTinymce'; import './components'; import OpenForms from './formio_module'; diff --git a/src/openforms/js/initTinymce.js b/src/openforms/js/initTinymce.js new file mode 100644 index 0000000000..3c124cfe89 --- /dev/null +++ b/src/openforms/js/initTinymce.js @@ -0,0 +1,91 @@ +// Taken from https://github.com/jazzband/django-tinymce/blob/master/tinymce/static/django_tinymce/init_tinymce.js +// Updated to add dark theme detection (L35-44) + +'use strict'; + +{ + function initTinyMCE(el) { + if (el.closest('.empty-form') === null) { + // Don't do empty inlines + var mce_conf = JSON.parse(el.dataset.mceConf); + + // There is no way to pass a JavaScript function as an option + // because all options are serialized as JSON. + const fns = [ + 'color_picker_callback', + 'file_browser_callback', + 'file_picker_callback', + 'images_dataimg_filter', + 'images_upload_handler', + 'paste_postprocess', + 'paste_preprocess', + 'setup', + 'urlconverter_callback', + ]; + fns.forEach(fn_name => { + if (typeof mce_conf[fn_name] != 'undefined') { + if (mce_conf[fn_name].includes('(')) { + mce_conf[fn_name] = eval('(' + mce_conf[fn_name] + ')'); + } else { + mce_conf[fn_name] = window[mce_conf[fn_name]]; + } + } + }); + + // TODO Django 4.2: use explicit theme names rather than the media query approach: + // https://github.com/django/django/blob/main/django/contrib/admin/static/admin/css/dark_mode.css#L36 + const useDarkMode = window.matchMedia('(prefers-color-scheme: dark)').matches; + mce_conf = { + ...mce_conf, + ...{ + skin: useDarkMode ? 'oxide-dark' : 'oxide', + content_css: useDarkMode ? 'dark' : 'default', + }, + }; + + const id = el.id; + if ('elements' in mce_conf && mce_conf['mode'] == 'exact') { + mce_conf['elements'] = id; + } + if (el.dataset.mceGzConf) { + tinyMCE_GZ.init(JSON.parse(el.dataset.mceGzConf)); + } + if (!tinyMCE.get(id)) { + tinyMCE.init(mce_conf); + } + } + } + + // Call function fn when the DOM is loaded and ready. If it is already + // loaded, call the function now. + // https://youmightnotneedjquery.com/#ready + function ready(fn) { + if (document.readyState !== 'loading') { + fn(); + } else { + document.addEventListener('DOMContentLoaded', fn); + } + } + + function initializeTinyMCE(element, formsetName) { + Array.from(element.querySelectorAll('.tinymce')).forEach(area => initTinyMCE(area)); + } + + ready(function () { + // initialize the TinyMCE editors on load + initializeTinyMCE(document); + + // initialize the TinyMCE editor after adding an inline in the django admin context. + if (typeof django !== 'undefined' && typeof django.jQuery !== 'undefined') { + django.jQuery(document).on('formset:added', (event, $row, formsetName) => { + if (event.detail && event.detail.formsetName) { + // Django >= 4.1 + initializeTinyMCE(event.target); + } else { + // Django < 4.1, use $row + initializeTinyMCE($row.get(0)); + } + }); + } + }); +} diff --git a/src/openforms/scss/admin/_admin_theme.scss b/src/openforms/scss/admin/_admin_theme.scss index ab584af493..3066bf13da 100644 --- a/src/openforms/scss/admin/_admin_theme.scss +++ b/src/openforms/scss/admin/_admin_theme.scss @@ -95,6 +95,11 @@ DO NOT PUT ANY TARGET APP-SPECIFIC RULES HERE. background-color: var(--form-input-bg); } + input[type='checkbox'], + input[type='radio'] { + color-scheme: dark; + } + body #toolbar { background: var(--body-bg); } diff --git a/src/openforms/scss/admin/_app_overrides.scss b/src/openforms/scss/admin/_app_overrides.scss index b380bb899a..150f9c41eb 100644 --- a/src/openforms/scss/admin/_app_overrides.scss +++ b/src/openforms/scss/admin/_app_overrides.scss @@ -211,16 +211,16 @@ $djai-border-width: 8px; } // re-apply django admin styles - background-color: buttonface; - border: 1px solid #ccc; + background-color: var(--form-input-bg); + border: 1px solid var(--border-color); border-radius: 4px; padding: 5px 6px; margin-top: 0; &:focus { color: inherit; - background-color: buttonface; - border-color: #999; + background-color: var(--form-input-bg); + border-color: var(--border-color); box-shadow: none; outline: initial; } diff --git a/src/openforms/scss/components/admin/_ReactModal.scss b/src/openforms/scss/components/admin/_ReactModal.scss index 58b0fcaef9..936e339b1a 100644 --- a/src/openforms/scss/components/admin/_ReactModal.scss +++ b/src/openforms/scss/components/admin/_ReactModal.scss @@ -20,8 +20,8 @@ position: absolute; width: 50vw; height: 50vh; - background: white; - border: solid 1px #eee; + background: var(--body-bg); + border: 1px solid var(--hairline-color); border-radius: 0; outline: none; padding: 20px; diff --git a/src/openforms/scss/components/admin/_sdk-snippet.scss b/src/openforms/scss/components/admin/_sdk-snippet.scss index 8afa0533c0..9144151ce7 100644 --- a/src/openforms/scss/components/admin/_sdk-snippet.scss +++ b/src/openforms/scss/components/admin/_sdk-snippet.scss @@ -3,11 +3,15 @@ display: inline-block; padding-top: 10px; padding-bottom: 10px; - background-color: #efefef; + background-color: var(--form-input-bg); + border-style: solid; + border-width: thin; + border-color: var(--border-color); pre { font-size: 100%; margin-bottom: 0; + color: var(--body-fg); } } diff --git a/src/openforms/scss/components/builder/_builder.scss b/src/openforms/scss/components/builder/_builder.scss index 5d6ee89457..c25cd56aa5 100644 --- a/src/openforms/scss/components/builder/_builder.scss +++ b/src/openforms/scss/components/builder/_builder.scss @@ -69,7 +69,8 @@ div.flatpickr-calendar.open { padding-top: 10px; } -[ref='editForm'] { +[ref='editForm'], +[ref='component'] { .choices__list { &--dropdown { background-color: var(--body-bg); @@ -226,4 +227,8 @@ div.flatpickr-calendar.open { } } } + + .formio-button-add-another { + color: var(--body-fg) !important; + } } diff --git a/src/openforms/scss/components/builder/_formio-component-file.scss b/src/openforms/scss/components/builder/_formio-component-file.scss new file mode 100644 index 0000000000..0f92ec6d54 --- /dev/null +++ b/src/openforms/scss/components/builder/_formio-component-file.scss @@ -0,0 +1,6 @@ +.formio-component-file { + .list-group-item { + background-color: var(--body-bg); + border-color: var(--hairline-color); + } +} diff --git a/src/openforms/scss/components/builder/_index.scss b/src/openforms/scss/components/builder/_index.scss index 1ba8b2ca34..fcdeaecab6 100644 --- a/src/openforms/scss/components/builder/_index.scss +++ b/src/openforms/scss/components/builder/_index.scss @@ -4,5 +4,8 @@ // fixes of styling broken by django admin styling @import 'formio-component-checkbox'; +// Fix for dark theme +@import 'formio-component-file'; + @import 'columns'; @import 'openforms-component'; diff --git a/src/openforms/scss/components/builder/_openforms-component.scss b/src/openforms/scss/components/builder/_openforms-component.scss index e87522eb2d..84feee4c79 100644 --- a/src/openforms/scss/components/builder/_openforms-component.scss +++ b/src/openforms/scss/components/builder/_openforms-component.scss @@ -1,3 +1,5 @@ +@import '~microscope-sass/lib/typography'; + @import '../../../ui/static/ui/scss/settings'; @import '../../vars'; @@ -14,6 +16,10 @@ $color-tooltip-background 20px ); + legend { + @include h2(auto); + } + label { color: $color_dark; } @@ -22,4 +28,12 @@ opacity: 0.9; } } + + .ck-editor__main { + // TODO: Formio uses CKEditor5, but using their dark theme seems more complex than for the tinymce. + // So for now we keep the default theme, but ensure that the text in the editor is dark and not light. + @media (prefers-color-scheme: dark) { + color: $color-dark; + } + } }