Code Coverage
 
Lines
Branches
Paths
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 66
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
CRAP
0.00% covered (danger)
0.00%
0 / 1
HighlightToggle
0.00% covered (danger)
0.00%
0 / 59
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
0.00% covered (danger)
0.00%
0 / 1
 build
0.00% covered (danger)
0.00%
0 / 59
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2
3declare(strict_types=1);
4
5namespace Drupal\display_builder\Plugin\display_builder\Island;
6
7use Drupal\Core\StringTranslation\TranslatableMarkup;
8use Drupal\display_builder\Attribute\Island;
9use Drupal\display_builder\InstanceInterface;
10use Drupal\display_builder\Island\IslandPluginBase;
11use Drupal\display_builder\Island\IslandType;
12
13/**
14 * Highlight toggle island plugin implementation.
15 *
16 * Floating control attached to the Builder and Scaffold panes: both render
17 * real component output that the highlighting annotates. Not the Wireframe or
18 * Tree panes - those are purely schematic, so their structure is already
19 * permanently outlined and there's nothing left for a highlight to reveal
20 * (@see components/layer/layer.css). In Scaffold it applies to the
21 * real-rendered "layout" components only; the schematic cards alongside
22 * them keep their own always-on treatment.
23 *
24 * A dropdown of independent checkboxes (Drop
25 * zones/Components/Blocks/Visual spacing), not a single on/off button:
26 * each kind of highlight - and the extra breathing room around them - is
27 * useful on its own, so they're not mutually exclusive. Components and
28 * blocks are split rather than one combined item since a canvas is often
29 * dominated by one or the other, and highlighting both at once just adds
30 * noise to whichever one you don't care about right now.
31 *
32 * Built directly here (not via IslandFloatingControlsTrait, which is only
33 * for a plain icon-button cluster) following the same
34 * display_builder:dropdown + display_builder:menu pattern as
35 * ViewportSwitcher's compact format.
36 *
37 * @see assets/js/highlight.js
38 * @see components/dropzone/dropzone.css
39 */
40#[Island(
41  id: 'highlight',
42  enabled_by_default: TRUE,
43  label: new TranslatableMarkup('Highlight'),
44  description: new TranslatableMarkup('Highlight zones to ease drag and move around for the canvas and scaffold panels.'),
45  type: IslandType::Floating,
46  attach_to: ['builder', 'scaffold'],
47)]
48class HighlightToggle extends IslandPluginBase {
49
50  /**
51   * {@inheritdoc}
52   */
53  public function build(InstanceInterface $builder, array $data = [], array $options = []): array {
54    // A plain title attribute, not tooltip (which wraps the trigger in a
55    // Shoelace <sl-tooltip>): Floating UI/ computes a permanently broken
56    // position for a tooltip that's part of the server-rendered HTML inside a
57    // floating controls cluster.
58    $button = $this->buildButton('', NULL, 'border');
59    $button['#attributes']['title'] = $this->t('Highlight zones to ease drag and move around.');
60    $button['#attributes']['size'] = 'small';
61
62    return [
63      '#type' => 'component',
64      '#component' => 'display_builder:dropdown',
65      '#slots' => [
66        'button' => $button,
67        'content' => [
68          '#type' => 'component',
69          '#component' => 'display_builder:menu',
70          '#props' => [
71            'items' => [
72              [
73                // Special-cased in highlight.js: checks/unchecks the 4
74                // items below together, and reflects whether all 4 are
75                // already checked whenever the menu opens.
76                'title' => $this->t('Select all'),
77                'value' => 'all',
78                'type' => 'checkbox',
79              ],
80              ['divider' => TRUE],
81              [
82                // A colored dot, not a functional icon: tinted per
83                // category in dropzone.css so the menu itself previews
84                // which color each checkbox controls, before checking
85                // anything.
86                'title' => $this->t('Drop zones'),
87                'value' => 'slot',
88                'type' => 'checkbox',
89                'icon' => 'circle-fill',
90              ],
91              [
92                'title' => $this->t('Components'),
93                'value' => 'component',
94                'type' => 'checkbox',
95                'icon' => 'circle-fill',
96              ],
97              [
98                'title' => $this->t('Blocks'),
99                'value' => 'block',
100                'type' => 'checkbox',
101                'icon' => 'circle-fill',
102              ],
103              ['divider' => TRUE],
104              [
105                'title' => $this->t('Visual spacing'),
106                'value' => 'space',
107                'type' => 'checkbox',
108              ],
109            ],
110          ],
111          '#attributes' => [
112            'class' => ['db-background'],
113          ],
114        ],
115      ],
116      '#attributes' => [
117        // db-background: visual surface now that this floats over the
118        // pane's own content, instead of sitting in the toolbar's chrome.
119        'class' => ['db-background'],
120        'data-highlight-menu' => TRUE,
121        // Checking one box shouldn't close the menu - these are
122        // independent toggles, not a single pick.
123        'stay-open-on-select' => TRUE,
124      ],
125      '#attached' => [
126        'library' => ['display_builder/highlight'],
127      ],
128    ];
129  }
130
131}