Skip to main content

Componentes visuales avanzados para Flet en Python

Project description

🚀 FletPlus

FletPlus es una librería de componentes visuales y utilidades para acelerar el desarrollo de interfaces modernas en Python usando Flet.
Proporciona un conjunto de controles personalizables como tablas inteligentes, grillas responsivas, barras laterales, gestores de tema y estructura modular de apps.


📦 Instalación

pip install fletplus
  • Incluye sistema de estilos, botones personalizados y utilidades de diseño responsivo.
  • Requiere Python 3.9+ y flet>=0.27.0

🧩 Componentes incluidos

Componente Descripción
SmartTable Tabla con paginación y ordenamiento integrados
SidebarAdmin Menú lateral dinámico con ítems y selección
ResponsiveGrid Distribución de contenido adaptable a pantalla
ResponsiveContainer Aplica estilos según breakpoints definidos
AdaptiveNavigationLayout Shell con navegación que cambia entre barra inferior, riel o columna según la plataforma
UniversalAdaptiveScaffold Estructura integral con navegación adaptable, panel secundario y controles de accesibilidad integrados
LineChart Gráfico de líneas interactivo basado en Canvas
ThemeManager Gestión centralizada de modo claro/oscuro
FletPlusApp Estructura base para apps con navegación y tema
SystemTray Icono de bandeja del sistema con eventos
PrimaryButton / SecondaryButton / IconButton Conjunto de botones tematizados y personalizables
ResponsiveVisibility Oculta o muestra controles según tamaño u orientación

📝 Logging

FletPlus utiliza el módulo estándar logging para registrar mensajes de la biblioteca. De forma predeterminada, FletPlusApp.start configura un registro básico a nivel INFO.

Para cambiar el nivel de salida en tu aplicación, ajusta logging antes de iniciar FletPlus:

import logging
from fletplus.core import FletPlusApp

logging.basicConfig(level=logging.DEBUG)

FletPlusApp.start(routes)

🎨 Sistema de estilos

El dataclass Style permite envolver cualquier control de Flet dentro de un Container aplicando márgenes, padding, colores y bordes de forma declarativa.

import flet as ft
from fletplus.styles import Style

def main(page: ft.Page):
    estilo = Style(padding=20, bgcolor=ft.Colors.AMBER_100, border_radius=10)
    saludo = estilo.apply(ft.Text("Hola estilo"))
    page.add(saludo)

ft.app(target=main)

🖱️ Botones personalizados

Incluye tres variantes listas para usar: PrimaryButton, SecondaryButton e IconButton, que aprovechan los tokens definidos en ThemeManager y aceptan Style para ajustes adicionales.

import flet as ft
from fletplus.components.buttons import PrimaryButton, SecondaryButton, IconButton
from fletplus.themes.theme_manager import ThemeManager

def main(page: ft.Page):
    theme = ThemeManager(page, tokens={"typography": {"button_size": 16}})
    theme.apply_theme()
    page.add(
        PrimaryButton("Guardar", icon=ft.icons.SAVE, theme=theme),
        SecondaryButton("Cancelar", theme=theme),
        IconButton(ft.icons.DELETE, label="Eliminar", theme=theme),
    )

ft.app(target=main)

🌓 Gestor de temas

ThemeManager permite centralizar los tokens de estilo y alternar entre modo claro y oscuro.

Nuevas paletas predefinidas

Además de las variantes originales ahora dispones de un catálogo ampliado con paletas listas para aplicar en cualquier dispositivo:

  • aurora
  • sunset
  • lagoon
  • midnight – tonos profundos azul marino con acentos cian para dashboards nocturnos
  • sakura – gradientes pastel inspirados en cerezos para interfaces creativas
  • selva – verdes botánicos con acentos lima ideales para proyectos sostenibles
  • marina – combinación de azules oceánicos con turquesas pensada para interfaces de analítica y streaming de datos
  • terracotta – tierra quemada con acentos turquesa para sitios editoriales cálidos
  • cyberwave – neones futuristas para paneles nocturnos
  • zenith – azules corporativos con destellos dorados
  • oasis – desértica con turquesas refrescantes
  • lumen – estética minimalista iluminada con ámbar
  • solstice – transición cálida del amanecer equilibrada con azules vibrantes
  • noir – monocromo elegante con acentos eléctricos para experiencias premium

Todas ellas incluyen tokens de gradiente gradients.app_header compatibles con el encabezado adaptable del layout.

📁 Cargar tokens/paletas desde JSON o YAML

Las paletas pueden definirse en un archivo JSON o YAML con las claves light y dark. Además de primary, FletPlus reconoce grupos semánticos como info, success, warning y error con tonos _100 ... _900 que luego se pueden consultar o modificar dinámicamente mediante get_token y set_token.

palette.json

{
  "light": {"primary": "#2196F3"},
  "dark": {"primary": "#0D47A1"}
}

palette.yaml

light:
  primary: "#2196F3"
dark:
  primary: "#0D47A1"

Grupos de colores semánticos

Además de la clave primary, se pueden definir grupos de estado con distintos tonos. Los grupos admitidos son info, success, warning y error, cada uno con tonos 100 a 900:

{
  "light": {
    "info": {
      "100": "#BBDEFB",
      "500": "#2196F3",
      "900": "#0D47A1"
    },
    "success": {
      "100": "#C8E6C9",
      "500": "#4CAF50",
      "900": "#1B5E20"
    },
    "warning": {
      "100": "#FFECB3",
      "500": "#FFC107",
      "900": "#FF6F00"
    },
    "error": {
      "100": "#FFCDD2",
      "500": "#F44336",
      "900": "#B71C1C"
    }
  }
}

load_palette_from_file aplanará automáticamente estas secciones en claves como info_100 o warning_500. Revisa el archivo palette_extended.json para una paleta completa con todos los tonos.

📐 Grid adaptable por dispositivo

El nuevo ResponsiveGridItem permite definir span personalizados tanto por breakpoint como por tipo de dispositivo (móvil, tablet, escritorio). También puedes asignar estilos responsivos a cada item mediante ResponsiveStyle.

import flet as ft
from fletplus.components import ResponsiveGrid, ResponsiveGridItem
from fletplus.styles import Style
from fletplus.utils.responsive_style import ResponsiveStyle

grid = ResponsiveGrid(
    items=[
        ResponsiveGridItem(
            ft.Text("Destacado"),
            span_devices={"mobile": 12, "tablet": 6, "desktop": 4},
            responsive_style=ResponsiveStyle(
                width={800: Style(padding=ft.Padding(24, 24, 24, 24))}
            ),
        ),
        ResponsiveGridItem(ft.Text("Complemento"), span_breakpoints={0: 12, 900: 4}),
    ],
    run_spacing=24,
)

Nuevas capacidades del grid responsivo:

  • Perfiles ampliados: puedes pasar device_profiles personalizados o usar los predeterminados que ahora incluyen large_desktop, ideal para monitores ultraanchos. El parámetro device_columns te permite mapear cuántas columnas debe renderizar cada perfil sin reescribir breakpoints manuales.
  • Espaciado inteligente: activa adaptive_spacing=True para que el padding entre tarjetas y el run_spacing crezcan gradualmente en tabletas, escritorios y grandes pantallas, manteniendo densidades legibles.
  • Cabeceras configurables: define header_layout="centered" o header_layout="split" para cambiar la distribución de título, metadatos y acciones. También puedes aportar una imagen o degradado mediante section_background_image, section_overlay_color y section_gradient_token para crear secciones tipo "hero" en la web.
  • Orientación consciente: los parámetros section_orientation_backgrounds y section_orientation_gradient_tokens permiten alternar fondos y degradados distintos al rotar la pantalla entre modo retrato y paisaje, manteniendo un diseño coherente en smartphones y tablets.
  • Densidad adaptable: con section_gap_by_device y section_max_content_width_by_device puedes fijar espacios y anchos máximos específicos para móvil, tablet, escritorio y monitores ultraanchos sin crear contenedores manuales.
  • Márgenes contextuales: controla el aire alrededor de cada sección con section_margin y section_margin_by_orientation, ideal para interfaces móviles en las que necesitas reducir bordes en modo retrato y ampliarlos en pantallas de escritorio.
  • Cabeceras dinámicas: personaliza el fondo de la cabecera mediante header_background_by_device, header_background_by_orientation y los nuevos mapas de degradado header_gradient_by_device, header_gradient_tokens_by_device y header_gradient_tokens_by_orientation.
  • Acciones adaptadas al contexto: ajusta la alineación de botones y filtros del encabezado con header_actions_alignment, así como mapas por dispositivo u orientación para mejorar la ergonomía en smartphones y escritorios.

🧭 Encabezados más expresivos

AdaptiveNavigationLayout detecta automáticamente los gradientes definidos en ThemeManager y envuelve el encabezado dentro de un contenedor estilizado con sombras suaves, bordes redondeados y soporte para botones de menú cuando se usa en móviles. Puedes aportar tu propio Style o ResponsiveStyle a través del parámetro header_style, o especificar tokens de color alternativos mediante header_background_token.

El componente AdaptiveAppHeader también evoluciona para escenarios multiplataforma:

  • Ajusta automáticamente la maquetación según la orientación (layout_by_orientation) para mantener acciones en línea en escritorio y apilarlas en móviles.
  • Permite alternar la posición del hero con hero_position o forzar un ancho máximo por dispositivo (hero_max_height_by_device), logrando portadas más cinematográficas en web sin sacrificar legibilidad en teléfonos.
  • Aplica relaciones de aspecto (hero_aspect_ratio) y rellenos adaptativos para que ilustraciones, gráficos o vídeos se escalen de forma uniforme al compartir la misma base de código entre web, escritorio y apps móviles.

🔄 Ejemplo completo con ThemeManager

El siguiente ejemplo muestra cómo cargar la paleta y alternar entre modo claro y oscuro:

import flet as ft
from fletplus.themes.theme_manager import ThemeManager, load_palette_from_file
import yaml


def main(page: ft.Page):
    # Cargar tokens de colores desde JSON
    colors = load_palette_from_file("palette.json", mode="light")

    # Si prefieres YAML:
    # with open("palette.yaml", "r", encoding="utf-8") as fh:
    #     colors = yaml.safe_load(fh)["light"]

    theme = ThemeManager(page, tokens={"colors": colors})
    theme.apply_theme()

    # Botón para alternar entre modo claro y oscuro
    toggle = ft.IconButton(
        ft.icons.DARK_MODE,
        on_click=lambda _: theme.toggle_dark_mode(),
    )
    page.add(ft.Text("Modo actual"), toggle)


ft.app(target=main)

📱 Diseño responsivo por dispositivo

Con ResponsiveVisibility se puede mostrar u ocultar un control según el ancho, alto u orientación de la página, facilitando interfaces adaptables.

import flet as ft
from fletplus.utils.responsive_visibility import ResponsiveVisibility

def main(page: ft.Page):
    txt = ft.Text("Solo en pantallas anchas")
    ResponsiveVisibility(page, txt, width_breakpoints={0: False, 800: True})
    page.add(txt)

ft.app(target=main)

♿ Interfaz adaptable y accesible

  • AdaptiveNavigationLayout alterna automáticamente entre barra de navegación inferior, riel lateral extendido o compactado y columnas adaptadas según el breakpoint detectado (mobile, tablet o desktop). El callback content_builder recibe el nombre del dispositivo activo para ajustar cada vista.
  • AccessibilityPreferences facilita activar alto contraste, escalado de texto, reducción de transiciones y mostrar captions textuales pensados para personas con limitaciones visuales o auditivas.
  • AccessibilityPanel ofrece un panel interactivo de controles (escala de texto, alto contraste, animaciones y subtítulos) que se redistribuye según el ancho disponible y puede incorporarse en páginas web, escritorios o móviles.
  • Los perfiles de dispositivo expuestos en fletplus.utils indican el número recomendado de columnas y permiten reaccionar a cambios de tamaño sin reescribir breakpoints manualmente.

🌐 UniversalAdaptiveScaffold: UI universal y accesible

UniversalAdaptiveScaffold combina navegación adaptable, paneles secundarios y controles de accesibilidad pensados para lector de pantalla y personas con baja audición. En móviles muestra una barra inferior accesible; en tabletas un NavigationRail compacto y en escritorio habilita un riel expandido junto a un panel lateral con información o herramientas.

Novedades recientes del scaffold universal:

  • Modo large_desktop: al detectar resoluciones ultraanchas se activa un tercer panel lateral que puede mostrar simultáneamente el panel de accesibilidad (auto habilitable) y el secundario de contenido.
  • Cabecera tematizada: la barra superior lee automáticamente el token gradients.app_header del ThemeManager (o el que indiques mediante app_bar_gradient_token) y ajusta padding según el dispositivo, aportando una estética consistente en web y escritorio.
  • Control de anchura: usa desktop_max_content_width para fijar el ancho máximo del contenido central y large_desktop_panel_width para definir cuánto ocupa el panel auxiliar en monitores grandes.
import flet as ft
from fletplus.components import (
    AdaptiveNavigationItem,
    UniversalAdaptiveScaffold,
    AccessibilityPanel,
)
from fletplus.utils.accessibility import AccessibilityPreferences


def main(page: ft.Page):
    prefs = AccessibilityPreferences(enable_captions=True, text_scale=1.1)
    items = [
        AdaptiveNavigationItem("home", "Inicio", ft.Icons.HOME_OUTLINED),
        AdaptiveNavigationItem("reports", "Reportes", ft.Icons.INSIGHTS_OUTLINED),
        AdaptiveNavigationItem("settings", "Ajustes", ft.Icons.SETTINGS_OUTLINED),
    ]

    scaffold = UniversalAdaptiveScaffold(
        navigation_items=items,
        accessibility=prefs,
        accessibility_panel=AccessibilityPanel(preferences=prefs),
        page_title="Panel adaptable",
        header_controls=[ft.Text("Estado del sistema", size=14)],
        content_builder=lambda item, _: ft.Text(f"Vista: {item.label}"),
        secondary_panel_builder=lambda item: ft.Text(f"Panel lateral de {item.label}"),
    )

    page.add(scaffold.build(page))


ft.app(target=main)
import flet as ft
from fletplus.components import AccessibilityPanel, AdaptiveDestination, AdaptiveNavigationLayout
from fletplus.utils.accessibility import AccessibilityPreferences


def main(page: ft.Page):
    prefs = AccessibilityPreferences(enable_captions=True, text_scale=1.1)
    panel = AccessibilityPanel(preferences=prefs)

    layout = AdaptiveNavigationLayout(
        [
            AdaptiveDestination("Inicio", ft.Icons.HOME_OUTLINED),
            AdaptiveDestination("Reportes", ft.Icons.INSERT_CHART_OUTLINED),
        ],
        lambda index, device: ft.Text(f"Vista {index} en {device}"),
        accessibility=prefs,
        accessibility_panel=panel,
    )

    page.add(layout.build(page))


ft.app(target=main)

🎨 Estilos responsivos

Para aplicar diferentes estilos según el tamaño u orientación de la página se puede combinar :class:ResponsiveManager con :class:ResponsiveStyle.

import flet as ft
from fletplus.styles import Style
from fletplus.utils import ResponsiveManager, ResponsiveStyle

def main(page: ft.Page):
    texto = ft.Text("Hola")
    estilos = ResponsiveStyle(width={0: Style(text_style=ft.TextStyle(size=10)), 600: Style(text_style=ft.TextStyle(size=20))})
    manager = ResponsiveManager(page)
    manager.register_styles(texto, estilos)
    page.add(texto)

ft.app(target=main)

🧱 ResponsiveContainer

ResponsiveContainer simplifica la aplicación de estilos responsivos a un control sin manejar manualmente las señales de tamaño de la página.

import flet as ft
from fletplus.components.responsive_container import ResponsiveContainer
from fletplus.styles import Style
from fletplus.utils.responsive_style import ResponsiveStyle

def main(page: ft.Page):
    estilos = ResponsiveStyle(width={0: Style(padding=10), 600: Style(padding=30)})
    contenedor = ResponsiveContainer(ft.Text("Hola"), estilos)
    page.add(contenedor.build(page))

ft.app(target=main)

🧪 Ejemplo rápido

import flet as ft
from fletplus.components.smart_table import SmartTable
from fletplus.styles import Style

def main(page: ft.Page):
    rows = [
        ft.DataRow(cells=[ft.DataCell(ft.Text("1")), ft.DataCell(ft.Text("Alice"))]),
        ft.DataRow(cells=[ft.DataCell(ft.Text("2")), ft.DataCell(ft.Text("Bob"))]),
    ]
    table = SmartTable(["ID", "Nombre"], rows, style=Style(bgcolor=ft.Colors.AMBER_50))
    page.add(table.build())

ft.app(target=main)

📈 Ejemplo de LineChart

import flet as ft
from fletplus.components.charts import LineChart
from fletplus.styles import Style

def main(page: ft.Page):
    datos = [(0, 0), (1, 3), (2, 1), (3, 4)]
    grafico = LineChart(datos, style=Style(padding=10))
    page.add(grafico.build())

ft.app(target=main)

🔔 Ejemplo de SystemTray

from fletplus.desktop.system_tray import SystemTray

tray = SystemTray(icon="icon.png", menu=["Abrir", "Salir"])
tray.on_click(lambda: print("Clic en el icono"))
tray.show()

🔧 Estructura del proyecto

fletplus/ ├── components/ │ ├── smart_table.py │ ├── sidebar_admin.py │ └── responsive_grid.py ├── themes/ │ └── theme_manager.py ├── core.py ← Clase FletPlusApp

📋 Tests

Todos los componentes aceptan un argumento opcional style de tipo Style para envolver la estructura principal con propiedades de margen, color de fondo y más. Los tests cubren estos comportamientos (ver carpeta tests/).

pytest --cov=fletplus

📱 Modo móvil

Nota: Para compilar y ejecutar en Android o iOS, es necesario tener configurado el entorno de Flet para cada plataforma. Consulta la documentación oficial de instalación y los requisitos de despliegue móvil antes de generar tu app.

🌐 Construcción PWA

Para generar los archivos necesarios de una PWA se incluye el módulo fletplus.web.pwa. Un flujo típico de build sería:

from fletplus.web.pwa import generate_manifest, generate_service_worker

generate_manifest(
    name="Mi App",
    icons=[{"src": "icon.png", "sizes": "192x192", "type": "image/png"}],
    start_url="/",
    output_dir="web",
)
generate_service_worker(["/", "/main.css"], output_dir="web")

Durante el inicio de la aplicación se puede registrar con:

from fletplus.web.pwa import register_pwa

def main(page):
    register_pwa(page)

🛠️ Contribuir

Las contribuciones son bienvenidas:

  1. Haz un fork

  2. Crea tu rama: git checkout -b feature/nueva-funcionalidad

  3. Abre un PR explicando el cambio

📄 Licencia

MIT License

Copyright (c) 2025 Adolfo González

💬 Contacto

Desarrollado por Adolfo González Hernández.

email: adolfogonzal@gmail.com

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

fletplus-0.2.3.tar.gz (102.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

fletplus-0.2.3-py3-none-any.whl (122.0 kB view details)

Uploaded Python 3

File details

Details for the file fletplus-0.2.3.tar.gz.

File metadata

  • Download URL: fletplus-0.2.3.tar.gz
  • Upload date:
  • Size: 102.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.12.10

File hashes

Hashes for fletplus-0.2.3.tar.gz
Algorithm Hash digest
SHA256 42e5f4aae06a0a51b519ca9e82b0632ecdb6d725eb069f2cd3f2ef9dd4052ff9
MD5 07997b35b1bc943a215e14a6bfa40996
BLAKE2b-256 e05fbca1c54e5cc95968df3d76a4c6cc830af50f9fe2a7928d7c39fe73e06151

See more details on using hashes here.

File details

Details for the file fletplus-0.2.3-py3-none-any.whl.

File metadata

  • Download URL: fletplus-0.2.3-py3-none-any.whl
  • Upload date:
  • Size: 122.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.12.10

File hashes

Hashes for fletplus-0.2.3-py3-none-any.whl
Algorithm Hash digest
SHA256 2cf02d415137666d725d19dcc7d1ed276d1325b3f31eb5297416887a3407891b
MD5 10fdbb2482de7c241ce359a69569246e
BLAKE2b-256 534511fc316e2d0c460aad7733c2d998c86810515cdf175ef9e534c0950681a8

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page