diff --git a/src/addons/addon-precedence.js b/src/addons/addon-precedence.js
index f99a3112af9..bfc80cc4b6a 100644
--- a/src/addons/addon-precedence.js
+++ b/src/addons/addon-precedence.js
@@ -3,10 +3,7 @@
// If an addon isn't listed here, it's interpreted to have lowest precedence and
// that its order with other unlisted addons does not matter.
const addonPrecedence = [
- 'columns',
- 'editor-stage-left',
- 'editor-theme3',
- 'hide-stage'
+
];
/**
diff --git a/src/addons/addons.js b/src/addons/addons.js
index 5b4ee291a4c..c3582f07e38 100644
--- a/src/addons/addons.js
+++ b/src/addons/addons.js
@@ -55,7 +55,6 @@ const addons = [
'block-duplicate',
'swap-local-global',
'editor-comment-previews',
- 'columns',
'number-pad',
'editor-number-arrow-keys',
'expanded-backpack',
diff --git a/src/addons/addons/columns/_manifest_entry.js b/src/addons/addons/columns/_manifest_entry.js
deleted file mode 100644
index 554103cceb9..00000000000
--- a/src/addons/addons/columns/_manifest_entry.js
+++ /dev/null
@@ -1,28 +0,0 @@
-/* generated by pull.js */
-const manifest = {
- "editorOnly": true,
- "noTranslations": true,
- "name": "Two-column category menu",
- "description": "Splits the block category menu into two columns and moves it to the top of the block palette, like in Scratch 2.0.",
- "credits": [
- {
- "name": "TheColaber",
- "link": "https://scratch.mit.edu/TheColaber"
- }
- ],
- "tags": [
- "theme"
- ],
- "dynamicDisable": true,
- "userscripts": [
- {
- "url": "userscript.js"
- }
- ],
- "userstyles": [
- {
- "url": "style.css"
- }
- ]
-};
-export default manifest;
diff --git a/src/addons/addons/columns/_runtime_entry.js b/src/addons/addons/columns/_runtime_entry.js
deleted file mode 100644
index 76c9ca1f431..00000000000
--- a/src/addons/addons/columns/_runtime_entry.js
+++ /dev/null
@@ -1,7 +0,0 @@
-/* generated by pull.js */
-import _js from "./userscript.js";
-import _css from "!css-loader!./style.css";
-export const resources = {
- "userscript.js": _js,
- "style.css": _css,
-};
diff --git a/src/addons/addons/columns/style.css b/src/addons/addons/columns/style.css
deleted file mode 100644
index 39970684dff..00000000000
--- a/src/addons/addons/columns/style.css
+++ /dev/null
@@ -1,100 +0,0 @@
-[class*="blocks_blocks_"] .blocklyToolboxDiv {
- width: 310px;
- height: auto !important;
-}
-
-.scratchCategoryMenu {
- width: 100%;
- columns: 2;
- column-gap: 0.5rem;
- padding: 0.25rem;
-}
-
-.scratchCategorySecondMenu {
- columns: 1;
- display: grid;
- grid-template-columns: repeat(2, 1fr);
- padding-bottom: 2.25rem;
-}
-
-.scratchCategorySecondMenu:empty {
- padding-top: 0;
- padding-bottom: 2rem;
-}
-
-.scratchCategoryMenuItem {
- display: inline-flex; /* inline so that it isn't split between both columns */
- width: 100%;
- padding: 0.25rem;
- border-radius: 0.875rem;
-}
-
-.scratchCategoryItemBubble,
-.scratchCategoryItemIcon {
- margin: 0;
- margin-inline-end: 0.5rem;
-}
-
-.scratchCategoryMenuItemLabel {
- flex: 1;
- display: flex;
- align-items: center;
-}
-
-[class*="gui_extension-button-container_"] {
- top: var(--sa-add-extension-button-y);
- bottom: auto;
- margin-inline-start: 0.5rem;
- width: calc(308px - 1rem);
- height: calc(1.75rem - 2px);
- background-color: transparent;
- border-color: var(--editorDarkMode-border, rgba(0, 0, 0, 0.15));
-}
-
-/* [dir] is for specificity to override editor-stage-left */
-[dir] [class*="gui_extension-button-container_"] {
- border-radius: 0.25rem;
-}
-
-[class*="gui_extension-button-container_"]:hover {
- background-color: var(--editorDarkMode-accent, white);
-}
-
-[class*="gui_extension-button-container_"]::before {
- display: none;
-}
-
-[class*="gui_extension-button_"] {
- display: flex;
- align-items: center;
- padding-inline: 0;
-}
-
-[class*="gui_extension-button-icon_"] {
- filter: var(--editorDarkMode-categoryMenu-invertedFilter, brightness(0.4));
-}
-
-[class*="gui_extension-button-container_"]:hover [class*="gui_extension-button-icon_"] {
- filter: var(--editorDarkMode-accent-invertedFilter, brightness(0.4));
-}
-
-.sa-add-extension-label {
- color: var(--editorDarkMode-categoryMenu-text, #575e75);
- font-size: 0.65rem;
-}
-
-[class*="gui_extension-button-container_"]:hover .sa-add-extension-label {
- color: var(--editorDarkMode-accent-text, #575e75);
- font-size: 0.65rem;
-}
-
-/* hide-flyout compatibility */
-
-[class*="gui_tabs_"] {
- --sa-flyout-width: 310px;
- --sa-category-width: 0;
-}
-
-.sa-flyout-placeHolder {
- top: calc(var(--sa-flyout-y));
-}
diff --git a/src/addons/addons/columns/userscript.js b/src/addons/addons/columns/userscript.js
deleted file mode 100644
index d19c059e8cc..00000000000
--- a/src/addons/addons/columns/userscript.js
+++ /dev/null
@@ -1,181 +0,0 @@
-export default async function ({ addon, msg, console }) {
- const Blockly = await addon.tab.traps.getBlockly();
-
- // https://github.com/scratchfoundation/scratch-blocks/blob/893c7e7ad5bfb416eaed75d9a1c93bdce84e36ab/core/toolbox.js#L235
- const _ToolboxPosition = Blockly.Toolbox.prototype.position;
- Blockly.Toolbox.prototype.position = function () {
- _ToolboxPosition.call(this);
-
- // Update flyout position when category menu height changes.
- if (this.HtmlDiv && !this.HtmlDiv._observer) {
- this.HtmlDiv._observer = new ResizeObserver(() => {
- this.flyout_.position();
- });
- this.HtmlDiv._observer.observe(this.HtmlDiv);
- }
- };
-
- // https://github.com/scratchfoundation/scratch-blocks/blob/893c7e7ad5bfb416eaed75d9a1c93bdce84e36ab/core/flyout_vertical.js#L314
- const _VerticalFlyoutPosition = Blockly.VerticalFlyout.prototype.position;
- Blockly.VerticalFlyout.prototype.position = function () {
- _VerticalFlyoutPosition.call(this);
- if (addon.self.disabled || !this.isVisible()) {
- return;
- }
- var targetWorkspaceMetrics = this.targetWorkspace_.getMetrics();
- if (!targetWorkspaceMetrics) {
- // Hidden components will return null.
- return;
- }
-
- // In RTL, subtract the total width of left and right workspace borders and the category menu border
- // from the workspace width.
- var x = this.toolboxPosition_ === Blockly.TOOLBOX_AT_RIGHT ? targetWorkspaceMetrics.viewWidth - 3 : 0;
- var y = this.parentToolbox_.HtmlDiv.offsetHeight;
-
- // Addon sets the width of the flyout to the width of the toolbox.
- this.width_ = this.parentToolbox_.getWidth();
- this.height_ = Math.max(0, targetWorkspaceMetrics.viewHeight - y);
-
- this.setBackgroundPath_(this.width_, this.height_);
-
- this.svgGroup_.setAttribute("width", this.width_);
- this.svgGroup_.setAttribute("height", this.height_);
- var transform = "translate(" + x + "px," + y + "px)";
- Blockly.utils.setCssTransform(this.svgGroup_, transform);
-
- // Update the scrollbar (if one exists).
- if (this.scrollbar_) {
- // Set the scrollbars origin to be the top left of the flyout.
- this.scrollbar_.setOrigin(
- x + (this.toolboxPosition_ === Blockly.TOOLBOX_AT_RIGHT ? 0 : this.width_ - this.getWidth()),
- y
- );
- this.scrollbar_.resize();
- }
-
- // Set CSS variables for the userstyle.
- const container = this.svgGroup_.closest("[class*='gui_tab-panel_']");
- container.style.setProperty("--sa-add-extension-button-y", `${y - 33}px`);
- container.parentElement.style.setProperty("--sa-flyout-y", `${y}px`);
- };
-
- // https://github.com/scratchfoundation/scratch-blocks/blob/893c7e7ad5bfb416eaed75d9a1c93bdce84e36ab/core/flyout_base.js#L370
- const _VerticalFlyoutGetWidth = Blockly.VerticalFlyout.prototype.getWidth;
- Blockly.VerticalFlyout.prototype.getWidth = function () {
- // In RTL, this will be called by Blockly to position blocks inside the flyout.
- let width = _VerticalFlyoutGetWidth.call(this);
- if (!addon.self.disabled) width += 60;
- return width;
- };
-
- // https://github.com/scratchfoundation/scratch-blocks/blob/893c7e7ad5bfb416eaed75d9a1c93bdce84e36ab/core/toolbox.js#L595
- const _CategoryMenuCreateDom = Blockly.Toolbox.CategoryMenu.prototype.createDom;
- Blockly.Toolbox.CategoryMenu.prototype.createDom = function () {
- _CategoryMenuCreateDom.call(this);
- if (addon.self.disabled) return;
- this.secondTable = document.createElement("div");
- this.secondTable.className =
- "scratchCategorySecondMenu " +
- (this.parent_.horizontalLayout_ ? "scratchCategoryMenuHorizontal" : "scratchCategoryMenu");
- this.parentHtml_.appendChild(this.secondTable);
- };
-
- // https://github.com/scratchfoundation/scratch-blocks/blob/893c7e7ad5bfb416eaed75d9a1c93bdce84e36ab/core/toolbox.js#L606
- const _CategoryMenuPopulate = Blockly.Toolbox.CategoryMenu.prototype.populate;
- Blockly.Toolbox.CategoryMenu.prototype.populate = function (domTree) {
- if (!domTree) return;
-
- const Categories = [
- "motion",
- "looks",
- "sound",
- "events",
- "control",
- "sensing",
- "operators",
- "variables",
- "lists",
- "myBlocks",
- ];
- const extensionsNodes = [];
- const extensionTree = domTree.cloneNode(true);
- if (!addon.self.disabled) {
- extensionTree.childNodes.forEach((child) => {
- if (child.tagName === "category" && !Categories.includes(child.id)) {
- extensionsNodes.push(child.cloneNode(true));
- child.remove();
- }
- });
- }
- _CategoryMenuPopulate.call(this, extensionTree);
- for (const child of extensionsNodes) {
- const row = document.createElement("div");
- row.className = "scratchCategoryMenuRow";
- this.secondTable.appendChild(row);
- if (child) {
- this.categories_.push(new Blockly.Toolbox.Category(this, row, child));
- }
- }
- if (!addon.self.disabled) {
- this.height_ = this.table.offsetHeight + this.secondTable.offsetHeight;
- }
- };
-
- // https://github.com/scratchfoundation/scratch-blocks/blob/893c7e7ad5bfb416eaed75d9a1c93bdce84e36ab/core/toolbox.js#L639
- const _CategoryMenuDispose = Blockly.Toolbox.CategoryMenu.prototype.dispose;
- Blockly.Toolbox.CategoryMenu.prototype.dispose = function () {
- _CategoryMenuDispose.call(this);
- if (this.secondTable) {
- this.secondTable.remove();
- this.secondTable = null;
- }
- };
-
- function updateToolbox() {
- const workspace = Blockly.getMainWorkspace();
- const toolbox = workspace.getToolbox();
- if (!toolbox) return;
- const categoryMenu = toolbox.categoryMenu_;
- if (!categoryMenu) return;
-
- // Scratch may have already updated the toolbox for us, so no need to update it again.
- if (categoryMenu.secondTable && !addon.self.disabled) return;
- // Must dispose and createDom the category menu so we can run our polluted commands.
- categoryMenu.dispose();
- categoryMenu.createDom();
- // Repopulate the category menu since we've just disposed it.
- toolbox.populate_(workspace.options.languageTree);
- // Reposition the toolbox, since it's likely our addon moved it.
- toolbox.position();
- }
-
- function updateClass() {
- // Add class to allow editor-compact to handle this addon
- if (addon.self.disabled) document.body.classList.remove("sa-columns-enabled");
- else document.body.classList.add("sa-columns-enabled");
- }
-
- updateToolbox();
- addon.self.addEventListener("disabled", updateToolbox);
- addon.self.addEventListener("reenabled", updateToolbox);
-
- updateClass();
- addon.self.addEventListener("disabled", updateClass);
- addon.self.addEventListener("reenabled", updateClass);
-
- while (true) {
- const addExtensionButton = await addon.tab.waitForElement("[class*='gui_extension-button_']", {
- markAsSeen: true,
- reduxEvents: ["scratch-gui/mode/SET_PLAYER", "fontsLoaded/SET_FONTS_LOADED", "scratch-gui/locales/SELECT_LOCALE"],
- condition: () => !addon.tab.redux.state.scratchGui.mode.isPlayerOnly,
- });
- const addExtensionLabel = Object.assign(document.createElement("span"), {
- className: "sa-add-extension-label",
- innerText: addon.tab.scratchMessage("gui.gui.addExtension"),
- });
- addon.tab.displayNoneWhileDisabled(addExtensionLabel);
- addExtensionButton.appendChild(addExtensionLabel);
- addExtensionButton.removeAttribute("title");
- }
-}
diff --git a/src/addons/generated/addon-entries.js b/src/addons/generated/addon-entries.js
index ec3f3944ac4..ae269bf0832 100644
--- a/src/addons/generated/addon-entries.js
+++ b/src/addons/generated/addon-entries.js
@@ -55,7 +55,6 @@ export default {
"block-duplicate": () => import(/* webpackChunkName: "addon-default-entry" */ "../addons/block-duplicate/_runtime_entry.js"),
"swap-local-global": () => import(/* webpackChunkName: "addon-entry-swap-local-global" */ "../addons/swap-local-global/_runtime_entry.js"),
"editor-comment-previews": () => import(/* webpackChunkName: "addon-default-entry" */ "../addons/editor-comment-previews/_runtime_entry.js"),
- "columns": () => import(/* webpackChunkName: "addon-entry-columns" */ "../addons/columns/_runtime_entry.js"),
"number-pad": () => import(/* webpackChunkName: "addon-entry-number-pad" */ "../addons/number-pad/_runtime_entry.js"),
"editor-number-arrow-keys": () => import(/* webpackChunkName: "addon-entry-editor-number-arrow-keys" */ "../addons/editor-number-arrow-keys/_runtime_entry.js"),
"expanded-backpack": () => import(/* webpackChunkName: "addon-entry-expanded-backpack" */ "../addons/expanded-backpack/_runtime_entry.js"),
diff --git a/src/addons/generated/addon-manifests.js b/src/addons/generated/addon-manifests.js
index d153c6beef4..d355905f1a4 100644
--- a/src/addons/generated/addon-manifests.js
+++ b/src/addons/generated/addon-manifests.js
@@ -53,7 +53,6 @@ import _disable_paste_offset from "../addons/disable-paste-offset/_manifest_entr
import _block_duplicate from "../addons/block-duplicate/_manifest_entry.js";
import _swap_local_global from "../addons/swap-local-global/_manifest_entry.js";
import _editor_comment_previews from "../addons/editor-comment-previews/_manifest_entry.js";
-import _columns from "../addons/columns/_manifest_entry.js";
import _number_pad from "../addons/number-pad/_manifest_entry.js";
import _editor_number_arrow_keys from "../addons/editor-number-arrow-keys/_manifest_entry.js";
import _expanded_backpack from "../addons/expanded-backpack/_manifest_entry.js";
@@ -119,7 +118,6 @@ export default {
"block-duplicate": _block_duplicate,
"swap-local-global": _swap_local_global,
"editor-comment-previews": _editor_comment_previews,
- "columns": _columns,
"number-pad": _number_pad,
"editor-number-arrow-keys": _editor_number_arrow_keys,
"expanded-backpack": _expanded_backpack,
diff --git a/src/components/blocks/blocks.css b/src/components/blocks/blocks.css
index 583f587f797..3577010e88d 100644
--- a/src/components/blocks/blocks.css
+++ b/src/components/blocks/blocks.css
@@ -44,7 +44,6 @@
border-right: 1px solid $ui-black-transparent;
border-bottom: 1px solid $ui-black-transparent;
box-sizing: content-box;
- height: calc(100% - 3.25rem) !important;
/*
For now, the layout cannot support scrollbars in the category menu.
@@ -55,6 +54,10 @@
-ms-overflow-style: none;
}
+.blocks :global(.blocklyToolboxDiv:not(.blocklyToolboxDivColumns)) {
+ height: calc(100% - 3.25rem) !important;
+}
+
[dir="rtl"] .blocks :global(.blocklyToolboxDiv) {
border-right: none;
border-left: 1px solid $ui-black-transparent;
diff --git a/src/components/editor-settings/editor-settings.jsx b/src/components/editor-settings/editor-settings.jsx
index 76f1d55907f..2fbc96d6fcd 100644
--- a/src/components/editor-settings/editor-settings.jsx
+++ b/src/components/editor-settings/editor-settings.jsx
@@ -71,6 +71,8 @@ class EditorSettingsModal extends React.Component {
+
+
@@ -95,7 +97,7 @@ class EditorSettingsModal extends React.Component {
-
+
diff --git a/src/components/gui/gui.css b/src/components/gui/gui.css
index 9633205ac9e..28494def7e5 100644
--- a/src/components/gui/gui.css
+++ b/src/components/gui/gui.css
@@ -271,10 +271,24 @@
border: 1px solid $looks-secondary;
box-sizing: content-box; /* To match scratch-block vertical toolbox borders */
}
+.extension-button-container.hover {
+ bottom: 0.75rem;
+ left: 15.5rem;
+ width: 2.75rem;
+ height: 2.75rem;
+ border-radius: 100%;
+ box-shadow: 0 0 0 4px $looks-transparent;
+ transition: transform, box-shadow 0.5s;
+}
+.extension-button-container.hover:hover {
+ background: $extensions-primary;
+ transform: scale(1.1);
+ box-shadow: 0 0 0 6px $looks-transparent;
+}
$fade-out-distance: 15px;
-.extension-button-container:before {
+.extension-button-container:not(.hover):before {
content: "";
position: absolute;
top: calc(calc(-1 * $fade-out-distance) - 1px);
diff --git a/src/components/gui/gui.jsx b/src/components/gui/gui.jsx
index ee7767e6eb4..73af52fc120 100644
--- a/src/components/gui/gui.jsx
+++ b/src/components/gui/gui.jsx
@@ -453,7 +453,7 @@ const GUIComponent = props => {
vm={vm}
/>
-
+