Skip to content

Instantly share code, notes, and snippets.

@JohanScheepers
Last active February 27, 2026 08:37
Show Gist options
  • Select an option

  • Save JohanScheepers/e50377eac402d0f485c781a5a84511b2 to your computer and use it in GitHub Desktop.

Select an option

Save JohanScheepers/e50377eac402d0f485c781a5a84511b2 to your computer and use it in GitHub Desktop.
no_material_flutter
import 'package:flutter/widgets.dart';
import 'dart:ui';
import 'package:signals/signals_flutter.dart';
/// Entry point of the application.
void main() {
runApp(const App());
}
/// The root widget of the application.
///
/// We use [WidgetsApp] instead of [MaterialApp] to maintain a completely
/// custom design language without Material or Cupertino dependencies.
class App extends StatelessWidget {
const App({super.key});
@override
Widget build(BuildContext context) {
return WidgetsApp(
title: 'Flutter No Material & Cupertino',
debugShowCheckedModeBanner: false,
color: AppTheme.primary,
// Minimalistic routing since we only have one main screen
pageRouteBuilder: <T>(RouteSettings settings, WidgetBuilder builder) =>
PageRouteBuilder<T>(
settings: settings,
pageBuilder: (context, animation, secondaryAnimation) =>
builder(context),
),
home: const CounterExample(),
);
}
}
/// The main page of the application demonstrating the [Signals] counter
/// and the high-fidelity [TechStackShowcase].
class CounterExample extends StatefulWidget {
const CounterExample({super.key});
@override
State<CounterExample> createState() => _CounterExampleState();
}
/// State for [CounterExample] using [SignalsMixin] for reactive updates.
class _CounterExampleState extends State<CounterExample> with SignalsMixin {
// A reactive signal to hold the counter value.
late final Signal<int> counter = createSignal(0);
/// Increments the signal value, triggering an efficient UI rebuild.
void _incrementCounter() {
counter.value++;
}
@override
Widget build(BuildContext context) {
return ColoredBox(
color: AppTheme.background,
child: SafeArea(
child: SingleChildScrollView(
child: Column(
children: [
// Custom Bar: Mimics an AppBar without Material dependencies.
Container(
height: AppTheme.appBarHeight,
width: double.infinity,
padding: AppTheme.appBarPadding,
alignment: Alignment.centerLeft,
child: const Text(
'Flutter Counter',
style: AppTheme.appBarTitle,
),
),
const SizedBox(height: 40),
// Counter Section
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text(
'You have pushed the button this many times:',
style: AppTheme.bodyText,
),
const SizedBox(height: 8),
// Watch automatically rebuilds this widget when the signal changes.
Watch(
(context) =>
Text('${counter.value}', style: AppTheme.counterText),
),
const SizedBox(height: 32),
// Styled Increment Button
GestureDetector(
onTap: _incrementCounter,
child: GlowContainer(
size: null, // Makes the container wrap the child text
borderRadius: AppTheme.buttonRadius,
padding: AppTheme.buttonPadding,
borderGradient: const LinearGradient(
colors: [
Color(0xFF54E0E0), // Cyan start
Color(0xFFE054E0), // Pink end
],
begin: Alignment.topLeft,
end: Alignment.bottomRight,
),
child: const Text(
'Increment',
style: AppTheme.buttonLabel,
),
),
),
],
),
const SizedBox(height: 80),
// Tech Stack Showcase: Horizontal bar with premium icons.
const TechStackShowcase(),
],
),
),
),
);
}
}
/// Central place for all colors, text styles, and spacing constants.
final class AppTheme {
// Brand Colors
static const Color primary = Color(0xFF2196F3);
static const Color background = Color(0xFF0F111A); // Deep Slate
static const Color onPrimary = Color(0xFFFFFFFF);
static const Color onBackground = Color(0xFFE0E0E0);
// Typography - Note: decoration is mandatory in WidgetsApp context
static const TextStyle appBarTitle = TextStyle(
color: onPrimary,
fontSize: 20,
fontWeight: FontWeight.w600,
decoration: TextDecoration.none,
);
static const TextStyle bodyText = TextStyle(
fontSize: 16,
color: onBackground,
decoration: TextDecoration.none,
);
static const TextStyle counterText = TextStyle(
fontSize: 48,
fontWeight: FontWeight.bold,
color: onBackground,
decoration: TextDecoration.none,
);
static const TextStyle buttonLabel = TextStyle(
color: onPrimary,
fontSize: 16,
fontWeight: FontWeight.w600,
decoration: TextDecoration.none,
);
// Layout Spacing
static const double appBarHeight = 56;
static const EdgeInsets appBarPadding = EdgeInsets.symmetric(horizontal: 16);
static const EdgeInsets buttonPadding = EdgeInsets.symmetric(
horizontal: 24,
vertical: 12,
);
static const double buttonRadius = 8;
}
/// A horizontally scrolling bar that showcases technology icons
/// with glassmorphism and glow effects.
class TechStackShowcase extends StatelessWidget {
const TechStackShowcase({super.key});
@override
Widget build(BuildContext context) {
// Shared gradient for icon borders to maintain visual consistency.
const iconBorderGradient = LinearGradient(
colors: [
Color(0xFF54E0E0), // Bright Cyan
Color(0xFFE054E0), // Vibrant Magenta
],
begin: Alignment.topLeft,
end: Alignment.bottomRight,
);
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Stack(
children: [
// Layer 1: Translucent bar background using low-opacity white.
Positioned.fill(
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 20.0),
child: Container(
decoration: BoxDecoration(
color: const Color(0xFFFFFFFF).withValues(alpha: 0.05),
border: Border.symmetric(
horizontal: BorderSide(
color: const Color(0xFFFFFFFF).withValues(alpha: 0.1),
width: 1.0,
),
),
),
),
),
),
// Layer 2: Centered icon row.
Padding(
padding: const EdgeInsets.symmetric(
horizontal: 24.0,
vertical: 32.0,
),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
GlowContainer(
borderGradient: iconBorderGradient,
child: const FlutterLogo(size: 40),
),
],
),
),
],
),
],
);
}
}
/// A specialized container that implements glassmorphism,
/// gradient borders, and directional glow.
class GlowContainer extends StatelessWidget {
const GlowContainer({
super.key,
required this.child,
required this.borderGradient,
this.innerBlur = 20.0,
this.borderRadius = 16.0,
this.padding = const EdgeInsets.all(12.0),
this.size = 80.0,
});
/// The widget to display inside the container.
final Widget child;
/// The gradient used for drawing the thin border.
final Gradient borderGradient;
/// The amount of backdrop blur for the frosted glass effect.
final double innerBlur;
/// The corner radius of the container.
final double borderRadius;
/// Internal padding for the child widget.
final EdgeInsets padding;
/// Optional fixed size. If null, the container shrink-wraps the child.
final double? size;
@override
Widget build(BuildContext context) {
final glowColors = borderGradient.colors;
return Container(
width: size,
height: size,
constraints: const BoxConstraints(),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(borderRadius),
boxShadow: [
// Directional Glow 1: Cyan glow offset top-left
BoxShadow(
color: glowColors.first.withValues(alpha: 0.4),
blurRadius: 20,
spreadRadius: -2,
offset: const Offset(-4, -4),
),
// Directional Glow 2: Magenta glow offset bottom-right
if (glowColors.length > 1)
BoxShadow(
color: glowColors.last.withValues(alpha: 0.4),
blurRadius: 20,
spreadRadius: -2,
offset: const Offset(4, 4),
),
// Layer 3: Subtle ambient glow for overall presence
BoxShadow(
color: glowColors.first.withValues(alpha: 0.1),
blurRadius: 40,
spreadRadius: 2,
),
],
),
child: ClipRRect(
borderRadius: BorderRadius.circular(borderRadius),
child: BackdropFilter(
// Frosted glass effect
filter: ImageFilter.blur(sigmaX: innerBlur, sigmaY: innerBlur),
child: CustomPaint(
// Custom painter for the 1px gradient border
painter: _GradientBorderPainter(
gradient: borderGradient,
radius: borderRadius,
strokeWidth: 2.0,
),
child: Container(
padding: padding,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(borderRadius),
// Increased transparency for the glass area around the icon
gradient: LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: [
const Color(0xFFFFFFFF).withValues(alpha: 0.05),
const Color(0xFFFFFFFF).withValues(alpha: 0.02),
],
),
),
// Center the child if a fixed size is provided,
// otherwise let it shrink-wrap.
child: size != null ? Center(child: child) : child,
),
),
),
),
);
}
}
/// A custom painter that draws a rounded rectangle border with a gradient shader.
class _GradientBorderPainter extends CustomPainter {
_GradientBorderPainter({
required this.gradient,
required this.radius,
required this.strokeWidth,
});
final Gradient gradient;
final double radius;
final double strokeWidth;
@override
void paint(Canvas canvas, Size size) {
// Create the rect and shrink it by half the stroke width
// to ensure the border is fully visible within the container bounds.
final rect = Offset.zero & size;
final RRect rrect = RRect.fromRectAndRadius(
rect.deflate(strokeWidth / 2),
Radius.circular(radius),
);
final paint = Paint()
..style = PaintingStyle.stroke
..strokeWidth = strokeWidth
..maskFilter = const MaskFilter.blur(BlurStyle.normal, 1.5)
..shader = gradient.createShader(rect);
canvas.drawRRect(rrect, paint);
}
@override
bool shouldRepaint(covariant _GradientBorderPainter oldDelegate) =>
oldDelegate.gradient != gradient ||
oldDelegate.radius != radius ||
oldDelegate.strokeWidth != strokeWidth;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment