```
import os
import platform
import subprocess

import flet as ft

from configs.path_config import IMAGES_DIR


class ImageBrowser:
    def __init__(self):
        self.root_dir = IMAGES_DIR

        self.current_dir = self.root_dir
        self.history = []

        # サポートする画像拡張子
        self.image_extensions = {'.jpg', '.jpeg', '.png', '.gif', '.bmp', '.webp'}

    def is_image(self, path):
        return path.suffix.lower() in self.image_extensions

    def open_image(self, image_path):
        """OSのデフォルトアプリケーションで画像を開く"""
        system = platform.system()
        if system == 'Darwin':  # macOS
            subprocess.run(['open', str(image_path)])
        elif system == 'Windows':
            os.startfile(str(image_path))
        else:  # Linux
            subprocess.run(['xdg-open', str(image_path)])

    def get_items(self):
        """現在のディレクトリのサブディレクトリと画像を取得"""
        items = []
        try:
            for item in sorted(self.current_dir.iterdir()):
                if item.is_dir() and not item.name.startswith('.'):
                    items.append(('dir', item))
                elif item.is_file() and self.is_image(item):
                    items.append(('image', item))
        except PermissionError:
            pass
        return items

    def navigate_to(self, path):
        """指定されたパスに移動"""
        if path.is_dir():
            self.history.append(self.current_dir)
            self.current_dir = path

    def go_back(self):
        """前のディレクトリに戻る"""
        if self.history:
            self.current_dir = self.history.pop()

    def go_to_root(self):
        """ルートディレクトリに戻る"""
        self.history.clear()
        self.current_dir = self.root_dir


def main(page: ft.Page):
    page.title = "画像ブラウザ"
    page.padding = 20

    browser = ImageBrowser()

    # パスを表示するテキスト
    path_text = ft.Text(
        value=str(browser.current_dir),
        size=16,
        weight=ft.FontWeight.BOLD
    )

    # カードを表示するグリッド
    grid = ft.GridView(
        expand=True,
        runs_count=5,  # 列数（画面幅に応じて自動調整される）
        max_extent=200,  # カードの最大幅
        child_aspect_ratio=1.0,  # カードのアスペクト比
        spacing=10,
        run_spacing=10,
    )

    def update_view():
        """ビューを更新"""
        path_text.value = str(browser.current_dir)
        grid.controls.clear()

        items = browser.get_items()
        for item_type, item_path in items:
            if item_type == 'dir':
                # ディレクトリカード
                card = ft.Card(
                    content=ft.Container(
                        content=ft.Column([
                            ft.Icon(
                                ft.Icons.FOLDER,
                                size=60,
                                color=ft.Colors.BLUE_400
                            ),
                            ft.Text(
                                item_path.name,
                                size=14,
                                text_align=ft.TextAlign.CENTER,
                                overflow=ft.TextOverflow.ELLIPSIS
                            )
                        ],
                            alignment=ft.MainAxisAlignment.CENTER,
                            horizontal_alignment=ft.CrossAxisAlignment.CENTER,
                            spacing=10
                        ),
                        padding=10,
                        on_click=lambda e, p=item_path: navigate_to_dir(p)
                    ),
                    elevation=2
                )
            else:
                # 画像カード
                card = ft.Card(
                    content=ft.Container(
                        content=ft.Column([
                            ft.Icon(
                                ft.Icons.IMAGE,
                                size=60,
                                color=ft.Colors.GREEN_400
                            ),
                            ft.Text(
                                item_path.name,
                                size=14,
                                text_align=ft.TextAlign.CENTER,
                                overflow=ft.TextOverflow.ELLIPSIS
                            )
                        ],
                            alignment=ft.MainAxisAlignment.CENTER,
                            horizontal_alignment=ft.CrossAxisAlignment.CENTER,
                            spacing=10
                        ),
                        padding=10,
                        on_click=lambda e, p=item_path: open_image(p)
                    ),
                    elevation=2
                )

            grid.controls.append(card)

        # ナビゲーションボタンの表示/非表示
        back_button.visible = browser.current_dir != browser.root_dir
        root_button.visible = browser.current_dir != browser.root_dir

        page.update()

    def navigate_to_dir(path):
        """ディレクトリに移動"""
        browser.navigate_to(path)
        update_view()

    def open_image(path):
        """画像を開く"""
        browser.open_image(path)

    def go_back(e):
        """前に戻る"""
        browser.go_back()
        update_view()

    def go_to_root(e):
        """ルートに戻る"""
        browser.go_to_root()
        update_view()

    # ナビゲーションボタン
    back_button = ft.IconButton(
        icon=ft.Icons.ARROW_BACK,
        on_click=go_back,
        tooltip="前に戻る",
        visible=False
    )

    root_button = ft.IconButton(
        icon=ft.Icons.HOME,
        on_click=go_to_root,
        tooltip="ルートに戻る",
        visible=False
    )

    # ヘッダー
    header = ft.Row([
        ft.Row([
            back_button,
            root_button,
        ], width=100),
        path_text
    ], spacing=10, height=50, )

    # メインレイアウト
    page.add(
        ft.Column([
            header,
            ft.Divider(),
            grid
        ], expand=True)
    )

    # 初期表示
    update_view()


ft.app(target=main)
```

Python 3.12, Flet 0.28.3.
上記のコードは画像のエクスプローラ。現在は単一のアプリケーションになっているので、これをタブとして返すようにして、エントリポイントではTabsにこのTabを追加して表示するようにして。