rtl_ui_guard 0.1.0
rtl_ui_guard: ^0.1.0 copied to clipboard
A lightweight Flutter toolkit for previewing, testing, and diagnosing Arabic, Kurdish Sorani, and other RTL user interfaces.
import 'package:flutter/material.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:rtl_ui_guard/rtl_ui_guard.dart';
void main() => runApp(const GuardExampleApp());
class GuardExampleApp extends StatefulWidget {
const GuardExampleApp({super.key});
@override
State<GuardExampleApp> createState() => _GuardExampleAppState();
}
class _GuardExampleAppState extends State<GuardExampleApp> {
late final RtlUiGuardController _controller;
@override
void initState() {
super.initState();
_controller = RtlUiGuardController(
supportedLocales: RtlGuardLocale.commonLocales,
);
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return ListenableBuilder(
listenable: _controller,
builder: (BuildContext context, Widget? child) {
return MaterialApp(
debugShowCheckedModeBanner: false,
locale: _controller.locale,
supportedLocales: _controller.supportedLocales,
localizationsDelegates: GlobalMaterialLocalizations.delegates,
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(
seedColor: const Color(0xFF1B6B5B),
brightness: Brightness.light,
),
useMaterial3: true,
),
darkTheme: ThemeData(
colorScheme: ColorScheme.fromSeed(
seedColor: const Color(0xFF52C7A5),
brightness: Brightness.dark,
),
useMaterial3: true,
),
builder: (BuildContext context, Widget? child) => RtlUiGuard(
controller: _controller,
child: child ?? const SizedBox.shrink(),
),
home: _Dashboard(locale: _controller.locale),
);
},
);
}
}
class _Dashboard extends StatelessWidget {
const _Dashboard({required this.locale});
final Locale locale;
@override
Widget build(BuildContext context) {
final copy = _Copy.forLocale(locale);
return Scaffold(
appBar: AppBar(
title: Text(copy.title),
actions: <Widget>[
IconButton(
tooltip: copy.notifications,
onPressed: () {},
icon: const Badge(child: Icon(Icons.notifications_outlined)),
),
const SizedBox(width: 12),
],
),
body: LayoutBuilder(
builder: (BuildContext context, BoxConstraints constraints) {
final columns = constraints.maxWidth >= 900
? 4
: constraints.maxWidth >= 600
? 2
: 1;
return GridView.count(
padding: const EdgeInsets.all(24),
crossAxisCount: columns,
mainAxisSpacing: 16,
crossAxisSpacing: 16,
childAspectRatio: columns == 1 ? 2.6 : 1.7,
children: <Widget>[
_MetricCard(
label: copy.meetings,
value: '24',
icon: Icons.groups_2_outlined,
),
_MetricCard(
label: copy.correspondence,
value: '138',
icon: Icons.mark_email_unread_outlined,
),
_MetricCard(
label: copy.followUps,
value: '17',
icon: Icons.task_alt_outlined,
),
_MetricCard(
label: copy.committees,
value: '9',
icon: Icons.account_balance_outlined,
),
],
);
},
),
);
}
}
class _MetricCard extends StatelessWidget {
const _MetricCard({
required this.label,
required this.value,
required this.icon,
});
final String label;
final String value;
final IconData icon;
@override
Widget build(BuildContext context) {
final colorScheme = Theme.of(context).colorScheme;
return Card(
clipBehavior: Clip.antiAlias,
child: Padding(
padding: const EdgeInsets.all(20),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Icon(icon, color: colorScheme.primary, size: 30),
const Spacer(),
Text(value, style: Theme.of(context).textTheme.headlineMedium),
const SizedBox(height: 4),
Text(
label,
maxLines: 2,
overflow: TextOverflow.ellipsis,
style: Theme.of(context).textTheme.titleMedium,
),
],
),
),
);
}
}
class _Copy {
const _Copy({
required this.title,
required this.notifications,
required this.meetings,
required this.correspondence,
required this.followUps,
required this.committees,
});
factory _Copy.forLocale(Locale locale) {
return switch (locale.languageCode) {
'ar' => const _Copy(
title: 'إدارة العلاقات الحكومية',
notifications: 'الإشعارات',
meetings: 'الاجتماعات الرسمية',
correspondence: 'المراسلات',
followUps: 'المتابعات',
committees: 'اللجان',
),
'ckb' => const _Copy(
title: 'بەڕێوەبردنی پەیوەندییە حکومییەکان',
notifications: 'ئاگادارکردنەوەکان',
meetings: 'کۆبوونەوە فەرمییەکان',
correspondence: 'نامە فەرمییەکان',
followUps: 'بەدواداچوونەکان',
committees: 'لیژنەکان',
),
_ => const _Copy(
title: 'Government Relations',
notifications: 'Notifications',
meetings: 'Official meetings',
correspondence: 'Correspondence',
followUps: 'Follow-ups',
committees: 'Committees',
),
};
}
final String title;
final String notifications;
final String meetings;
final String correspondence;
final String followUps;
final String committees;
}