New features and enhancements
- Introduce NiceGUI script mode to replace the awkward auto-index page (#5005 by @rodja, @falkoschindler)
- Introduce
root
page parameter forui.run
to simplify single-page applications (#4964, #5005 by @rodja, @falkoschindler) - Introduce an
Event
system to communicate between UI and long-living objects (#5107 by @falkoschindler, @denniswittich) - Simplify pytests by loading a main file with runpy (#5102 by @rodja, @falkoschindler)
- Make props, classes and style observable to send updates automatically (#4978 by @lawrenceakka, @falkoschindler, @rodja)
- Upgrade to Tailwind 4 (#5057 by @falkoschindler)
- Drop support for Python 3.8 (#4329 by @Solipsistmonkey, @falkoschindler)
- Introduce
ValueChangeEventArguments.previous_value
(#4410, #4456 by @me21, @falkoschindler, @evnchn) - Introduce a
strict
option for binding methods (#5040 by @denniswittich, @codingpaula, @falkoschindler) - Improve support for languages with right-to-left text direction (#5045, #5058 by @M6stafa, @falkoschindler)
- Use
q-scroll_area
forui.log
to preserve a fixed height (#4925, #4935 by @e-nesse, @falkoschindler) - Let
ui.clipboard.read()
returnNone
if the clipboard API isn't available (#4236, #4237 by @weinibuliu, @falkoschindler, @evnchn) - Remove deprecated code and APIs (#5037 by @falkoschindler)
⚠️ Breaking changes and migration guide
We always try to keep breaking changes to a minimum, guide you through the migration process using deprecation warnings, and provide migration instructions. Please read the following release notes carefully to understand the changes and adapt your code accordingly before upgrading.
-
Shared auto-index pages (not using
@ui.page
)UI elements defined in global scope have been added to a static shared "auto-index client" served at "/". This caused a multitude of problems throughout the code base, so we decided to remove this shared client.
In version 3.0 you have the following options:
-
Keep putting (all) UI elements in global scope. We call such apps without page functions "NiceGUI scripts". They will automatically re-evaluated inside an implicit page function when visiting "/". This is almost a drop-in replacement for the auto-index client, but:
- NiceGUI scripts can't contain page functions.
- The UI isn't shared but re-created on every page visit.
-
Wrap all UI in a singe function and pass it to the new positional
root
parameter inui.run
. This is especially handy in combination withui.sub_pages
. This way you can create rich single-page applications without worrying about defining the correct routes with@page
decorators. -
Use page functions for all your pages, including the index page at "/".
Note that we are introducing a new
Event
class (see below). Together with the binding module this helps to synchronize long-living objects with short-living UI without relying on a long-living shared client. -
-
Calling
.props()
,.classes()
or.style()
with subsequent.update()
A subsequent
.update()
is not necessary anymore because props, classes and style are now observable collections that trigger updates automatically.When overwriting the
update
method in custom elements, infinite recursions can occur. If, e.g., theupdate
methods uses.prop()
before callingsuper().update()
, the.prop()
call will cause an infinite cycle. Wrap it withwith self._props.suspend_updates():
(and similar for classes and style) to pause automatic updates in such cases. -
Upgrade to Tailwind 4; dropping the
ui.element.tailwind
APIAlthough very similar, Tailwind 4 comes with some breaking changes. Check your layout carefully after upgrading. We noticed differences especially with line spacing and borders.
For technical reasons updating and maintaining our
ui.element.tailwind
API became unfeasible. So we decided to remove it. For auto-completing Tailwind classes, we recommend the NiceGUI extension for Visual Studio Code by @DaelonSuzuka. -
Dropping support for Python 3.8
Almost one year after Python 3.8 reached its end-of-life, it was time to drop support. This allowed us to update the code to a newer standard and resolve some issues with Python dependencies that already dropped 3.8 a while ago.
-
ValueChangeEventArguments
got a newprevious_value
attributeIn some situations it might be helpful to have access to both, the current and the previous value. Therefore we added
previous_value
to theValueChangeEventArguments
.Custom elements that emit
ValueChangeEventArguments
need to provide the previous value. -
Binding from and to non-existing object properties
Binding used to fail silently if one of the attributes doesn't exist. In case of dictionaries this was intended, because they are often used to bind to persistent storage which is empty by default. But for object properties this can lead to very subtle bugs, e.g. after renaming properties and not updating the attribue names in binding functions.
In 3.0 object properties will be checked for existence by default. Missing dictionaries will continue to be ignored.
You can fine-tune this behavior using the
strict: bool | None = None
parameter (None
: check object properties and ignore dictionaries). -
ui.log
with unspecified width can collapse inside containers with unspecified widthWe noticed that the height of
ui.log
could be affected by its content, which is unexpected. Therefore we decided to use a scroll area for a more robust layout.Now the width of
ui.log
can collapse when placed inside a container with an unspecified width. Either give the container some width or specify the width ofui.log
. -
ui.clipboard.read()
returnsNone
if the clipboard API isn't availableThe
read()
function used to return an empty string if the clipboard API is not available. This was indistinguishable from an empty clipboard.Now the
read()
function returnsNone
if the clipboard API is not available. -
Remove deprecated code and APIs (#5037 by @falkoschindler)
app.add_static_file
andapp.add_media_file
raisesFileNotFoundError
instead ofValueError
in case of non-existing files. SinceFileNotFoundError
is NOT a subclass ofValueError
, existing code whichexcept ValueError
will fail to catch the newFileNotFoundError
.ui.aggrid
:run_column_method
is gone. Userun_grid_method
instead.ui.table
callingadd_rows()
/remove_rows()
with variable-length arguments no longer works. Pass a list instead or useadd_row()
/remove_row()
for a single row.ui.open
is gone. Useui.navigate.to
.nicegui.testing.conftest
is gone and you can no longer import it. Usepytest_plugins = ["nicegui.testing.plugin"]
instead.element.on
parameterjs_handler
now has typestr
instead ofstr | None
. You can pass aNone
and it still works, but your type checker won't be happy, and we can't promise it will work for much longer afterwards.
JavaScript Dependencies
The infrastructure for managing node packages has been improved significantly (#4163, #5021 by @simontaurus, @evnchn, @falkoschindler).
The following JavaScript dependencies have been updated to the latest versions (#5034 by @falkoschindler):
- @tailwindcss/browser: 3.4.10 → 4.1.11 (#5057 by @falkoschindler)
- es-module-shims: 1.10.0 → 2.6.2
- quasar: 2.16.9 → 2.18.2 (resolves #4892 by @eddie3ruff, @evnchn, @xaptronic, @falkoschindler)
- socket.io: 4.7.5 → 4.8.1
- vue: 3.4.28 → 3.5.18
- ag-grid-community: 32.1.0 → 34.1.1 (resolves #3854 by @python-and-novella, @mockey, @falkoschindler)
- codemirror: 6.0.1 → 6.0.2
- @codemirror/language-data: 6.5.1 (new)
- @codemirror/theme-one-dark: 6.1.3 (new)
- @uiw/codemirror-themes-all: 4.24.2 (new)
- @babel/runtime: 7.28.2 (new)
- echarts: 5.5.1 → 6.0.0
- echarts-gl: 2.0.9 (unchanged)
- nipplejs: 0.10.2 (unchanged)
- vanilla-jsoneditor: 0.23.8 → 3.8.0
- leaflet: 1.9.4 (unchanged)
- leaflet-draw: 1.0.4 (unchanged)
- mermaid: 11.0.2 → 11.9.0
- plotly.js: 2.35.0 → 3.1.0
- three: 0.168.0 → 0.179.1
- @tweenjs/tween.js: 25.0.0 (unchanged)