diff --git a/core/modules/layout_builder/css/layout-builder.css b/core/modules/layout_builder/css/layout-builder.css index edb0c48cb7..5d8d831a72 100644 --- a/core/modules/layout_builder/css/layout-builder.css +++ b/core/modules/layout_builder/css/layout-builder.css @@ -114,3 +114,9 @@ display: block; padding: 15px 0 15px 25px; } + +[data-layout-builder-highlight-id].layout-builder-highlight { + position: relative; + z-index: 1; + outline: 3px solid; +} diff --git a/core/modules/layout_builder/js/layout-builder.es6.js b/core/modules/layout_builder/js/layout-builder.es6.js index f8f7b0be46..99b7a413fc 100644 --- a/core/modules/layout_builder/js/layout-builder.es6.js +++ b/core/modules/layout_builder/js/layout-builder.es6.js @@ -51,4 +51,18 @@ }); }, }; + $(window).on('dialog:aftercreate', (event, dialog, $element) => { + $('.layout-builder-highlight').removeClass('layout-builder-highlight'); + const id = $element + .find('[data-layout-builder-target-highlight-id]') + .attr('data-layout-builder-target-highlight-id'); + if (id) { + $(`[data-layout-builder-highlight-id="${id}"]`).addClass( + 'layout-builder-highlight', + ); + } + }); + $(window).on('dialog:afterclose', () => { + $('.layout-builder-highlight').removeClass('layout-builder-highlight'); + }); })(jQuery, Drupal); diff --git a/core/modules/layout_builder/js/layout-builder.js b/core/modules/layout_builder/js/layout-builder.js index 0f0de275ef..9ddaaaf000 100644 --- a/core/modules/layout_builder/js/layout-builder.js +++ b/core/modules/layout_builder/js/layout-builder.js @@ -32,4 +32,14 @@ }); } }; + $(window).on('dialog:aftercreate', function (event, dialog, $element) { + $('.layout-builder-highlight').removeClass('layout-builder-highlight'); + var id = $element.find('[data-layout-builder-target-highlight-id]').attr('data-layout-builder-target-highlight-id'); + if (id) { + $('[data-layout-builder-highlight-id="' + id + '"]').addClass('layout-builder-highlight'); + } + }); + $(window).on('dialog:afterclose', function () { + $('.layout-builder-highlight').removeClass('layout-builder-highlight'); + }); })(jQuery, Drupal); \ No newline at end of file diff --git a/core/modules/layout_builder/src/Controller/ChooseBlockController.php b/core/modules/layout_builder/src/Controller/ChooseBlockController.php index 9bd76bacc1..07be062d2f 100644 --- a/core/modules/layout_builder/src/Controller/ChooseBlockController.php +++ b/core/modules/layout_builder/src/Controller/ChooseBlockController.php @@ -111,7 +111,10 @@ public function build(SectionStorageInterface $section_storage, $delta, $region) } $block_categories['#type'] = 'container'; - $block_categories['#attributes']['class'][] = 'block-categories'; + $block_categories['#attributes'] = [ + 'data-layout-builder-target-highlight-id' => "block-$delta-$region", + 'class' => ['block-categories'], + ]; // @todo Explicitly cast delta to an integer, remove this in // https://www.drupal.org/project/drupal/issues/2984509. diff --git a/core/modules/layout_builder/src/Controller/ChooseSectionController.php b/core/modules/layout_builder/src/Controller/ChooseSectionController.php index 3405692e53..3c76e39526 100644 --- a/core/modules/layout_builder/src/Controller/ChooseSectionController.php +++ b/core/modules/layout_builder/src/Controller/ChooseSectionController.php @@ -98,6 +98,7 @@ public function build(SectionStorageInterface $section_storage, $delta) { 'class' => [ 'layout-selection', ], + 'data-layout-builder-target-highlight-id' => "section-$delta", ], ]; diff --git a/core/modules/layout_builder/src/Controller/LayoutBuilderController.php b/core/modules/layout_builder/src/Controller/LayoutBuilderController.php index 90104848fd..0b751321b3 100644 --- a/core/modules/layout_builder/src/Controller/LayoutBuilderController.php +++ b/core/modules/layout_builder/src/Controller/LayoutBuilderController.php @@ -205,6 +205,7 @@ protected function buildAddSectionLink(SectionStorageInterface $section_storage, '#type' => 'container', '#attributes' => [ 'class' => ['new-section'], + 'data-layout-builder-highlight-id' => "section-$delta", ], ]; } @@ -270,7 +271,10 @@ protected function buildAdministrativeSection(SectionStorageInterface $section_s ), ]; $build[$region]['layout_builder_add_block']['#type'] = 'container'; - $build[$region]['layout_builder_add_block']['#attributes'] = ['class' => ['new-block']]; + $build[$region]['layout_builder_add_block']['#attributes'] = [ + 'class' => ['new-block'], + 'data-layout-builder-highlight-id' => "block-$delta-$region", + ]; $build[$region]['layout_builder_add_block']['#weight'] = 1000; $build[$region]['#attributes']['data-region'] = $region; $build[$region]['#attributes']['class'][] = 'layout-builder--layout__region'; diff --git a/core/modules/layout_builder/tests/src/FunctionalJavascript/LayoutBuilderUiTest.php b/core/modules/layout_builder/tests/src/FunctionalJavascript/LayoutBuilderUiTest.php index 9dc7dd3e7e..c6c6c62cbe 100644 --- a/core/modules/layout_builder/tests/src/FunctionalJavascript/LayoutBuilderUiTest.php +++ b/core/modules/layout_builder/tests/src/FunctionalJavascript/LayoutBuilderUiTest.php @@ -41,6 +41,13 @@ protected function setUp() { 'administer node display', 'administer node fields', ])); + + // Enable layout builder. + $this->drupalPostForm( + static::FIELD_UI_PREFIX . '/display/default', + ['layout[enabled]' => TRUE], + 'Save' + ); } /** @@ -50,13 +57,6 @@ public function testUnsavedChangesMessage() { $assert_session = $this->assertSession(); $page = $this->getSession()->getPage(); - // Enable layout builder. - $this->drupalPostForm( - static::FIELD_UI_PREFIX . '/display/default', - ['layout[enabled]' => TRUE], - 'Save' - ); - // Make and then discard changes. $this->assertModifiedLayout(static::FIELD_UI_PREFIX . '/display-layout/default'); $page->clickLink('Discard changes'); @@ -92,4 +92,29 @@ protected function assertModifiedLayout($path) { $assert_session->pageTextContainsOnce('You have unsaved changes.'); } + /** + * Tests for current "Add Section" and "Add Block" targets being highlighted. + */ + public function testAddHighlights() { + $assert_session = $this->assertSession(); + $page = $this->getSession()->getPage(); + + $this->drupalGet(static::FIELD_UI_PREFIX . '/display-layout/default'); + $this->assertCount(2, $page->findAll('css', '.new-section')); + $assert_session->elementNotExists('css', '.layout-builder-highlight'); + $page->clickLink('Add Section'); + $this->assertNotEmpty($assert_session->waitForElement('css', '.new-section.layout-builder-highlight[data-layout-builder-highlight-id="section-0"]')); + $this->assertCount(1, $page->findAll('css', '.layout-builder-highlight')); + + // Add a section to ensure there are 2 new block links on the page. + $page->clickLink('One column'); + $this->assertNotEmpty($assert_session->waitForElementVisible('css', '[data-layout-delta="1"]')); + $this->assertCount(2, $page->findAll('css', '.new-block')); + $assert_session->elementNotExists('css', 'layout-builder-highlight'); + + $page->clickLink('Add Block'); + $this->assertNotEmpty($assert_session->waitForElement('css', '.new-block.layout-builder-highlight[data-layout-builder-highlight-id="block-0-content"]')); + $this->assertCount(1, $page->findAll('css', '.layout-builder-highlight')); + } + }