feat: Make selectable component cards (#38010)

- Styles to make component cards selectable.
- Action to select a component and send a message to the parent of the iframe
- Handler for a "deselect all" message and for selecting a specific component
This commit is contained in:
Chris Chávez
2026-02-18 15:34:35 -05:00
committed by GitHub
parent 43690553f6
commit 5e75d3cce4
2 changed files with 41 additions and 0 deletions

View File

@@ -43,6 +43,7 @@ function($, _, Backbone, gettext, BasePage,
'click .collapse-button': 'collapseXBlock',
'click .xblock-view-action-button': 'viewXBlockContent',
'click .xblock-view-group-link': 'viewXBlockContent',
'click .xblock-header-primary': 'selectXBlock',
},
options: {
@@ -182,6 +183,13 @@ function($, _, Backbone, gettext, BasePage,
offset: document.getElementById(data.payload.locator).offsetTop
}, document.referrer);
break;
case 'clearSelection':
this.$('.studio-xblock-wrapper.is-selected').removeClass('is-selected');
break;
case 'selectXBlock':
this.$('.studio-xblock-wrapper.is-selected').removeClass('is-selected');
xblockWrapper.addClass('is-selected');
break;
default:
console.warn('Unhandled message type:', data.type);
}
@@ -476,6 +484,30 @@ function($, _, Backbone, gettext, BasePage,
});
},
selectXBlock: function(event) {
// Only select when clicking on the header's white space, not on
// buttons, links, inputs, or other interactive elements within it.
var $target = $(event.target);
if ($target.closest('button, a, input, label, .actions-list').length) {
return;
}
var $wrapper = $target.closest('.studio-xblock-wrapper');
// Deselect all other xblocks
this.$('.studio-xblock-wrapper.is-selected').not($wrapper).removeClass('is-selected');
$wrapper.toggleClass('is-selected');
if (this.options.isIframeEmbed) {
const contentId = this.findXBlockElement(event.target).data('locator');
this.postMessageToParent({
type: 'xblockSelected',
payload: { contentId },
});
}
},
editXBlock: function(event, options) {
event.preventDefault();
const isAccessButton = event.currentTarget.className === 'access-button';

View File

@@ -35,9 +35,18 @@ body,
border-color: transparent;
}
.studio-xblock-wrapper {
// STATE: selected
&.is-selected {
border-color: $primary;
box-shadow: 0 0 3px 3px $primary;
}
}
.xblock-header-primary {
padding: ($baseline * 1.2) ($baseline * 1.2) ($baseline / 1.67);
border-bottom: none;
cursor: pointer;
.header-details {
.xblock-display-title {