diff --git a/reviewboard/actions/base.py b/reviewboard/actions/base.py
index 37f03bba6b5fa06d6667970af84bb89af1943736..af86d0f2b41a932acaf52dac420d34260e6ddbf5 100644
--- a/reviewboard/actions/base.py
+++ b/reviewboard/actions/base.py
@@ -146,6 +146,18 @@ class BaseAction:
     #:     str
     url_name: Optional[str] = None
 
+    #: The user-visible verbose label.
+    #:
+    #: This can be used to provide a longer label for wider UIs that would
+    #: benefit from a more descriptive label. It's also intended for ARIA
+    #: labels.
+    #:
+    #: This is always optional.
+    #:
+    #: Version Added:
+    #:     7.1
+    verbose_label: (StrOrPromise | None) = None
+
     #: Whether this action is visible.
     #:
     #: Type:
@@ -266,7 +278,6 @@ class BaseAction:
         """
         dom_id = self.get_dom_element_id()
         icon_class = self.icon_class
-        label = self.get_label(context=context)
         url = self.get_url(context=context)
         visible = self.get_visible(context=context)
 
@@ -284,9 +295,12 @@ class BaseAction:
         if self.is_custom_rendered():
             data['isCustomRendered'] = True
 
-        if label:
+        if (label := self.get_label(context=context)):
             data['label'] = str(label)
 
+        if (verbose_label := self.get_verbose_label(context=context)):
+            data['verboseLabel'] = str(verbose_label)
+
         if url:
             data['url'] = url
 
@@ -313,7 +327,7 @@ class BaseAction:
         self,
         *,
         context: Context,
-    ) -> StrOrPromise:
+    ) -> StrOrPromise | None:
         """Return the label for the action.
 
         Args:
@@ -324,9 +338,31 @@ class BaseAction:
             str:
             The label to use for the action.
         """
-        assert self.label is not None
         return self.label
 
+    def get_verbose_label(
+        self,
+        *,
+        context: Context,
+    ) -> StrOrPromise | None:
+        """Return the verbose label for the action.
+
+         This can be used to provide a longer label for wider UIs that would
+         benefit from a more descriptive label. It's always optional.
+
+         Version Added:
+             7.1
+
+        Args:
+            context (django.template.Context):
+                The current rendering context.
+
+        Returns:
+            str:
+            The verbose label to use for the action.
+        """
+        return self.verbose_label
+
     def get_url(
         self,
         *,
@@ -395,6 +431,7 @@ class BaseAction:
             'id': self.action_id,
             'label': self.get_label(context=context),
             'url': self.get_url(context=context),
+            'verbose_label': self.get_verbose_label(context=context),
             'visible': self.get_visible(context=context),
         }
 
diff --git a/reviewboard/reviews/actions.py b/reviewboard/reviews/actions.py
index 42d942da43f0c1e880e9386ac80aa60147597cee..4c78c31ceca01b6da914257da8b9b0789abedfb3 100644
--- a/reviewboard/reviews/actions.py
+++ b/reviewboard/reviews/actions.py
@@ -327,7 +327,8 @@ class CreateReviewAction(BaseAction):
     parent_id: (str | None) = 'review-menu'
     apply_to = all_review_request_url_names
     attachment = AttachmentPoint.UNIFIED_BANNER
-    label = _('Create a new review')
+    label = _('Create Review')
+    verbose_label = _('Create a new review')
     description = [
         _('Your review will start off blank, but you can add text and '
           'general comments to it.'),
@@ -377,7 +378,8 @@ class EditReviewAction(BaseAction):
     parent_id: (str | None) = 'review-menu'
     apply_to = all_review_request_url_names
     attachment = AttachmentPoint.UNIFIED_BANNER
-    label = _('Edit your review')
+    label = _('Edit Review')
+    verbose_label = _('Edit your review')
     description = [
         _('Edit your comments and publish your review.'),
     ]
@@ -424,7 +426,8 @@ class AddGeneralCommentAction(BaseAction):
     parent_id: (str | None) = 'review-menu'
     apply_to = all_review_request_url_names
     attachment = AttachmentPoint.UNIFIED_BANNER
-    label = _('Add a general comment')
+    label = _('Add General Comment')
+    verbose_label = _('Add a general comment')
     description = [
         _('Add a new general comment about the change, not attached to '
           'any code or file attachments.'),
@@ -471,7 +474,8 @@ class ShipItAction(BaseAction):
     parent_id: (str | None) = 'review-menu'
     apply_to = all_review_request_url_names
     attachment = AttachmentPoint.UNIFIED_BANNER
-    label = _('Ship it!')
+    label = _('Ship It!')
+    verbose_label = _('Ship it!')
     description = [
         _("You're happy with what you're seeing, and would like to "
           'approve it.'),
@@ -512,7 +516,7 @@ class ShipItAction(BaseAction):
             not is_site_read_only_for(user) and
             review_request is not None and
             (user.pk != review_request.submitter_id or
-             siteconfig.get('reviews_allow_self_shipit'))
+             bool(siteconfig.get('reviews_allow_self_shipit')))
         )
 
 
@@ -527,7 +531,6 @@ class QuickAccessShipItAction(QuickAccessActionMixin, ShipItAction):
     """
 
     action_id = 'quickaccess-ship-it'
-    label = _('Ship It!')
 
 
 class QuickAccessCreateReviewAction(QuickAccessActionMixin,
@@ -542,7 +545,6 @@ class QuickAccessCreateReviewAction(QuickAccessActionMixin,
     """
 
     action_id = 'quickaccess-create-review'
-    label = _('Create Review')
 
 
 class QuickAccessEditReviewAction(QuickAccessActionMixin, EditReviewAction):
@@ -556,7 +558,6 @@ class QuickAccessEditReviewAction(QuickAccessActionMixin, EditReviewAction):
     """
 
     action_id = 'quickaccess-edit-review'
-    label = _('Edit Review')
 
 
 class QuickAccessAddGeneralCommentAction(QuickAccessActionMixin,
@@ -571,7 +572,6 @@ class QuickAccessAddGeneralCommentAction(QuickAccessActionMixin,
     """
 
     action_id = 'quickaccess-add-general-comment'
-    label = _('Add General Comment')
 
 
 class LegacyAddGeneralCommentAction(BaseAction):
diff --git a/reviewboard/static/rb/js/common/actions/models/actionModel.ts b/reviewboard/static/rb/js/common/actions/models/actionModel.ts
index 08232d88d3b1ea98c77e6f59f6a0c82c02ee5a68..d20e5e1eb91620d6baa6c5bb0367d36f799797a5 100644
--- a/reviewboard/static/rb/js/common/actions/models/actionModel.ts
+++ b/reviewboard/static/rb/js/common/actions/models/actionModel.ts
@@ -81,6 +81,20 @@ export interface ActionAttrs {
      */
     url: string | null;
 
+    /**
+     * The verbose label for the action.
+     *
+     * This can be used to provide a longer label for wider UIs that would
+     * benefit from a more descriptive label. It's also intended for ARIA
+     * labels.
+     *
+     * It's always optional.
+     *
+     * Version Added:
+     *     7.1
+     */
+    verboseLabel: string | null;
+
     /**
      * Whether the action should be visible or hidden.
      */
@@ -115,6 +129,7 @@ export class Action<
         isQuickAccessEnabled: false,
         label: null,
         url: null,
+        verboseLabel: null,
         visible: false,
     };
 
diff --git a/reviewboard/templates/actions/button_action.html b/reviewboard/templates/actions/button_action.html
index 7bdc2c6c97300914646140948017858189a68732..db72036e03a0760b8e6603c0a5167cf6fad82e27 100644
--- a/reviewboard/templates/actions/button_action.html
+++ b/reviewboard/templates/actions/button_action.html
@@ -6,6 +6,9 @@
 {%  definevar "action_attrs" spaceless %}
  class="ink-c-button"
  {{action_attrs}}
+{%  if verbose_label %}
+ aria-label="{{verbose_label}}"
+{%  endif %}
 {%  if action.description %}
  title="{{action.description|join:'&#10;&#10;'}}"
 {%  endif %}
diff --git a/reviewboard/templates/actions/detailed_menuitem_action.html b/reviewboard/templates/actions/detailed_menuitem_action.html
index 4de9da6d3f83cc9ce1d9f9124fb5388620b6a36d..f219817913cfbad087cc38a7f6309d574f7bb24d 100644
--- a/reviewboard/templates/actions/detailed_menuitem_action.html
+++ b/reviewboard/templates/actions/detailed_menuitem_action.html
@@ -6,7 +6,7 @@
    role="menuitem">
  <h4>
   <span class="{{action.icon_class}}"></span>
-  {{label}}
+  {{verbose_label|default:label}}
  </h4>
 {%  for description_part in action.description %}
  <p>
diff --git a/reviewboard/templates/actions/menu_action.html b/reviewboard/templates/actions/menu_action.html
index a74589f6334f0034b0412410ea3ba94e9f3f5d3c..a9e2835e7a36d9ea3b0e5d392401f7fb281e5564 100644
--- a/reviewboard/templates/actions/menu_action.html
+++ b/reviewboard/templates/actions/menu_action.html
@@ -9,7 +9,7 @@
 
 {% block action_content %}
 <a href="#" role="presentation"
-   aria-label="{{label}}">
+   aria-label="{{verbose_label|default:label}}">
  <label class="rb-c-actions__action-label">
 {%  if action.icon_class %}
   <span class="{{action.icon_class}}"></span>
