v2.0.0

Textualize/textualv2.0.0Feb 16, 2025by willmcgugan

AI Summary

A major feature release introducing arbitrary text selection, smoother scrolling for supported terminals, and a new content system, replacing Rich markup with Textual markup.

Key Highlights

  • Arbitrary text selection (Ctrl+C to copy)
  • Smoother scrolling for Kitty, Ghostty, and supported terminals
  • New Content system
  • Textual markup replaces Rich markup

Breaking Changes

  • OptionList no longer supports `Separator` (use `None`)
  • Removed `wrap` argument from OptionList
  • Removed `tooltip` argument from OptionList
  • Strings returned from `render()` now use `Content.from_markup` instead of `Rich.from_markup`

New Features

  • `Select.type_to_search`
  • `from_app_focus` to `Focus` event
  • `Blurred` message to `Input` widget
  • `Offset.transpose`
  • `screen--selection` component class
  • `Widget.select_container` property
  • `Widget.select_all`
  • `Widget.ALLOW_SELECT` classvar
  • `Widget.allow_select` method
  • `App.ALLOW_SELECT` for global switch
  • `DOMNode.query_ancestor`
  • Selection to Log widget
  • `text-wrap` and `text-overflow` CSS values
  • Textual markup

Full Release Notes

This is a big release!

- Arbitrary text selection. You can now select text, and hit ctrl+c to copy it to the clipboard. This works just about everywhere, although there a re a few widgets were it isn't yet implemented.


https://github.com/user-attachments/assets/91ff4d9e-9d1d-4023-aa52-66bc52bd56f8

- [Smoother scrolling](https://textual.textualize.io/blog/2025/02/16/smoother-scrolling-in-the-terminal-mdash-a-feature-decades-in-the-making/), for Kitty, Ghostty, and some other terminals.
- [New content system](https://textual.textualize.io/guide/content/)
- Many fixes, see the full changelog below...


**Breaking change**: Strings returned from `render()` and other places will now be interpreted with `Content.from_markup`, rather than `Rich.from_markup`. This may result in slightly different colors, and emoji codes (like `":smiley:"`) will no longer be processed automatically. If you want to restore the old behavior you can return `Rich.from_markup("Your output here")` rather than string literal.


## Why 2.0.0 ?

It took us more than 3 years to get to 1.0. But a couple of months to get to 2.0? Why?

We follow [Semver](https://semver.org/) which says that after 1.0, all breaking changes bump the major version number. We have some breaking changes here, which will be trivial to fix -- if they effect you at all. But a breaking change is a breaking change!

## 2.0.0 - 2024-02-16

### Added

- Added `Select.type_to_search` which allows you to type to move the cursor to a matching option https://github.com/Textualize/textual/pull/5403
- Added `from_app_focus` to `Focus` event to indicate if a widget is being focused because the app itself has regained focus or not https://github.com/Textualize/textual/pull/5379
- Added `Blurred` message to `Input` widget (matching `Submitted` and `Changed`) to make it easier to synchronize with `validate_on` parameter when set to 'blur'.
- Added `Offset.transpose` https://github.com/Textualize/textual/pull/5409
- Added `screen--selection` component class to define style for selection https://github.com/Textualize/textual/pull/5409
- Added `Widget.select_container` property https://github.com/Textualize/textual/pull/5409
- Added `Widget.select_all` https://github.com/Textualize/textual/pull/5409
- Added `Region.bottom_right_inclusive` https://github.com/Textualize/textual/pull/5409
- Added double click to select, triple click to select all in container https://github.com/Textualize/textual/pull/5409
- Added arbitrary text selection https://github.com/Textualize/textual/pull/5409
- Added Widget.ALLOW_SELECT classvar for a per-widget switch to disable text selection https://github.com/Textualize/textual/pull/5409
- Added Widget.allow_select method for programmatic control of text selection https://github.com/Textualize/textual/pull/5409
- Added App.ALLOW_SELECT for a global switch to disable text selection https://github.com/Textualize/textual/pull/5409
- Added `DOMNode.query_ancestor` https://github.com/Textualize/textual/pull/5409
- Added selection to Log widget https://github.com/Textualize/textual/pull/5467
- Added `text-wrap` and `text-overflow` CSS values https://github.com/Textualize/textual/pull/5485
- Added Textual markup to replace Rich markup https://github.com/Textualize/textual/pull/5485
- Added `Content.from_markup` https://github.com/Textualize/textual/pull/5485

### Fixed

- Fixed `Pilot.click` not working with `times` parameter https://github.com/Textualize/textual/pull/5398
- Fixed select refocusing itself too late https://github.com/Textualize/textual/pull/5420
- Fixed layout of the keys in the help panel when a key has a tooltip but no description https://github.com/Textualize/textual/issues/5436
- The content of an `Input` will now only be automatically selected when the widget is focused by the user, not when the app itself has regained focus (similar to web browsers). https://github.com/Textualize/textual/pull/5379
- Updated `TextArea` and `Input` behavior when there is a selection and the user presses left or right https://github.com/Textualize/textual/pull/5400
- Footer can now be scrolled horizontally without holding `shift` https://github.com/Textualize/textual/pull/5404
- Modified _on_blur method in `Input` to post a `Blurred` message
- Fixed Log widget not refreshing on resize https://github.com/Textualize/textual/pull/5460
- Fixed special case with calculating the height of a container where all children have dynamic heights https://github.com/Textualize/textual/pull/5463
- Fixed scrollbars ignoring background opacity https://github.com/Textualize/textual/issues/5458
- Fixed `Header` icon showing command palette tooltip when disabled https://github.com/Textualize/textual/pull/5427

### Changed

- Breaking change: OptionList no longer supports `Separator`, a separator may be specified with `None`
- Implemented smooth (pixel perfect) scrolling on supported terminals. Set `TEXTUAL_SMOOTH_SCROLL=0` to disable. 

### Removed

- Breaking change: Removed `wrap` argument from OptionList (use CSS `text-wrap: nowrap; text-overflow: ellipses`)
- Breaking change: Removed `tooltip` argument from OptionList. Use `tooltip` attribute or `with_tooltip(...)` method.