first commit

This commit is contained in:
Lucas Saburido
2026-05-13 16:26:45 +01:00
commit cabf2025cd
252 changed files with 13524 additions and 0 deletions

View File

@@ -0,0 +1,96 @@
import 'package:flutter/material.dart';
class AppAnimations {
const AppAnimations._();
/// A standard fade transition
static Widget fade({
required Widget child,
Duration duration = const Duration(milliseconds: 300),
}) {
return AnimatedSwitcher(
duration: duration,
child: child,
);
}
/// A slide transition from the bottom (Brutalist style)
static Widget slideIn({
required Widget child,
Offset begin = const Offset(0, 0.1),
Duration duration = const Duration(milliseconds: 400),
}) {
return TweenAnimationBuilder<Offset>(
tween: Tween<Offset>(begin: begin, end: Offset.zero),
duration: duration,
curve: Curves.easeOutQuart,
builder: (context, offset, child) {
return FractionalTranslation(
translation: offset,
child: child,
);
},
child: child,
);
}
/// A simple "Glitch" effect using staggered offsets and opacities
/// This simulates an underground/grunge signal interference.
static Widget glitch({required Widget child}) {
return _GlitchWidget(child: child);
}
}
class _GlitchWidget extends StatefulWidget {
final Widget child;
const _GlitchWidget({required this.child});
@override
State<_GlitchWidget> createState() => _GlitchWidgetState();
}
class _GlitchWidgetState extends State<_GlitchWidget> with SingleTickerProviderStateMixin {
late AnimationController _controller;
@override
void initState() {
super.initState();
_controller = AnimationController(
vsync: this,
duration: const Duration(milliseconds: 500),
)..repeat();
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return AnimatedBuilder(
animation: _controller,
builder: (context, child) {
final double glitchFactor = _controller.value;
// Only glitch occasionally
if (glitchFactor > 0.9) {
return Stack(
children: [
Transform.translate(
offset: const Offset(2, 0),
child: Opacity(opacity: 0.5, child: widget.child),
),
Transform.translate(
offset: const Offset(-2, 1),
child: Opacity(opacity: 0.5, child: widget.child),
),
widget.child,
],
);
}
return widget.child;
},
);
}
}

View File

@@ -0,0 +1,35 @@
import 'package:flutter/material.dart';
class AppColors {
const AppColors._();
// Core Palette
static const black = Color(0xFF000000); // Pitch black
static const blackRaised = Color(0xFF1A1A1A); // Slightly raised black
static const blackSoft = Color(0xFF0F0F0F); // Soft black for backgrounds
static const darkGrey = Color(0xFF0A0A0A);
static const white = Color(0xFFFFFFFF);
static const offWhite = Color(0xFFEBEBEB); // For body text readability
// RIOTZ Red Tones (Aggressive & Premium)
static const neonRed = Color(0xFFFF0033); // Primary accent
static const bloodRed = Color(0xFF8B0000); // Secondary
static const deepRed = Color(0xFF4A0000); // Muted backgrounds
// Purple Accents
static const neonPurple = Color(0xFF9D00FF); // Neon purple accent
// Surfaces & Borders
static const surface = Color(0xFF0D0D0D); // Elevated surfaces
static const surfaceLight = Color(0xFF1A1A1A);
static const border = Color(0xFF262626); // Brutalist outlines
// Neutral / Muted
static const grey = Color(0xFF757575);
static const greyDark = Color(0xFF424242);
static const greyMuted = Color(0xFF212121);
// Semantic
static const error = Color(0xFFFF0033);
static const success = Color(0xFF00FF66); // Acid green for contrast
}

View File

@@ -0,0 +1,12 @@
import 'package:flutter/material.dart';
class AppMotion {
const AppMotion._();
static const fast = Duration(milliseconds: 120);
static const normal = Duration(milliseconds: 220);
static const slow = Duration(milliseconds: 360);
static const standardCurve = Curves.easeOutCubic;
static const emphasizedCurve = Curves.easeOutQuart;
}

View File

@@ -0,0 +1,131 @@
import 'package:flutter/material.dart';
import 'app_colors.dart';
import 'app_typography.dart';
import 'app_motion.dart';
class AppTheme {
const AppTheme._();
static ThemeData get dark {
final textTheme = AppTypography.darkTextTheme();
return ThemeData(
useMaterial3: true,
brightness: Brightness.dark,
scaffoldBackgroundColor: AppColors.black,
colorScheme: const ColorScheme.dark(
primary: AppColors.neonRed,
secondary: AppColors.bloodRed,
surface: AppColors.surface,
onPrimary: AppColors.white,
onSecondary: AppColors.white,
onSurface: AppColors.white,
error: AppColors.error,
outline: AppColors.border,
),
textTheme: textTheme,
// App Bar Theme - Centralized & Brutalist
appBarTheme: AppBarTheme(
backgroundColor: AppColors.black,
elevation: 0,
centerTitle: true,
iconTheme: const IconThemeData(color: AppColors.white, size: 20),
titleTextStyle: textTheme.headlineMedium?.copyWith(
color: AppColors.white,
),
),
// Card Theme - Sharp Edges, Subtle Borders
cardTheme: CardThemeData(
color: AppColors.surface,
elevation: 0,
margin: EdgeInsets.zero,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.zero,
side: BorderSide(color: AppColors.border, width: 1),
),
),
// Input Decoration - Industrial / Terminal style
inputDecorationTheme: InputDecorationTheme(
filled: true,
fillColor: AppColors.surface,
contentPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 18),
hintStyle: textTheme.bodySmall?.copyWith(color: AppColors.greyDark),
labelStyle: textTheme.bodyMedium?.copyWith(color: AppColors.grey),
border: const OutlineInputBorder(
borderRadius: BorderRadius.zero,
borderSide: BorderSide(color: AppColors.border),
),
enabledBorder: const OutlineInputBorder(
borderRadius: BorderRadius.zero,
borderSide: BorderSide(color: AppColors.border),
),
focusedBorder: const OutlineInputBorder(
borderRadius: BorderRadius.zero,
borderSide: BorderSide(color: AppColors.neonRed, width: 1.5),
),
errorBorder: const OutlineInputBorder(
borderRadius: BorderRadius.zero,
borderSide: BorderSide(color: AppColors.error),
),
),
// Button Themes
filledButtonTheme: FilledButtonThemeData(
style: FilledButton.styleFrom(
backgroundColor: AppColors.neonRed,
foregroundColor: AppColors.white,
shape: const RoundedRectangleBorder(borderRadius: BorderRadius.zero),
textStyle: textTheme.labelLarge,
padding: const EdgeInsets.symmetric(vertical: 16, horizontal: 24),
),
),
outlinedButtonTheme: OutlinedButtonThemeData(
style: OutlinedButton.styleFrom(
foregroundColor: AppColors.white,
side: const BorderSide(color: AppColors.white, width: 1.5),
shape: const RoundedRectangleBorder(borderRadius: BorderRadius.zero),
textStyle: textTheme.labelLarge,
padding: const EdgeInsets.symmetric(vertical: 16, horizontal: 24),
),
),
// Navigation Bar - Custom Riotz Feel
navigationBarTheme: NavigationBarThemeData(
backgroundColor: AppColors.black,
indicatorColor: AppColors.neonRed.withOpacity(0.1),
labelTextStyle: WidgetStateProperty.resolveWith((states) {
if (states.contains(WidgetState.selected)) {
return textTheme.bodySmall?.copyWith(color: AppColors.neonRed, fontWeight: FontWeight.bold);
}
return textTheme.bodySmall?.copyWith(color: AppColors.grey);
}),
iconTheme: WidgetStateProperty.resolveWith((states) {
if (states.contains(WidgetState.selected)) {
return const IconThemeData(color: AppColors.neonRed, size: 24);
}
return const IconThemeData(color: AppColors.grey, size: 24);
}),
),
// Dialog Theme
dialogTheme: const DialogThemeData(
backgroundColor: AppColors.surface,
elevation: 0,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.zero,
side: BorderSide(color: AppColors.border, width: 1),
),
),
dividerTheme: const DividerThemeData(
color: AppColors.border,
thickness: 1,
space: 1,
),
);
}
}

View File

@@ -0,0 +1,91 @@
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import 'app_colors.dart';
class AppTypography {
const AppTypography._();
// Primary heading font: Aggressive, industrial, and bold
static String get headingFont => GoogleFonts.bebasNeue().fontFamily!;
// Body font: Monospace or clean Sans for that "terminal/underground" feel
static String get bodyFont => GoogleFonts.inter().fontFamily!;
static String get monoFont => GoogleFonts.jetBrainsMono().fontFamily!;
static TextTheme darkTextTheme() {
return TextTheme(
displayLarge: TextStyle(
fontFamily: headingFont,
fontSize: 72,
fontWeight: FontWeight.w900,
color: AppColors.white,
letterSpacing: -1.0,
height: 0.9,
),
displayMedium: TextStyle(
fontFamily: headingFont,
fontSize: 48,
fontWeight: FontWeight.bold,
color: AppColors.white,
letterSpacing: 0.5,
height: 1.0,
),
headlineLarge: TextStyle(
fontFamily: headingFont,
fontSize: 32,
fontWeight: FontWeight.bold,
color: AppColors.neonRed,
letterSpacing: 1.5,
),
headlineMedium: TextStyle(
fontFamily: headingFont,
fontSize: 24,
fontWeight: FontWeight.bold,
color: AppColors.white,
letterSpacing: 1.2,
),
titleLarge: TextStyle(
fontFamily: bodyFont,
fontSize: 20,
fontWeight: FontWeight.w900,
color: AppColors.white,
letterSpacing: -0.5,
),
titleMedium: TextStyle(
fontFamily: bodyFont,
fontSize: 16,
fontWeight: FontWeight.w700,
color: AppColors.white,
),
bodyLarge: TextStyle(
fontFamily: bodyFont,
fontSize: 16,
fontWeight: FontWeight.normal,
color: AppColors.offWhite,
height: 1.5,
),
bodyMedium: TextStyle(
fontFamily: bodyFont,
fontSize: 14,
fontWeight: FontWeight.normal,
color: AppColors.offWhite,
height: 1.4,
),
bodySmall: TextStyle(
fontFamily: monoFont,
fontSize: 12,
fontWeight: FontWeight.w400,
color: AppColors.grey,
letterSpacing: 0.5,
),
labelLarge: TextStyle(
fontFamily: headingFont,
fontSize: 18,
fontWeight: FontWeight.bold,
color: AppColors.white,
letterSpacing: 2.0,
),
);
}
}