|
26 | 26 | // See COPYRIGHT and LICENSE files for more details. |
27 | 27 | //++ |
28 | 28 |
|
| 29 | +import { html, render } from 'lit-html'; |
| 30 | + |
29 | 31 | // Builds the custom native drag preview for a sortable item: a sanitised clone |
30 | 32 | // of the item's preview target, sized to match and carrying the originating |
31 | 33 | // Box's density so its card styling survives being mounted outside the Box. |
@@ -54,11 +56,14 @@ const PREVIEW_STRIPPED_ATTRIBUTES = [ |
54 | 56 | // `.Box--condensed .Box-card`) would not apply to it otherwise. |
55 | 57 | const BOX_DENSITY_VARIANT_CLASSES = ['Box--condensed', 'Box--spacious'] as const; |
56 | 58 |
|
57 | | -// The count badge added to a multi-card drag's preview. Styled inline rather |
58 | | -// than through a stylesheet class, matching this file's own approach for the |
59 | | -// clone's width and margin above: the preview is a native drag image built |
60 | | -// outside the page's normal render tree, so it must be legible even where no |
61 | | -// stylesheet has had a chance to apply to it. |
| 59 | +// The count badge added to a multi-card drag's preview. Styled on Primer's |
| 60 | +// Counter contract (the same `Counter`/`Counter--primary` classes the |
| 61 | +// Angular PrimerCounterComponent renders) plus this class for the |
| 62 | +// positioning that Counter itself doesn't own; see |
| 63 | +// frontend/src/global_styles/content/drag_and_drop.sass. Building it as an |
| 64 | +// Angular custom element is not an option here: the native drag snapshot is |
| 65 | +// taken synchronously at dragstart, before an Angular element would have |
| 66 | +// painted, so this layer stays framework-agnostic by contract. |
62 | 67 | const BATCH_BADGE_CLASS = 'op-sortable-lists-drag-preview-batch-badge'; |
63 | 68 |
|
64 | 69 | export function renderDragPreview({ |
@@ -103,36 +108,26 @@ export function renderDragPreview({ |
103 | 108 | // Anchors the badge's absolute positioning to the container itself |
104 | 109 | // rather than whatever ancestor Pragmatic happens to mount it under. |
105 | 110 | container.style.position = 'relative'; |
106 | | - container.append(renderBatchBadge(preview.ownerDocument, batchSize)); |
| 111 | + renderBatchBadge(container, batchSize); |
107 | 112 | } |
108 | 113 | } |
109 | 114 |
|
110 | | -// Absolutely positioned over the card clone's top-right corner. The |
111 | | -// container is the preview mount Pragmatic hands render(); giving it |
112 | | -// position:relative here (rather than assuming the caller already set it) |
113 | | -// keeps the badge anchored to the card regardless of what else mounts there. |
114 | | -function renderBatchBadge(document:Document, batchSize:number):HTMLElement { |
115 | | - const badge = document.createElement('span'); |
116 | | - badge.className = BATCH_BADGE_CLASS; |
117 | | - badge.textContent = String(batchSize); |
118 | | - Object.assign(badge.style, { |
119 | | - position: 'absolute', |
120 | | - top: '-8px', |
121 | | - right: '-8px', |
122 | | - minWidth: '20px', |
123 | | - height: '20px', |
124 | | - padding: '0 6px', |
125 | | - borderRadius: '999px', |
126 | | - backgroundColor: 'var(--bgColor-emphasis, #1f2328)', |
127 | | - color: 'var(--fgColor-onEmphasis, #ffffff)', |
128 | | - fontSize: '12px', |
129 | | - fontWeight: '600', |
130 | | - lineHeight: '20px', |
131 | | - textAlign: 'center', |
132 | | - boxShadow: 'var(--shadow-floating-medium, 0 1px 3px rgba(0, 0, 0, 0.3))', |
133 | | - }); |
134 | | - |
135 | | - return badge; |
| 115 | +// Absolutely positioned over the card clone's top-right corner (see the sass |
| 116 | +// block in drag_and_drop.sass for the geometry, including the Firefox |
| 117 | +// inset). The container is the preview mount Pragmatic hands render(); |
| 118 | +// giving it position:relative here (rather than assuming the caller already |
| 119 | +// set it) keeps the badge anchored to the card regardless of what else |
| 120 | +// mounts there. |
| 121 | +// |
| 122 | +// lit-html's render() is safe to call directly on `container` here even |
| 123 | +// though the sanitised preview clone was already appended to it above: |
| 124 | +// render() only inserts a marker comment before its own end node (the |
| 125 | +// container's end, when unset) and manages content from that marker |
| 126 | +// onward — it does not clear pre-existing children. The clone and the |
| 127 | +// badge coexist; see the "anchors the badge to the container without |
| 128 | +// disturbing the already-appended preview clone" spec. |
| 129 | +function renderBatchBadge(container:HTMLElement, batchSize:number):void { |
| 130 | + render(html`<span class="Counter Counter--primary ${BATCH_BADGE_CLASS}">${batchSize}</span>`, container); |
136 | 131 | } |
137 | 132 |
|
138 | 133 | export function sanitizePreview(element:HTMLElement):void { |
|
0 commit comments