From 5757a028d650ccef58bd0f4106e9d317b4f40a8d Mon Sep 17 00:00:00 2001
From: godyaev <andrey.godyaev@loginom.ru>
Date: Tue, 17 Sep 2024 00:50:00 +0300
Subject: [PATCH 1/6] Fix legend size calculations when it is anchored to
 container.

---
 src/components/legend/draw.js | 65 ++++++++++++++++++++++++-----------
 1 file changed, 44 insertions(+), 21 deletions(-)

diff --git a/src/components/legend/draw.js b/src/components/legend/draw.js
index 8e7abcf29fa..62b1f99e52e 100644
--- a/src/components/legend/draw.js
+++ b/src/components/legend/draw.js
@@ -774,18 +774,30 @@ function computeLegendDimensions(gd, groups, traces, legendObj) {
     var endPad = 2 * (bw + itemGap);
 
     var yanchor = getYanchor(legendObj);
-    var isBelowPlotArea = legendObj.y < 0 || (legendObj.y === 0 && yanchor === 'top');
-    var isAbovePlotArea = legendObj.y > 1 || (legendObj.y === 1 && yanchor === 'bottom');
+    var isBelowPlotArea;
+    var isAbovePlotArea;
 
     var traceGroupGap = legendObj.tracegroupgap;
     var legendGroupWidths = {};
 
-    // - if below/above plot area, give it the maximum potential margin-push value
-    // - otherwise, extend the height of the plot area
-    legendObj._maxHeight = Math.max(
-        (isBelowPlotArea || isAbovePlotArea) ? fullLayout.height / 2 : gs.h,
-        30
-    );
+    if (legendObj.yref === 'paper') {
+        isBelowPlotArea = legendObj.y < 0 || (legendObj.y === 0 && yanchor === 'top');
+        isAbovePlotArea = legendObj.y > 1 || (legendObj.y === 1 && yanchor === 'bottom');
+        // - if below/above plot area, give it the maximum potential margin-push value
+        // - otherwise, extend the height of the plot area
+        legendObj._maxHeight = Math.max(
+            (isBelowPlotArea || isAbovePlotArea) ? fullLayout.height / 2 : gs.h,
+            30
+        );
+    } else {
+        if (yanchor === 'top')
+            legendObj._maxHeight = legendObj.y * fullLayout.height;
+        else if (yanchor === 'bottom')
+            legendObj._maxHeight = (1 - legendObj.y) * fullLayout.height;
+        else // if (yanchor === 'middle')
+            legendObj._maxHeight = 2 * Math.min(1 - legendObj.y, legendObj.y) * fullLayout.height;
+        legendObj._maxHeight = Math.max(legendObj._maxHeight, 30);
+    }
 
     var toggleRectWidth = 0;
     legendObj._width = 0;
@@ -815,19 +827,30 @@ function computeLegendDimensions(gd, groups, traces, legendObj) {
         }
     } else {
         var xanchor = getXanchor(legendObj);
-        var isLeftOfPlotArea = legendObj.x < 0 || (legendObj.x === 0 && xanchor === 'right');
-        var isRightOfPlotArea = legendObj.x > 1 || (legendObj.x === 1 && xanchor === 'left');
-        var isBeyondPlotAreaY = isAbovePlotArea || isBelowPlotArea;
-        var hw = fullLayout.width / 2;
-
-        // - if placed within x-margins, extend the width of the plot area
-        // - else if below/above plot area and anchored in the margin, extend to opposite margin,
-        // - otherwise give it the maximum potential margin-push value
-        legendObj._maxWidth = Math.max(
-            isLeftOfPlotArea ? ((isBeyondPlotAreaY && xanchor === 'left') ? gs.l + gs.w : hw) :
-            isRightOfPlotArea ? ((isBeyondPlotAreaY && xanchor === 'right') ? gs.r + gs.w : hw) :
-            gs.w,
-        2 * textGap);
+        if (legendObj.xref === 'paper') {
+            var isLeftOfPlotArea = legendObj.x < 0 || (legendObj.x === 0 && xanchor === 'right');
+            var isRightOfPlotArea = legendObj.x > 1 || (legendObj.x === 1 && xanchor === 'left');
+            var isBeyondPlotAreaY = isAbovePlotArea || isBelowPlotArea;
+            var hw = fullLayout.width / 2;
+
+            // - if placed within x-margins, extend the width of the plot area
+            // - else if below/above plot area and anchored in the margin, extend to opposite margin,
+            // - otherwise give it the maximum potential margin-push value
+            legendObj._maxWidth = Math.max(
+                isLeftOfPlotArea ? ((isBeyondPlotAreaY && xanchor === 'left') ? gs.l + gs.w : hw) :
+                isRightOfPlotArea ? ((isBeyondPlotAreaY && xanchor === 'right') ? gs.r + gs.w : hw) :
+                gs.w,
+                2 * textGap);
+        } else {
+            if (xanchor === 'right')
+                legendObj._maxWidth = legendObj.x * fullLayout.width;
+            else if (xanchor === 'left')
+                legendObj._maxWidth = (1 - legendObj.x) * fullLayout.width;
+            else // if (xanchor === 'center')
+                legendObj._maxWidth = 2 * Math.min(1 - legendObj.x, legendObj.x) * fullLayout.width;
+            legendObj._maxWidth = Math.max(legendObj._maxWidth, 2 * textGap);
+        }
+
         var maxItemWidth = 0;
         var combinedItemWidth = 0;
         traces.each(function(d) {

From d5e9935b3facd7d8e4e3ec848e3301f0231a7ff5 Mon Sep 17 00:00:00 2001
From: godyaev <andrey.godyaev@loginom.ru>
Date: Tue, 17 Sep 2024 01:03:44 +0300
Subject: [PATCH 2/6] Add draftlog for PR 7072

---
 draftlogs/7072-fix.md | 1 +
 1 file changed, 1 insertion(+)
 create mode 100644 draftlogs/7072-fix.md

diff --git a/draftlogs/7072-fix.md b/draftlogs/7072-fix.md
new file mode 100644
index 00000000000..f837fc49392
--- /dev/null
+++ b/draftlogs/7072-fix.md
@@ -0,0 +1 @@
+Fix maximum dimensions for legend that is anchored to container [[#7072](https://github.com/plotly/plotly.js/pull/7072)]
\ No newline at end of file

From 1fc426683642a7292c24b157a9c177f2eac0a5f7 Mon Sep 17 00:00:00 2001
From: godyaev <andrey.godyaev@loginom.ru>
Date: Tue, 17 Sep 2024 12:49:29 +0300
Subject: [PATCH 3/6] Code formatting.

---
 src/components/legend/draw.js | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/src/components/legend/draw.js b/src/components/legend/draw.js
index 62b1f99e52e..e7b4af77491 100644
--- a/src/components/legend/draw.js
+++ b/src/components/legend/draw.js
@@ -780,7 +780,7 @@ function computeLegendDimensions(gd, groups, traces, legendObj) {
     var traceGroupGap = legendObj.tracegroupgap;
     var legendGroupWidths = {};
 
-    if (legendObj.yref === 'paper') {
+    if(legendObj.yref === 'paper') {
         isBelowPlotArea = legendObj.y < 0 || (legendObj.y === 0 && yanchor === 'top');
         isAbovePlotArea = legendObj.y > 1 || (legendObj.y === 1 && yanchor === 'bottom');
         // - if below/above plot area, give it the maximum potential margin-push value
@@ -790,9 +790,9 @@ function computeLegendDimensions(gd, groups, traces, legendObj) {
             30
         );
     } else {
-        if (yanchor === 'top')
+        if(yanchor === 'top')
             legendObj._maxHeight = legendObj.y * fullLayout.height;
-        else if (yanchor === 'bottom')
+        else if(yanchor === 'bottom')
             legendObj._maxHeight = (1 - legendObj.y) * fullLayout.height;
         else // if (yanchor === 'middle')
             legendObj._maxHeight = 2 * Math.min(1 - legendObj.y, legendObj.y) * fullLayout.height;
@@ -827,7 +827,7 @@ function computeLegendDimensions(gd, groups, traces, legendObj) {
         }
     } else {
         var xanchor = getXanchor(legendObj);
-        if (legendObj.xref === 'paper') {
+        if(legendObj.xref === 'paper') {
             var isLeftOfPlotArea = legendObj.x < 0 || (legendObj.x === 0 && xanchor === 'right');
             var isRightOfPlotArea = legendObj.x > 1 || (legendObj.x === 1 && xanchor === 'left');
             var isBeyondPlotAreaY = isAbovePlotArea || isBelowPlotArea;
@@ -842,9 +842,9 @@ function computeLegendDimensions(gd, groups, traces, legendObj) {
                 gs.w,
                 2 * textGap);
         } else {
-            if (xanchor === 'right')
+            if(xanchor === 'right')
                 legendObj._maxWidth = legendObj.x * fullLayout.width;
-            else if (xanchor === 'left')
+            else if(xanchor === 'left')
                 legendObj._maxWidth = (1 - legendObj.x) * fullLayout.width;
             else // if (xanchor === 'center')
                 legendObj._maxWidth = 2 * Math.min(1 - legendObj.x, legendObj.x) * fullLayout.width;

From 68980a4227f570e713533c862c5af52f5b87cbfc Mon Sep 17 00:00:00 2001
From: godyaev <andrey.godyaev@loginom.ru>
Date: Tue, 17 Sep 2024 13:04:39 +0300
Subject: [PATCH 4/6] Calculate flags isBelowPlotArea/isAbovePlotArea when
 legend yref is container.

Need these for the case yref === 'container' && xref === 'paper'
---
 src/components/legend/draw.js | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/src/components/legend/draw.js b/src/components/legend/draw.js
index e7b4af77491..67710c3bfc8 100644
--- a/src/components/legend/draw.js
+++ b/src/components/legend/draw.js
@@ -790,6 +790,8 @@ function computeLegendDimensions(gd, groups, traces, legendObj) {
             30
         );
     } else {
+        isBelowPlotArea = legendObj.y * fullLayout.height < gs.b || (legendObj.y * fullLayout.height === gs.b && yanchor === 'top');
+        isAbovePlotArea = legendObj.y * fullLayout.height > gs.b + gs.h || (legendObj.y * fullLayout.height === gs.b + gs.h && yanchor === 'bottom');
         if(yanchor === 'top')
             legendObj._maxHeight = legendObj.y * fullLayout.height;
         else if(yanchor === 'bottom')

From 1d5aea2f7e60a670c26ea9914eb806fb782ba0ff Mon Sep 17 00:00:00 2001
From: Mojtaba Samimi <33888540+archmoj@users.noreply.github.com>
Date: Mon, 16 Dec 2024 13:22:18 -0500
Subject: [PATCH 5/6] Update draftlogs/7072-fix.md

---
 draftlogs/7072-fix.md | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/draftlogs/7072-fix.md b/draftlogs/7072-fix.md
index f837fc49392..f363f589e40 100644
--- a/draftlogs/7072-fix.md
+++ b/draftlogs/7072-fix.md
@@ -1 +1,2 @@
-Fix maximum dimensions for legend that is anchored to container [[#7072](https://github.com/plotly/plotly.js/pull/7072)]
\ No newline at end of file
+ - Fix maximum dimensions for legend that is anchored to container [[#7072](https://github.com/plotly/plotly.js/pull/7072)],
+   with thanks to @attatrol for the contribution!
\ No newline at end of file

From 4a1119ab592cc35502739099ea3d2c790cc27086 Mon Sep 17 00:00:00 2001
From: Cameron DeCoster <cameron.decoster@gmail.com>
Date: Tue, 22 Apr 2025 06:47:41 -0600
Subject: [PATCH 6/6] Update block to handle user specified maxheight

---
 src/components/legend/draw.js | 28 ++++++++++++++++------------
 1 file changed, 16 insertions(+), 12 deletions(-)

diff --git a/src/components/legend/draw.js b/src/components/legend/draw.js
index 6e9dee970d1..e4cd1440466 100644
--- a/src/components/legend/draw.js
+++ b/src/components/legend/draw.js
@@ -770,24 +770,28 @@ function computeLegendDimensions(gd, groups, traces, legendObj) {
     var legendGroupWidths = {};
 
     
-    if(legendObj.yref === 'paper') {
+    var { maxheight, orientation, yref } = legendObj;
+    var heightToBeScaled = orientation === "v" && yref === "paper" ? gs.h : fullLayout.height;
+    legendObj._maxHeight = maxheight > 1 ? maxheight : maxheight * heightToBeScaled;
+
+    if (legendObj.yref === 'paper') {
         isBelowPlotArea = legendObj.y < 0 || (legendObj.y === 0 && yanchor === 'top');
         isAbovePlotArea = legendObj.y > 1 || (legendObj.y === 1 && yanchor === 'bottom');
-        
-        var { maxheight, orientation, yref } = legendObj;
-        var heightToBeScaled = orientation === "v" && yref === "paper" ? gs.h : fullLayout.height;
-        legendObj._maxHeight = Math.max(maxheight > 1 ? maxheight : maxheight * heightToBeScaled, 30);
     } else {
         isBelowPlotArea = legendObj.y * fullLayout.height < gs.b || (legendObj.y * fullLayout.height === gs.b && yanchor === 'top');
         isAbovePlotArea = legendObj.y * fullLayout.height > gs.b + gs.h || (legendObj.y * fullLayout.height === gs.b + gs.h && yanchor === 'bottom');
-        if(yanchor === 'top')
-            legendObj._maxHeight = legendObj.y * fullLayout.height;
-        else if(yanchor === 'bottom')
-            legendObj._maxHeight = (1 - legendObj.y) * fullLayout.height;
-        else // if (yanchor === 'middle')
-            legendObj._maxHeight = 2 * Math.min(1 - legendObj.y, legendObj.y) * fullLayout.height;
-        legendObj._maxHeight = Math.max(legendObj._maxHeight, 30);
+        var maxAvailableHeight;
+        if (yanchor === 'top') {
+            maxAvailableHeight = legendObj.y * fullLayout.height;
+        } else if (yanchor === 'bottom') {
+            maxAvailableHeight = (1 - legendObj.y) * fullLayout.height;
+        } else {
+            // yanchor is 'middle' or 'auto'
+            maxAvailableHeight = 2 * Math.min(1 - legendObj.y, legendObj.y) * fullLayout.height;
+        }
+        legendObj._maxHeight = Math.min(legendObj._maxHeight, maxAvailableHeight)
     }
+    legendObj._maxHeight = Math.max(legendObj._maxHeight, 30);
 
     var toggleRectWidth = 0;
     legendObj._width = 0;