diff --git a/docs/guide/devtools.md b/docs/guide/devtools.md
index 487700c8e..63f515af0 100644
--- a/docs/guide/devtools.md
+++ b/docs/guide/devtools.md
@@ -30,13 +30,13 @@ textual run my_app.py:alternative_app
When running any terminal application, you can no longer use `print` when debugging (or log to the console). This is because anything you write to standard output would overwrite application content, making it unreadable. Fortunately Textual supplies a debug console of its own which has some super helpful features.
-To use the console, open up 2 terminal emulators. In the first one, run the following:
+To use the console, open up 2 terminal emulators. Run the following in one of the terminals:
```bash
textual console
```
-This should look something like the following:
+You should see the Textual devtools welcome message:
```{.textual title="textual console" path="docs/examples/getting_started/console.py", press="_,_"}
```
@@ -47,5 +47,16 @@ In the other console, run your application using `textual run` and the `--dev` s
textual run --dev my_app.py
```
-Anything you `print` from your application will be displayed in the console window. You can also call the [`log()`][textual.message_pump.MessagePump.log] method on App and Widget objects for advanced formatting. Try it with `self.log(self.tree)`.
+Anything you `print` from your application will be displayed in the console window.
+
+### Textual log
+
+In addition to printing strings, Textual console supports more advanced formatting in logs. To write advanced logs import `log` from `textual` as follows:
+
+```python
+from textual import log
+```
+
+You can logs strings, other Python data types which will be pretty printed in the console. You can also log [Rich renderables](https://rich.readthedocs.io/en/stable/protocol.html).
+
diff --git a/docs/guide/layout.md b/docs/guide/layout.md
index e69de29bb..6f10cf228 100644
--- a/docs/guide/layout.md
+++ b/docs/guide/layout.md
@@ -0,0 +1,56 @@
+# Layout
+
+TODO: Explanation of layout
+
+## Vertical layout
+
+
+--8<-- "docs/images/layout_vertical.excalidraw.svg"
+
+
+
+TODO: Explanation of vertical layout
+
+
+## Horizontal layout
+
+
+--8<-- "docs/images/layout_horizontal.excalidraw.svg"
+
+
+
+TODO: Explantion of horizontal layout
+
+## Center layout
+
+
+--8<-- "docs/images/layout_center.excalidraw.svg"
+
+
+
+TODO: Explanation of center layout
+
+## Table layout
+
+
+
+--8<-- "docs/images/layout_table.excalidraw.svg"
+
+
+
+TODO: Explanation of table layout
+
+
+## Dock
+
+TODO: Diagram
+TODO: Explanation of dock
+
+## Offsets
+
+TODO: Diagram
+TODO: Offsets
+
+## Box Model
+
+TBC
diff --git a/docs/how-to/animation.md b/docs/how-to/animation.md
new file mode 100644
index 000000000..4709f033e
--- /dev/null
+++ b/docs/how-to/animation.md
@@ -0,0 +1 @@
+# Animation
diff --git a/docs/how-to/mouse-and-keyboard.md b/docs/how-to/mouse-and-keyboard.md
new file mode 100644
index 000000000..1707580e4
--- /dev/null
+++ b/docs/how-to/mouse-and-keyboard.md
@@ -0,0 +1 @@
+# Mouse and Keyboard
diff --git a/docs/how-to/scroll.md b/docs/how-to/scroll.md
new file mode 100644
index 000000000..a12cc92b4
--- /dev/null
+++ b/docs/how-to/scroll.md
@@ -0,0 +1 @@
+# Scroll
diff --git a/docs/images/layout_align.excalidraw.svg b/docs/images/layout_align.excalidraw.svg
new file mode 100644
index 000000000..fd2f8e94f
--- /dev/null
+++ b/docs/images/layout_align.excalidraw.svg
@@ -0,0 +1,16 @@
+
+
+ eyJ2ZXJzaW9uIjoiMSIsImVuY29kaW5nIjoiYnN0cmluZyIsImNvbXByZXNzZWQiOnRydWUsImVuY29kZWQiOiJ4nN2ZW1PbOFx1MDAxNMff+Vx1MDAxNJn0tXGtozszOzuUy5altEOBXHUwMDAy2d1hXHUwMDE0W0nU+FbbIUCH776yk8FJSCBAmmY3XHUwMDBmmVhcdTAwMTfrSOd3pP9RfmzUavX8JtH1zVpdX3sqMH6qXHUwMDA29bdF+ZVOM1x1MDAxM0e2XG7K5yzup17ZspvnSbb57l2o0p7Ok0B52rkyWV9cdTAwMDVZ3vdN7Hhx+M7kOsx+L74/qVD/lsShn6dONUhD+yaP0+FYOtChjvLMvv0v+1xcq/0ov8esS7WXq6hcdTAwMTPoskNZVVx1MDAxOYhcdTAwMTibLv1cdTAwMTRHpbHAXHUwMDEwYEJcdTAwMTm9b2CyXHUwMDFkO1xcrn1b27Ym66qmKKpnW1x1MDAwM6EvTz5cdTAwMWOdnr3fa1x1MDAxZJxkUVx1MDAwMnvVqG1cdTAwMTNcdTAwMDTH+U1QWuWlcZY1uir3ulWLLE/jnj4zft4tbJsqv++bxXYhql5p3O90I51lXHUwMDEzfeJEeSa/KcpcXPe+dLhcdTAwMTCbtark2j41sHQkRoy4XGaq6Vx1MDAxNn1cdTAwMDGowySarFx1MDAxOJqzXHUwMDFkXHUwMDA31lx01pw3bvmpXGZqKa/XsVZF/n2bPFVRlqjUuqpqN1x1MDAxOE2USOZgLuTEIF1tOt3c1mJcdTAwMTCOIJiPja9LXHUwMDE3MExBuEJWXHUwMDFlLFx1MDAwNk32/Vx1MDAxMoZ/plevq9JktEr1rHhcdTAwMTgzuLB1d4ykqnM/8dXQ41x1MDAxNlx1MDAxNVx1MDAwMClcdEOYVMtcdTAwMWOYqGcro35cdTAwMTBUZbHXqyApS+/evlx1MDAwME6MYVx1MDAxZZyYcNc67Fx1MDAxOXBcdTAwMWX+eXmjm4KdXFxsN1x1MDAwZre/tHZC+s28XHUwMDFjTlghnMJhhJFJXHUwMDA2hnBcdTAwMTKHulj+ZDiJM4dMYFx1MDAwZVx1MDAwMuTKXHUwMDE5bFwiXHUwMDBltKhcdTAwMDOyOjixnafgiMGy4NRBYJJsJpqA5Dw0keQu48DIwmgmX1x1MDAwN9ffZPiRXFxk/T3VXHUwMDEwaciO8jloTuH1y3ZMwFx1MDAwZZZAuUDTOyZGzit5fNNWXHUwMDE0KDxkXHUwMDExgVx1MDAwM2gqXHUwMDEw7mlEyCFcdTAwMTSPmzNiXHUwMDExXHUwMDEzbMstXHUwMDFiq9wnhSDUXHUwMDA1vFxuXHUwMDE0OZ6LXCJcdTAwMDEhXHUwMDAwU1xuXHUwMDBis8j7/n7nNHa1Pr+J6EHe3PrgrzmLyEHUKpVcdTAwMDe7I3ZcdTAwMWSKXHUwMDEwR4K/lsaW69Jl0YiElVx1MDAxOcSVzP1/4oiBz8NRWlx1MDAxMjlnXHUwMDBis9jS+GBcdTAwMDBR0NKn6UHb97RcdTAwMWY1d9abRXskMjnp9+FJbVx1MDAwNSbikr2WRVx1MDAwNC0h2NJYtFwiym7g7D+9NT6e31x1MDAxMHdcdTAwMWWN4Fwiq53AJXhhIHezXXLFaf/w6svOIblIzPlutrXeQDaAO5Iz+iCxYfZcdTAwMDCniD52VHtcdTAwMTJcdTAwMTSol0tHJMlDXHUwMDE4XHUwMDA1OLTQ7kDk8PNcdTAwMDBKZOWmRDbtWT6Uo4qKolx0knJ9Xc1izO2oXHUwMDFm7feDi+/87PiA9D73veOji9v6fbu70a9HkyZhsV9cdPEwllx1MDAxM00nTcz6m3G+MO9KZb3P9HTPoEP5/Xa7Sa9JStebd4RsUsJcXPRcdTAwMDB4zMB5Qlxm2L1VYb1q3u1cdTAwMGVk5YCF/iekSi/jPaTNVFxydHT058fuye5547ZcdTAwMWSe9Z7HOyfAV8Q7XHUwMDEy83hHYNeWXG54XHUwMDA28a7ZYrHMzVx1MDAwMf/jsnnph3nnrIPWm3hcdTAwMGKWQ9hkXHUwMDE2XvS0M3eeuFx1MDAxYii0qGr9XHUwMDAy4IFTzsZud34x8OeXn8yHILyNzuLUfFx1MDAxZPS6unlknlx0vMDAllx1MDAwNfyEnVx1MDAxM1x1MDAxN2JzpbWk3Eo5gVx1MDAxNiZ99qG21qQ3XHUwMDAwZmtcdTAwMTkuXHUwMDFkhtnjm/tcdTAwMDJi5k273Z5cdTAwMDG5mFx1MDAwMTl1p6lGrnCxxf5nbOPLVFx1MDAxNpWH4yg/NrdDKTxRuqdCXHUwMDEz3Ey4qSSyUFx1MDAwNIHpRI2uXHKTW9tQXHUwMDA1m7W/o0C38/F1zbS1onjtmLIu+m9cdTAwMTV9i5d4dl46nVx1MDAwMDw3nlxu7lx1MDAxYoTG98d3e69cdTAwMTjLvjPdX0SGW+M6JlLByVxcm0uLX1x1MDAxNoFzxVWhOFx1MDAwMGOQi4fg7HN2rUNcdTAwMTBcdTAwMDGaI6+4sElmue+/SmC9Klx1MDAwNjHh5Z3zSq9Wni92llx1MDAxZoLTXHUwMDExtYIgfFwiN3g6XGJHXHUwMDA2vCxcZtG8MFx1MDAxNFx1MDAwMPYkJGLxpH724b/WUVxilMyWfJw4jE9dyr9A9L3uILRWMcQpXvH/ks9VYMuPwrRcXJNVXHUwMDA24Vx1MDAxM+nK00E4NHlcdTAwMTiDXHUwMDFiI4VbV0lynNvVtV2GXHUwMDExaVx1MDAxZGj80Vx1MDAxMlUrWr8yevB+Nj1cdTAwMDVAXHUwMDFio7guQkhcdTAwMTfu+3G3cfcvaFx1MDAxZGxTIn0=
+
+
+
+ align-horizontal: left align-horizontal: center align-horizontal: right
\ No newline at end of file
diff --git a/docs/images/layout_center.excalidraw.svg b/docs/images/layout_center.excalidraw.svg
new file mode 100644
index 000000000..b9e15e7a9
--- /dev/null
+++ b/docs/images/layout_center.excalidraw.svg
@@ -0,0 +1,16 @@
+
+
+ eyJ2ZXJzaW9uIjoiMSIsImVuY29kaW5nIjoiYnN0cmluZyIsImNvbXByZXNzZWQiOnRydWUsImVuY29kZWQiOiJ4nNWXW2/bNlx1MDAxNMff+ylcZve1UXhcdTAwMTdcdTAwMTlgXHUwMDE4nHRZ0mxuV6fpsmFcdTAwMThcdTAwMTiJllx0U5eJtHNDvvsoObUsx1x1MDAwZbzUMDI9XGLQ4eVcdTAwMWPy/Pg/4v2bTqfrblx1MDAwYtU96HTVTSSNjkt53X1X2aeqtDrPfFx1MDAxM6q/bT4po7rnyLnCXHUwMDFl7O+nslx1MDAxYytXXHUwMDE4XHUwMDE5qWCq7URcdTAwMWHrJrHOgyhP97VTqf2xevdlqn4o8jR2ZdA42VOxdnk586WMSlXmrJ/9T//d6dzX74XoSlx1MDAxNTmZJUbVXHUwMDAz6qaFXHUwMDAwXHUwMDAxW7b286xcdTAwMGWWUoxpXGJDMO+g7XvvzqnYt1x1MDAwZX3IqmmpTN2Pn0+MMlx1MDAxZk4tXHUwMDFj9tXPXHUwMDE3VCfclo3XoTZm4G5NXHUwMDFkVVTm1u6NpItGTVx1MDAwZuvKfKy+6tiNfFx1MDAxZrhkn4+1ud+IZlSZT5JRpqxtjclcdTAwMGJcdTAwMTlpd1vZQLOE2UZcdTAwMWN0XHUwMDFhy43/wkBcdTAwMDRIIMF4SOdcctVQRFnAXHUwMDA1oiGHiC6Fc5RcdTAwMWKfXHUwMDA0XHUwMDFmzltQP01AVzJcdTAwMWEnPqosnvdxpcxsIUufqqbf9eNCiWBcdTAwMDFcdTAwMGW5XHUwMDAwbMHJSOlk5KrgXHUwMDEwXHUwMDBmOMFcdTAwMGKRWVWnQISQYoZ5s5bKaXFcdTAwMWHXMPy1vHsjWVx1MDAxNo+71LXVx0LAVaw/LZDUXGaeXHUwMDE0sZxlXHUwMDFjMoaQXHUwMDEwzHuFeN5udDb2jdnEmMaWR+NcdTAwMDaS2vrw7lx1MDAwNXBCLtbBiYDgXHUwMDA0YkrJxnT+dszkP72LL/BzL75y4PBTf7CWziXC2lxcop1yXHUwMDE5glx1MDAxMOBF+r5xXHShgKSFzPa5JMFcdTAwMWEokfePIFx1MDAxMCuwRJwwgVx1MDAwNWW7w1x1MDAxMvtlUlx1MDAxNHK0LSyVMbqwq6Gk4VooXHUwMDExXHUwMDAxXGJ7IdmYSWhcXFx1MDAxNNvxydHFuexHe1NzqT9+eFx0kzvUSlx1MDAwNFx1MDAwMr/h5KlWMuphpeC7tfLtUFJE0VNcdTAwMWUhXG5cdTAwMTAkbS2cXHUwMDEzXHRhQGjroDzyXHUwMDE4+lPCXHUwMDE5RWR3PFwiwSmFLNyaTD7DI4JwXHUwMDFkj1x1MDAxMFx1MDAxMVx1MDAwZVx1MDAxOSB0cyBvpoOz+DzLit4vJ1x0j/hcdTAwMTFOXHUwMDBm81dcdTAwMGUkIUFcdTAwMThS3FaqXHUwMDE5kSSgXHUwMDAyhu26/jJcIq+8wmyLSFx1MDAwMlx1MDAwMWV0p1xuuVNcIlx1MDAxOV1LJIWCXHUwMDAyXHUwMDA0Nq/al45cXJP4MFx1MDAxMX+MP/V+7+9l788y/sqBXGZBgCHHtFVcdTAwMWRnQOJAXGK+JJ4vXHUwMDAxXHUwMDEyoivO2baAhIRcdTAwMDJIOcbof0zks7+SbKEoLzPJIeC+ZjG2MZQ4Oc56N3eEqPIqncqvf5dwcLZcdTAwMDbKkYxGk1K9XHUwMDAyLFx1MDAxOVx1MDAwYsBcbpXEOFxmQkp5XHUwMDFi15fXbbZcdTAwMDJL7zb45qKeiK2gk/tb0PLReOSTcsaxXHUwMDFmvlPF9GXD/83RbfHp1I1bhWbI15HJWMh8XHKHm5dvfX7X+7KX0PjXy/MzejhMU927fe1g+ppcdTAwMTCQZakkSFx1MDAwNP5g0u+WymdvOIw85XCFPFwi4C+9XHUwMDAy7PSi/d/VsUlznrmBvpvdk1vWY5lqc9vKVI2lj9TnPVFucSut8j5nXG7Z6t0zOqnA7Vx1MDAxYTVsXHUwMDEz7XQkzbzZ5Vx1MDAwYiuPvHfppytP4+VV5KVOdCbNeTuS2WHy73qPurIoXHUwMDA2zu+Q7zE7Wj5cdDp+XFxmM193qtX14Spxqp9q1vqAVmdBVSm4f3jz8C/DXFz9NyJ9
+
+
+
+ Widget
\ No newline at end of file
diff --git a/docs/images/layout_horizontal.excalidraw.svg b/docs/images/layout_horizontal.excalidraw.svg
new file mode 100644
index 000000000..25ce496f2
--- /dev/null
+++ b/docs/images/layout_horizontal.excalidraw.svg
@@ -0,0 +1,16 @@
+
+
+ eyJ2ZXJzaW9uIjoiMSIsImVuY29kaW5nIjoiYnN0cmluZyIsImNvbXByZXNzZWQiOnRydWUsImVuY29kZWQiOiJ4nO2aa0/bSFx1MDAxNIa/8ytQ+rVM536ptFpcdTAwMTEuLTQtlNAtdFVVjj1JZnFsYztcdGnFf9+xQ+PE2GxcYlHKatdCSTzX45nnXHUwMDFjvzPDj63t7UY6iXTj9XZD37iOb7zYXHUwMDE5N15m6SNcdTAwMWQnJlxmbFx1MDAxNs7vk3BcdTAwMTi7ecl+mkbJ61evXHUwMDA2Tnyl08h3XFxcckYmXHUwMDE5On6SXHUwMDBlPVx1MDAxM1x1MDAwMjdcdTAwMWO8MqlcdTAwMWUkv2efXHUwMDFmnIH+LVxuXHUwMDA3Xlx1MDAxYYOik1x1MDAxZO2ZNIynfWlfXHUwMDBmdJAmtvU/7f329o/8c866WLupXHUwMDEz9HydV8izXG5cdTAwMDNcdTAwMTFH5dRcdTAwMGZhkFx1MDAxYitcdTAwMDRnTFBOZ1x1MDAwNUyyb7tLtWdzu9ZkXeRkSY1wrHY6o1x1MDAxMbuiTv8vfja8uWw3o6LXrvH9djrxc6vcOEySnb6Tuv2iRJLG4ZX+bLy0n9lWSp/VTUI7XHUwMDEwRa04XHUwMDFj9vqBTpKFOmHkuCadZGlcdTAwMTDOUqdcdTAwMDPxertIubF3XHUwMDFjXHUwMDAxXHUwMDA0XHUwMDEx45jNkvOKXHUwMDA0XHUwMDAyXHUwMDBlXHUwMDA1xUhcblYyZi/07Vx1MDAxNFhjXsD8KszpOO5Vz9pcdTAwMTR4szJp7Fx1MDAwNEnkxHaiinLju8ekilx1MDAwM1wipILz3fe16fVTm0uwXHUwMDA0kpL5/nU+XHUwMDAxXGJhXHUwMDAyle2ZzHKyXqMjL2fha3nw+k5cdTAwMWPdXHJSI8lu5izOjD2YXHUwMDAzqag8jDxnOuGIc4yVXCJcbjNajJ5vgiubXHUwMDE5XGZ9v0hcdTAwMGLdq4KRPPX25SpsXHUwMDEyXsemopxcdTAwMGKO4fJs9odB29//LryTZvzHXHUwMDA1jpLjT+ZdXHKbJb5cdTAwMTapxJukktPFuc8rYlx1MDAwNVx1MDAwNJSqRMXaqaSgXHUwMDA2ScxcdTAwMDHCXGKqKii55Vx1MDAxMVNcdTAwMDHR5qAkXHUwMDEwYiigQOuCUvu+iZJqJFx1MDAxMalDkiNCqP1cdTAwMTNLI/lpsPd2ctChqOd8eXt4zVvHcFx1MDAxZq2C5OZcdTAwMDKlwFx1MDAwMImFaDiNk1xuMIZcdTAwMDV5KpEvulx1MDAwZcNcZt+nXHUwMDExYYBRyVx1MDAxN2Y8XCJcdTAwMDQoI1xi36NcdTAwMTFbw1xiUYJvNERaKyGkXHUwMDFioZGLOlx1MDAxYe1gXHREkIBqaVx1MDAxY9E5vWmpTtg62lx1MDAxOUYnh63v3eB493njaN+cwlx1MDAwZYLi94mUgFx1MDAxMlXGYiVcIjtcdTAwMTCytVx1MDAxMVx0MWFIWiY3TyTeXHUwMDAwkVx1MDAxONfKSeuLUmJCKVmayPeuuL5pXlx1MDAxY6TiYHzcla0v+/1o/3lcdTAwMTOJsOWC2ZBTISaFXHUwMDE1ckzAJyOJcEdKvi4kXHUwMDExQlx1MDAxMCumXHUwMDE4+1x1MDAxNyP5oI7k9WtcdTAwMWOroZVgXG7hpZmM3r9PzpvDvdZxcn74RSr+5qzztobJvuP2h7H+9VRcblx1MDAwMaxywVx1MDAxMpWZXHUwMDE0XGYwWKZ19Vx1MDAxNzevopJZuShcdFOVWGIuXHUwMDAxrMKSWIVPIedqk1QqSlx1MDAxMCNiXVSm+iatVpGyXHUwMDE2SIVskGRKLS8jj1x1MDAwZttJ2mpCdlx1MDAxMnjJ8FrH74KLi+dO5DROksVcdTAwMTVGVlx1MDAxNUtcYlxixvjJSD64upnb1ChQrFjNWFxirYhcIlx1MDAxYlxczWShUVwiwsgjICzmOlxm0rb5rnOlsZB66FxmjD9ZmK6cTmupnfyeTufHMtG2z5xGuVB61ze9jN+Gr7uLYKfGdfxZdlx1MDAxYc49uWt7d2xz8ZFXfoowNj1cdTAwMTM4/vmiJatHeilonWNcdFx1MDAxYuelJIIv7Ve4NWiN+67eXHUwMDFm6dbHyWRMh2ejo+fuV5gxUN5cdTAwMWGYRnr7XG6AVns+OdJP1UdlpIdcdTAwMWPYt7pYeM3MRXpcdTAwMDZ4aZPtp59Jqz6gIHijXHUwMDEyRFFcdTAwMWJq4WP8bHUwXHUwMDE1YnVgXCJMoWBYLs3ldde9hEcn15+Cvve5N1x1MDAxYZs2Pfz23Lkkklx1MDAwMJS90O8pXHUwMDEwXHUwMDA0eFmarIIlxrKjq7HkXHUwMDE4SJ53QVV2iSo4XHUwMDE1kFx1MDAwNFcqXHUwMDExpCRWVJBccitcdTAwMTEsXHUwMDA15OuCs1aJqHouKYNcdTAwMWOJR+xnnYs3x6NT7/SjY051e6/3wfF26/aznlxymFhIIGBpVTZcdTAwMTVcIlx1MDAxMqh1bCGsQYhQqlxis4vHTetcdTAwMTAqXHUwMDFmJYb/Szqk1qPkXHUwMDAzXHUwMDEyhNs4w+dm8Vx1MDAxZlx1MDAwZtQ+XHUwMDFmOJff6NklvDa9sVaBOPlr8tw9imJcdTAwMDHKbvPToaDgpf3jX6TsieJ2sUfxpj0qO7T636Oyr3tcdTAwMWXlxHE4rnQpWOtSdrVoXHUwMDAzOH/EnuK3uHnK946uXHUwMDA35uDj8I1vlHmz667mUlx1MDAxYjxcdJSA4vu73FxmXCLwkCtJ0WWdp1x1MDAxY1x1MDAwMTJA+KK7XHUwMDE2+4mAK1U6XHUwMDE4v/MtaHOs4EUr7HHn1q3mW1xmMkVcdTAwMWVz6jJnh1x1MDAxM6dNXHUwMDEzeCbolavowKvJ8Z0k3Vx1MDAwYlx1MDAwN1x1MDAwM5NaM05DXHUwMDEzpOVcdTAwMTJ5u7tcdTAwMTnVfe3cc1x1MDAxMdvyfF5cdTAwMTn/KGux+K+O7Cp+bVx1MDAxN3zkN7PfX19Wlq6Yyewq5rBoYGv++3brrsmGXHUwMDEzRe3UXHUwMDBluDVo6rh2To13XHUwMDE3kYrnaoyMXHUwMDFlN6v2XHUwMDA38ytcdTAwMGJcdTAwMDC5+2d+prOn+3G7dfs38GbaXHUwMDA3In0=
+
+
+
+ Widget Widget Widget
\ No newline at end of file
diff --git a/docs/images/layout_table.excalidraw.svg b/docs/images/layout_table.excalidraw.svg
new file mode 100644
index 000000000..b1c03573d
--- /dev/null
+++ b/docs/images/layout_table.excalidraw.svg
@@ -0,0 +1,16 @@
+
+
+ eyJ2ZXJzaW9uIjoiMSIsImVuY29kaW5nIjoiYnN0cmluZyIsImNvbXByZXNzZWQiOnRydWUsImVuY29kZWQiOiJ4nN2ZW0/bWFx1MDAxMMff+ylQ+tq4Z+bcK61WNFxcWiCUkt1cdTAwMDK7WlWO41x1MDAxMINcdTAwMTNcdTAwMWLbIUDV775jhyU33KZpakXrXHUwMDA3Kz5zLmP7l5n/XHUwMDFjf3mxtVXL7mO/9mar5t95blx1MDAxOHRcdTAwMTJ3VHuVt9/6SVx1MDAxYURcdTAwMDMyYXGdRsPEK3r2sixO37x+3XeTaz+LQ9fzndsgXHUwMDFkumGaXHI7QeR4Uf91kPn99Pf8fOz2/d/iqN/JXHUwMDEyZ7JI3e9cdTAwMDRZlIzX8kO/71x1MDAwZrKUZv+brre2vlx1MDAxNOcp71x1MDAxMt/L3MFl6Fx1MDAxN1x1MDAwM1xu05SDTM23XHUwMDFlR4PCWVx1MDAwNOTaWG6fOlx1MDAwNOlcdTAwMGUtl/lcdTAwMWSydsllf2LJm2pcdTAwMTdcdTAwMDfN7bOP7frZyd1d4+P1kN1cdTAwMWPeXHUwMDFkTFbtXHUwMDA2YdjK7sPCKy+J0rTeczOvN+mRZkl07Z9cdTAwMDWdrEd9YK79aWxcdTAwMWHRg5iMSqLhZW/gp+nMmCh2vSC7z9tcdTAwMTh7alx1MDAxZD+IN1uTlruih3CEZchcdTAwMDXX8slSjFXGYahnXHJjd1x1MDAxYVFIL4HcecmKY+JQ2/WuL8mrQeepT5a4gzR2XHUwMDEzelWTfqPHXHUwMDFiXHUwMDE1Vjn5o2ZcbieL9PzgspeRlaNxzOz6fvFcblx1MDAwMFx1MDAxOFdWXHUwMDAzm1jyVeP3nYKGf+ZcdTAwMWZfz03ix8dUS/OLKY9zZ3enUJpcZlx1MDAxZcZcdTAwMWR3/MpBKURrpURE82RcdTAwMGaDwTVcdTAwMTlcdTAwMDfDMJy0Rd71hJKi9eurXHUwMDE16Fx1MDAwNFx1MDAwM2V0guBKaCNcdTAwMDCWxvNcYsxprD9fdi5cdTAwMWV6O63zXHUwMDA2unB+VYLnXHUwMDFjYrNgYqVgcqlcdTAwMDWCWVx1MDAwMFM7XHUwMDAytFXml4IpnFx1MDAxMipROYDA7HNcXGpjXHUwMDE0SKOhOi45Y2BcYk25Li79MFxm4vR5KqUujZkoKIqgxaWhvOrsXHUwMDFknkrVPd/fPYhakDWu9o6OVoGywmhcdMIxhlx1MDAxOWlcdTAwMTeipVaO1ajkNDIrQPmy60qUuFxiJKCDIGaj4Vx1MDAxM5JcdTAwMDCOkFx1MDAxY3BcdTAwMDFII1x1MDAwNCCNstXxiNYoxrTBXG54RCiPknTboJiQy1x1MDAwM3kxVKOjpOPtn7jhcFx1MDAwZmL3Pey3N1x1MDAxY0huXHUwMDFkgVKb6Xc/5lE6c5iuRmObMbkuXHUwMDFhuZVGXHUwMDE4i/p/SqOSpTRKsJIhXHUwMDEzS8PoS+1dnN6c3lxmP0Rvd0+McuuNvVxyh1FRzlRcdTAwMGLpmkhcXENcXFx1MDAwNGxTbl1cdTAwMTeJkKdpbqyqMFGvXHUwMDFkxW9cbkhrTVx1MDAxOYzSkuLnQsilYey6Ot1vXFy+P/N6fHR80N5pZp/LUnXP9XrDxN9cdTAwMDBcdTAwMWOBqlx1MDAwN2VBzMi4fCwyiprCzkrL1ZO1elx1MDAwNktkzGGP6rWYiC/SqfE/XHUwMDFkK2xxLJY5hkojToK30jJH0YpcYpVQXG6kmMsw5VxmhEa5fFx1MDAxMZ707el+eLB90k/f3orgoKWPd+NNp5RzokAzzfh8XG7PKdWG46xlvZhcdTAwMWHm6HGJP55cdTAwMDdWoVx1MDAxNCWn0GZs1ZRcbjS6XCJKVWndQ9U4ZVx1MDAxMSHN8tX4X432fnB1XHUwMDA28Knree+uXHUwMDFlLpvHO+6mcyqQ6nEln9koQkrBQuHcJs56OaVk7fBcXM4+MjjF2vKg0lx1MDAxZkqRXGJcdTAwMDNd7a6R4sZIUVxyqGxKXcyHU7p3kNOJ6HucNk+UVz+Fm/1MRkN5eNjubsNg0zlcdTAwMDXMNZ9kiyVcdTAwMTFn6Fx1MDAwMJvfUVpdi/66tE/AUEZQrFJxaiVJRlVR2kdRXrhcdTAwMDMgKVx1MDAxMMaXl6cgdlx1MDAwMqyLXHUwMDExXHUwMDBm7Fx1MDAwNV5cdTAwMWaMwtG7/t2mg8q5cJixZiGeckZllDVM/OxcdTAwMDbnNzhdT95XUkqOouK8XHUwMDBmjH5UgymXvFx1MDAxNFOhlFGag15cdTAwMWFTb7dxdXHYPKvzT6zVvv/ktnpRuOmYXG60jmTymS1Pzlx1MDAxNFnAyp/Wp+WcgrCOnT5WyftcdTAwMDCSdFx1MDAwYlx1MDAxM9XugloltGZr25X/TjyV5Vx1MDAxZjNcdTAwMTknSjmI5Vx1MDAwNWrrfK/ZxEHWYSzTf/x5XFw/yuKdTVx1MDAwNzVP/FZcdTAwMGLFXHUwMDE2QbXaoeQ2Z1lcdTAwMDVURNP2n0/8XHUwMDE2SFx1MDAxZetcdTAwMTlp8SOhNP9yXHUwMDA0lPaqJVx1MDAxNOn/W9H3TNI0paFcdTAwMTSlUcL+XGKhn/vx1Yc06D58XGa3e7fRUe9cdTAwMTQu2KZcdTAwMTOah1LEMkKZYXOidb2EUsJy7PhTgfiJXHUwMDEySoE1WHkopVxmJNRcdTAwMGaDSudi0ppcdTAwMWLHrYymJPNcdTAwMThb8jrotIJcdTAwMDd/ZprabeCP3j5XmFx1MDAxNkftxSP8OV9+7vOXry++/lx1MDAwYntetL4ifQ==
+
+
+
+
\ No newline at end of file
diff --git a/docs/images/layout_vertical.excalidraw.svg b/docs/images/layout_vertical.excalidraw.svg
new file mode 100644
index 000000000..fff71ecf9
--- /dev/null
+++ b/docs/images/layout_vertical.excalidraw.svg
@@ -0,0 +1,16 @@
+
+
+ eyJ2ZXJzaW9uIjoiMSIsImVuY29kaW5nIjoiYnN0cmluZyIsImNvbXByZXNzZWQiOnRydWUsImVuY29kZWQiOiJ4nO2ZW2/aSFx1MDAxNIDf8ytcIvrauHO/VFqtXHUwMDAyTdrck9KkTVdVNLFcdTAwMDdwMLbXXHUwMDFlXHUwMDEyoOp/37FJMVx1MDAxOFx1MDAxY1FcdTAwMWFRtrt+MPjM7XjmO2fOXHUwMDE5f93a3q6ZYaxrr7dreuCqwPdcdTAwMTL1UHuZye91kvpRaItQ/pxG/cTNa3aMidPXr171VNLVJlx1MDAwZZSrnXs/7asgNX3Pj1x1MDAxYzfqvfKN7qV/ZvdT1dN/xFHPM4lTXGayoz3fRMl4LFx1MDAxZOieXHUwMDBlTWp7/8s+b29/ze9T2iXaNSpsXHUwMDA3Om+QXHUwMDE3XHUwMDE1XG5CLsrS0yjMlYVcdTAwMDJRxFx1MDAxMGZsUsNP39jxjPZsccvqrIuSTFS7rNdcdTAwMGbj+/6RSNBdfFF/84lcdTAwMGZIUlxm2/KDoGmGQa6Wm0RputNRxu1cdTAwMTQ1UpNEXf3R90wn06Akn7RNIztcdTAwMTNFqyTqtzuhTtOZNlGsXFzfXGYzXHUwMDE5XHUwMDAwXHUwMDEz6XgmXm9cdTAwMTeSQbZOQjqSUFxmXHUwMDExncjzloI6XHUwMDE4gVx1MDAxOflYl0ZcdTAwMTTYJbC6vFx1MDAwMPlVaHOr3G7bqlx1MDAxNHqTOiZRYVx1MDAxYavELlRR7+HxLYlkXHUwMDBl5kJcdTAwMDI2NUhH++2OsaVcdTAwMThcdEdcdTAwMTDMp8bX+fxD24ZcdTAwMGLBWVGSjVx1MDAxYVx1MDAxZng5XHUwMDBiX8pz11FJ/DhHtTR7mNI4U3ZvXG6konE/9tR4vSFjXGJJiVx1MDAwMVx1MDAxN6yYvMBcdTAwMGa7tjDsXHUwMDA3QSGL3G6BSC799nJcdTAwMTU2KapiU2AkhSRkeTRcdTAwMTk4XCJcdTAwMThGh+qm8/Gi07jY8y/gTVx1MDAwNZolvGahROuDUlx1MDAwModIXHUwMDA0XHUwMDA1L0NJXHUwMDFjgGd5eX4oiVNBJGJcdTAwMGVEXHUwMDEwyFx1MDAwNUxcIkgpwFx1MDAxOK5cdTAwMTFJXGZcdTAwMDCUjHD0XFxI6iDw43QxkKjSWVxujJl1XHUwMDE0kixccuS+PLl517x6f/k+uvp09Fx1MDAwZXXdYd1bXHUwMDA1yPV5SVxmoFx1MDAwMyBlZSdpWSmJV8DxRUtRu+HMo1xikYMgmfWBXHUwMDEzXHUwMDE4IXRKbvu7e+SIQYq5/Fx1MDAxN3vHp1BcdTAwMTSVvpFbs4VcdTAwMThRsDSKny/SgTm6eXu81/Aurlx1MDAxM91NSXC04ShcIupQXHUwMDA2KGFz3lFcIuu5XHUwMDEwnt0zV+LxXHUwMDE2XHUwMDAw+lxcPFwiwFx0XHUwMDAzkEn8e1x1MDAwMmnjxCogXHQj2DpqKZZcdTAwMDbyslx1MDAxZTY/XHUwMDFm3lx1MDAwNVx1MDAwZnz0rn/gN+7vXFx8sOFAUuhAYO9cdTAwMGLcI3IwXHUwMDEwVP4skFx1MDAxMN1cbsGeXHUwMDBiSMKJpIKJ3zZ8xE+kNvaShEO8PJLnXHUwMDFmklH3nDY8vvu3fHOTXHUwMDA0QI3OKpDsKLfTT/RcdTAwMDZAXHSBXHUwMDAz5YJcdTAwMTDSukeHlZBZfc+mXHUwMDBivCQhwsk8nlxcSCW1Sc04r1wiMrtcdTAwMDQr44lcdTAwMTBEmGNcdTAwMDLXiifN7Eg8XHUwMDE3nkZcdTAwMGbMQl9Z6SohQ4xhgsDyiVxybV2NTsO3g+udYDS63mVR86ZcdTAwMTFvOpg2S5jlkZKf4fDJVIaRef5cdTAwMTbEi1x1MDAxNkKbSeBcco9cdTAwMTeLdY1C0/RHOlx1MDAwZi1mpPuq51x1MDAwN8OZpclBtJrahW5rMz2VqbZjjk97ZmrvXHUwMDA2fjtDtVx1MDAxNujWLMPGd1UwKTbR1Ju7dnRlu0tcdTAwMGW88ltEid/2Q1x1MDAxNXyY1WR1705cdTAwMTCv9u6SXHUwMDAwIaRcXD5cdTAwMDKW51x1MDAxMFx1MDAxY1x1MDAwZY7htZa3rZM9fkz76d6mXHUwMDFiXHUwMDExXHUwMDA20mFcdTAwMDLPXHUwMDA2XHUwMDE2w9ztXHUwMDEzR1xiJH7y1OpcdTAwMDVcdTAwMDEuoJwtXGI5XGIlXHUwMDBlp7jihFx1MDAwMELqXGLISFaaXHUwMDBmXHUwMDAz56yNXCJJKON0vdFcdTAwMDdcdTAwMDXUboZriT4oJlV8YmRcdTAwMTM0xvnyeKrPO83hzd6nncuTw+O6XHUwMDFj+Gr/Q3Pj8bTBXHUwMDA3gVxczmVoWWhApSzFXHUwMDA2K1x1MDAwMeoy3aKLXHUwMDAxtUFxJaCEOyjXazzIPJ9cYoBcZm+I15utUWhDtWfjUyVJ9LD4XHUwMDFjqzpX43ZcdTAwMGKU8Fx1MDAwN+KP+5OUjc5cdTAwMGUur0x8XHUwMDE2JOfDs1x1MDAwN4YvVmNzfUerwsa/slx1MDAxY1x1MDAwMH8/yypHrWUybVx1MDAxYaawfprMqlxcXHI4nHO8OFXDXGI5XHUwMDA0US5cdTAwMTZcdTAwMWZnXHRcblxiWyFcdTAwMWPONVt3eJJcdTAwMWGVmLpcdTAwMWZ6ftguN9GhV1FcdTAwMTKo1DSiXs83Vo3zyFx1MDAwZk25Rt7vblx1MDAwNnZHq7kow/Y8XVa2gDjrsfhSll3Fv+1cdTAwMDKR/GHy/8vLxbXnVjK7ptew6GFr+vdHs1x1MDAwNVwiy8JJoGMxlVhQtLy1plx1MDAwN/qwvdc+xfuXcrA/knetNiSbvpNYN+0ghNjc0Vxutnnk/LeIX5M/XHUwMDAwTG3ehjb9POW/lEBUWZR84ps3QcKGrj/wzftYJo2O2b3bXHUwMDFk6uOr3TPVc+/ev918i+JcdTAwMGVcdTAwMTFg/vScWIviXGbymVx1MDAxM6NfZFFYXHUwMDEwXHS53aP/t6i1W9TW475XU3HcNHaGbI2xfdlF8L3H1yz6q937+qG+6IQwv7JecyvN7EFnS/D129a3f1x1MDAwMLFE1Vx1MDAwMCJ9
+
+
+
+ Widget Widget Widget
\ No newline at end of file
diff --git a/docs/index.md b/docs/index.md
index a3fdfc8ea..dd59b082b 100644
--- a/docs/index.md
+++ b/docs/index.md
@@ -70,7 +70,5 @@ Textual is a framework for building applications that run within your terminal.
=== "Example 2"
- ```{.textual path="docs/examples/introduction/timers.py"}
- ```
diff --git a/mkdocs.yml b/mkdocs.yml
index 1e84692a9..46367e352 100644
--- a/mkdocs.yml
+++ b/mkdocs.yml
@@ -7,9 +7,13 @@ nav:
- "introduction.md"
- Guide:
- "guide/devtools.md"
+ - "guide/layout.md"
- "guide/CSS.md"
- "guide/events.md"
-
+ - How to:
+ - "how-to/animation.md"
+ - "how-to/mouse-and-keyboard.md"
+ - "how-to/scroll.md"
- "actions.md"
- Events:
- "events/blur.md"
diff --git a/src/textual/_doc.py b/src/textual/_doc.py
index 88770bd95..6a73696a6 100644
--- a/src/textual/_doc.py
+++ b/src/textual/_doc.py
@@ -1,5 +1,6 @@
from __future__ import annotations
+import runpy
import os
from typing import cast, TYPE_CHECKING
@@ -11,36 +12,36 @@ if TYPE_CHECKING:
def format_svg(source, language, css_class, options, md, attrs, **kwargs) -> str:
"""A superfences formatter to insert a SVG screenshot."""
- path: str = attrs["path"]
- _press = attrs.get("press", None)
- press = [*_press.split(",")] if _press else ["_"]
- title = attrs.get("title")
-
- os.environ["COLUMNS"] = attrs.get("columns", "80")
- os.environ["LINES"] = attrs.get("lines", "24")
-
- print(f"screenshotting {path!r}")
-
- cwd = os.getcwd()
- examples_path, filename = os.path.split(path)
try:
- os.chdir(examples_path)
- with open(filename, "rt") as python_code:
- source = python_code.read()
- app_vars: dict[str, object] = {}
- exec(source, app_vars)
+ path: str = attrs["path"]
+ _press = attrs.get("press", None)
+ press = [*_press.split(",")] if _press else ["_"]
+ title = attrs.get("title")
- app: App = cast("App", app_vars["app"])
- app.run(
- quit_after=5,
- press=press or ["ctrl+c"],
- headless=True,
- screenshot=True,
- screenshot_title=title,
- )
- svg = app._screenshot
- finally:
- os.chdir(cwd)
+ os.environ["COLUMNS"] = attrs.get("columns", "80")
+ os.environ["LINES"] = attrs.get("lines", "24")
- assert svg is not None
- return svg
+ print(f"screenshotting {path!r}")
+
+ cwd = os.getcwd()
+ try:
+ app_vars = runpy.run_path(path)
+ app: App = cast("App", app_vars["app"])
+ app.run(
+ quit_after=5,
+ press=press or ["ctrl+c"],
+ headless=True,
+ screenshot=True,
+ screenshot_title=title,
+ )
+ svg = app._screenshot
+ finally:
+ os.chdir(cwd)
+
+ assert svg is not None
+ return svg
+
+ except Exception as error:
+ import traceback
+
+ traceback.print_exception(error)
diff --git a/src/textual/message_pump.py b/src/textual/message_pump.py
index 4700538d8..01cecabca 100644
--- a/src/textual/message_pump.py
+++ b/src/textual/message_pump.py
@@ -112,6 +112,11 @@ class MessagePump(metaclass=MessagePumpMeta):
@property
def log(self) -> Logger:
+ """Get a logger for this object.
+
+ Returns:
+ Logger: A logger.
+ """
return self.app._logger
def _attach(self, parent: MessagePump) -> None: