diff --git a/vendor/magento/module-contact/view/frontend/layout/contact_index_index.xml b/vendor/magento/module-contact/view/frontend/layout/contact_index_index.xml
index 078c1a4ff562..9fb4fea6c773 100644
--- a/vendor/magento/module-contact/view/frontend/layout/contact_index_index.xml
+++ b/vendor/magento/module-contact/view/frontend/layout/contact_index_index.xml
@@ -12,6 +12,9 @@
     <body>
         <referenceContainer name="content">
             <block class="Magento\Contact\Block\ContactForm" name="contactForm" template="Magento_Contact::form.phtml">
+                <arguments>
+                    <argument name="button_lock_manager" xsi:type="object">Magento\Framework\View\Element\ButtonLockManager</argument>
+                </arguments>
                 <container name="form.additional.info" label="Form Additional Info"/>
             </block>
         </referenceContainer>
diff --git a/vendor/magento/module-contact/view/frontend/templates/form.phtml b/vendor/magento/module-contact/view/frontend/templates/form.phtml
index 99e61e8249da..54bb9e78287c 100644
--- a/vendor/magento/module-contact/view/frontend/templates/form.phtml
+++ b/vendor/magento/module-contact/view/frontend/templates/form.phtml
@@ -80,7 +80,11 @@ $viewModel = $block->getViewModel();
     <div class="actions-toolbar">
         <div class="primary">
             <input type="hidden" name="hideit" id="hideit" value="" />
-            <button type="submit" title="<?= $block->escapeHtmlAttr(__('Submit')) ?>" class="action submit primary">
+            <button type="submit" title="<?= $block->escapeHtmlAttr(__('Submit')) ?>" class="action submit primary"
+                    id="send2"
+                <?php if ($block->getButtonLockManager()->isDisabled('contact_us_form_submit')): ?>
+                    disabled="disabled"
+                <?php endif; ?>>
                 <span><?= $block->escapeHtml(__('Submit')) ?></span>
             </button>
         </div>
diff --git a/vendor/magento/module-customer/ViewModel/CreateAccountButton.php b/vendor/magento/module-customer/ViewModel/CreateAccountButton.php
deleted file mode 100644
index 8fa8718fe37e..000000000000
--- a/vendor/magento/module-customer/ViewModel/CreateAccountButton.php
+++ /dev/null
@@ -1,26 +0,0 @@
-<?php
-/**
- * Copyright © Magento, Inc. All rights reserved.
- * See COPYING.txt for license details.
- */
-declare(strict_types=1);
-
-namespace Magento\Customer\ViewModel;
-
-use Magento\Framework\View\Element\Block\ArgumentInterface;
-
-/**
- * Custom Create Account button view model
- */
-class CreateAccountButton implements ArgumentInterface
-{
-    /**
-     * If Create Account button should be disabled
-     *
-     * @return bool
-     */
-    public function disabled(): bool
-    {
-        return false;
-    }
-}
diff --git a/vendor/magento/module-customer/ViewModel/ForgotPasswordButton.php b/vendor/magento/module-customer/ViewModel/ForgotPasswordButton.php
deleted file mode 100644
index 4a68227dd27b..000000000000
--- a/vendor/magento/module-customer/ViewModel/ForgotPasswordButton.php
+++ /dev/null
@@ -1,26 +0,0 @@
-<?php
-/**
- * Copyright © Magento, Inc. All rights reserved.
- * See COPYING.txt for license details.
- */
-declare(strict_types=1);
-
-namespace Magento\Customer\ViewModel;
-
-use Magento\Framework\View\Element\Block\ArgumentInterface;
-
-/**
- * Forgot password button view model
- */
-class ForgotPasswordButton implements ArgumentInterface
-{
-    /**
-     * If Forgot password button should be disabled
-     *
-     * @return bool
-     */
-    public function disabled(): bool
-    {
-        return false;
-    }
-}
diff --git a/vendor/magento/module-customer/ViewModel/LoginButton.php b/vendor/magento/module-customer/ViewModel/LoginButton.php
deleted file mode 100644
index 75349043e8ba..000000000000
--- a/vendor/magento/module-customer/ViewModel/LoginButton.php
+++ /dev/null
@@ -1,26 +0,0 @@
-<?php
-/**
- * Copyright © Magento, Inc. All rights reserved.
- * See COPYING.txt for license details.
- */
-declare(strict_types=1);
-
-namespace Magento\Customer\ViewModel;
-
-use Magento\Framework\View\Element\Block\ArgumentInterface;
-
-/**
- * Custom Login button view model
- */
-class LoginButton implements ArgumentInterface
-{
-    /**
-     * If Login button should be disabled
-     *
-     * @return bool
-     */
-    public function disabled(): bool
-    {
-        return false;
-    }
-}
diff --git a/vendor/magento/module-customer/view/frontend/layout/customer_account_create.xml b/vendor/magento/module-customer/view/frontend/layout/customer_account_create.xml
index c75086e8ea49..0afe06becc53 100644
--- a/vendor/magento/module-customer/view/frontend/layout/customer_account_create.xml
+++ b/vendor/magento/module-customer/view/frontend/layout/customer_account_create.xml
@@ -18,7 +18,7 @@
                 <arguments>
                     <argument name="attribute_data" xsi:type="object">Magento\Customer\Block\DataProviders\AddressAttributeData</argument>
                     <argument name="region_provider" xsi:type="object">Magento\Customer\ViewModel\Address\RegionProvider</argument>
-                    <argument name="create_account_button_view_model" xsi:type="object">Magento\Customer\ViewModel\CreateAccountButton</argument>
+                    <argument name="button_lock_manager" xsi:type="object">Magento\Framework\View\Element\ButtonLockManager</argument>
                 </arguments>
                 <container name="form.additional.info" as="form_additional_info"/>
                 <container name="customer.form.register.fields.before" as="form_fields_before" label="Form Fields Before" htmlTag="div" htmlClass="customer-form-before"/>
diff --git a/vendor/magento/module-customer/view/frontend/layout/customer_account_edit.xml b/vendor/magento/module-customer/view/frontend/layout/customer_account_edit.xml
index e89aa5ab624d..3dd38d61aee0 100644
--- a/vendor/magento/module-customer/view/frontend/layout/customer_account_edit.xml
+++ b/vendor/magento/module-customer/view/frontend/layout/customer_account_edit.xml
@@ -21,6 +21,9 @@
         </referenceBlock>
         <referenceContainer name="content">
             <block class="Magento\Customer\Block\Form\Edit" name="customer_edit" template="Magento_Customer::form/edit.phtml" cacheable="false">
+                <arguments>
+                    <argument name="button_lock_manager" xsi:type="object">Magento\Framework\View\Element\ButtonLockManager</argument>
+                </arguments>
                 <container name="form.additional.info" as="form_additional_info"/>
             </block>
         </referenceContainer>
diff --git a/vendor/magento/module-customer/view/frontend/layout/customer_account_forgotpassword.xml b/vendor/magento/module-customer/view/frontend/layout/customer_account_forgotpassword.xml
index 7c8a6991e5a8..7fcf612de0c0 100644
--- a/vendor/magento/module-customer/view/frontend/layout/customer_account_forgotpassword.xml
+++ b/vendor/magento/module-customer/view/frontend/layout/customer_account_forgotpassword.xml
@@ -18,7 +18,7 @@
         <referenceContainer name="content">
             <block class="Magento\Customer\Block\Account\Forgotpassword" name="forgotPassword" template="Magento_Customer::form/forgotpassword.phtml">
                 <arguments>
-                    <argument name="forgot_password_button_view_model" xsi:type="object">Magento\Customer\ViewModel\ForgotPasswordButton</argument>
+                    <argument name="button_lock_manager" xsi:type="object">Magento\Framework\View\Element\ButtonLockManager</argument>
                 </arguments>
                 <container name="form.additional.info" as="form_additional_info"/>
             </block>
diff --git a/vendor/magento/module-customer/view/frontend/layout/customer_account_login.xml b/vendor/magento/module-customer/view/frontend/layout/customer_account_login.xml
index 8fb51eeb6650..90cd080cf2f6 100644
--- a/vendor/magento/module-customer/view/frontend/layout/customer_account_login.xml
+++ b/vendor/magento/module-customer/view/frontend/layout/customer_account_login.xml
@@ -16,7 +16,7 @@
                 <block class="Magento\Customer\Block\Form\Login" name="customer_form_login" template="Magento_Customer::form/login.phtml">
                     <container name="form.additional.info" as="form_additional_info"/>
                     <arguments>
-                        <argument name="login_button_view_model" xsi:type="object">Magento\Customer\ViewModel\LoginButton</argument>
+                        <argument name="button_lock_manager" xsi:type="object">Magento\Framework\View\Element\ButtonLockManager</argument>
                     </arguments>
                 </block>
                 <block class="Magento\Customer\Block\Form\Login\Info" name="customer.new" template="Magento_Customer::newcustomer.phtml"/>
diff --git a/vendor/magento/module-customer/view/frontend/templates/form/edit.phtml b/vendor/magento/module-customer/view/frontend/templates/form/edit.phtml
index 6734e9ad30a4..342f1ea23cdf 100644
--- a/vendor/magento/module-customer/view/frontend/templates/form/edit.phtml
+++ b/vendor/magento/module-customer/view/frontend/templates/form/edit.phtml
@@ -115,8 +115,11 @@ use Magento\Customer\Block\Widget\Name;
 
     <div class="actions-toolbar">
         <div class="primary">
-            <button type="submit" class="action save primary" title="<?= $block->escapeHtmlAttr(__('Save')) ?>">
-                <span><?= $block->escapeHtml(__('Save')) ?></span>
+            <button type="submit" class="action save primary" title="<?= $block->escapeHtmlAttr(__('Save')) ?>"
+                <?php if ($block->getButtonLockManager()->isDisabled('customer_edit_form_submit')): ?>
+                    disabled="disabled"
+                <?php endif; ?>>
+            <span><?= $block->escapeHtml(__('Save')) ?></span>
             </button>
         </div>
         <div class="secondary">
diff --git a/vendor/magento/module-customer/view/frontend/templates/form/forgotpassword.phtml b/vendor/magento/module-customer/view/frontend/templates/form/forgotpassword.phtml
index 2c6615828394..1455fdbbd9f1 100644
--- a/vendor/magento/module-customer/view/frontend/templates/form/forgotpassword.phtml
+++ b/vendor/magento/module-customer/view/frontend/templates/form/forgotpassword.phtml
@@ -9,8 +9,6 @@
 // phpcs:disable Generic.Files.LineLength.TooLong
 
 /** @var \Magento\Customer\Block\Account\Forgotpassword $block */
-/** @var \Magento\Customer\ViewModel\ForgotPasswordButton $forgotPasswordButtonViewModel */
-$forgotPasswordButtonViewModel = $block->getData('forgot_password_button_view_model');
 ?>
 <form class="form password forget"
       action="<?= $block->escapeUrl($block->getUrl('*/*/forgotpasswordpost')) ?>"
@@ -29,7 +27,7 @@ $forgotPasswordButtonViewModel = $block->getData('forgot_password_button_view_mo
     </fieldset>
     <div class="actions-toolbar">
         <div class="primary">
-            <button type="submit" class="action submit primary" id="send2" <?php if ($forgotPasswordButtonViewModel->disabled()): ?> disabled="disabled" <?php endif; ?>><span><?= $block->escapeHtml(__('Reset My Password')) ?></span></button>
+            <button type="submit" class="action submit primary" id="send2" <?php if ($block->getButtonLockManager()->isDisabled('customer_forgot_password_form_submit')): ?> disabled="disabled" <?php endif; ?>><span><?= $block->escapeHtml(__('Reset My Password')) ?></span></button>
         </div>
         <div class="secondary">
             <a class="action back" href="<?= $block->escapeUrl($block->getLoginUrl()) ?>"><span><?= $block->escapeHtml(__('Go back')) ?></span></a>
diff --git a/vendor/magento/module-customer/view/frontend/templates/form/login.phtml b/vendor/magento/module-customer/view/frontend/templates/form/login.phtml
index 0cc3dd5973b2..15500f4241ff 100644
--- a/vendor/magento/module-customer/view/frontend/templates/form/login.phtml
+++ b/vendor/magento/module-customer/view/frontend/templates/form/login.phtml
@@ -7,8 +7,6 @@
 // phpcs:disable Generic.Files.LineLength.TooLong
 
 /** @var \Magento\Customer\Block\Form\Login $block */
-/** @var \Magento\Customer\ViewModel\LoginButton $loginButtonViewModel */
-$loginButtonViewModel = $block->getData('login_button_view_model');
 ?>
 <div class="block block-customer-login">
     <div class="block-title">
@@ -49,7 +47,11 @@ $loginButtonViewModel = $block->getData('login_button_view_model');
                 </div>
                 <?= $block->getChildHtml('form_additional_info') ?>
                 <div class="actions-toolbar">
-                    <div class="primary"><button type="submit" class="action login primary" name="send" id="send2" <?php if ($loginButtonViewModel->disabled()): ?> disabled="disabled" <?php endif; ?>><span><?= $block->escapeHtml(__('Sign In')) ?></span></button></div>
+                    <div class="primary">
+                        <button type="submit" class="action login primary" name="send" id="send2" <?php if ($block->getButtonLockManager()->isDisabled('customer_login_form_submit')): ?> disabled="disabled" <?php endif; ?>>
+                            <span><?= $block->escapeHtml(__('Sign In')) ?></span>
+                        </button>
+                    </div>
                     <div class="secondary"><a class="action remind" href="<?= $block->escapeUrl($block->getForgotPasswordUrl()) ?>"><span><?= $block->escapeHtml(__('Forgot Your Password?')) ?></span></a></div>
                 </div>
             </fieldset>
diff --git a/vendor/magento/module-customer/view/frontend/templates/form/register.phtml b/vendor/magento/module-customer/view/frontend/templates/form/register.phtml
index 900be3d20bf2..58af2f1bf594 100644
--- a/vendor/magento/module-customer/view/frontend/templates/form/register.phtml
+++ b/vendor/magento/module-customer/view/frontend/templates/form/register.phtml
@@ -17,8 +17,6 @@ $directoryHelper = $block->getData('directoryHelper');
 /** @var \Magento\Customer\ViewModel\Address\RegionProvider $regionProvider */
 $regionProvider = $block->getRegionProvider();
 $formData = $block->getFormData();
-/** @var \Magento\Customer\ViewModel\CreateAccountButton $createAccountButtonViewModel */
-$createAccountButtonViewModel = $block->getData('create_account_button_view_model');
 ?>
 <?php $displayAll = $block->getConfig('general/region/display_all'); ?>
 <?= $block->getChildHtml('form_fields_before') ?>
@@ -296,7 +294,9 @@ $createAccountButtonViewModel = $block->getData('create_account_button_view_mode
                     class="action submit primary"
                     title="<?= $escaper->escapeHtmlAttr(__('Create an Account')) ?>"
                     id="send2"
-                    <?php if ($createAccountButtonViewModel->disabled()): ?> disabled="disabled" <?php endif; ?>>
+                <?php if ($block->getButtonLockManager()->isDisabled('customer_create_form_submit')): ?>
+                    disabled="disabled"
+                <?php endif; ?>>
                 <span><?= $escaper->escapeHtml(__('Create an Account')) ?></span>
             </button>
         </div>
diff --git a/vendor/magento/module-newsletter/view/frontend/layout/default.xml b/vendor/magento/module-newsletter/view/frontend/layout/default.xml
index 32a08359333c..6a2835862096 100644
--- a/vendor/magento/module-newsletter/view/frontend/layout/default.xml
+++ b/vendor/magento/module-newsletter/view/frontend/layout/default.xml
@@ -11,7 +11,11 @@
             <block class="Magento\Framework\View\Element\Js\Components" name="newsletter_head_components" template="Magento_Newsletter::js/components.phtml" ifconfig="newsletter/general/active"/>
         </referenceBlock>
         <referenceContainer name="footer">
-            <block class="Magento\Newsletter\Block\Subscribe" name="form.subscribe" as="subscribe" before="-" template="Magento_Newsletter::subscribe.phtml" ifconfig="newsletter/general/active"/>
+            <block class="Magento\Newsletter\Block\Subscribe" name="form.subscribe" as="subscribe" before="-" template="Magento_Newsletter::subscribe.phtml" ifconfig="newsletter/general/active">
+                <arguments>
+                    <argument name="button_lock_manager" xsi:type="object">Magento\Framework\View\Element\ButtonLockManager</argument>
+                </arguments>
+            </block>
         </referenceContainer>
     </body>
 </page>
diff --git a/vendor/magento/module-newsletter/view/frontend/templates/subscribe.phtml b/vendor/magento/module-newsletter/view/frontend/templates/subscribe.phtml
index 768c97ef316f..554cc4e16bd6 100644
--- a/vendor/magento/module-newsletter/view/frontend/templates/subscribe.phtml
+++ b/vendor/magento/module-newsletter/view/frontend/templates/subscribe.phtml
@@ -33,7 +33,10 @@
                 <button class="action subscribe primary"
                         title="<?= $block->escapeHtmlAttr(__('Subscribe')) ?>"
                         type="submit"
-                        aria-label="Subscribe">
+                        aria-label="Subscribe"
+                    <?php if ($block->getButtonLockManager()->isDisabled('newsletter_form_submit')): ?>
+                        disabled="disabled"
+                    <?php endif; ?>>
                     <span><?= $block->escapeHtml(__('Subscribe')) ?></span>
                 </button>
             </div>
diff --git a/vendor/magento/module-review/view/frontend/layout/catalog_product_view.xml b/vendor/magento/module-review/view/frontend/layout/catalog_product_view.xml
index a6b46f8f25a7..b714bac3a7ab 100644
--- a/vendor/magento/module-review/view/frontend/layout/catalog_product_view.xml
+++ b/vendor/magento/module-review/view/frontend/layout/catalog_product_view.xml
@@ -23,6 +23,9 @@
                     <argument name="sort_order" xsi:type="string">30</argument>
                 </arguments>
                 <block class="Magento\Review\Block\Form" name="product.review.form" as="review_form" ifconfig="catalog/review/active">
+                    <arguments>
+                        <argument name="button_lock_manager" xsi:type="object">Magento\Framework\View\Element\ButtonLockManager</argument>
+                    </arguments>
                     <container name="product.review.form.fields.before" as="form_fields_before" label="Review Form Fields Before"/>
                 </block>
             </block>
diff --git a/vendor/magento/module-review/view/frontend/layout/checkout_cart_configure.xml b/vendor/magento/module-review/view/frontend/layout/checkout_cart_configure.xml
index 8a853cdd2e40..815d7ee1f3ad 100644
--- a/vendor/magento/module-review/view/frontend/layout/checkout_cart_configure.xml
+++ b/vendor/magento/module-review/view/frontend/layout/checkout_cart_configure.xml
@@ -11,6 +11,7 @@
         <referenceBlock name="reviews.tab">
             <block class="Magento\Review\Block\Form\Configure" name="product.review.form" as="review_form" ifconfig="catalog/review/active">
                 <arguments>
+                    <argument name="button_lock_manager" xsi:type="object">Magento\Framework\View\Element\ButtonLockManager</argument>
                     <argument name="jsLayout" xsi:type="array">
                         <item name="components" xsi:type="array">
                             <item name="review-form" xsi:type="array">
diff --git a/vendor/magento/module-review/view/frontend/layout/wishlist_index_configure.xml b/vendor/magento/module-review/view/frontend/layout/wishlist_index_configure.xml
index 8a853cdd2e40..815d7ee1f3ad 100644
--- a/vendor/magento/module-review/view/frontend/layout/wishlist_index_configure.xml
+++ b/vendor/magento/module-review/view/frontend/layout/wishlist_index_configure.xml
@@ -11,6 +11,7 @@
         <referenceBlock name="reviews.tab">
             <block class="Magento\Review\Block\Form\Configure" name="product.review.form" as="review_form" ifconfig="catalog/review/active">
                 <arguments>
+                    <argument name="button_lock_manager" xsi:type="object">Magento\Framework\View\Element\ButtonLockManager</argument>
                     <argument name="jsLayout" xsi:type="array">
                         <item name="components" xsi:type="array">
                             <item name="review-form" xsi:type="array">
diff --git a/vendor/magento/module-review/view/frontend/templates/form.phtml b/vendor/magento/module-review/view/frontend/templates/form.phtml
index 6b00bf681c1e..1a01bfd387cd 100644
--- a/vendor/magento/module-review/view/frontend/templates/form.phtml
+++ b/vendor/magento/module-review/view/frontend/templates/form.phtml
@@ -74,7 +74,12 @@
     </fieldset>
     <div class="actions-toolbar review-form-actions">
         <div class="primary actions-primary">
-            <button type="submit" class="action submit primary"><span><?= $block->escapeHtml(__('Submit Review')) ?></span></button>
+            <button type="submit" class="action submit primary"
+                <?php if ($block->getButtonLockManager()->isDisabled('review_form_submit')): ?>
+                    disabled="disabled"
+                <?php endif; ?>>
+                <span><?= $block->escapeHtml(__('Submit Review')) ?></span>
+            </button>
         </div>
     </div>
 </form>
diff --git a/vendor/magento/module-send-friend/view/frontend/layout/sendfriend_product_send.xml b/vendor/magento/module-send-friend/view/frontend/layout/sendfriend_product_send.xml
index 4d6f3d8c628b..0f76607a4ab7 100644
--- a/vendor/magento/module-send-friend/view/frontend/layout/sendfriend_product_send.xml
+++ b/vendor/magento/module-send-friend/view/frontend/layout/sendfriend_product_send.xml
@@ -14,6 +14,9 @@
         </referenceBlock>
         <referenceContainer name="content">
             <block class="Magento\SendFriend\Block\Send" name="sendfriend.send" cacheable="false" template="Magento_SendFriend::send.phtml">
+                <arguments>
+                    <argument name="button_lock_manager" xsi:type="object">Magento\Framework\View\Element\ButtonLockManager</argument>
+                </arguments>
                 <container name="form.additional.info" as="form_additional_info"/>
             </block>
         </referenceContainer>
diff --git a/vendor/magento/module-send-friend/view/frontend/templates/send.phtml b/vendor/magento/module-send-friend/view/frontend/templates/send.phtml
index bcfc243a4364..2e3058cae896 100644
--- a/vendor/magento/module-send-friend/view/frontend/templates/send.phtml
+++ b/vendor/magento/module-send-friend/view/frontend/templates/send.phtml
@@ -40,7 +40,8 @@
                 <span><?= $block->escapeHtml(__('Email')) ?></span>
             </label>
             <div class="control">
-                <input name="recipients[email][<%- data._index_ %>]" title="<?= $block->escapeHtmlAttr(__('Email')) ?>"
+                <input name="recipients[email][<%- data._index_ %>]"
+                       title="<?= $block->escapeHtmlAttr(__('Email')) ?>"
                        id="recipients-email<%- data._index_ %>" type="email" class="input-text"
                        data-mage-init='{"mage/trim-input":{}}'
                        data-validate="{required:true, 'validate-email':true}"/>
@@ -71,7 +72,8 @@
             <label for="sender-name" class="label"><span><?= $block->escapeHtml(__('Name')) ?></span></label>
             <div class="control">
                 <input name="sender[name]" value="<?= $block->escapeHtmlAttr($block->getUserName()) ?>"
-                       title="<?= $block->escapeHtmlAttr(__('Name')) ?>" id="sender-name" type="text" class="input-text"
+                       title="<?= $block->escapeHtmlAttr(__('Name')) ?>"
+                       id="sender-name" type="text" class="input-text"
                        data-validate="{required:true}"/>
             </div>
         </div>
@@ -88,7 +90,9 @@
         </div>
 
         <div class="field text required">
-            <label for="sender-message" class="label"><span><?= $block->escapeHtml(__('Message')) ?></span></label>
+            <label for="sender-message" class="label">
+                <span><?= $block->escapeHtml(__('Message')) ?></span>
+            </label>
             <div class="control">
                 <textarea name="sender[message]" class="input-text" id="sender-message" cols="3" rows="3"
                           data-validate="{required:true}"><?= $block->escapeHtml($block->getMessage()) ?></textarea>
@@ -103,7 +107,8 @@
         <div id="recipients-options"></div>
         <?php if ($block->getMaxRecipients()): ?>
             <div id="max-recipient-message" class="message notice limit" role="alert">
-                <span><?= $block->escapeHtml(__('Maximum %1 email addresses allowed.', $block->getMaxRecipients())) ?>
+                <span>
+                    <?= $block->escapeHtml(__('Maximum %1 email addresses allowed.', $block->getMaxRecipients())) ?>
                 </span>
             </div>
             <?= /* @noEscape */ $secureRenderer->renderStyleAsTag("display: none;", 'div#max-recipient-message') ?>
@@ -122,7 +127,11 @@
     <div class="actions-toolbar">
         <div class="primary">
             <button type="submit"
-                    class="action submit primary"<?php if (!$block->canSend()): ?> disabled="disabled"<?php endif ?>>
+                    class="action submit primary"
+                    <?php if (!$block->canSend() ||
+                        $block->getButtonLockManager()->isDisabled('sendfriend_form_submit')): ?>
+                    disabled="disabled"
+                    <?php endif ?>>
                 <span><?= $block->escapeHtml(__('Send Email')) ?></span></button>
         </div>
         <div class="secondary">
diff --git a/vendor/magento/framework/View/Element/ButtonLockInterface.php b/vendor/magento/framework/View/Element/ButtonLockInterface.php
new file mode 100644
index 000000000000..e65ce3f245a8
--- /dev/null
+++ b/vendor/magento/framework/View/Element/ButtonLockInterface.php
@@ -0,0 +1,28 @@
+<?php
+/**
+ * Copyright © Magento, Inc. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+declare(strict_types=1);
+
+namespace Magento\Framework\View\Element;
+
+use Magento\Framework\Exception\InputException;
+
+interface ButtonLockInterface
+{
+    /**
+     * Get button code
+     *
+     * @return string
+     */
+    public function getCode(): string;
+
+    /**
+     * If the button should be temporary disabled
+     *
+     * @return bool
+     * @throws InputException
+     */
+    public function isDisabled(): bool;
+}
diff --git a/vendor/magento/framework/View/Element/ButtonLockManager.php b/vendor/magento/framework/View/Element/ButtonLockManager.php
new file mode 100644
index 000000000000..63976deb5b1a
--- /dev/null
+++ b/vendor/magento/framework/View/Element/ButtonLockManager.php
@@ -0,0 +1,42 @@
+<?php
+/**
+ * Copyright © Magento, Inc. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+declare(strict_types=1);
+
+namespace Magento\Framework\View\Element;
+
+use Magento\Framework\View\Element\Block\ArgumentInterface;
+
+class ButtonLockManager implements ArgumentInterface
+{
+    /**
+     * @var ButtonLockInterface[]
+     */
+    private array $buttonLockPool;
+
+    /**
+     * @param array $buttonLockPool
+     */
+    public function __construct(array $buttonLockPool = [])
+    {
+        $this->buttonLockPool = $buttonLockPool;
+    }
+
+    /**
+     * Returns true if the button has to be disabled.
+     *
+     * @param string $buttonCode
+     * @return bool
+     * @throws \Magento\Framework\Exception\InputException
+     */
+    public function isDisabled(string $buttonCode): bool
+    {
+        $result = array_filter($this->buttonLockPool, function ($item) use ($buttonCode) {
+            return $item->getCode() === $buttonCode && $item->isDisabled();
+        });
+
+        return !empty($result);
+    }
+}
