geniuslink_design_system 1.0.1 copy "geniuslink_design_system: ^1.0.1" to clipboard
geniuslink_design_system: ^1.0.1 copied to clipboard

A Flutter design-system package for GeniusLink browser-style workspace tabs, previews, menus, and RTL-ready navigation.

example/lib/main.dart

// ignore_for_file: deprecated_member_use

// ============================================================
// GeniusLink — BrowserStyleTabBar example app.
// A realistic embed: a workspace shell (nav rail + window chrome) hosting
// the tab strip, plus the full component gallery. Toggle dark/light.
//
// The component is self-contained — it only needs its own
// `BrowserStyleTabBarThemeData` registered on the app theme (see _appTheme).
//
//   Run:  cd flutter/example && flutter pub get && flutter run -d chrome
// ============================================================

import 'package:flutter/material.dart';
import 'package:geniuslink_design_system/geniuslink_design_system.dart';
import 'browser_tabs_demo.dart';

void main() => runApp(const ExampleApp());

/// Builds an app ThemeData that registers the component's ThemeExtension.
/// That single extension carries everything BrowserStyleTabBar paints with.
ThemeData _appTheme(Brightness b) {
  final ext = b == Brightness.dark
      ? BrowserStyleTabBarThemeData.dark
      : BrowserStyleTabBarThemeData.light;
  return ThemeData(
    brightness: b,
    useMaterial3: true,
    scaffoldBackgroundColor: ext.bg,
    fontFamily: BrowserStyleTabBarThemeData.bodyFont,
    extensions: [ext],
  );
}

class ExampleApp extends StatefulWidget {
  const ExampleApp({super.key});
  @override
  State<ExampleApp> createState() => _ExampleAppState();
}

class _ExampleAppState extends State<ExampleApp> {
  bool _light = false;
  int _screen = 0; // 0 = workspace, 1 = gallery

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'GeniusLink · Example',
      debugShowCheckedModeBanner: false,
      theme: _appTheme(Brightness.light),
      darkTheme: _appTheme(Brightness.dark),
      themeMode: _light ? ThemeMode.light : ThemeMode.dark,
      supportedLocales: const [Locale('en'), Locale('ar')],
      home: _screen == 1
          // The documentation gallery (moved into this example).
          ? BrowserTabsDemo(
              light: _light, onToggleTheme: (v) => setState(() => _light = v))
          // A realistic product shell embedding the component.
          : WorkspaceScreen(
              light: _light,
              onToggleTheme: (v) => setState(() => _light = v),
              onOpenGallery: () => setState(() => _screen = 1),
            ),
    );
  }
}

// ════════════════════════════════════════════════════════════
// WORKSPACE SHELL — nav rail + window chrome + BrowserStyleTabBar
// ════════════════════════════════════════════════════════════
class WorkspaceScreen extends StatefulWidget {
  final bool light;
  final ValueChanged<bool> onToggleTheme;
  final VoidCallback onOpenGallery;
  const WorkspaceScreen(
      {super.key,
      required this.light,
      required this.onToggleTheme,
      required this.onOpenGallery});
  @override
  State<WorkspaceScreen> createState() => _WorkspaceScreenState();
}

class _WorkspaceScreenState extends State<WorkspaceScreen> {
  int _nav = 0;

  @override
  Widget build(BuildContext context) {
    final s = BrowserStyleTabBarThemeData.of(context);
    return Scaffold(
      backgroundColor: s.bg,
      body: SafeArea(
        child: Row(
          children: [
            _NavRail(
              selected: _nav,
              onSelect: (i) => setState(() => _nav = i),
              light: widget.light,
              onToggleTheme: widget.onToggleTheme,
              onOpenGallery: widget.onOpenGallery,
            ),
            Expanded(
              child: Padding(
                padding: const EdgeInsets.fromLTRB(28, 24, 28, 28),
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    // top bar
                    Row(
                      children: [
                        Text('Workspace',
                            style: TextStyle(
                                fontFamily:
                                    BrowserStyleTabBarThemeData.displayFont,
                                fontSize: 24,
                                fontWeight: FontWeight.w800,
                                letterSpacing: -0.6,
                                color: s.fg1)),
                        const SizedBox(width: 12),
                        const _Pill('GeniusLink Co.'),
                        const Spacer(),
                        const _AvatarChip(
                            name: 'Mohammed Nasser', role: 'Accountant'),
                      ],
                    ),
                    const SizedBox(height: 20),
                    // window chrome hosting the component
                    const Expanded(child: _Window(child: BrowserStyleTabBar())),
                  ],
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

// ── left navigation rail ──
class _NavRail extends StatelessWidget {
  final int selected;
  final ValueChanged<int> onSelect;
  final bool light;
  final ValueChanged<bool> onToggleTheme;
  final VoidCallback onOpenGallery;
  const _NavRail({
    required this.selected,
    required this.onSelect,
    required this.light,
    required this.onToggleTheme,
    required this.onOpenGallery,
  });

  static const _items = [
    (Icons.dashboard_outlined, 'Overview'),
    (Icons.menu_book_outlined, 'Ledger'),
    (Icons.storefront_outlined, 'Branches'),
    (Icons.bar_chart_rounded, 'Reports'),
    (Icons.people_alt_outlined, 'People'),
  ];

  @override
  Widget build(BuildContext context) {
    final s = BrowserStyleTabBarThemeData.of(context);
    return Container(
      width: 76,
      decoration: BoxDecoration(
        color: s.surface,
        border: Border(right: BorderSide(color: s.border)),
      ),
      child: Column(
        children: [
          const SizedBox(height: 18),
          // brand mark
          Container(
            width: 38,
            height: 38,
            alignment: Alignment.center,
            decoration: BoxDecoration(
                color: BrowserStyleTabBarThemeData.accent,
                borderRadius: BorderRadius.circular(
                    BrowserStyleTabBarThemeData.radiusMd)),
            child: const Text('G',
                style: TextStyle(
                    fontFamily: BrowserStyleTabBarThemeData.displayFont,
                    fontSize: 20,
                    fontWeight: FontWeight.w800,
                    color: Colors.white)),
          ),
          const SizedBox(height: 22),
          for (int i = 0; i < _items.length; i++)
            _RailItem(
                icon: _items[i].$1,
                label: _items[i].$2,
                selected: i == selected,
                onTap: () => onSelect(i)),
          const Spacer(),
          _RailItem(
              icon: Icons.widgets_outlined,
              label: 'Gallery',
              selected: false,
              onTap: onOpenGallery),
          _RailItem(
            icon: light ? Icons.dark_mode_outlined : Icons.light_mode_outlined,
            label: light ? 'Dark' : 'Light',
            selected: false,
            onTap: () => onToggleTheme(!light),
          ),
          const SizedBox(height: 14),
        ],
      ),
    );
  }
}

class _RailItem extends StatefulWidget {
  final IconData icon;
  final String label;
  final bool selected;
  final VoidCallback onTap;
  const _RailItem(
      {required this.icon,
      required this.label,
      required this.selected,
      required this.onTap});
  @override
  State<_RailItem> createState() => _RailItemState();
}

class _RailItemState extends State<_RailItem> {
  bool _hover = false;
  @override
  Widget build(BuildContext context) {
    final s = BrowserStyleTabBarThemeData.of(context);
    final on = widget.selected;
    final color =
        on ? BrowserStyleTabBarThemeData.accent : (_hover ? s.fg1 : s.fg3);
    return Tooltip(
      message: widget.label,
      waitDuration: const Duration(milliseconds: 400),
      child: MouseRegion(
        cursor: SystemMouseCursors.click,
        onEnter: (_) => setState(() => _hover = true),
        onExit: (_) => setState(() => _hover = false),
        child: GestureDetector(
          onTap: widget.onTap,
          child: Container(
            width: 48,
            height: 44,
            margin: const EdgeInsets.symmetric(vertical: 4),
            decoration: BoxDecoration(
              color: on
                  ? BrowserStyleTabBarThemeData.accent.withOpacity(0.12)
                  : (_hover ? s.hover : Colors.transparent),
              borderRadius:
                  BorderRadius.circular(BrowserStyleTabBarThemeData.radiusMd),
            ),
            child: Icon(widget.icon, size: 21, color: color),
          ),
        ),
      ),
    );
  }
}

// ── faux app-window chrome around the component ──
class _Window extends StatelessWidget {
  final Widget child;
  const _Window({required this.child});
  @override
  Widget build(BuildContext context) {
    final s = BrowserStyleTabBarThemeData.of(context);
    return Container(
      decoration: BoxDecoration(
        color: s.bg,
        border: Border.all(color: s.border),
        borderRadius:
            BorderRadius.circular(BrowserStyleTabBarThemeData.radiusXl),
        boxShadow: BrowserStyleTabBarThemeData.cardShadow,
      ),
      clipBehavior: Clip.antiAlias,
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          // title bar (traffic lights + address)
          Container(
            height: 40,
            padding: const EdgeInsets.symmetric(horizontal: 14),
            decoration: BoxDecoration(
                border: Border(bottom: BorderSide(color: s.border))),
            child: Row(
              children: [
                _dot(const Color(0xFFEF4444)),
                const SizedBox(width: 7),
                _dot(const Color(0xFFF59E0B)),
                const SizedBox(width: 7),
                _dot(const Color(0xFF22C55E)),
                const SizedBox(width: 16),
                Expanded(
                  child: Container(
                    height: 24,
                    alignment: Alignment.center,
                    decoration: BoxDecoration(
                        color: s.surface,
                        borderRadius: BorderRadius.circular(
                            BrowserStyleTabBarThemeData.radiusSm)),
                    child: Text('app.geniuslink.co / workspace',
                        style: TextStyle(
                            fontFamily: BrowserStyleTabBarThemeData.monoFont,
                            fontSize: 11.5,
                            color: s.fg3)),
                  ),
                ),
                const SizedBox(width: 60),
              ],
            ),
          ),
          // the component embeds directly under the chrome
          Expanded(
            child: SingleChildScrollView(
              padding: const EdgeInsets.all(20),
              child: child,
            ),
          ),
        ],
      ),
    );
  }

  Widget _dot(Color c) => Container(
      width: 11,
      height: 11,
      decoration: BoxDecoration(color: c, shape: BoxShape.circle));
}

// ── small shared bits ──
class _Pill extends StatelessWidget {
  final String text;
  const _Pill(this.text);
  @override
  Widget build(BuildContext context) {
    return Container(
      padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 4),
      decoration: BoxDecoration(
          color: BrowserStyleTabBarThemeData.accent.withOpacity(0.14),
          borderRadius: BorderRadius.circular(999)),
      child: Text(text,
          style: const TextStyle(
              fontFamily: BrowserStyleTabBarThemeData.bodyFont,
              fontSize: 11.5,
              fontWeight: FontWeight.w700,
              color: BrowserStyleTabBarThemeData.accent)),
    );
  }
}

class _AvatarChip extends StatelessWidget {
  final String name, role;
  const _AvatarChip({required this.name, required this.role});
  @override
  Widget build(BuildContext context) {
    final s = BrowserStyleTabBarThemeData.of(context);
    final initials = name
        .split(' ')
        .where((w) => w.isNotEmpty)
        .take(2)
        .map((w) => w[0])
        .join();
    return Row(
      children: [
        Column(
          crossAxisAlignment: CrossAxisAlignment.end,
          children: [
            Text(name,
                style: TextStyle(
                    fontFamily: BrowserStyleTabBarThemeData.bodyFont,
                    fontSize: 13,
                    fontWeight: FontWeight.w600,
                    color: s.fg1)),
            Text(role,
                style: TextStyle(
                    fontFamily: BrowserStyleTabBarThemeData.bodyFont,
                    fontSize: 11.5,
                    color: s.fg3)),
          ],
        ),
        const SizedBox(width: 10),
        Container(
          width: 36,
          height: 36,
          alignment: Alignment.center,
          decoration: BoxDecoration(
              color: const HSLColor.fromAHSL(1, 250, 0.42, 0.40).toColor(),
              shape: BoxShape.circle),
          child: Text(initials,
              style: const TextStyle(
                  fontFamily: BrowserStyleTabBarThemeData.displayFont,
                  fontSize: 13,
                  fontWeight: FontWeight.w700,
                  color: Colors.white)),
        ),
      ],
    );
  }
}
0
likes
0
points
387
downloads

Publisher

unverified uploader

Weekly Downloads

A Flutter design-system package for GeniusLink browser-style workspace tabs, previews, menus, and RTL-ready navigation.

Repository (GitHub)
View/report issues

Topics

#design-system #flutter-widget #navigation #tabs

License

unknown (license)

Dependencies

flutter

More

Packages that depend on geniuslink_design_system