diff --git a/src/js/_enqueues/admin/postbox.js b/src/js/_enqueues/admin/postbox.js index b6d1b6569dc84..fc339afd14d2b 100644 --- a/src/js/_enqueues/admin/postbox.js +++ b/src/js/_enqueues/admin/postbox.js @@ -394,6 +394,24 @@ opacity: 0.65, start: function() { $( 'body' ).addClass( 'is-dragging-metaboxes' ); + + /* + * Equalize the height of the dashboard sortable drop areas to the + * tallest column. The drop placeholder only appears where the dragged + * item overlaps a `.meta-box-sortables` area, so without this a widget + * dragged past the end of a shorter column gets no drop indicator. + */ + var $dashboardSortables = $( '#dashboard-widgets .meta-box-sortables' ), + maxSortableHeight = 0; + + $dashboardSortables.each( function() { + maxSortableHeight = Math.max( maxSortableHeight, $( this ).height() ); + }); + + if ( maxSortableHeight ) { + $dashboardSortables.css( 'min-height', maxSortableHeight + 'px' ); + } + // Refresh the cached positions of all the sortable items so that the min-height set while dragging works. $( '.meta-box-sortables' ).sortable( 'refreshPositions' ); }, @@ -402,6 +420,9 @@ $( 'body' ).removeClass( 'is-dragging-metaboxes' ); + // Remove the temporary equal-height drop areas set in `start`. + $( '#dashboard-widgets .meta-box-sortables' ).css( 'min-height', '' ); + if ( $el.find( '#dashboard_browser_nag' ).is( ':visible' ) && 'dashboard_browser_nag' != this.firstChild.id ) { $el.sortable('cancel'); return; diff --git a/src/wp-admin/css/common.css b/src/wp-admin/css/common.css index 63e960b482c00..bc264e14f7936 100644 --- a/src/wp-admin/css/common.css +++ b/src/wp-admin/css/common.css @@ -2258,12 +2258,25 @@ html.wp-toolbar { color: #a7aaad; } -.sortable-placeholder:not(.empty-container .sortable-placeholder) { - border: 1px dashed #c3c4c7; +.sortable-placeholder { + box-sizing: border-box; + border: 2px dashed var(--wp-admin-theme-color, #c3c4c7); + background: rgba(var(--wp-admin-theme-color--rgb, 56, 88, 233), 0.08); border-radius: 8px; margin-bottom: 20px; } +/* + * Empty containers render their own drop outline, so the placeholder inside + * them is redundant. Kept as a separate rule (instead of a `:not()` with a + * descendant combinator) so unsupported-selector engines can't drop the main + * placeholder styles and leave the drop indicator invisible. + */ +.empty-container .sortable-placeholder { + border: none; + background: none; +} + .postbox, .stuffbox { margin-bottom: 20px; diff --git a/src/wp-admin/css/dashboard.css b/src/wp-admin/css/dashboard.css index ab73f828f7067..4018ff7262df3 100644 --- a/src/wp-admin/css/dashboard.css +++ b/src/wp-admin/css/dashboard.css @@ -39,7 +39,13 @@ } #dashboard-widgets-wrap { - overflow: hidden; + /* + * Use flow-root to contain the floated postbox columns without clipping. + * `overflow: hidden` would clip the jQuery UI Sortable drag helper when it + * leaves the wrap bounds (e.g. while scroll-dragging near the edges), + * making the drop zone glitch or disappear. + */ + display: flow-root; margin: 0 -8px; } @@ -87,13 +93,13 @@ #dashboard-widgets .postbox-container .empty-container:after { content: attr(data-emptystring); - margin: auto; position: absolute; - top: 50%; + top: 0; left: 0; right: 0; - transform: translateY( -50% ); - padding: 0 2em; + /* Keep the hint near the top of the drop zone instead of floating it to the + vertical center of a tall empty column. */ + padding: 32px 2em; text-align: center; color: #646970; font-size: 16px;