diff --git a/assets/diagram-js.css b/assets/diagram-js.css index 2c983012a..31420a6ba 100644 --- a/assets/diagram-js.css +++ b/assets/diagram-js.css @@ -54,8 +54,9 @@ --palette-background-color: var(--color-grey-225-10-97); --palette-border-color: var(--color-grey-225-10-75); + --popup-font-size: 14px; --popup-header-entry-selected-color: var(--color-blue-205-100-50); - --popup-header-separator-color: var(--color-grey-225-10-75); + --popup-header-font-weight: bolder; --popup-background-color: var(--color-white); --popup-border-color: var(--color-grey-225-10-75); --popup-shadow-color: var(--color-grey-225-10-80); @@ -536,12 +537,13 @@ marker.djs-dragger tspan { box-shadow: 0px 2px 10px var(--popup-shadow-color); min-width: 120px; outline: none; + font-size: var(--popup-font-size); } .djs-popup-search input { width: 100%; box-sizing: border-box; - font-size: 14px; + font-size: var(--popup-font-size); padding: 3px 6px; border-radius: 2px; border: solid 1px var(--popup-search-border-color); @@ -562,7 +564,6 @@ marker.djs-dragger tspan { } .djs-popup-header .entry { - font-size: 19.5px; border-radius: 2px; } @@ -579,11 +580,10 @@ marker.djs-dragger tspan { } .djs-popup-title { - font-size: 14px; - font-weight: 500; + font-size: var(--popup-font-size); + font-weight: var(--popup-header-font-weight); flex: 1; margin: 0; - width: max-content; } .djs-popup-search { @@ -620,19 +620,26 @@ marker.djs-dragger tspan { padding: 5px 7px; cursor: default; border-radius: 4px; - font-size: 14px; } .djs-popup-body .entry-header { - font-weight: 500; + font-weight: var(--popup-header-font-weight); color: var(--popup-entry-title-color); padding-left: 0; } +.djs-popup [class*="icon"] .djs-popup-label, +.djs-popup-label:not(:first-child) { + margin-left: .5rem; +} + +.djs-popup [class*="icon"]:before, .djs-popup-entry-icon { - width: 16px; - margin-right: 0.5rem; - margin-bottom: -0.2rem; + width: 1em; + height: 1em; + display: inline-block; + font-size: 1.4em; + vertical-align: middle; } .djs-popup-body .entry-header:not(:first-child) { @@ -666,10 +673,15 @@ marker.djs-dragger tspan { color: var(--popup-description-color); } -.djs-popup-entry-name, +.djs-popup-label, .djs-popup-entry-description { line-height: 1.4em; - display: block; +} + +.djs-popup-title, +.djs-popup-label, +.djs-popup-entry-description, +.djs-popup .entry-header { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; @@ -686,15 +698,6 @@ marker.djs-dragger tspan { overflow: hidden; } -.djs-popup-entry-name[class^="bpmn-icon-"]:before, -.djs-popup-entry-name[class*=" bpmn-icon-"]:before, -.djs-popup-entry-icon { - display: inline-block; - font-size: 1.4em; - vertical-align: middle; - margin-right: 0.5rem; -} - .djs-popup-body { flex-direction: column; width: auto; @@ -711,13 +714,12 @@ marker.djs-dragger tspan { .djs-popup *::-webkit-scrollbar-track { box-shadow: none; - background: transparent1; + background: transparent; margin: 0; padding: 5px; } .djs-popup-no-results { - font-size: 14px; padding: 0 12px 12px 12px; color: var(--popup-no-results-color); } diff --git a/lib/features/popup-menu/PopupMenuComponent.js b/lib/features/popup-menu/PopupMenuComponent.js index fd8dfccae..1592d832a 100644 --- a/lib/features/popup-menu/PopupMenuComponent.js +++ b/lib/features/popup-menu/PopupMenuComponent.js @@ -184,18 +184,23 @@ export default function PopupMenuComponent(props) { > ${ displayHeader && html`
-

${ title }

+

${ title }

${ headerEntries.map(entry => html` onSelect(event, entry) } - title=${ entry.title } + title=${ entry.title || entry.label } data-id=${ entry.id } onMouseEnter=${ () => setSelectedEntry(entry) } onMouseLeave=${ () => setSelectedEntry(null) } > - ${ entry.imageUrl ? html`` : null } - ${ entry.label ? entry.label : null } + ${ entry.imageUrl ? html` + + ` : null } + + ${ entry.label ? html` + ${ entry.label } + ` : null } `) }
diff --git a/lib/features/popup-menu/PopupMenuItem.js b/lib/features/popup-menu/PopupMenuItem.js index 823f40cca..3504d3a64 100644 --- a/lib/features/popup-menu/PopupMenuItem.js +++ b/lib/features/popup-menu/PopupMenuItem.js @@ -24,14 +24,11 @@ export default function PopupMenuItem(props) { onClick } = props; - const createImage = imageUrl => { - return html``; - }; - return html`
  • - ${ entry.imageUrl ? createImage(entry.imageUrl) : null } - ${ entry.label || entry.name } + ${ entry.imageUrl ? html` + + ` : null } + + ${ entry.label ? html` + + ${ entry.label } + + ` : null } ${ entry.description && html` ${ groups.map(group => html` ${ group.name && html` -
    +
    ${ group.name }
    ` } diff --git a/test/spec/features/popup-menu/PopupMenuComponentSpec.js b/test/spec/features/popup-menu/PopupMenuComponentSpec.js index 0755a5dca..f74f0a76c 100644 --- a/test/spec/features/popup-menu/PopupMenuComponentSpec.js +++ b/test/spec/features/popup-menu/PopupMenuComponentSpec.js @@ -7,21 +7,49 @@ import { import { bootstrapDiagram, + insertCSS, inject } from 'test/TestHelper'; import { + domify, query as domQuery, queryAll as domQueryAll } from 'min-dom'; +const TEST_IMAGE_URL = `data:image/svg+xml;utf8,${ + encodeURIComponent(` + + + + `) +}`; + +insertCSS('fake-font.css', ` + .bpmn-icon-sun:before { + content: '☼'; + font-style: normal; + font-weight: normal; + display: inline-block; + text-decoration: inherit; + width: 1em; + height: 1em; + text-align: center; + font-variant: normal; + text-transform: none; + line-height: 1em; + } +`); + + describe('features/popup-menu - ', function() { let container, teardown; beforeEach(function() { - container = document.createElement('div'); + container = domify('
    '); + document.body.appendChild(container); }); @@ -59,8 +87,8 @@ describe('features/popup-menu - ', function() { const popupBounds = popup.getBoundingClientRect(); // then - expect(popupBounds.x).to.eql(100); - expect(popupBounds.y).to.eql(100); + expect(popupBounds.x).to.be.closeTo(100, 1); + expect(popupBounds.y).to.be.closeTo(100, 1); })); @@ -126,6 +154,56 @@ describe('features/popup-menu - ', function() { })); + it('should render complex', inject(function() { + + const imageUrl = TEST_IMAGE_URL; + + // given + const headerEntries = [ + { id: '1', label: '|A|' }, + { id: '1.1', label: '|A|', imageUrl }, + { id: '2', imageUrl, title: 'Toggle foo' }, + { id: '3', className: 'bpmn-icon-sun' } + ]; + + const iconGroup = { + id: 'icons', + name: 'Icon Group' + }; + + const entries = [ + { id: '4', label: 'Just label' }, + { id: '5', imageUrl, title: 'Toggle foo' }, + { id: '6', imageUrl, label: 'Toggle foo' }, + { id: '7', label: 'with description', description: 'I DESCRIBE IT' }, + { id: '7.1', label: 'with long title and description, you cannot believe what happened next', description: 'A very long description, you cannot believe what happened next' }, + { id: '7.2', label: 'with long title and description, you cannot believe what happened next', description: 'A very long description, you cannot believe what happened next', documentationRef: 'http://localhost' }, + { id: '8', imageUrl, label: 'with image + description', description: 'I DESCRIBE more stuff' }, + { id: '9', imageUrl, label: 'WITH DOC REF', documentationRef: 'http://localhost' }, + { id: '10', imageUrl, label: 'FOO', description: 'WITH DOC REF', documentationRef: 'http://localhost' }, + { id: '11', className: 'bpmn-icon-sun', label: 'FONT ICON + description', description: 'WITH DOC REF', group: iconGroup }, + { id: '11.1', className: 'bpmn-icon-sun', label: 'FONT ICON', group: iconGroup }, + { id: '11.2', className: 'bpmn-icon-sun', title: 'icon only', group: iconGroup }, + { id: '12', className: 'bpmn-icon-sun', title: 'icon only', group: { + id: 'super long', + name: 'Extremely super long group incredible!' + } } + ]; + + createPopupMenu({ + container, + title: 'Popup menu with super long title', + headerEntries, + entries, + position: () => { + return { x: 100, y: 200 }; + }, + width: 250 + }); + + })); + + describe('close', function() { it('should close on background click', inject(function() { @@ -217,6 +295,67 @@ describe('features/popup-menu - ', function() { expect(popupBodyEl).not.to.exist; })); + + it('should render body entry', inject(function() { + + // given + const imageUrl = TEST_IMAGE_URL; + + const entries = [ + { id: '1', label: '1' }, + { id: '2', imageUrl, title: 'Toggle foo' }, + { id: '3', label: 'FOO', description: 'I DESCRIBE IT' } + ]; + + createPopupMenu({ container, entries }); + + // when + const [ + firstEntry, + secondEntry, + describedEntry + ] = domQueryAll('.entry', container); + + // then + expect(firstEntry.title).to.eql('1'); + expect(firstEntry.textContent).to.eql('1'); + + expect(secondEntry.title).to.eql('Toggle foo'); + expect(secondEntry.textContent).to.eql(''); + expect(secondEntry.innerHTML).to.include(``); + + expect(describedEntry.title).to.eql('FOO'); + expect(describedEntry.textContent).to.eql('FOOI DESCRIBE IT'); + })); + + + it('should render entry header', inject(function() { + + // given + const entries = [ + { + id: '1', + label: '1', + group: { + id: 'SAD', + name: 'SOME GROUP' + } + } + ]; + + createPopupMenu({ container, entries }); + + // when + const [ + groupHeader + ] = domQueryAll('.entry-header', container); + + // then + expect(groupHeader).to.exist; + expect(groupHeader.title).to.eql('SOME GROUP'); + expect(groupHeader.textContent).to.eql('SOME GROUP'); + })); + }); @@ -225,9 +364,11 @@ describe('features/popup-menu - ', function() { it('should render header entry', inject(function() { // given + const imageUrl = TEST_IMAGE_URL; + const headerEntries = [ { id: '1', label: '1' }, - { id: '2', imageUrl: 'http://localhost/404.png', title: 'Toggle foo' } + { id: '2', imageUrl, title: 'Toggle foo' } ]; createPopupMenu({ container, headerEntries }); @@ -239,12 +380,12 @@ describe('features/popup-menu - ', function() { ] = domQueryAll('.entry', container); // then - expect(firstEntry.title).to.be.empty; + expect(firstEntry.title).to.eql('1'); expect(firstEntry.textContent).to.eql('1'); expect(secondEntry.title).to.eql('Toggle foo'); expect(secondEntry.textContent).to.eql(''); - expect(secondEntry.innerHTML).to.eql(''); + expect(secondEntry.innerHTML).to.eql(``); })); @@ -291,8 +432,8 @@ describe('features/popup-menu - ', function() { // then var titleElement = domQuery('.djs-popup-title', container); expect(titleElement).to.exist; + expect(titleElement.title).to.eql(title); expect(titleElement.innerHTML).to.eql(title); - }));