diff --git a/README.md b/README.md index 124da7f..02fc1c2 100644 --- a/README.md +++ b/README.md @@ -4,12 +4,12 @@ Каждый пример — рабочий интерфейс и отдельная читаемая Python-функция; кнопка `` рядом с примером открывает точную строку исходного кода в репозитории. -В каталоге 27 интерактивных примеров: кнопки, поля ввода, controls выбора, +В каталоге 28 интерактивных примеров: кнопки, поля ввода, controls выбора, типографика, карточки, списки, адаптивные layouts, навигация, таблицы, progress, -dialogs, snackbar и bottom sheet. Постоянная кнопка настроек позволяет менять +dialogs, snackbar, banner и bottom sheet. Постоянная кнопка настроек позволяет менять светлую/тёмную/системную тему, Material 3 accent color и видимость кнопок кода. Разделы открываются через выдвижное меню в AppBar. Отдельный каталог всех иконок -Flet поддерживает поиск по имени и копирует готовое выражение `ft.Icon(ft.Icons.HOME)` +Flet поддерживает поиск по имени и копирует имя иконки `ft.Icons.HOME` при нажатии. ## Запуск @@ -45,7 +45,7 @@ ARMv8 в Android соответствует ABI `arm64-v8a`: uv run flet build apk src --arch arm64-v8a --yes \ --project flet_component_gallery \ --product "Flet Material Catalog" \ - --build-version 0.2.0 \ + --build-version 0.3.0 \ --org su.snw ``` diff --git a/pyproject.toml b/pyproject.toml index b28694d..9bf63d0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "flet-component-gallery" -version = "0.2.0" +version = "0.3.0" description = "Composer-inspired interactive gallery of Flet controls" readme = "README.md" requires-python = ">=3.11" diff --git a/src/gallery/app.py b/src/gallery/app.py index c1784f9..7286271 100644 --- a/src/gallery/app.py +++ b/src/gallery/app.py @@ -147,7 +147,7 @@ class GalleryApp: controls=[ ft.Text(self.selected_category, theme_style=ft.TextThemeStyle.DISPLAY_SMALL), ft.Text( - (f"{count} иконок · нажмите, чтобы скопировать код" if self.selected_category == "Иконки" else f"{count} интерактивных примеров · Flet 1.0.1 · каталог 0.2.0"), + (f"{count} иконок · нажмите, чтобы скопировать код" if self.selected_category == "Иконки" else f"{count} интерактивных примеров · Flet 1.0.1 · каталог 0.3.0"), color=ft.Colors.ON_SURFACE_VARIANT, ), ], diff --git a/src/gallery/examples/data_feedback.py b/src/gallery/examples/data_feedback.py index 576519a..c3b4ee3 100644 --- a/src/gallery/examples/data_feedback.py +++ b/src/gallery/examples/data_feedback.py @@ -61,11 +61,28 @@ def bottom_sheet() -> ft.Control: return ft.FilledButton("Открыть bottom sheet", icon=ft.Icons.VERTICAL_ALIGN_TOP, on_click=show) +def banner() -> ft.Control: + def show(e: ft.Event[ft.FilledButton]) -> None: + page = e.control.page + page.show_dialog( + ft.Banner( + leading=ft.Icons.WIFI_OFF, + content="Нет подключения к сети. Проверьте соединение и повторите попытку.", + actions=[ + ft.TextButton("Закрыть", on_click=lambda event: event.control.page.pop_dialog()), + ft.TextButton("Повторить", on_click=lambda event: event.control.page.pop_dialog()), + ], + ) + ) + + return ft.FilledButton("Показать banner", icon=ft.Icons.CAMPAIGN_OUTLINED, on_click=show) + + EXAMPLES = [ Example("data-table", "DataTable", "Табличные структурированные данные.", "Данные и feedback", data_table), Example("progress", "Progress indicators", "Определённая и бесконечная загрузка.", "Данные и feedback", progress_indicators), Example("dialog", "AlertDialog", "Модальное подтверждение важного действия.", "Данные и feedback", alert_dialog), Example("snackbar", "SnackBar", "Краткое неблокирующее сообщение.", "Данные и feedback", snackbar), Example("bottom-sheet", "BottomSheet", "Дополнительный мобильный слой.", "Данные и feedback", bottom_sheet), + Example("banner", "Banner", "Важное сообщение с действиями в верхней части экрана.", "Данные и feedback", banner), ] - diff --git a/src/gallery/examples/navigation.py b/src/gallery/examples/navigation.py index 656ea12..e2aaab2 100644 --- a/src/gallery/examples/navigation.py +++ b/src/gallery/examples/navigation.py @@ -10,7 +10,14 @@ def tabs() -> ft.Control: content=ft.Column( controls=[ ft.TabBar(tabs=[ft.Tab(label="Обзор", icon=ft.Icons.DASHBOARD), ft.Tab(label="Код", icon=ft.Icons.CODE), ft.Tab(label="API", icon=ft.Icons.DATA_OBJECT)]), - ft.TabBarView(controls=[ft.Container(ft.Text("Обзор компонента"), padding=20), ft.Container(ft.Text("Пример кода"), padding=20), ft.Container(ft.Text("Справка API"), padding=20)]), + ft.TabBarView( + controls=[ + ft.Container(ft.Text("Обзор компонента"), padding=20), + ft.Container(ft.Text("Пример кода"), padding=20), + ft.Container(ft.Text("Справка API"), padding=20), + ], + height=96, + ), ] ), height=160, @@ -45,4 +52,3 @@ EXAMPLES = [ Example("navigation-bar", "NavigationBar", "Основные разделы мобильного приложения.", "Навигация", navigation_bar), Example("popup-menu", "PopupMenuButton", "Редкие действия в компактном меню.", "Навигация", popup_menu), ] - diff --git a/src/gallery/icon_catalog.py b/src/gallery/icon_catalog.py index e4634f5..73d8af0 100644 --- a/src/gallery/icon_catalog.py +++ b/src/gallery/icon_catalog.py @@ -14,5 +14,4 @@ def matching_icons(query: str) -> tuple[str, ...]: def icon_snippet(name: str) -> str: if name not in ICON_NAMES: raise ValueError(f"Unknown Flet icon: {name}") - return f"ft.Icon(ft.Icons.{name})" - + return f"ft.Icons.{name}" diff --git a/src/gallery/source_manifest.json b/src/gallery/source_manifest.json index fe4ed6e..9688fc5 100644 --- a/src/gallery/source_manifest.json +++ b/src/gallery/source_manifest.json @@ -1,4 +1,9 @@ { + "banner": { + "function": "banner", + "line": 64, + "path": "src/gallery/examples/data_feedback.py" + }, "bottom-sheet": { "function": "bottom_sheet", "line": 49, @@ -66,7 +71,7 @@ }, "navigation-bar": { "function": "navigation_bar", - "line": 20, + "line": 27, "path": "src/gallery/examples/navigation.py" }, "outlined-buttons": { @@ -76,7 +81,7 @@ }, "popup-menu": { "function": "popup_menu", - "line": 31, + "line": 38, "path": "src/gallery/examples/navigation.py" }, "progress": { diff --git a/tests/test_gallery.py b/tests/test_gallery.py index d6922e3..46862da 100644 --- a/tests/test_gallery.py +++ b/tests/test_gallery.py @@ -2,6 +2,7 @@ import json from pathlib import Path from gallery.examples import ALL_EXAMPLES +from gallery.examples.navigation import tabs from gallery.icon_catalog import ICON_NAMES, PAGE_SIZE, icon_snippet, matching_icons ROOT = Path(__file__).resolve().parents[1] @@ -31,4 +32,9 @@ def test_icon_catalog_searches_every_icon_and_copies_valid_flet_code() -> None: assert len(ICON_NAMES) > PAGE_SIZE assert "HOME" in matching_icons("home") assert "HOME_OUTLINED" in matching_icons("home outlined") - assert icon_snippet("HOME") == "ft.Icon(ft.Icons.HOME)" + assert icon_snippet("HOME") == "ft.Icons.HOME" + + +def test_tabs_view_has_bounded_height() -> None: + tabs_control = tabs() + assert tabs_control.content.controls[1].height == 96 diff --git a/uv.lock b/uv.lock index da4f4c2..6330ee3 100644 --- a/uv.lock +++ b/uv.lock @@ -50,7 +50,7 @@ wheels = [ [[package]] name = "flet-component-gallery" -version = "0.2.0" +version = "0.3.0" source = { virtual = "." } dependencies = [ { name = "flet" },