diff --git a/src/bundle/Resources/encore/ibexa.js.config.js b/src/bundle/Resources/encore/ibexa.js.config.js index 072de90032..575ae162cf 100644 --- a/src/bundle/Resources/encore/ibexa.js.config.js +++ b/src/bundle/Resources/encore/ibexa.js.config.js @@ -54,6 +54,7 @@ const layout = [ path.resolve(__dirname, '../public/js/scripts/admin.form.autosubmit.js'), path.resolve(__dirname, '../public/js/scripts/admin.anchor.navigation'), path.resolve(__dirname, '../public/js/scripts/admin.context.menu'), + path.resolve(__dirname, '../public/js/scripts/admin.focus.mode.js'), path.resolve(__dirname, '../public/js/scripts/sidebar/main.menu.js'), path.resolve(__dirname, '../public/js/scripts/admin.input.text.js'), path.resolve(__dirname, '../public/js/scripts/admin.table.js'), diff --git a/src/bundle/Resources/public/js/scripts/admin.focus.mode.js b/src/bundle/Resources/public/js/scripts/admin.focus.mode.js new file mode 100644 index 0000000000..900bcbf516 --- /dev/null +++ b/src/bundle/Resources/public/js/scripts/admin.focus.mode.js @@ -0,0 +1,61 @@ +(function (global, doc, ibexa) { + let activeFieldEdit = null; + const ENABLE_FOCUS_MODE_EVENT_NAME = 'ibexa-focus-mode:on'; + const DISABLE_FOCUS_MODE_EVENT_NAME = 'ibexa-focus-mode:off'; + const focusModeEnableBtns = doc.querySelectorAll('.ibexa-field-edit__focus-mode-control-btn--enable'); + const focusModeDisbaleBtns = doc.querySelectorAll('.ibexa-field-edit__focus-mode-control-btn--disable'); + const changeFocusModeState = (active) => { + if (!activeFieldEdit) { + return; + } + + const dispatchEventName = active ? ENABLE_FOCUS_MODE_EVENT_NAME : DISABLE_FOCUS_MODE_EVENT_NAME; + const editorSourceElement = activeFieldEdit.querySelector('.ibexa-data-source__richtext'); + const editorInstance = editorSourceElement.ckeditorInstance; + + activeFieldEdit.classList.toggle('ibexa-field-edit--focus-mode-active', active); + editorInstance.set('focusModeActive', active); + + doc.body.dispatchEvent( + new CustomEvent(dispatchEventName, { + detail: { + activeFieldEdit, + }, + }), + ); + + if (!active) { + activeFieldEdit = null; + } + }; + const watchDisableFocusModeByKeyboard = (event) => { + if (event.key === 'Escape' || event.keyCode === 27) { + changeFocusModeState(false); + } + }; + + focusModeEnableBtns.forEach((btn) => { + btn.addEventListener( + 'click', + ({ currentTarget }) => { + activeFieldEdit = currentTarget.closest('.ibexa-field-edit'); + changeFocusModeState(true); + }, + false, + ); + }); + focusModeDisbaleBtns.forEach((btn) => { + btn.addEventListener('click', () => changeFocusModeState(false), false); + }); + + doc.body.addEventListener( + ENABLE_FOCUS_MODE_EVENT_NAME, + () => doc.body.addEventListener('keydown', watchDisableFocusModeByKeyboard), + false, + ); + doc.body.addEventListener( + DISABLE_FOCUS_MODE_EVENT_NAME, + () => doc.body.removeEventListener('keydown', watchDisableFocusModeByKeyboard), + false, + ); +})(window, window.document, window.ibexa); diff --git a/src/bundle/Resources/public/scss/_alerts.scss b/src/bundle/Resources/public/scss/_alerts.scss index 404ae487fc..f85114c592 100644 --- a/src/bundle/Resources/public/scss/_alerts.scss +++ b/src/bundle/Resources/public/scss/_alerts.scss @@ -199,4 +199,14 @@ } } } + + &--complementary { + color: $ibexa-color-complementary-700; + background-color: $ibexa-color-complementary-100; + border-color: $ibexa-color-complementary; + + .ibexa-icon { + fill: $ibexa-color-complementary-700; + } + } } diff --git a/src/bundle/Resources/public/scss/fieldType/edit/_base-field.scss b/src/bundle/Resources/public/scss/fieldType/edit/_base-field.scss index 7ee540cd04..c34fd56967 100644 --- a/src/bundle/Resources/public/scss/fieldType/edit/_base-field.scss +++ b/src/bundle/Resources/public/scss/fieldType/edit/_base-field.scss @@ -15,6 +15,35 @@ color: $ibexa-color-danger; } + &__focus-mode { + display: flex; + flex-direction: column; + height: auto; + background: $ibexa-color-white; + border-radius: $ibexa-border-radius $ibexa-border-radius 0 0; + } + + &__focus-mode-notice-container { + display: none; + } + + &__focus-mode-control-container { + display: flex; + align-self: flex-end; + } + + &__focus-mode-control-btn { + align-self: flex-end; + + &--enable { + display: inline-flex; + } + + &--disable { + display: none; + } + } + .ibexa-input-text-wrapper { width: auto; } @@ -59,6 +88,108 @@ } } } + + &--has-focus-mode { + display: flex; + flex-wrap: wrap; + + .ibexa-field-edit { + &__focus-mode { + margin: auto 0 0 0; + align-self: baseline; + } + + &__label-wrapper { + width: 80%; + } + + &__focus-mode { + width: 20%; + } + + &__data { + width: 100%; + } + } + } + + &--focus-mode-active { + position: fixed; + top: 0; + left: 0; + z-index: 1080; + flex-direction: column; + width: 100vw; + height: 100vh; + padding: calculateRem(16px); + background: $ibexa-color-black; + + .ibexa-field-edit { + &__label-wrapper { + display: none; + } + + &__focus-mode { + width: 100%; + height: fit-content; + padding: calculateRem(32px) calculateRem(32px) 0 calculateRem(32px); + } + + &__focus-mode-notice-container { + display: block; + width: 100%; + } + + &__focus-mode-control-container { + height: calculateRem(40px); + } + + &__focus-mode-control-btn { + margin: 0; + + &--enable { + display: none; + } + + &--disable { + display: inline-flex; + } + } + + &__data { + width: 100%; + overflow-y: auto; + align-self: stretch; + flex-grow: 1; + padding: calculateRem(8px) calculateRem(32px) calculateRem(32px) calculateRem(32px); + background: $ibexa-color-white; + border-radius: 0 0 $ibexa-border-radius $ibexa-border-radius; + + .ibexa-data-source { + height: 100%; + } + } + } + + .ibexa-alert { + margin-bottom: calculateRem(4px); + } + } + + &--focus-mode-active.is-invalid { + .ibexa-field-edit { + &__data { + border-radius: 0; + padding-bottom: 0; + } + } + + .ibexa-form-error { + padding: calculateRem(16px) calculateRem(32px); + background: $ibexa-color-white; + border-radius: 0 0 $ibexa-border-radius $ibexa-border-radius; + } + } } .ibexa-content-edit { diff --git a/src/bundle/Resources/translations/messages.en.xliff b/src/bundle/Resources/translations/messages.en.xliff index e4274df093..68f592157a 100644 --- a/src/bundle/Resources/translations/messages.en.xliff +++ b/src/bundle/Resources/translations/messages.en.xliff @@ -458,6 +458,21 @@ Show key: fieldview.toggler.show + + Distraction free mode + Distraction free mode + key: focus_mode.disable.label + + + To exit distraction free mode, click the %icon% or press Esc + To exit distraction free mode, click the %icon% or press Esc + key: focus_mode.disbale_hint + + + Focus mode + Focus mode + key: focus_mode.enable.label + diff --git a/src/bundle/Resources/views/themes/admin/content/form_fields.html.twig b/src/bundle/Resources/views/themes/admin/content/form_fields.html.twig index 44d7dfdb3f..c8209085e5 100644 --- a/src/bundle/Resources/views/themes/admin/content/form_fields.html.twig +++ b/src/bundle/Resources/views/themes/admin/content/form_fields.html.twig @@ -80,9 +80,10 @@ {% set fieldtype_identifier = fieldtype.vars.value.fieldDefinition.fieldTypeIdentifier %} {% set translation_mode = fieldtype.vars.mainLanguageCode != fieldtype.vars.languageCode %} {% set fieldtype_is_not_translatable = translation_mode and not fieldtype.vars.value.fieldDefinition.isTranslatable %} + {% set has_focus_mode = fieldtype_identifier == 'ezrichtext' %} {% set widget_wrapper_attr = widget_wrapper_attr|default({})|merge({'class': (widget_wrapper_attr.class|default('') ~ ' ibexa-field-edit__data ibexa-field-edit__data')|trim}) %} - {% set wrapper_class = 'ibexa-field-edit ibexa-field-edit--' ~ fieldtype_identifier ~ ' ibexa-field-edit ibexa-field-edit--' ~ fieldtype_identifier %} + {% set wrapper_class = 'ibexa-field-edit ibexa-field-edit--' ~ fieldtype_identifier ~ ' ibexa-field-edit ibexa-field-edit--' ~ fieldtype_identifier ~ (has_focus_mode ? ' ibexa-field-edit--has-focus-mode') %} {% if fieldtype.vars.disabled %} {% set wrapper_class = wrapper_class ~ ' ibexa-field-edit--disabled ibexa-field-edit--disabled' %} @@ -114,9 +115,13 @@
- {% with { 'compound': false } %}{{- block('form_label') }}{% endwith %} + {% with { 'compound': false } %}{{ block('form_label') }}{% endwith %}
+ {% if has_focus_mode %} + {{- block('focus_mode') }} + {% endif %} + {% if widget_container_block is defined %} {{ widget_container_block|raw }} {% else %} diff --git a/src/bundle/Resources/views/themes/admin/ui/form_fields.html.twig b/src/bundle/Resources/views/themes/admin/ui/form_fields.html.twig index a599b77d89..61d124552c 100644 --- a/src/bundle/Resources/views/themes/admin/ui/form_fields.html.twig +++ b/src/bundle/Resources/views/themes/admin/ui/form_fields.html.twig @@ -270,7 +270,6 @@ {%- block richtext_widget -%} {% set attr = attr|merge({ 'hidden': true }) %} -
@@ -500,3 +499,43 @@ {{- form_errors(form) -}}
{%- endblock %} + +{%- block focus_mode -%} + {%- set title_icon -%} + + + + {%- endset -%} + {%- set title -%} + {{ 'focus_mode.disbale_hint'|trans({ '%icon%': title_icon|raw })|desc('To exit distraction free mode, click the %icon% or press Esc')|raw }} + {%- endset -%} + +
+
+ {% include '@ibexadesign/ui/component/alert/alert.html.twig' with { + type: 'complementary', + title, + icon_path: ibexa_icon_path('system-information'), + show_close_btn: true + } only %} +
+
+ + +
+
+{%- endblock -%}