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:
aurorasunsetlagoonmidnight– tonos profundos azul marino con acentos cian para dashboards nocturnossakura– gradientes pastel inspirados en cerezos para interfaces creativasselva– verdes botánicos con acentos lima ideales para proyectos sosteniblesmarina– combinación de azules oceánicos con turquesas pensada para interfaces de analítica y streaming de datosterracotta– tierra quemada con acentos turquesa para sitios editoriales cálidoscyberwave– neones futuristas para paneles nocturnoszenith– azules corporativos con destellos doradosoasis– desértica con turquesas refrescanteslumen– estética minimalista iluminada con ámbarsolstice– transición cálida del amanecer equilibrada con azules vibrantesnoir– 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_profilespersonalizados o usar los predeterminados que ahora incluyenlarge_desktop, ideal para monitores ultraanchos. El parámetrodevice_columnste permite mapear cuántas columnas debe renderizar cada perfil sin reescribir breakpoints manuales. - Espaciado inteligente: activa
adaptive_spacing=Truepara que el padding entre tarjetas y elrun_spacingcrezcan gradualmente en tabletas, escritorios y grandes pantallas, manteniendo densidades legibles. - Cabeceras configurables: define
header_layout="centered"oheader_layout="split"para cambiar la distribución de título, metadatos y acciones. También puedes aportar una imagen o degradado mediantesection_background_image,section_overlay_colorysection_gradient_tokenpara crear secciones tipo "hero" en la web. - Orientación consciente: los parámetros
section_orientation_backgroundsysection_orientation_gradient_tokenspermiten 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_deviceysection_max_content_width_by_devicepuedes 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_marginysection_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_orientationy los nuevos mapas de degradadoheader_gradient_by_device,header_gradient_tokens_by_deviceyheader_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_positiono 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
AdaptiveNavigationLayoutalterna automáticamente entre barra de navegación inferior, riel lateral extendido o compactado y columnas adaptadas según el breakpoint detectado (mobile,tabletodesktop). El callbackcontent_builderrecibe el nombre del dispositivo activo para ajustar cada vista.AccessibilityPreferencesfacilita activar alto contraste, escalado de texto, reducción de transiciones y mostrar captions textuales pensados para personas con limitaciones visuales o auditivas.AccessibilityPanelofrece 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.utilsindican 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_headerdelThemeManager(o el que indiques medianteapp_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_widthpara fijar el ancho máximo del contenido central ylarge_desktop_panel_widthpara 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:
-
Haz un fork
-
Crea tu rama: git checkout -b feature/nueva-funcionalidad
-
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
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
42e5f4aae06a0a51b519ca9e82b0632ecdb6d725eb069f2cd3f2ef9dd4052ff9
|
|
| MD5 |
07997b35b1bc943a215e14a6bfa40996
|
|
| BLAKE2b-256 |
e05fbca1c54e5cc95968df3d76a4c6cc830af50f9fe2a7928d7c39fe73e06151
|
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2cf02d415137666d725d19dcc7d1ed276d1325b3f31eb5297416887a3407891b
|
|
| MD5 |
10fdbb2482de7c241ce359a69569246e
|
|
| BLAKE2b-256 |
534511fc316e2d0c460aad7733c2d998c86810515cdf175ef9e534c0950681a8
|