Repository: Textualize/textual

Issue:
Setting `loading` to `True` causes widgets to overwrite notifications
Given this code:

```python
from textual.app import App, ComposeResult
from textual.widgets import Label

class LoadingOverlayApp(App[None]):

    CSS = """
    Label {
        width: 90%;
        height: 1fr;
        text-align: center;
        border: solid red;
    }
    """

    def compose(self) -> ComposeResult:
        yield Label("This is a really big label")

    def on_mount(self) -> None:
        self.notify(
            "This is a really big notification. Loading should not overwrite it.",
            timeout=9_999_999
        )
        self.query_one(Label).loading = True

if __name__ == "__main__":
    LoadingOverlayApp().run()
```

you get this result:

![Screenshot 2023-11-14 at 15 32 15](https://github.com/Textualize/textual/assets/28237/9dedad31-c5f6-412f-a61f-864af1ee9876)

a widget in `loading=True` state shouldn't appear to overwrite notifications.


Discussion:
As previously requested, tagging @willmcgugan on something that should probably TODO sooner rather than later.
Here's another interesting one:
if you set a scrollable container to load, you can still scroll, it'll show content that was past the current scrolling position, and the loading indicator overlay will move around as well:

https://github.com/Textualize/textual/assets/5621605/503094d6-1049-44ee-8d10-7f41f8ded433



Resolving patch:
diff --git a/src/textual/screen.py b/src/textual/screen.py
--- a/src/textual/screen.py
+++ b/src/textual/screen.py
@@ -244,7 +244,7 @@ def layers(self) -> tuple[str, ...]:
         Returns:
             Tuple of layer names.
         """
-        extras = []
+        extras = ["_loading"]
         if not self.app._disable_notifications:
             extras.append("_toastrack")
         if not self.app._disable_tooltips:
diff --git a/src/textual/widgets/_loading_indicator.py b/src/textual/widgets/_loading_indicator.py
--- a/src/textual/widgets/_loading_indicator.py
+++ b/src/textual/widgets/_loading_indicator.py
@@ -1,7 +1,8 @@
 from __future__ import annotations
 
 from time import time
-from typing import Awaitable
+from typing import Awaitable, ClassVar
+from weakref import WeakKeyDictionary
 
 from rich.console import RenderableType
 from rich.style import Style
@@ -25,11 +26,22 @@ class LoadingIndicator(Widget):
         color: $accent;
     }
     LoadingIndicator.-overlay {
-        overlay: screen;
+        layer: _loading;
         background: $boost;
     }
     """
 
+    _widget_state: ClassVar[
+        WeakKeyDictionary[Widget, tuple[bool, str, str]]
+    ] = WeakKeyDictionary()
+    """Widget state that must be restore after loading.
+    
+    The tuples indicate the original values of the:
+     - widget disabled state;
+     - widget style overflow_x rule; and
+     - widget style overflow_y rule.
+    """
+
     def __init__(
         self,
         name: str | None = None,
@@ -62,11 +74,19 @@ def apply(self, widget: Widget) -> AwaitMount:
             AwaitMount: An awaitable for mounting the indicator.
         """
         self.add_class("-overlay")
-        await_mount = widget.mount(self, before=0)
+        await_mount = widget.mount(self)
+        self._widget_state[widget] = (
+            widget.disabled,
+            widget.styles.overflow_x,
+            widget.styles.overflow_y,
+        )
+        widget.styles.overflow_x = "hidden"
+        widget.styles.overflow_y = "hidden"
+        widget.disabled = True
         return await_mount
 
     @classmethod
-    def clear(cls, widget: Widget) -> Awaitable:
+    def clear(cls, widget: Widget) -> Awaitable[None]:
         """Clear any loading indicator from the given widget.
 
         Args:
@@ -83,7 +103,13 @@ async def null() -> None:
                 """Nothing to remove"""
                 return None
 
-            return null()
+            await_remove = null()
+
+        if widget in cls._widget_state:
+            disabled, overflow_x, overflow_y = cls._widget_state[widget]
+            widget.disabled = disabled
+            widget.styles.overflow_x = overflow_x
+            widget.styles.overflow_y = overflow_y
 
         return await_remove
 


Test patch:
diff --git a/tests/snapshot_tests/__snapshots__/test_snapshots.ambr b/tests/snapshot_tests/__snapshots__/test_snapshots.ambr
--- a/tests/snapshot_tests/__snapshots__/test_snapshots.ambr
+++ b/tests/snapshot_tests/__snapshots__/test_snapshots.ambr
@@ -22489,6 +22489,147 @@
   
   '''
 # ---
+# name: test_notifications_loading_overlap_order
+  '''
+  <svg class="rich-terminal" viewBox="0 0 994 538.0" xmlns="http://www.w3.org/2000/svg">
+      <!-- Generated with Rich https://www.textualize.io -->
+      <style>
+  
+      @font-face {
+          font-family: "Fira Code";
+          src: local("FiraCode-Regular"),
+                  url("https://cdnjs.cloudflare.com/ajax/libs/firacode/6.2.0/woff2/FiraCode-Regular.woff2") format("woff2"),
+                  url("https://cdnjs.cloudflare.com/ajax/libs/firacode/6.2.0/woff/FiraCode-Regular.woff") format("woff");
+          font-style: normal;
+          font-weight: 400;
+      }
+      @font-face {
+          font-family: "Fira Code";
+          src: local("FiraCode-Bold"),
+                  url("https://cdnjs.cloudflare.com/ajax/libs/firacode/6.2.0/woff2/FiraCode-Bold.woff2") format("woff2"),
+                  url("https://cdnjs.cloudflare.com/ajax/libs/firacode/6.2.0/woff/FiraCode-Bold.woff") format("woff");
+          font-style: bold;
+          font-weight: 700;
+      }
+  
+      .terminal-1517911659-matrix {
+          font-family: Fira Code, monospace;
+          font-size: 20px;
+          line-height: 24.4px;
+          font-variant-east-asian: full-width;
+      }
+  
+      .terminal-1517911659-title {
+          font-size: 18px;
+          font-weight: bold;
+          font-family: arial;
+      }
+  
+      .terminal-1517911659-r1 { fill: #c5c8c6 }
+  .terminal-1517911659-r2 { fill: #56c278 }
+  .terminal-1517911659-r3 { fill: #2e3339 }
+  .terminal-1517911659-r4 { fill: #e3e4e4 }
+      </style>
+  
+      <defs>
+      <clipPath id="terminal-1517911659-clip-terminal">
+        <rect x="0" y="0" width="975.0" height="487.0" />
+      </clipPath>
+      <clipPath id="terminal-1517911659-line-0">
+      <rect x="0" y="1.5" width="976" height="24.65"/>
+              </clipPath>
+  <clipPath id="terminal-1517911659-line-1">
+      <rect x="0" y="25.9" width="976" height="24.65"/>
+              </clipPath>
+  <clipPath id="terminal-1517911659-line-2">
+      <rect x="0" y="50.3" width="976" height="24.65"/>
+              </clipPath>
+  <clipPath id="terminal-1517911659-line-3">
+      <rect x="0" y="74.7" width="976" height="24.65"/>
+              </clipPath>
+  <clipPath id="terminal-1517911659-line-4">
+      <rect x="0" y="99.1" width="976" height="24.65"/>
+              </clipPath>
+  <clipPath id="terminal-1517911659-line-5">
+      <rect x="0" y="123.5" width="976" height="24.65"/>
+              </clipPath>
+  <clipPath id="terminal-1517911659-line-6">
+      <rect x="0" y="147.9" width="976" height="24.65"/>
+              </clipPath>
+  <clipPath id="terminal-1517911659-line-7">
+      <rect x="0" y="172.3" width="976" height="24.65"/>
+              </clipPath>
+  <clipPath id="terminal-1517911659-line-8">
+      <rect x="0" y="196.7" width="976" height="24.65"/>
+              </clipPath>
+  <clipPath id="terminal-1517911659-line-9">
+      <rect x="0" y="221.1" width="976" height="24.65"/>
+              </clipPath>
+  <clipPath id="terminal-1517911659-line-10">
+      <rect x="0" y="245.5" width="976" height="24.65"/>
+              </clipPath>
+  <clipPath id="terminal-1517911659-line-11">
+      <rect x="0" y="269.9" width="976" height="24.65"/>
+              </clipPath>
+  <clipPath id="terminal-1517911659-line-12">
+      <rect x="0" y="294.3" width="976" height="24.65"/>
+              </clipPath>
+  <clipPath id="terminal-1517911659-line-13">
+      <rect x="0" y="318.7" width="976" height="24.65"/>
+              </clipPath>
+  <clipPath id="terminal-1517911659-line-14">
+      <rect x="0" y="343.1" width="976" height="24.65"/>
+              </clipPath>
+  <clipPath id="terminal-1517911659-line-15">
+      <rect x="0" y="367.5" width="976" height="24.65"/>
+              </clipPath>
+  <clipPath id="terminal-1517911659-line-16">
+      <rect x="0" y="391.9" width="976" height="24.65"/>
+              </clipPath>
+  <clipPath id="terminal-1517911659-line-17">
+      <rect x="0" y="416.3" width="976" height="24.65"/>
+              </clipPath>
+  <clipPath id="terminal-1517911659-line-18">
+      <rect x="0" y="440.7" width="976" height="24.65"/>
+              </clipPath>
+      </defs>
+  
+      <rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1" x="1" y="1" width="992" height="536" rx="8"/><text class="terminal-1517911659-title" fill="#c5c8c6" text-anchor="middle" x="496" y="27">LoadingOverlayApp</text>
+              <g transform="translate(26,22)">
+              <circle cx="0" cy="0" r="7" fill="#ff5f57"/>
+              <circle cx="22" cy="0" r="7" fill="#febc2e"/>
+              <circle cx="44" cy="0" r="7" fill="#28c840"/>
+              </g>
+          
+      <g transform="translate(9, 41)" clip-path="url(#terminal-1517911659-clip-terminal)">
+      <rect fill="#222222" x="0" y="1.5" width="207.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#222222" x="207.4" y="1.5" width="768.6" height="24.65" shape-rendering="crispEdges"/><rect fill="#222222" x="0" y="25.9" width="207.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#222222" x="207.4" y="25.9" width="768.6" height="24.65" shape-rendering="crispEdges"/><rect fill="#222222" x="0" y="50.3" width="207.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#222222" x="207.4" y="50.3" width="768.6" height="24.65" shape-rendering="crispEdges"/><rect fill="#222222" x="0" y="74.7" width="207.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#222222" x="207.4" y="74.7" width="768.6" height="24.65" shape-rendering="crispEdges"/><rect fill="#222222" x="0" y="99.1" width="207.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#222222" x="207.4" y="99.1" width="768.6" height="24.65" shape-rendering="crispEdges"/><rect fill="#222222" x="0" y="123.5" width="207.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#222222" x="207.4" y="123.5" width="768.6" height="24.65" shape-rendering="crispEdges"/><rect fill="#222222" x="0" y="147.9" width="207.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#222222" x="207.4" y="147.9" width="61" height="24.65" shape-rendering="crispEdges"/><rect fill="#2e3339" x="268.4" y="147.9" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#2e3339" x="280.6" y="147.9" width="658.8" height="24.65" shape-rendering="crispEdges"/><rect fill="#1d1d1d" x="939.4" y="147.9" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#222222" x="951.6" y="147.9" width="24.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#222222" x="0" y="172.3" width="207.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#222222" x="207.4" y="172.3" width="61" height="24.65" shape-rendering="crispEdges"/><rect fill="#2e3339" x="268.4" y="172.3" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#2e3339" x="280.6" y="172.3" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#2e3339" x="292.8" y="172.3" width="329.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#2e3339" x="622.2" y="172.3" width="305" height="24.65" shape-rendering="crispEdges"/><rect fill="#2e3339" x="927.2" y="172.3" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#1d1d1d" x="939.4" y="172.3" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#222222" x="951.6" y="172.3" width="24.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#222222" x="0" y="196.7" width="207.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#222222" x="207.4" y="196.7" width="61" height="24.65" shape-rendering="crispEdges"/><rect fill="#2e3339" x="268.4" y="196.7" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#2e3339" x="280.6" y="196.7" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#2e3339" x="292.8" y="196.7" width="329.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#2e3339" x="622.2" y="196.7" width="305" height="24.65" shape-rendering="crispEdges"/><rect fill="#2e3339" x="927.2" y="196.7" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#1d1d1d" x="939.4" y="196.7" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#222222" x="951.6" y="196.7" width="24.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#222222" x="0" y="221.1" width="207.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#222222" x="207.4" y="221.1" width="61" height="24.65" shape-rendering="crispEdges"/><rect fill="#2e3339" x="268.4" y="221.1" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#2e3339" x="280.6" y="221.1" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#2e3339" x="292.8" y="221.1" width="329.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#2e3339" x="622.2" y="221.1" width="305" height="24.65" shape-rendering="crispEdges"/><rect fill="#2e3339" x="927.2" y="221.1" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#1d1d1d" x="939.4" y="221.1" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#222222" x="951.6" y="221.1" width="24.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#222222" x="0" y="245.5" width="207.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#222222" x="207.4" y="245.5" width="61" height="24.65" shape-rendering="crispEdges"/><rect fill="#2e3339" x="268.4" y="245.5" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#2e3339" x="280.6" y="245.5" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#2e3339" x="292.8" y="245.5" width="329.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#2e3339" x="622.2" y="245.5" width="305" height="24.65" shape-rendering="crispEdges"/><rect fill="#2e3339" x="927.2" y="245.5" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#1d1d1d" x="939.4" y="245.5" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#222222" x="951.6" y="245.5" width="24.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#222222" x="0" y="269.9" width="207.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#222222" x="207.4" y="269.9" width="61" height="24.65" shape-rendering="crispEdges"/><rect fill="#2e3339" x="268.4" y="269.9" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#2e3339" x="280.6" y="269.9" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#2e3339" x="292.8" y="269.9" width="329.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#2e3339" x="622.2" y="269.9" width="305" height="24.65" shape-rendering="crispEdges"/><rect fill="#2e3339" x="927.2" y="269.9" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#1d1d1d" x="939.4" y="269.9" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#222222" x="951.6" y="269.9" width="24.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#222222" x="0" y="294.3" width="207.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#222222" x="207.4" y="294.3" width="61" height="24.65" shape-rendering="crispEdges"/><rect fill="#2e3339" x="268.4" y="294.3" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#2e3339" x="280.6" y="294.3" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#2e3339" x="292.8" y="294.3" width="329.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#2e3339" x="622.2" y="294.3" width="305" height="24.65" shape-rendering="crispEdges"/><rect fill="#2e3339" x="927.2" y="294.3" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#1d1d1d" x="939.4" y="294.3" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#222222" x="951.6" y="294.3" width="24.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#222222" x="0" y="318.7" width="207.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#222222" x="207.4" y="318.7" width="61" height="24.65" shape-rendering="crispEdges"/><rect fill="#2e3339" x="268.4" y="318.7" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#2e3339" x="280.6" y="318.7" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#2e3339" x="292.8" y="318.7" width="329.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#2e3339" x="622.2" y="318.7" width="305" height="24.65" shape-rendering="crispEdges"/><rect fill="#2e3339" x="927.2" y="318.7" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#1d1d1d" x="939.4" y="318.7" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#222222" x="951.6" y="318.7" width="24.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#222222" x="0" y="343.1" width="207.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#222222" x="207.4" y="343.1" width="61" height="24.65" shape-rendering="crispEdges"/><rect fill="#2e3339" x="268.4" y="343.1" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#2e3339" x="280.6" y="343.1" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#2e3339" x="292.8" y="343.1" width="329.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#2e3339" x="622.2" y="343.1" width="305" height="24.65" shape-rendering="crispEdges"/><rect fill="#2e3339" x="927.2" y="343.1" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#1d1d1d" x="939.4" y="343.1" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#222222" x="951.6" y="343.1" width="24.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#222222" x="0" y="367.5" width="207.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#222222" x="207.4" y="367.5" width="61" height="24.65" shape-rendering="crispEdges"/><rect fill="#2e3339" x="268.4" y="367.5" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#2e3339" x="280.6" y="367.5" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#2e3339" x="292.8" y="367.5" width="329.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#2e3339" x="622.2" y="367.5" width="305" height="24.65" shape-rendering="crispEdges"/><rect fill="#2e3339" x="927.2" y="367.5" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#1d1d1d" x="939.4" y="367.5" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#222222" x="951.6" y="367.5" width="24.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#222222" x="0" y="391.9" width="207.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#222222" x="207.4" y="391.9" width="61" height="24.65" shape-rendering="crispEdges"/><rect fill="#2e3339" x="268.4" y="391.9" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#2e3339" x="280.6" y="391.9" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#2e3339" x="292.8" y="391.9" width="329.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#2e3339" x="622.2" y="391.9" width="305" height="24.65" shape-rendering="crispEdges"/><rect fill="#2e3339" x="927.2" y="391.9" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#1d1d1d" x="939.4" y="391.9" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#222222" x="951.6" y="391.9" width="24.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#222222" x="0" y="416.3" width="207.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#222222" x="207.4" y="416.3" width="61" height="24.65" shape-rendering="crispEdges"/><rect fill="#2e3339" x="268.4" y="416.3" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#2e3339" x="280.6" y="416.3" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#2e3339" x="292.8" y="416.3" width="634.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#2e3339" x="927.2" y="416.3" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#1d1d1d" x="939.4" y="416.3" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#222222" x="951.6" y="416.3" width="24.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#222222" x="0" y="440.7" width="207.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#222222" x="207.4" y="440.7" width="61" height="24.65" shape-rendering="crispEdges"/><rect fill="#2e3339" x="268.4" y="440.7" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#2e3339" x="280.6" y="440.7" width="658.8" height="24.65" shape-rendering="crispEdges"/><rect fill="#1d1d1d" x="939.4" y="440.7" width="12.2" height="24.65" shape-rendering="crispEdges"/><rect fill="#222222" x="951.6" y="440.7" width="24.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#222222" x="0" y="465.1" width="207.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#222222" x="207.4" y="465.1" width="768.6" height="24.65" shape-rendering="crispEdges"/>
+      <g class="terminal-1517911659-matrix">
+      <text class="terminal-1517911659-r1" x="976" y="20" textLength="12.2" clip-path="url(#terminal-1517911659-line-0)">
+  </text><text class="terminal-1517911659-r1" x="976" y="44.4" textLength="12.2" clip-path="url(#terminal-1517911659-line-1)">
+  </text><text class="terminal-1517911659-r1" x="976" y="68.8" textLength="12.2" clip-path="url(#terminal-1517911659-line-2)">
+  </text><text class="terminal-1517911659-r1" x="976" y="93.2" textLength="12.2" clip-path="url(#terminal-1517911659-line-3)">
+  </text><text class="terminal-1517911659-r1" x="976" y="117.6" textLength="12.2" clip-path="url(#terminal-1517911659-line-4)">
+  </text><text class="terminal-1517911659-r1" x="976" y="142" textLength="12.2" clip-path="url(#terminal-1517911659-line-5)">
+  </text><text class="terminal-1517911659-r2" x="268.4" y="166.4" textLength="12.2" clip-path="url(#terminal-1517911659-line-6)">▎</text><text class="terminal-1517911659-r3" x="939.4" y="166.4" textLength="12.2" clip-path="url(#terminal-1517911659-line-6)">▊</text><text class="terminal-1517911659-r1" x="976" y="166.4" textLength="12.2" clip-path="url(#terminal-1517911659-line-6)">
+  </text><text class="terminal-1517911659-r2" x="268.4" y="190.8" textLength="12.2" clip-path="url(#terminal-1517911659-line-7)">▎</text><text class="terminal-1517911659-r4" x="292.8" y="190.8" textLength="329.4" clip-path="url(#terminal-1517911659-line-7)">This&#160;is&#160;a&#160;big&#160;notification.</text><text class="terminal-1517911659-r3" x="939.4" y="190.8" textLength="12.2" clip-path="url(#terminal-1517911659-line-7)">▊</text><text class="terminal-1517911659-r1" x="976" y="190.8" textLength="12.2" clip-path="url(#terminal-1517911659-line-7)">
+  </text><text class="terminal-1517911659-r2" x="268.4" y="215.2" textLength="12.2" clip-path="url(#terminal-1517911659-line-8)">▎</text><text class="terminal-1517911659-r4" x="292.8" y="215.2" textLength="329.4" clip-path="url(#terminal-1517911659-line-8)">This&#160;is&#160;a&#160;big&#160;notification.</text><text class="terminal-1517911659-r3" x="939.4" y="215.2" textLength="12.2" clip-path="url(#terminal-1517911659-line-8)">▊</text><text class="terminal-1517911659-r1" x="976" y="215.2" textLength="12.2" clip-path="url(#terminal-1517911659-line-8)">
+  </text><text class="terminal-1517911659-r2" x="268.4" y="239.6" textLength="12.2" clip-path="url(#terminal-1517911659-line-9)">▎</text><text class="terminal-1517911659-r4" x="292.8" y="239.6" textLength="329.4" clip-path="url(#terminal-1517911659-line-9)">This&#160;is&#160;a&#160;big&#160;notification.</text><text class="terminal-1517911659-r3" x="939.4" y="239.6" textLength="12.2" clip-path="url(#terminal-1517911659-line-9)">▊</text><text class="terminal-1517911659-r1" x="976" y="239.6" textLength="12.2" clip-path="url(#terminal-1517911659-line-9)">
+  </text><text class="terminal-1517911659-r2" x="268.4" y="264" textLength="12.2" clip-path="url(#terminal-1517911659-line-10)">▎</text><text class="terminal-1517911659-r4" x="292.8" y="264" textLength="329.4" clip-path="url(#terminal-1517911659-line-10)">This&#160;is&#160;a&#160;big&#160;notification.</text><text class="terminal-1517911659-r3" x="939.4" y="264" textLength="12.2" clip-path="url(#terminal-1517911659-line-10)">▊</text><text class="terminal-1517911659-r1" x="976" y="264" textLength="12.2" clip-path="url(#terminal-1517911659-line-10)">
+  </text><text class="terminal-1517911659-r2" x="268.4" y="288.4" textLength="12.2" clip-path="url(#terminal-1517911659-line-11)">▎</text><text class="terminal-1517911659-r4" x="292.8" y="288.4" textLength="329.4" clip-path="url(#terminal-1517911659-line-11)">This&#160;is&#160;a&#160;big&#160;notification.</text><text class="terminal-1517911659-r3" x="939.4" y="288.4" textLength="12.2" clip-path="url(#terminal-1517911659-line-11)">▊</text><text class="terminal-1517911659-r1" x="976" y="288.4" textLength="12.2" clip-path="url(#terminal-1517911659-line-11)">
+  </text><text class="terminal-1517911659-r2" x="268.4" y="312.8" textLength="12.2" clip-path="url(#terminal-1517911659-line-12)">▎</text><text class="terminal-1517911659-r4" x="292.8" y="312.8" textLength="329.4" clip-path="url(#terminal-1517911659-line-12)">This&#160;is&#160;a&#160;big&#160;notification.</text><text class="terminal-1517911659-r3" x="939.4" y="312.8" textLength="12.2" clip-path="url(#terminal-1517911659-line-12)">▊</text><text class="terminal-1517911659-r1" x="976" y="312.8" textLength="12.2" clip-path="url(#terminal-1517911659-line-12)">
+  </text><text class="terminal-1517911659-r2" x="268.4" y="337.2" textLength="12.2" clip-path="url(#terminal-1517911659-line-13)">▎</text><text class="terminal-1517911659-r4" x="292.8" y="337.2" textLength="329.4" clip-path="url(#terminal-1517911659-line-13)">This&#160;is&#160;a&#160;big&#160;notification.</text><text class="terminal-1517911659-r3" x="939.4" y="337.2" textLength="12.2" clip-path="url(#terminal-1517911659-line-13)">▊</text><text class="terminal-1517911659-r1" x="976" y="337.2" textLength="12.2" clip-path="url(#terminal-1517911659-line-13)">
+  </text><text class="terminal-1517911659-r2" x="268.4" y="361.6" textLength="12.2" clip-path="url(#terminal-1517911659-line-14)">▎</text><text class="terminal-1517911659-r4" x="292.8" y="361.6" textLength="329.4" clip-path="url(#terminal-1517911659-line-14)">This&#160;is&#160;a&#160;big&#160;notification.</text><text class="terminal-1517911659-r3" x="939.4" y="361.6" textLength="12.2" clip-path="url(#terminal-1517911659-line-14)">▊</text><text class="terminal-1517911659-r1" x="976" y="361.6" textLength="12.2" clip-path="url(#terminal-1517911659-line-14)">
+  </text><text class="terminal-1517911659-r2" x="268.4" y="386" textLength="12.2" clip-path="url(#terminal-1517911659-line-15)">▎</text><text class="terminal-1517911659-r4" x="292.8" y="386" textLength="329.4" clip-path="url(#terminal-1517911659-line-15)">This&#160;is&#160;a&#160;big&#160;notification.</text><text class="terminal-1517911659-r3" x="939.4" y="386" textLength="12.2" clip-path="url(#terminal-1517911659-line-15)">▊</text><text class="terminal-1517911659-r1" x="976" y="386" textLength="12.2" clip-path="url(#terminal-1517911659-line-15)">
+  </text><text class="terminal-1517911659-r2" x="268.4" y="410.4" textLength="12.2" clip-path="url(#terminal-1517911659-line-16)">▎</text><text class="terminal-1517911659-r4" x="292.8" y="410.4" textLength="329.4" clip-path="url(#terminal-1517911659-line-16)">This&#160;is&#160;a&#160;big&#160;notification.</text><text class="terminal-1517911659-r3" x="939.4" y="410.4" textLength="12.2" clip-path="url(#terminal-1517911659-line-16)">▊</text><text class="terminal-1517911659-r1" x="976" y="410.4" textLength="12.2" clip-path="url(#terminal-1517911659-line-16)">
+  </text><text class="terminal-1517911659-r2" x="268.4" y="434.8" textLength="12.2" clip-path="url(#terminal-1517911659-line-17)">▎</text><text class="terminal-1517911659-r3" x="939.4" y="434.8" textLength="12.2" clip-path="url(#terminal-1517911659-line-17)">▊</text><text class="terminal-1517911659-r1" x="976" y="434.8" textLength="12.2" clip-path="url(#terminal-1517911659-line-17)">
+  </text><text class="terminal-1517911659-r2" x="268.4" y="459.2" textLength="12.2" clip-path="url(#terminal-1517911659-line-18)">▎</text><text class="terminal-1517911659-r3" x="939.4" y="459.2" textLength="12.2" clip-path="url(#terminal-1517911659-line-18)">▊</text><text class="terminal-1517911659-r1" x="976" y="459.2" textLength="12.2" clip-path="url(#terminal-1517911659-line-18)">
+  </text>
+      </g>
+      </g>
+  </svg>
+  
+  '''
+# ---
 # name: test_notifications_through_modes
   '''
   <svg class="rich-terminal" viewBox="0 0 994 635.5999999999999" xmlns="http://www.w3.org/2000/svg">
diff --git a/tests/snapshot_tests/snapshot_apps/notifications_above_loading.py b/tests/snapshot_tests/snapshot_apps/notifications_above_loading.py
new file mode 100644
--- /dev/null
+++ b/tests/snapshot_tests/snapshot_apps/notifications_above_loading.py
@@ -0,0 +1,31 @@
+from textual.app import App, ComposeResult
+from textual.containers import VerticalScroll
+from textual.widgets import Label
+
+
+class LoadingOverlayApp(App[None]):
+    CSS = """
+    VerticalScroll {
+        height: 20;
+    }
+    
+    Toast {
+        max-width: 100%;
+        width: 70%;  /* We need this to cover the dots of the loading indicator
+        so that we don't have flakiness in the tests because the screenshot
+        might be taken a couple ms earlier or later. */
+    }"""
+
+    def compose(self) -> ComposeResult:
+        with VerticalScroll():
+            yield Label("another big label\n"*30)  # Ensure there's a scrollbar.
+
+    def on_mount(self):
+        self.notify(
+            "This is a big notification.\n" * 10,
+            timeout=9_999_999
+        )
+        self.query_one(VerticalScroll).loading = True
+
+if __name__ == "__main__":
+    LoadingOverlayApp().run()
diff --git a/tests/snapshot_tests/test_snapshots.py b/tests/snapshot_tests/test_snapshots.py
--- a/tests/snapshot_tests/test_snapshots.py
+++ b/tests/snapshot_tests/test_snapshots.py
@@ -902,3 +902,12 @@ def test_button_outline(snap_compare):
     Regression test for https://github.com/Textualize/textual/issues/3628
     """
     assert snap_compare(SNAPSHOT_APPS_DIR / "button_outline.py")
+
+
+def test_notifications_loading_overlap_order(snap_compare):
+    """Regression test for https://github.com/Textualize/textual/issues/3677.
+
+    This tests that notifications stay on top of loading indicators and it also
+    tests that loading a widget will remove its scrollbars.
+    """
+    assert snap_compare(SNAPSHOT_APPS_DIR / "notifications_above_loading.py", terminal_size=(80, 20))
diff --git a/tests/test_loading.py b/tests/test_loading.py
new file mode 100644
--- /dev/null
+++ b/tests/test_loading.py
@@ -0,0 +1,36 @@
+from textual.app import App, ComposeResult
+from textual.containers import VerticalScroll
+from textual.widgets import Label
+
+
+class LoadingApp(App[None]):
+    CSS = """
+    VerticalScroll {
+        height: 20;
+    }
+    """
+
+    BINDINGS = [("l", "loading")]
+
+    def compose(self) -> ComposeResult:
+        with VerticalScroll():
+            yield Label("another big label\n" * 30)  # Ensure there's a scrollbar.
+
+    def action_loading(self):
+        self.query_one(VerticalScroll).loading = True
+
+
+async def test_loading_disables_and_remove_scrollbars():
+    app = LoadingApp()
+    async with app.run_test() as pilot:
+        vs = app.query_one(VerticalScroll)
+        # Sanity checks:
+        assert not vs.disabled
+        assert vs.styles.overflow_y != "hidden"
+
+        await pilot.press("l")
+        await pilot.pause()
+
+        assert vs.disabled
+        assert vs.styles.overflow_x == "hidden"
+        assert vs.styles.overflow_y == "hidden"