Created
July 14, 2026 13:36
-
-
Save dickermoshe/894bb2de3625e3f7d270313930a859fe to your computer and use it in GitHub Desktop.
main.dart
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import 'package:flutter/material.dart'; | |
| import 'package:style/style.dart'; | |
| void main() { | |
| runApp(const MyApp()); | |
| } | |
| class MyApp extends StatelessWidget { | |
| const MyApp({super.key}); | |
| @override | |
| Widget build(BuildContext context) { | |
| return MaterialApp( | |
| title: 'Style Tailwind Showcase', | |
| debugShowCheckedModeBanner: false, | |
| theme: ThemeData( | |
| colorScheme: ColorScheme.fromSeed( | |
| seedColor: Colors.cyan, | |
| brightness: Brightness.dark, | |
| ), | |
| fontFamily: 'Roboto', | |
| useMaterial3: true, | |
| ), | |
| home: const TailwindShowcase(), | |
| ); | |
| } | |
| } | |
| class TailwindShowcase extends StatelessWidget { | |
| const TailwindShowcase({super.key}); | |
| @override | |
| Widget build(BuildContext context) { | |
| return Scaffold( | |
| backgroundColor: const Color(0xFF020617), | |
| body: SafeArea( | |
| child: SingleChildScrollView( | |
| child: Style( | |
| 'min-h-screen bg-slate-950 text-slate-100', | |
| child: Style( | |
| 'relative overflow-hidden px-4 py-4 sm:px-6 lg:px-8', | |
| children: [ | |
| Style( | |
| 'relative mx-auto max-w-7xl flex flex-col gap-6', | |
| children: const [ | |
| _TopNav(), | |
| _HeroPanel(), | |
| _MetricsGrid(), | |
| _OperationsGrid(), | |
| _LowerGrid(), | |
| ], | |
| ), | |
| ], | |
| ), | |
| ), | |
| ), | |
| ), | |
| ); | |
| } | |
| } | |
| class _TopNav extends StatelessWidget { | |
| const _TopNav(); | |
| @override | |
| Widget build(BuildContext context) { | |
| return Style( | |
| 'flex flex-col gap-4 rounded-3xl border border-white/10 bg-white/5 p-4 shadow-2xl backdrop-blur-xl lg:flex-row lg:items-center lg:justify-between', | |
| children: [ | |
| Style( | |
| 'flex flex-row items-center gap-3', | |
| children: const [ | |
| _IconBadge( | |
| icon: Icons.auto_awesome, | |
| classes: | |
| 'size-12 rounded-2xl bg-gradient-to-br from-cyan-400 to-blue-600 text-white shadow-lg shadow-cyan-500/30', | |
| ), | |
| Style( | |
| 'flex flex-col', | |
| children: [ | |
| _StyledText( | |
| 'Tailwind Ops', | |
| 'text-xl font-black tracking-tight text-white', | |
| ), | |
| _StyledText( | |
| 'A Flutter UI composed with utility classes', | |
| 'text-sm text-slate-400', | |
| ), | |
| ], | |
| ), | |
| ], | |
| ), | |
| Style( | |
| 'flex flex-row flex-wrap items-center gap-2', | |
| children: const [ | |
| _Pill(label: 'Realtime', icon: Icons.bolt, active: true), | |
| _Pill(label: 'Automations', icon: Icons.hub), | |
| _Pill(label: 'Dark Mode', icon: Icons.dark_mode), | |
| ], | |
| ), | |
| ], | |
| ); | |
| } | |
| } | |
| class _HeroPanel extends StatelessWidget { | |
| const _HeroPanel(); | |
| @override | |
| Widget build(BuildContext context) { | |
| return Style( | |
| 'grid grid-cols-1 gap-6 lg:grid-cols-12', | |
| children: const [ | |
| Style( | |
| 'lg:col-span-7 relative overflow-hidden rounded-3xl border border-cyan-400/20 bg-gradient-to-br from-slate-900 via-slate-900 to-cyan-950 p-6 shadow-2xl shadow-cyan-950/40', | |
| children: [ | |
| Style( | |
| 'absolute right-0 top-0 h-56 w-56 rounded-full bg-cyan-400/20 blur-3xl', | |
| child: SizedBox(), | |
| ), | |
| Style( | |
| 'relative flex flex-col gap-6', | |
| children: [ | |
| Style( | |
| 'flex flex-row flex-wrap items-center gap-3', | |
| children: [ | |
| _StatusDot(label: 'Live control room'), | |
| _StatusDot(label: '99.98% uptime', tone: 'emerald'), | |
| ], | |
| ), | |
| _StyledText( | |
| 'Build expressive Flutter screens with Tailwind-style utility classes.', | |
| 'max-w-3xl text-4xl font-black leading-tight tracking-tight text-white md:text-6xl', | |
| ), | |
| _StyledText( | |
| 'This mock command center mixes responsive grids, glass cards, gradients, rings, shadows, badges, progress systems, stat tiles, timelines, and interactive hover states using the style package.', | |
| 'max-w-2xl text-base leading-relaxed text-slate-300 md:text-lg', | |
| ), | |
| Style( | |
| 'flex flex-row flex-wrap gap-3', | |
| children: [ | |
| _CtaButton( | |
| label: 'Launch Mission', | |
| icon: Icons.rocket_launch, | |
| classes: | |
| 'bg-cyan-400 text-slate-950 hover:bg-cyan-300 active:bg-cyan-500 shadow-lg shadow-cyan-500/30', | |
| ), | |
| _CtaButton( | |
| label: 'View Telemetry', | |
| icon: Icons.query_stats, | |
| classes: | |
| 'border border-white/10 bg-white/10 text-white hover:bg-white/15', | |
| ), | |
| ], | |
| ), | |
| _SignalStrip(), | |
| ], | |
| ), | |
| ], | |
| ), | |
| Style( | |
| 'lg:col-span-5 rounded-3xl border border-white/10 bg-white/5 p-5 shadow-2xl backdrop-blur-xl', | |
| child: _OrbitalCard(), | |
| ), | |
| ], | |
| ); | |
| } | |
| } | |
| class _MetricsGrid extends StatelessWidget { | |
| const _MetricsGrid(); | |
| static const metrics = [ | |
| ( | |
| title: 'Fleet Health', | |
| value: '98.7%', | |
| delta: '+2.4%', | |
| icon: Icons.favorite, | |
| tone: 'emerald', | |
| ), | |
| ( | |
| title: 'Active Nodes', | |
| value: '1,284', | |
| delta: '+146', | |
| icon: Icons.memory, | |
| tone: 'cyan', | |
| ), | |
| ( | |
| title: 'Threat Score', | |
| value: 'Low', | |
| delta: '-18%', | |
| icon: Icons.shield, | |
| tone: 'blue', | |
| ), | |
| ( | |
| title: 'Throughput', | |
| value: '42 TB', | |
| delta: '+9.1%', | |
| icon: Icons.speed, | |
| tone: 'fuchsia', | |
| ), | |
| ]; | |
| @override | |
| Widget build(BuildContext context) { | |
| return Style( | |
| 'grid grid-cols-1 gap-4 sm:grid-cols-2 xl:grid-cols-4', | |
| children: [ | |
| for (final metric in metrics) | |
| _MetricCard( | |
| title: metric.title, | |
| value: metric.value, | |
| delta: metric.delta, | |
| icon: metric.icon, | |
| tone: metric.tone, | |
| ), | |
| ], | |
| ); | |
| } | |
| } | |
| class _OperationsGrid extends StatelessWidget { | |
| const _OperationsGrid(); | |
| @override | |
| Widget build(BuildContext context) { | |
| return Style( | |
| 'grid grid-cols-1 gap-6 xl:grid-cols-12', | |
| children: const [ | |
| Style( | |
| 'xl:col-span-8 rounded-3xl border border-white/10 bg-slate-900/80 p-5 shadow-2xl', | |
| child: _TelemetryPanel(), | |
| ), | |
| Style( | |
| 'xl:col-span-4 rounded-3xl border border-white/10 bg-white/5 p-5 shadow-2xl backdrop-blur-xl', | |
| child: _MissionQueue(), | |
| ), | |
| ], | |
| ); | |
| } | |
| } | |
| class _LowerGrid extends StatelessWidget { | |
| const _LowerGrid(); | |
| @override | |
| Widget build(BuildContext context) { | |
| return Style( | |
| 'grid grid-cols-1 gap-6 pb-8 lg:grid-cols-3', | |
| children: const [_ThreatMatrix(), _CrewPanel(), _LaunchPanel()], | |
| ); | |
| } | |
| } | |
| class _OrbitalCard extends StatelessWidget { | |
| const _OrbitalCard(); | |
| @override | |
| Widget build(BuildContext context) { | |
| return Style( | |
| 'flex flex-col gap-5', | |
| children: [ | |
| Style( | |
| 'flex flex-row items-center justify-between', | |
| children: const [ | |
| Style( | |
| 'flex flex-col', | |
| children: [ | |
| _StyledText('Orbital Mesh', 'text-lg font-bold text-white'), | |
| _StyledText('Signal integrity map', 'text-sm text-slate-400'), | |
| ], | |
| ), | |
| _IconBadge( | |
| icon: Icons.satellite_alt, | |
| classes: 'size-11 rounded-2xl bg-cyan-400/10 text-cyan-300', | |
| ), | |
| ], | |
| ), | |
| Style( | |
| 'relative h-80 overflow-hidden rounded-3xl border border-cyan-300/10 bg-slate-950', | |
| children: const [ | |
| Style( | |
| 'absolute inset-6 rounded-full border border-cyan-300/20', | |
| child: SizedBox(), | |
| ), | |
| Style( | |
| 'absolute inset-14 rounded-full border border-blue-300/20', | |
| child: SizedBox(), | |
| ), | |
| Style( | |
| 'absolute inset-24 rounded-full border border-fuchsia-300/20', | |
| child: SizedBox(), | |
| ), | |
| Style( | |
| 'absolute left-1/2 top-1/2 size-16 -translate-x-1/2 -translate-y-1/2 rounded-full bg-gradient-to-br from-cyan-300 to-blue-500 shadow-2xl shadow-cyan-400/50', | |
| child: Icon(Icons.public, color: Colors.white, size: 34), | |
| ), | |
| _OrbitNode( | |
| label: 'NYC', | |
| classes: | |
| 'absolute left-10 top-14 bg-emerald-400 text-slate-950 shadow-emerald-400/40', | |
| ), | |
| _OrbitNode( | |
| label: 'SFO', | |
| classes: | |
| 'absolute right-10 top-20 bg-cyan-400 text-slate-950 shadow-cyan-400/40', | |
| ), | |
| _OrbitNode( | |
| label: 'LDN', | |
| classes: | |
| 'absolute bottom-14 left-14 bg-blue-400 text-slate-950 shadow-blue-400/40', | |
| ), | |
| _OrbitNode( | |
| label: 'SIN', | |
| classes: | |
| 'absolute bottom-10 right-12 bg-fuchsia-400 text-slate-950 shadow-fuchsia-400/40', | |
| ), | |
| ], | |
| ), | |
| ], | |
| ); | |
| } | |
| } | |
| class _TelemetryPanel extends StatelessWidget { | |
| const _TelemetryPanel(); | |
| static const bars = [52, 76, 64, 88, 43, 96, 71, 84, 58, 91, 67, 79]; | |
| @override | |
| Widget build(BuildContext context) { | |
| return Style( | |
| 'flex flex-col gap-6', | |
| children: [ | |
| Style( | |
| 'flex flex-col gap-3 lg:flex-row lg:items-start lg:justify-between', | |
| children: const [ | |
| Style( | |
| 'flex flex-col gap-1', | |
| children: [ | |
| _StyledText( | |
| 'Telemetry Throughput', | |
| 'text-2xl font-black tracking-tight text-white', | |
| ), | |
| _StyledText( | |
| 'Twelve-region packet flow over the last operational window.', | |
| 'text-sm text-slate-400', | |
| ), | |
| ], | |
| ), | |
| Style( | |
| 'rounded-2xl border border-emerald-400/20 bg-emerald-400/10 px-4 py-2', | |
| child: _StyledText( | |
| 'Peak load balanced', | |
| 'text-sm font-semibold text-emerald-300', | |
| ), | |
| ), | |
| ], | |
| ), | |
| Style( | |
| 'h-72 rounded-3xl border border-white/10 bg-slate-950 p-4', | |
| child: Style( | |
| 'flex h-full flex-row items-end gap-2', | |
| children: [ | |
| for (var barIndex = 0; barIndex < bars.length; barIndex++) | |
| _ChartBar(index: barIndex, value: bars[barIndex]), | |
| ], | |
| ), | |
| ), | |
| Style( | |
| 'grid grid-cols-1 gap-3 md:grid-cols-3', | |
| children: const [ | |
| _InlineStat(label: 'Ingress', value: '18.4 Gb/s'), | |
| _InlineStat(label: 'Egress', value: '21.9 Gb/s'), | |
| _InlineStat(label: 'Latency', value: '23 ms'), | |
| ], | |
| ), | |
| ], | |
| ); | |
| } | |
| } | |
| class _MissionQueue extends StatelessWidget { | |
| const _MissionQueue(); | |
| static const missions = [ | |
| ( | |
| label: 'Deploy edge cache', | |
| meta: 'North America', | |
| progress: 'w-4/5', | |
| tone: 'cyan', | |
| ), | |
| ( | |
| label: 'Rotate access keys', | |
| meta: 'Security cluster', | |
| progress: 'w-2/3', | |
| tone: 'fuchsia', | |
| ), | |
| ( | |
| label: 'Rebalance streams', | |
| meta: 'EU West mesh', | |
| progress: 'w-3/5', | |
| tone: 'blue', | |
| ), | |
| ( | |
| label: 'Warm standby fleet', | |
| meta: 'Asia Pacific', | |
| progress: 'w-1/2', | |
| tone: 'emerald', | |
| ), | |
| ]; | |
| @override | |
| Widget build(BuildContext context) { | |
| return Style( | |
| 'flex flex-col gap-5', | |
| children: [ | |
| Style( | |
| 'flex flex-row items-center justify-between', | |
| children: const [ | |
| Style( | |
| 'flex flex-col', | |
| children: [ | |
| _StyledText('Mission Queue', 'text-xl font-black text-white'), | |
| _StyledText('Automations in flight', 'text-sm text-slate-400'), | |
| ], | |
| ), | |
| _IconBadge( | |
| icon: Icons.route, | |
| classes: 'size-10 rounded-xl bg-white/10 text-cyan-300', | |
| ), | |
| ], | |
| ), | |
| for (final mission in missions) | |
| _MissionRow( | |
| label: mission.label, | |
| meta: mission.meta, | |
| progress: mission.progress, | |
| tone: mission.tone, | |
| ), | |
| ], | |
| ); | |
| } | |
| } | |
| class _ThreatMatrix extends StatelessWidget { | |
| const _ThreatMatrix(); | |
| @override | |
| Widget build(BuildContext context) { | |
| return Style( | |
| 'rounded-3xl border border-white/10 bg-white/5 p-5 shadow-2xl backdrop-blur-xl', | |
| child: Style( | |
| 'flex flex-col gap-5', | |
| children: const [ | |
| _SectionHeader( | |
| title: 'Threat Matrix', | |
| subtitle: 'Live risk signals', | |
| icon: Icons.radar, | |
| ), | |
| _RiskRow(label: 'Credential drift', level: 'Low', value: 'w-1/4'), | |
| _RiskRow(label: 'Packet anomaly', level: 'Medium', value: 'w-1/2'), | |
| _RiskRow(label: 'Policy coverage', level: 'Strong', value: 'w-5/6'), | |
| _RiskRow(label: 'Infra exposure', level: 'Low', value: 'w-1/5'), | |
| ], | |
| ), | |
| ); | |
| } | |
| } | |
| class _CrewPanel extends StatelessWidget { | |
| const _CrewPanel(); | |
| static const crew = [ | |
| (name: 'Ari', role: 'Incident lead', color: 'bg-cyan-400'), | |
| (name: 'Noa', role: 'Platform', color: 'bg-fuchsia-400'), | |
| (name: 'Kai', role: 'Security', color: 'bg-emerald-400'), | |
| ]; | |
| @override | |
| Widget build(BuildContext context) { | |
| return Style( | |
| 'rounded-3xl border border-white/10 bg-slate-900/80 p-5 shadow-2xl', | |
| child: Style( | |
| 'flex flex-col gap-5', | |
| children: [ | |
| const _SectionHeader( | |
| title: 'Crew Console', | |
| subtitle: 'People on console', | |
| icon: Icons.groups, | |
| ), | |
| for (final member in crew) | |
| Style( | |
| 'flex flex-row items-center justify-between rounded-2xl border border-white/10 bg-white/5 p-3 hover:bg-white/10', | |
| children: [ | |
| Style( | |
| 'flex flex-row items-center gap-3', | |
| children: [ | |
| Style( | |
| 'size-11 rounded-2xl ${member.color} text-slate-950 flex items-center justify-center font-black', | |
| child: Text(member.name.substring(0, 1)), | |
| ), | |
| Style( | |
| 'flex flex-col', | |
| children: [ | |
| _StyledText(member.name, 'font-bold text-white'), | |
| _StyledText(member.role, 'text-sm text-slate-400'), | |
| ], | |
| ), | |
| ], | |
| ), | |
| const Style( | |
| 'size-2.5 rounded-full bg-emerald-400 shadow-lg shadow-emerald-400/40', | |
| child: SizedBox(), | |
| ), | |
| ], | |
| ), | |
| ], | |
| ), | |
| ); | |
| } | |
| } | |
| class _LaunchPanel extends StatelessWidget { | |
| const _LaunchPanel(); | |
| @override | |
| Widget build(BuildContext context) { | |
| return Style( | |
| 'relative overflow-hidden rounded-3xl border border-cyan-300/20 bg-gradient-to-br from-cyan-500/20 via-blue-500/10 to-fuchsia-500/20 p-5 shadow-2xl shadow-cyan-950/40', | |
| child: Style( | |
| 'flex flex-col gap-5', | |
| children: const [ | |
| Style( | |
| 'absolute -right-10 -top-10 size-40 rounded-full bg-cyan-400/20 blur-3xl', | |
| child: SizedBox(), | |
| ), | |
| _SectionHeader( | |
| title: 'Launch Window', | |
| subtitle: 'Next scheduled push', | |
| icon: Icons.rocket_launch, | |
| ), | |
| _StyledText( | |
| '02:48:12', | |
| 'text-5xl font-black tracking-tight text-white', | |
| ), | |
| _StyledText( | |
| 'All preflight checks are green. Canary traffic is staged at 12% with automatic rollback armed.', | |
| 'text-sm leading-relaxed text-slate-300', | |
| ), | |
| _CtaButton( | |
| label: 'Arm Release', | |
| icon: Icons.lock_open, | |
| classes: | |
| 'bg-white text-slate-950 hover:bg-cyan-100 active:bg-cyan-200', | |
| ), | |
| ], | |
| ), | |
| ); | |
| } | |
| } | |
| class _MetricCard extends StatelessWidget { | |
| const _MetricCard({ | |
| required this.title, | |
| required this.value, | |
| required this.delta, | |
| required this.icon, | |
| required this.tone, | |
| }); | |
| final String title; | |
| final String value; | |
| final String delta; | |
| final IconData icon; | |
| final String tone; | |
| @override | |
| Widget build(BuildContext context) { | |
| return Style( | |
| 'group rounded-3xl border border-white/10 bg-white/5 p-5 shadow-xl backdrop-blur-xl transition-all duration-300 hover:-translate-y-1 hover:bg-white/10', | |
| child: Style( | |
| 'flex flex-col gap-5', | |
| children: [ | |
| Style( | |
| 'flex flex-row items-center justify-between', | |
| children: [ | |
| _IconBadge( | |
| icon: icon, | |
| classes: | |
| 'size-11 rounded-2xl bg-$tone-400/10 text-$tone-300 group-hover:bg-$tone-400/20', | |
| ), | |
| Style( | |
| 'rounded-full bg-emerald-400/10 px-3 py-1', | |
| child: _StyledText(delta, 'text-xs font-bold text-emerald-300'), | |
| ), | |
| ], | |
| ), | |
| Style( | |
| 'flex flex-col gap-1', | |
| children: [ | |
| _StyledText(title, 'text-sm text-slate-400'), | |
| _StyledText(value, 'text-3xl font-black text-white'), | |
| ], | |
| ), | |
| ], | |
| ), | |
| ); | |
| } | |
| } | |
| class _ChartBar extends StatelessWidget { | |
| const _ChartBar({required this.index, required this.value}); | |
| final int index; | |
| final int value; | |
| @override | |
| Widget build(BuildContext context) { | |
| final colors = [ | |
| 'from-cyan-400 to-blue-500', | |
| 'from-blue-400 to-fuchsia-500', | |
| 'from-emerald-400 to-cyan-500', | |
| ]; | |
| final height = value * 2; | |
| return Style( | |
| 'grow flex flex-col items-center justify-end gap-2', | |
| children: [ | |
| Style( | |
| 'w-full rounded-t-2xl bg-gradient-to-t ${colors[index % colors.length]} shadow-lg shadow-cyan-950/40 hover:opacity-80', | |
| child: SizedBox(height: height.toDouble()), | |
| ), | |
| _StyledText('${index + 1}', 'text-xs text-slate-500'), | |
| ], | |
| ); | |
| } | |
| } | |
| class _MissionRow extends StatelessWidget { | |
| const _MissionRow({ | |
| required this.label, | |
| required this.meta, | |
| required this.progress, | |
| required this.tone, | |
| }); | |
| final String label; | |
| final String meta; | |
| final String progress; | |
| final String tone; | |
| @override | |
| Widget build(BuildContext context) { | |
| return Style( | |
| 'flex flex-col gap-3 rounded-2xl border border-white/10 bg-slate-950/60 p-4', | |
| children: [ | |
| Style( | |
| 'flex flex-row items-center justify-between gap-3', | |
| children: [ | |
| Style( | |
| 'flex flex-col', | |
| children: [ | |
| _StyledText(label, 'font-bold text-white'), | |
| _StyledText(meta, 'text-sm text-slate-400'), | |
| ], | |
| ), | |
| Style( | |
| 'size-9 rounded-xl bg-$tone-400/10 text-$tone-300 flex items-center justify-center', | |
| child: const Icon(Icons.arrow_forward, size: 18), | |
| ), | |
| ], | |
| ), | |
| Style( | |
| 'h-2 overflow-hidden rounded-full bg-white/10', | |
| child: Style( | |
| 'h-full $progress rounded-full bg-$tone-400', | |
| child: const SizedBox(), | |
| ), | |
| ), | |
| ], | |
| ); | |
| } | |
| } | |
| class _RiskRow extends StatelessWidget { | |
| const _RiskRow({ | |
| required this.label, | |
| required this.level, | |
| required this.value, | |
| }); | |
| final String label; | |
| final String level; | |
| final String value; | |
| @override | |
| Widget build(BuildContext context) { | |
| return Style( | |
| 'flex flex-col gap-2', | |
| children: [ | |
| Style( | |
| 'flex flex-row items-center justify-between', | |
| children: [ | |
| _StyledText(label, 'text-sm font-semibold text-slate-200'), | |
| _StyledText(level, 'text-xs font-bold uppercase text-cyan-300'), | |
| ], | |
| ), | |
| Style( | |
| 'h-2 overflow-hidden rounded-full bg-white/10', | |
| child: Style( | |
| 'h-full $value rounded-full bg-gradient-to-r from-cyan-400 to-blue-500', | |
| child: const SizedBox(), | |
| ), | |
| ), | |
| ], | |
| ); | |
| } | |
| } | |
| class _InlineStat extends StatelessWidget { | |
| const _InlineStat({required this.label, required this.value}); | |
| final String label; | |
| final String value; | |
| @override | |
| Widget build(BuildContext context) { | |
| return Style( | |
| 'rounded-2xl border border-white/10 bg-white/5 p-4', | |
| child: Style( | |
| 'flex flex-col gap-1', | |
| children: [ | |
| _StyledText(label, 'text-sm text-slate-400'), | |
| _StyledText(value, 'text-xl font-black text-white'), | |
| ], | |
| ), | |
| ); | |
| } | |
| } | |
| class _SectionHeader extends StatelessWidget { | |
| const _SectionHeader({ | |
| required this.title, | |
| required this.subtitle, | |
| required this.icon, | |
| }); | |
| final String title; | |
| final String subtitle; | |
| final IconData icon; | |
| @override | |
| Widget build(BuildContext context) { | |
| return Style( | |
| 'flex flex-row items-center justify-between', | |
| children: [ | |
| Style( | |
| 'flex flex-col', | |
| children: [ | |
| _StyledText(title, 'text-xl font-black text-white'), | |
| _StyledText(subtitle, 'text-sm text-slate-400'), | |
| ], | |
| ), | |
| _IconBadge( | |
| icon: icon, | |
| classes: 'size-10 rounded-xl bg-white/10 text-cyan-300', | |
| ), | |
| ], | |
| ); | |
| } | |
| } | |
| class _SignalStrip extends StatelessWidget { | |
| const _SignalStrip(); | |
| @override | |
| Widget build(BuildContext context) { | |
| return Style( | |
| 'grid grid-cols-3 gap-3 pt-2', | |
| children: const [ | |
| _InlineStat(label: 'Regions', value: '12'), | |
| _InlineStat(label: 'Signals', value: '8.2M'), | |
| _InlineStat(label: 'SLO', value: '99.9'), | |
| ], | |
| ); | |
| } | |
| } | |
| class _CtaButton extends StatelessWidget { | |
| const _CtaButton({ | |
| required this.label, | |
| required this.icon, | |
| required this.classes, | |
| }); | |
| final String label; | |
| final IconData icon; | |
| final String classes; | |
| @override | |
| Widget build(BuildContext context) { | |
| return Style( | |
| 'cursor-pointer select-none rounded-2xl px-5 py-3 font-bold transition-all duration-300 hover:-translate-y-0.5 $classes', | |
| child: Style( | |
| 'flex flex-row items-center gap-2', | |
| children: [Icon(icon, size: 18), Text(label)], | |
| ), | |
| ); | |
| } | |
| } | |
| class _IconBadge extends StatelessWidget { | |
| const _IconBadge({required this.icon, required this.classes}); | |
| final IconData icon; | |
| final String classes; | |
| @override | |
| Widget build(BuildContext context) { | |
| return Style( | |
| '$classes flex items-center justify-center', | |
| child: Icon(icon, size: 22), | |
| ); | |
| } | |
| } | |
| class _Pill extends StatelessWidget { | |
| const _Pill({required this.label, required this.icon, this.active = false}); | |
| final String label; | |
| final IconData icon; | |
| final bool active; | |
| @override | |
| Widget build(BuildContext context) { | |
| final classes = active | |
| ? 'border-cyan-300/30 bg-cyan-400/10 text-cyan-200' | |
| : 'border-white/10 bg-white/5 text-slate-300 hover:bg-white/10'; | |
| return Style( | |
| 'rounded-full border px-3 py-2 text-sm font-semibold $classes', | |
| child: Style( | |
| 'flex flex-row items-center gap-2', | |
| children: [Icon(icon, size: 16), Text(label)], | |
| ), | |
| ); | |
| } | |
| } | |
| class _StatusDot extends StatelessWidget { | |
| const _StatusDot({required this.label, this.tone = 'cyan'}); | |
| final String label; | |
| final String tone; | |
| @override | |
| Widget build(BuildContext context) { | |
| return Style( | |
| 'rounded-full border border-$tone-300/20 bg-$tone-400/10 px-3 py-1.5 text-$tone-200', | |
| child: Style( | |
| 'flex flex-row items-center gap-2', | |
| children: [ | |
| Style( | |
| 'size-2 rounded-full bg-$tone-300 shadow-lg shadow-$tone-300/40', | |
| child: const SizedBox(), | |
| ), | |
| _StyledText(label, 'text-xs font-bold uppercase tracking-wide'), | |
| ], | |
| ), | |
| ); | |
| } | |
| } | |
| class _OrbitNode extends StatelessWidget { | |
| const _OrbitNode({required this.label, required this.classes}); | |
| final String label; | |
| final String classes; | |
| @override | |
| Widget build(BuildContext context) { | |
| return Style( | |
| '$classes size-12 rounded-2xl flex items-center justify-center text-xs font-black shadow-lg', | |
| child: Text(label), | |
| ); | |
| } | |
| } | |
| class _StyledText extends StatelessWidget { | |
| const _StyledText(this.text, this.classes); | |
| final String text; | |
| final String classes; | |
| @override | |
| Widget build(BuildContext context) { | |
| return Style(classes, child: Text(text)); | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment