Repository: Textualize/textual

Issue:
Writing to a hidden RichLog breaks table alignment
I've got a `RichLog` that is often hidden and I write text to it. I'm using a `Rich.Table` to left/right justify two pieces of text on a single line.

This works as expected while the widget is shown.

If the widget has either `visible=False` or `display=False` set, then any text written during that time is collapsed together into a single string.

I'm not sure if this is a side effect of not having the widget displayed (no space is calculated for it so it doesn't know what sizes to use when writing the `Table`?) or not. If this is working as expected, might there be any way to write to the widget while it's hidden but preserve the appropriate sizing?

The following is an example of writing to the widget both while it is shown, has `visible=False` and `display=False`.

![hidden-width](https://github.com/Textualize/textual/assets/11033703/1cc78911-f193-4186-9b6a-7fc0e0246bf5)

Example Code (same that produced `gif` above).
```python
from __future__ import annotations

import random

from rich.align import Align
from rich.table import Table
from rich.text import Text
from textual.app import App, ComposeResult
from textual.widgets import RichLog


class Example(App):
    BINDINGS = [
        ("w", "write_line", "Write Line"),
        ("h", "toggle_visible", "Toggle Visibility"),
        ("d", "toggle_display", "Toggle Display"),
        ("q", "quit", "Quit"),
    ]

    DEFAULT_CSS = """
    #one  {
        border: round white;
        height: 1fr;
    }
    #two  {
        border: round white;
        height: 1fr;
    }
    """

    def compose(self) -> ComposeResult:
        log1 = RichLog(id="one")
        log1.border_title = "Log 1"
        log2 = RichLog(id="two")
        log2.border_title = "Log 2"
        yield log1
        yield log2

    def action_toggle_visible(self) -> None:
        log1 = self.query_one("#one", RichLog)
        log2 = self.query_one("#two", RichLog)

        log2.visible = not log2.visible
        log1.write(f"log2 visibility={log2.visible}")

    def action_toggle_display(self) -> None:
        log1 = self.query_one("#one", RichLog)
        log2 = self.query_one("#two", RichLog)

        log2.display = not log2.display
        log1.write(f"log2 display={log2.display}")

    def action_write_line(self) -> None:
        """Write a line to log 2"""
        log1 = self.query_one("#one", RichLog)
        log2 = self.query_one("#two", RichLog)

        left = Text("something: text on the left")
        right = Text("Stuff on the right")
        table = Table.grid(expand=True)
        table.add_row(left, Align.right(right))

        log2.write(table, expand=True)
        log1.write("Wrote to log2")


if __name__ == "__main__":
    app = Example()
    app.run()
```

# Textual Diagnostics

## Versions

| Name    | Value  |
|---------|--------|
| Textual | 0.46.0 |
| Rich    | 13.7.0 |

## Python

| Name           | Value                                                     |
|----------------|-----------------------------------------------------------|
| Version        | 3.8.10                                                    |
| Implementation | CPython                                                   |
| Compiler       | Clang 14.0.3 (clang-1403.0.22.14.1)                       |
| Executable     | /Users/geoff/Documents/projects/kafka-tui/venv/bin/python |

## Operating System

| Name    | Value                                                                                                 |
|---------|-------------------------------------------------------------------------------------------------------|
| System  | Darwin                                                                                                |
| Release | 23.3.0                                                                                                |
| Version | Darwin Kernel Version 23.3.0: Wed Dec 20 21:30:27 PST 2023; root:xnu-10002.81.5~7/RELEASE_ARM64_T8103 |

## Terminal

| Name                 | Value           |
|----------------------|-----------------|
| Terminal Application | vscode (1.86.0) |
| TERM                 | xterm-256color  |
| COLORTERM            | truecolor       |
| FORCE_COLOR          | *Not set*       |
| NO_COLOR             | *Not set*       |

## Rich Console options

| Name           | Value                |
|----------------|----------------------|
| size           | width=115, height=40 |
| legacy_windows | False                |
| min_width      | 1                    |
| max_width      | 115                  |
| is_terminal    | True                 |
| encoding       | utf-8                |
| max_height     | 40                   |
| justify        | None                 |
| overflow       | None                 |
| no_wrap        | False                |
| highlight      | None                 |
| markup         | None                 |
| height         | None                 |

Feel free to add screenshots and / or videos. These can be very helpful!



Discussion:
We found the following entry in the [FAQ](https://textual.textualize.io/FAQ/) which you may find helpful:


- [How do I center a widget in a screen?](https://textual.textualize.io/FAQ/#how-do-i-center-a-widget-in-a-screen)

Feel free to close this issue if you found an answer in the FAQ. Otherwise, please give us a little time to review.

This is an automated reply, generated by [FAQtory](https://github.com/willmcgugan/faqtory)
> I'm not sure if this is a side effect of not having the widget displayed (no space is calculated for it so it doesn't know what sizes to use when writing the `Table`?) or not. If this is working as expected, might there be any way to write to the widget while it's hidden but preserve the appropriate sizing?

I think you're right about `Rich.Table` not knowing how to calculate the column width.

Perhaps you could set `table.width = log2.scrollable_content_region.width` as a workaround?

Gave it a whirl but unfortunately that doesn't seem to be working either. Looks to be writing empty lines in that case when it's not displayed. The width reported while it's hidden is 0.

<img width="744" alt="image" src="https://github.com/Textualize/textual/assets/11033703/3cc00216-c358-4b27-a54c-5a38c2f004b2">


Resolving patch:
diff --git a/src/textual/widgets/_rich_log.py b/src/textual/widgets/_rich_log.py
--- a/src/textual/widgets/_rich_log.py
+++ b/src/textual/widgets/_rich_log.py
@@ -88,9 +88,15 @@ def __init__(
         """Automatically scroll to the end on write."""
         self.highlighter = ReprHighlighter()
 
+        self._last_container_width: int = min_width
+        """Record the last width we rendered content at."""
+
     def notify_style_update(self) -> None:
         self._line_cache.clear()
 
+    def on_resize(self) -> None:
+        self._last_container_width = self.scrollable_content_region.width
+
     def _make_renderable(self, content: RenderableType | object) -> RenderableType:
         """Make content renderable.
 
@@ -153,14 +159,22 @@ def write(
         render_width = measure_renderables(
             console, render_options, [renderable]
         ).maximum
+
         container_width = (
             self.scrollable_content_region.width if width is None else width
         )
-        if container_width:
-            if expand and render_width < container_width:
-                render_width = container_width
-            if shrink and render_width > container_width:
-                render_width = container_width
+
+        # Use the container_width if it's available, otherwise use the last available width.
+        container_width = (
+            container_width if container_width else self._last_container_width
+        )
+
+        if expand and render_width < container_width:
+            render_width = container_width
+        if shrink and render_width > container_width:
+            render_width = container_width
+
+        render_width = max(render_width, self.min_width)
 
         segments = self.app.console.render(
             renderable, render_options.update_width(render_width)


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
@@ -30380,6 +30380,161 @@
   
   '''
 # ---
+# name: test_richlog_width
+  '''
+  <svg class="rich-terminal" viewBox="0 0 994 635.5999999999999" 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-31396663-matrix {
+          font-family: Fira Code, monospace;
+          font-size: 20px;
+          line-height: 24.4px;
+          font-variant-east-asian: full-width;
+      }
+  
+      .terminal-31396663-title {
+          font-size: 18px;
+          font-weight: bold;
+          font-family: arial;
+      }
+  
+      .terminal-31396663-r1 { fill: #e1e1e1 }
+  .terminal-31396663-r2 { fill: #c5c8c6 }
+      </style>
+  
+      <defs>
+      <clipPath id="terminal-31396663-clip-terminal">
+        <rect x="0" y="0" width="975.0" height="584.5999999999999" />
+      </clipPath>
+      <clipPath id="terminal-31396663-line-0">
+      <rect x="0" y="1.5" width="976" height="24.65"/>
+              </clipPath>
+  <clipPath id="terminal-31396663-line-1">
+      <rect x="0" y="25.9" width="976" height="24.65"/>
+              </clipPath>
+  <clipPath id="terminal-31396663-line-2">
+      <rect x="0" y="50.3" width="976" height="24.65"/>
+              </clipPath>
+  <clipPath id="terminal-31396663-line-3">
+      <rect x="0" y="74.7" width="976" height="24.65"/>
+              </clipPath>
+  <clipPath id="terminal-31396663-line-4">
+      <rect x="0" y="99.1" width="976" height="24.65"/>
+              </clipPath>
+  <clipPath id="terminal-31396663-line-5">
+      <rect x="0" y="123.5" width="976" height="24.65"/>
+              </clipPath>
+  <clipPath id="terminal-31396663-line-6">
+      <rect x="0" y="147.9" width="976" height="24.65"/>
+              </clipPath>
+  <clipPath id="terminal-31396663-line-7">
+      <rect x="0" y="172.3" width="976" height="24.65"/>
+              </clipPath>
+  <clipPath id="terminal-31396663-line-8">
+      <rect x="0" y="196.7" width="976" height="24.65"/>
+              </clipPath>
+  <clipPath id="terminal-31396663-line-9">
+      <rect x="0" y="221.1" width="976" height="24.65"/>
+              </clipPath>
+  <clipPath id="terminal-31396663-line-10">
+      <rect x="0" y="245.5" width="976" height="24.65"/>
+              </clipPath>
+  <clipPath id="terminal-31396663-line-11">
+      <rect x="0" y="269.9" width="976" height="24.65"/>
+              </clipPath>
+  <clipPath id="terminal-31396663-line-12">
+      <rect x="0" y="294.3" width="976" height="24.65"/>
+              </clipPath>
+  <clipPath id="terminal-31396663-line-13">
+      <rect x="0" y="318.7" width="976" height="24.65"/>
+              </clipPath>
+  <clipPath id="terminal-31396663-line-14">
+      <rect x="0" y="343.1" width="976" height="24.65"/>
+              </clipPath>
+  <clipPath id="terminal-31396663-line-15">
+      <rect x="0" y="367.5" width="976" height="24.65"/>
+              </clipPath>
+  <clipPath id="terminal-31396663-line-16">
+      <rect x="0" y="391.9" width="976" height="24.65"/>
+              </clipPath>
+  <clipPath id="terminal-31396663-line-17">
+      <rect x="0" y="416.3" width="976" height="24.65"/>
+              </clipPath>
+  <clipPath id="terminal-31396663-line-18">
+      <rect x="0" y="440.7" width="976" height="24.65"/>
+              </clipPath>
+  <clipPath id="terminal-31396663-line-19">
+      <rect x="0" y="465.1" width="976" height="24.65"/>
+              </clipPath>
+  <clipPath id="terminal-31396663-line-20">
+      <rect x="0" y="489.5" width="976" height="24.65"/>
+              </clipPath>
+  <clipPath id="terminal-31396663-line-21">
+      <rect x="0" y="513.9" width="976" height="24.65"/>
+              </clipPath>
+  <clipPath id="terminal-31396663-line-22">
+      <rect x="0" y="538.3" 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="633.6" rx="8"/><text class="terminal-31396663-title" fill="#c5c8c6" text-anchor="middle" x="496" y="27">RichLogWidth</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-31396663-clip-terminal)">
+      <rect fill="#f4005f" x="0" y="1.5" width="244" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="244" y="1.5" width="707.6" height="24.65" shape-rendering="crispEdges"/><rect fill="#14191f" x="951.6" y="1.5" width="24.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#98e024" x="0" y="25.9" width="244" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="244" y="25.9" width="707.6" height="24.65" shape-rendering="crispEdges"/><rect fill="#14191f" x="951.6" y="25.9" width="24.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#9d65ff" x="0" y="50.3" width="244" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="244" y="50.3" width="707.6" height="24.65" shape-rendering="crispEdges"/><rect fill="#14191f" x="951.6" y="50.3" width="24.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#fd971f" x="0" y="74.7" width="244" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="244" y="74.7" width="707.6" height="24.65" shape-rendering="crispEdges"/><rect fill="#14191f" x="951.6" y="74.7" width="24.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="99.1" width="951.6" height="24.65" shape-rendering="crispEdges"/><rect fill="#14191f" x="951.6" y="99.1" width="24.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="123.5" width="951.6" height="24.65" shape-rendering="crispEdges"/><rect fill="#14191f" x="951.6" y="123.5" width="24.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="147.9" width="951.6" height="24.65" shape-rendering="crispEdges"/><rect fill="#14191f" x="951.6" y="147.9" width="24.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="172.3" width="951.6" height="24.65" shape-rendering="crispEdges"/><rect fill="#14191f" x="951.6" y="172.3" width="24.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="196.7" width="951.6" height="24.65" shape-rendering="crispEdges"/><rect fill="#14191f" x="951.6" y="196.7" width="24.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="221.1" width="951.6" height="24.65" shape-rendering="crispEdges"/><rect fill="#14191f" x="951.6" y="221.1" width="24.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="245.5" width="951.6" height="24.65" shape-rendering="crispEdges"/><rect fill="#14191f" x="951.6" y="245.5" width="24.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="269.9" width="951.6" height="24.65" shape-rendering="crispEdges"/><rect fill="#14191f" x="951.6" y="269.9" width="24.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="294.3" width="951.6" height="24.65" shape-rendering="crispEdges"/><rect fill="#14191f" x="951.6" y="294.3" width="24.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="318.7" width="951.6" height="24.65" shape-rendering="crispEdges"/><rect fill="#14191f" x="951.6" y="318.7" width="24.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="343.1" width="951.6" height="24.65" shape-rendering="crispEdges"/><rect fill="#14191f" x="951.6" y="343.1" width="24.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="367.5" width="951.6" height="24.65" shape-rendering="crispEdges"/><rect fill="#14191f" x="951.6" y="367.5" width="24.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="391.9" width="951.6" height="24.65" shape-rendering="crispEdges"/><rect fill="#14191f" x="951.6" y="391.9" width="24.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="416.3" width="951.6" height="24.65" shape-rendering="crispEdges"/><rect fill="#14191f" x="951.6" y="416.3" width="24.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="440.7" width="951.6" height="24.65" shape-rendering="crispEdges"/><rect fill="#14191f" x="951.6" y="440.7" width="24.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="465.1" width="951.6" height="24.65" shape-rendering="crispEdges"/><rect fill="#14191f" x="951.6" y="465.1" width="24.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="489.5" width="951.6" height="24.65" shape-rendering="crispEdges"/><rect fill="#14191f" x="951.6" y="489.5" width="24.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="513.9" width="951.6" height="24.65" shape-rendering="crispEdges"/><rect fill="#14191f" x="951.6" y="513.9" width="24.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="538.3" width="951.6" height="24.65" shape-rendering="crispEdges"/><rect fill="#14191f" x="951.6" y="538.3" width="24.4" height="24.65" shape-rendering="crispEdges"/><rect fill="#1e1e1e" x="0" y="562.7" width="951.6" height="24.65" shape-rendering="crispEdges"/><rect fill="#14191f" x="951.6" y="562.7" width="24.4" height="24.65" shape-rendering="crispEdges"/>
+      <g class="terminal-31396663-matrix">
+      <text class="terminal-31396663-r1" x="0" y="20" textLength="244" clip-path="url(#terminal-31396663-line-0)">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;hello1</text><text class="terminal-31396663-r2" x="976" y="20" textLength="12.2" clip-path="url(#terminal-31396663-line-0)">
+  </text><text class="terminal-31396663-r1" x="0" y="44.4" textLength="244" clip-path="url(#terminal-31396663-line-1)">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;world2</text><text class="terminal-31396663-r2" x="976" y="44.4" textLength="12.2" clip-path="url(#terminal-31396663-line-1)">
+  </text><text class="terminal-31396663-r1" x="0" y="68.8" textLength="244" clip-path="url(#terminal-31396663-line-2)">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;hello3</text><text class="terminal-31396663-r2" x="976" y="68.8" textLength="12.2" clip-path="url(#terminal-31396663-line-2)">
+  </text><text class="terminal-31396663-r1" x="0" y="93.2" textLength="244" clip-path="url(#terminal-31396663-line-3)">&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;world4</text><text class="terminal-31396663-r2" x="976" y="93.2" textLength="12.2" clip-path="url(#terminal-31396663-line-3)">
+  </text><text class="terminal-31396663-r2" x="976" y="117.6" textLength="12.2" clip-path="url(#terminal-31396663-line-4)">
+  </text><text class="terminal-31396663-r2" x="976" y="142" textLength="12.2" clip-path="url(#terminal-31396663-line-5)">
+  </text><text class="terminal-31396663-r2" x="976" y="166.4" textLength="12.2" clip-path="url(#terminal-31396663-line-6)">
+  </text><text class="terminal-31396663-r2" x="976" y="190.8" textLength="12.2" clip-path="url(#terminal-31396663-line-7)">
+  </text><text class="terminal-31396663-r2" x="976" y="215.2" textLength="12.2" clip-path="url(#terminal-31396663-line-8)">
+  </text><text class="terminal-31396663-r2" x="976" y="239.6" textLength="12.2" clip-path="url(#terminal-31396663-line-9)">
+  </text><text class="terminal-31396663-r2" x="976" y="264" textLength="12.2" clip-path="url(#terminal-31396663-line-10)">
+  </text><text class="terminal-31396663-r2" x="976" y="288.4" textLength="12.2" clip-path="url(#terminal-31396663-line-11)">
+  </text><text class="terminal-31396663-r2" x="976" y="312.8" textLength="12.2" clip-path="url(#terminal-31396663-line-12)">
+  </text><text class="terminal-31396663-r2" x="976" y="337.2" textLength="12.2" clip-path="url(#terminal-31396663-line-13)">
+  </text><text class="terminal-31396663-r2" x="976" y="361.6" textLength="12.2" clip-path="url(#terminal-31396663-line-14)">
+  </text><text class="terminal-31396663-r2" x="976" y="386" textLength="12.2" clip-path="url(#terminal-31396663-line-15)">
+  </text><text class="terminal-31396663-r2" x="976" y="410.4" textLength="12.2" clip-path="url(#terminal-31396663-line-16)">
+  </text><text class="terminal-31396663-r2" x="976" y="434.8" textLength="12.2" clip-path="url(#terminal-31396663-line-17)">
+  </text><text class="terminal-31396663-r2" x="976" y="459.2" textLength="12.2" clip-path="url(#terminal-31396663-line-18)">
+  </text><text class="terminal-31396663-r2" x="976" y="483.6" textLength="12.2" clip-path="url(#terminal-31396663-line-19)">
+  </text><text class="terminal-31396663-r2" x="976" y="508" textLength="12.2" clip-path="url(#terminal-31396663-line-20)">
+  </text><text class="terminal-31396663-r2" x="976" y="532.4" textLength="12.2" clip-path="url(#terminal-31396663-line-21)">
+  </text><text class="terminal-31396663-r2" x="976" y="556.8" textLength="12.2" clip-path="url(#terminal-31396663-line-22)">
+  </text>
+      </g>
+      </g>
+  </svg>
+  
+  '''
+# ---
 # name: test_rule_horizontal_rules
   '''
   <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/richlog_width.py b/tests/snapshot_tests/snapshot_apps/richlog_width.py
new file mode 100644
--- /dev/null
+++ b/tests/snapshot_tests/snapshot_apps/richlog_width.py
@@ -0,0 +1,12 @@
+from rich.text import Text
+from textual.app import App, ComposeResult
+from textual.widgets import RichLog
+
+
+class RichLogWidth(App[None]):
+    def compose(self) -> ComposeResult:
+        yield RichLog(min_width=20)
+
+app = RichLogWidth()
+if __name__ == "__main__":
+    app.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
@@ -4,7 +4,7 @@
 
 from tests.snapshot_tests.language_snippets import SNIPPETS
 from textual.widgets.text_area import Selection, BUILTIN_LANGUAGES
-from textual.widgets import TextArea, Input, Button
+from textual.widgets import RichLog, TextArea, Input, Button
 from textual.widgets.text_area import TextAreaTheme
 
 # These paths should be relative to THIS directory.
@@ -570,6 +570,26 @@ def test_richlog_scroll(snap_compare):
     assert snap_compare(SNAPSHOT_APPS_DIR / "richlog_scroll.py")
 
 
+def test_richlog_width(snap_compare):
+    """Check that min_width applies in RichLog and that we can write
+    to the RichLog when it's not visible, and it still renders as expected
+    when made visible again."""
+    async def setup(pilot):
+        from rich.text import Text
+        rich_log: RichLog = pilot.app.query_one(RichLog)
+        rich_log.write(Text("hello1", style="on red", justify="right"), expand=True)
+        rich_log.visible = False
+        rich_log.write(Text("world2", style="on green", justify="right"), expand=True)
+        rich_log.visible = True
+        rich_log.write(Text("hello3", style="on blue", justify="right"), expand=True)
+        rich_log.display = False
+        rich_log.write(Text("world4", style="on yellow", justify="right"), expand=True)
+        rich_log.display = True
+
+    assert snap_compare(SNAPSHOT_APPS_DIR / "richlog_width.py",
+                        run_before=setup)
+
+
 def test_tabs_invalidate(snap_compare):
     assert snap_compare(
         SNAPSHOT_APPS_DIR / "tabs_invalidate.py",