Files
flux/lib/core/theme/theme.dart

272 lines
9.0 KiB
Dart
Raw Normal View History

2026-04-04 19:25:55 +02:00
// lib/theme.dart
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
class FluxColors {
// === Palette comune (dal logo) ===
static const Color primaryBlue = Color(
0xFF007BFF,
); // Blu Elettrico (Affidabilità)
static const Color accentTurquoise = Color(
0xFF17A2B8,
); // Turchese (Flusso/Tech)
// === Palette Tech Dark (esistente) ===
static const Color darkBackground = Color(0xFF0A0E17);
static const Color darkSurface = Color(0xFF161B22);
static const Color darkTextPrimary = Colors.white;
static const Color darkTextSecondary = Color(0xFF8B949E);
// === Palette Tech Light (NUOVA) ===
static const Color lightBackground = Color(
0xFFF0F2F5,
); // Grigio chiarissimo "pulito"
static const Color lightSurface = Colors.white; // Pannelli bianchi puri
static const Color lightTextPrimary = Color(
0xFF1C1E21,
); // Quasi nero per contrasto
static const Color lightTextSecondary = Color(0xFF606770); // Grigio medio
}
// --- Configurazione Tipografica Comune ---
TextTheme _buildFluxTextTheme(
TextTheme base,
Color primaryColor,
Color secondaryColor,
) {
return GoogleFonts.poppinsTextTheme(base).copyWith(
headlineMedium: GoogleFonts.poppins(
color: primaryColor,
fontWeight: FontWeight.w600,
letterSpacing: 0.5,
),
titleLarge: GoogleFonts.poppins(
color: primaryColor,
fontWeight: FontWeight.w500,
),
titleSmall: GoogleFonts.poppins(
color:
FluxColors.accentTurquoise, // Sempre turchese per i titoli di sezione
fontWeight: FontWeight.w600,
letterSpacing: 1.2,
),
bodyMedium: GoogleFonts.poppins(color: secondaryColor),
);
}
// ==========================================
// === TEMA SCURO (esistente, ottimizzato) ===
// ==========================================
ThemeData fluxDarkTheme = ThemeData(
useMaterial3: true,
brightness: Brightness.dark,
primaryColor: FluxColors.primaryBlue,
scaffoldBackgroundColor: FluxColors.darkBackground,
colorScheme: const ColorScheme.dark(
primary: FluxColors.primaryBlue,
secondary: FluxColors.accentTurquoise,
surface: FluxColors.darkSurface,
onPrimary: Colors.white,
onSurface: FluxColors.darkTextPrimary,
),
hoverColor: FluxColors.accentTurquoise.withValues(
alpha: 0.08,
), // <--- AGGIUNGI QUESTO
splashColor: FluxColors.accentTurquoise.withValues(
alpha: 0.12,
), // <--- AGGIUNGI QUESTO
highlightColor: Colors.transparent,
2026-04-04 19:25:55 +02:00
textTheme: _buildFluxTextTheme(
ThemeData.dark().textTheme,
FluxColors.darkTextPrimary,
FluxColors.darkTextSecondary,
),
appBarTheme: const AppBarTheme(
backgroundColor: FluxColors.darkBackground,
elevation: 0,
centerTitle: false,
iconTheme: IconThemeData(color: FluxColors.darkTextPrimary),
titleTextStyle: TextStyle(
color: FluxColors.darkTextPrimary,
fontSize: 20,
fontWeight: FontWeight.w600,
),
),
cardTheme: const CardThemeData(
color: FluxColors.darkSurface,
elevation: 2,
margin: EdgeInsets.all(8),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(12)),
),
),
listTileTheme: ListTileThemeData(
// Definiamo la forma arrotondata (fondamentale per l'effetto moderno)
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
// Colore dell'icona (Turchese Flux)
iconColor: FluxColors.accentTurquoise,
// Colore del testo
titleTextStyle: GoogleFonts.poppins(
color: FluxColors.darkTextPrimary,
fontSize: 16,
fontWeight: FontWeight.w500,
),
subtitleTextStyle: GoogleFonts.poppins(
color: FluxColors.darkTextSecondary,
fontSize: 13,
),
// Per far apparire la "manina" su Web/Desktop
mouseCursor: WidgetStateProperty.all(SystemMouseCursors.click),
// NOTA: Se overlayColor non esiste, Flutter userà i colori
// di default del tema (splashColor e hoverColor) definiti nel ThemeData generale.
),
2026-04-04 19:25:55 +02:00
elevatedButtonTheme: ElevatedButtonThemeData(
style: ElevatedButton.styleFrom(
backgroundColor: FluxColors.primaryBlue,
foregroundColor: Colors.white,
elevation: 3,
padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 12),
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)),
),
),
// Colore delle icone non attive nella BottomNav
unselectedWidgetColor: FluxColors.darkTextSecondary,
);
// ==========================================
// === TEMA CHIARO (NUOVO) ===
// ==========================================
ThemeData fluxLightTheme = ThemeData(
useMaterial3: true,
brightness: Brightness.light,
primaryColor: FluxColors.primaryBlue,
// Sfondo chiarissimo per staccare dalle card bianche
scaffoldBackgroundColor: FluxColors.lightBackground,
hoverColor: FluxColors.primaryBlue.withValues(alpha: 0.05),
splashColor: FluxColors.primaryBlue.withValues(alpha: 0.1),
highlightColor: Colors.transparent,
2026-04-04 19:25:55 +02:00
colorScheme: const ColorScheme.light(
primary: FluxColors.primaryBlue,
secondary: FluxColors.accentTurquoise,
surface: FluxColors.lightSurface,
onPrimary: Colors.white,
onSurface: FluxColors.lightTextPrimary,
),
// Applica la stessa tipografia ma con colori scuri
textTheme: _buildFluxTextTheme(
ThemeData.light().textTheme,
FluxColors.lightTextPrimary,
FluxColors.lightTextSecondary,
),
appBarTheme: const AppBarTheme(
backgroundColor: FluxColors.lightSurface, // AppBar bianca
elevation: 1, // Leggera ombra per staccare dallo sfondo
centerTitle: false,
iconTheme: IconThemeData(color: FluxColors.lightTextPrimary),
titleTextStyle: TextStyle(
color: FluxColors.lightTextPrimary,
fontSize: 20,
fontWeight: FontWeight.w600,
),
),
cardTheme: const CardThemeData(
color: FluxColors.lightSurface, // Card bianca pura
elevation: 4, // Ombra più marcata su sfondo chiaro
margin: EdgeInsets.all(8),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(12)),
),
),
listTileTheme: ListTileThemeData(
// Definiamo la forma arrotondata (fondamentale per l'effetto moderno)
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
// Colore dell'icona (Turchese Flux)
iconColor: FluxColors.accentTurquoise,
// Colore del testo
titleTextStyle: GoogleFonts.poppins(
color: FluxColors.darkTextPrimary,
fontSize: 16,
fontWeight: FontWeight.w500,
),
subtitleTextStyle: GoogleFonts.poppins(
color: FluxColors.darkTextSecondary,
fontSize: 13,
),
// Per far apparire la "manina" su Web/Desktop
mouseCursor: WidgetStateProperty.all(SystemMouseCursors.click),
// NOTA: Se overlayColor non esiste, Flutter userà i colori
// di default del tema (splashColor e hoverColor) definiti nel ThemeData generale.
),
2026-04-04 19:25:55 +02:00
// Il pulsante principale rimane Blu Elettrico, molto visibile
elevatedButtonTheme: ElevatedButtonThemeData(
style: ElevatedButton.styleFrom(
backgroundColor: FluxColors.primaryBlue,
foregroundColor: Colors.white,
elevation: 4,
padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 12),
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)),
),
),
// TabBar (usata nelle Anagrafiche) ottimizzata per il chiaro
tabBarTheme: const TabBarThemeData(
labelColor: FluxColors.primaryBlue,
unselectedLabelColor: FluxColors.lightTextSecondary,
indicatorColor: FluxColors.accentTurquoise,
indicatorSize: TabBarIndicatorSize.label,
),
// BottomNavigationBar (usata nella HomeScreen)
bottomNavigationBarTheme: const BottomNavigationBarThemeData(
backgroundColor: FluxColors.lightSurface,
selectedItemColor: FluxColors.primaryBlue,
unselectedItemColor: FluxColors.lightTextSecondary,
elevation: 8,
),
// Colore delle icone generiche
iconTheme: const IconThemeData(color: FluxColors.lightTextSecondary),
);
extension FluxThemeContext on BuildContext {
2026-04-13 18:26:17 +02:00
// Scorciatoie per il TextTheme
TextStyle get titleLarge => Theme.of(this).textTheme.titleLarge!;
TextStyle get titleMedium => Theme.of(this).textTheme.titleMedium!;
TextStyle get bodyMedium => Theme.of(this).textTheme.bodyMedium!;
2026-04-06 10:55:56 +02:00
// --- Colori del Brand ---
Color get primary => Theme.of(this).colorScheme.primary; // Blu Flux
Color get accent => Theme.of(this).colorScheme.secondary; // Turchese Flux
2026-04-06 10:55:56 +02:00
// --- Superfici ---
Color get surface => Theme.of(this).colorScheme.surface;
2026-04-06 10:55:56 +02:00
Color get background =>
Theme.of(this).colorScheme.surfaceContainerHighest; // O background
// --- Testi (La parte mancante) ---
// Mappiamo primaryText sul colore del titolo e secondaryText su quello del corpo
Color get primaryText =>
2026-04-06 10:55:56 +02:00
Theme.of(this).textTheme.titleLarge?.color ?? Colors.white;
Color get secondaryText =>
Theme.of(this).textTheme.bodyMedium?.color ?? Colors.grey;
// Opzionale: un colore ancora più tenue per suggerimenti o icone disabilitate
Color get hintText =>
Theme.of(this).textTheme.bodySmall?.color ??
Colors.grey.withValues(alpha: 0.5);
}