rtl_ui_guard 0.1.0 copy "rtl_ui_guard: ^0.1.0" to clipboard
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.

example/lib/main.dart

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;
}
2
likes
160
points
85
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

A lightweight Flutter toolkit for previewing, testing, and diagnosing Arabic, Kurdish Sorani, and other RTL user interfaces.

Repository (GitHub)
View/report issues
Contributing

Topics

#rtl #localization #diagnostics #arabic #testing

License

MIT (license)

Dependencies

flutter

More

Packages that depend on rtl_ui_guard