kin_ui 1.2.0 copy "kin_ui: ^1.2.0" to clipboard
kin_ui: ^1.2.0 copied to clipboard

A Native inspired Flutter design system. Tokens, primitives, components, adaptive shell, and templates out of the box.

example/main.dart

import 'package:flutter/material.dart';
import 'package:kin_ui/kin_ui.dart';

// ── Custom themes ────────────────────────────────────────────────
const _lightTheme = KinTheme(
  primary: Color(0xFF6C63FF),
  primaryContainer: Color(0xFFE8E6FF),
  surface: Color(0xFFF5F5F0),
  surfaceVariant: Color(0xFFFFFFFF),
  onSurface: Color(0xFF1C1C1E),
  onSurfaceVariant: Color(0xFF8E8E93),
  outline: Color(0xFFE0E0E0),
  destructive: Color(0xFFFF453A),
);

const _darkTheme = KinTheme(
  primary: Color(0xFF6C63FF),
  primaryContainer: Color(0xFF3D35A3),
  surface: Color(0xFF1C1C1E),
  surfaceVariant: Color(0xFF2C2C2E),
  onSurface: Color(0xFFFFFFFF),
  onSurfaceVariant: Color(0xFF8E8E93),
  outline: Color(0xFF3A3A3C),
  destructive: Color(0xFFFF453A),
);

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

class ExampleApp extends StatelessWidget {
  const ExampleApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        useMaterial3: true,
        brightness: Brightness.light,
        scaffoldBackgroundColor: _lightTheme.surface,
        colorScheme: ColorScheme.light(
          primary: _lightTheme.primary,
          surface: _lightTheme.surface,
          onSurface: _lightTheme.onSurface,
          error: _lightTheme.destructive,
          outline: _lightTheme.outline,
        ),
        extensions: const [_lightTheme],
      ),
      darkTheme: ThemeData(
        useMaterial3: true,
        brightness: Brightness.dark,
        scaffoldBackgroundColor: _darkTheme.surface,
        colorScheme: ColorScheme.dark(
          primary: _darkTheme.primary,
          surface: _darkTheme.surface,
          onSurface: _darkTheme.onSurface,
          error: _darkTheme.destructive,
          outline: _darkTheme.outline,
        ),
        extensions: const [_darkTheme],
      ),
      home: const KinApp(child: _Home()),
    );
  }
}

class _Home extends StatefulWidget {
  const _Home();

  @override
  State<_Home> createState() => _HomeState();
}

class _HomeState extends State<_Home> {
  Color _pickedColor = const Color(0xFF6C63FF);
  int _rating = 0;
  double _sliderValue = 0.5;
  int _sortCol = 0;
  KinSortDirection _sortDir = KinSortDirection.ascending;
  KinAIOrbState _orbState = KinAIOrbState.idle;

  // Chart data
  final _barEntries = const [
    KinChartEntry(label: 'Mon', value: 40),
    KinChartEntry(label: 'Tue', value: 70),
    KinChartEntry(label: 'Wed', value: 55),
    KinChartEntry(label: 'Thu', value: 90),
    KinChartEntry(label: 'Fri', value: 65),
    KinChartEntry(label: 'Sat', value: 30),
  ];

  final _lineEntries = const [
    KinChartEntry(label: 'Jan', value: 20),
    KinChartEntry(label: 'Feb', value: 45),
    KinChartEntry(label: 'Mar', value: 35),
    KinChartEntry(label: 'Apr', value: 80),
    KinChartEntry(label: 'May', value: 60),
    KinChartEntry(label: 'Jun', value: 95),
  ];

  final _pieEntries = const [
    KinChartEntry(label: 'Design', value: 35),
    KinChartEntry(label: 'Dev', value: 45),
    KinChartEntry(label: 'Testing', value: 20),
  ];

  @override
  Widget build(BuildContext context) {
    final theme = KinTheme.of(context);
    return Scaffold(
      backgroundColor: theme.surface,
      body: SafeArea(
        child: ListView(
          padding: const EdgeInsets.all(KinSpacing.md),
          children: [
            KinText.titleLarge(
              'Kin UI Showcase',
              color: theme.onSurface,
            ),
            const SizedBox(height: KinSpacing.lg),

            // ── AI Gradient Section ──
            _sectionTitle(theme, 'AI Gradient'),
            const SizedBox(height: KinSpacing.sm),

            // Full-width card — touch to interact
            ClipRRect(
              borderRadius: BorderRadius.circular(16),
              child: SizedBox(
                height: 200,
                child: KinAIGradient(
                  mood: KinAIGradientMood.ember,
                  animation: KinAIGradientAnimation.orbit,
                  child: Center(
                    child: KinText.titleMedium(
                      'Touch & drag me',
                      color: const Color(0xCCFFFFFF),
                    ),
                  ),
                ),
              ),
            ),
            const SizedBox(height: KinSpacing.sm),

            // Row of different moods & form-factors
            SizedBox(
              height: 100,
              child: Row(
                spacing: KinSpacing.sm,
                children: [
                  Expanded(
                    child: KinAIGradient(
                      mood: KinAIGradientMood.flora,
                      animation: KinAIGradientAnimation.wave,
                      borderRadius: BorderRadius.circular(12),
                    ),
                  ),
                  Expanded(
                    child: KinAIGradient(
                      mood: KinAIGradientMood.nebula,
                      animation: KinAIGradientAnimation.breathe,
                      borderRadius: BorderRadius.circular(12),
                    ),
                  ),
                  Expanded(
                    child: KinAIGradient(
                      mood: KinAIGradientMood.solar,
                      animation: KinAIGradientAnimation.pulse,
                      borderRadius: BorderRadius.circular(12),
                    ),
                  ),
                ],
              ),
            ),
            const SizedBox(height: KinSpacing.sm),

            // Circle + pill shapes
            Row(
              spacing: KinSpacing.md,
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                const KinAIGradient(
                  mood: KinAIGradientMood.iridescent,
                  animation: KinAIGradientAnimation.shimmer,
                  shape: BoxShape.circle,
                  size: Size(72, 72),
                ),
                const KinAIGradient(
                  mood: KinAIGradientMood.mycelium,
                  animation: KinAIGradientAnimation.breathe,
                  shape: BoxShape.circle,
                  size: Size(72, 72),
                  speed: 1.5,
                ),
                const KinAIGradient(
                  mood: KinAIGradientMood.frost,
                  animation: KinAIGradientAnimation.orbit,
                  shape: BoxShape.circle,
                  size: Size(72, 72),
                ),
                KinAIGradient(
                  mood: KinAIGradientMood.abyss,
                  animation: KinAIGradientAnimation.wave,
                  borderRadius: BorderRadius.circular(20),
                  size: const Size(72, 72),
                ),
              ],
            ),
            const SizedBox(height: KinSpacing.lg),

            // ── AI Orb Section ──
            _sectionTitle(theme, 'AI Orb'),
            const SizedBox(height: KinSpacing.sm),

            // Orb states showcase
            Center(
              child: Column(
                children: [
                  KinAIOrb(
                    state: _orbState,
                    size: 96,
                    onTap: () {
                      const states = KinAIOrbState.values;
                      setState(() {
                        _orbState = states[
                            (states.indexOf(_orbState) + 1) % states.length];
                      });
                    },
                    label: _orbState.name[0].toUpperCase() +
                        _orbState.name.substring(1),
                  ),
                  const SizedBox(height: KinSpacing.sm),
                  KinText.labelSmall(
                    'Tap orb to cycle states',
                    color: theme.onSurfaceVariant,
                  ),
                ],
              ),
            ),
            const SizedBox(height: KinSpacing.sm),

            // Row of all states
            Wrap(
              spacing: KinSpacing.md,
              runSpacing: KinSpacing.md,
              alignment: WrapAlignment.center,
              children: KinAIOrbState.values
                  .map((s) => KinAIOrb(state: s, size: 48, label: s.name))
                  .toList(),
            ),
            const SizedBox(height: KinSpacing.lg),

            // ── Rich Text Editor Section ──
            _sectionTitle(theme, 'Rich Text Editor'),
            const SizedBox(height: KinSpacing.sm),

            KinRichEditor(
              placeholder: 'Write something beautiful…',
              minLines: 6,
            ),
            const SizedBox(height: KinSpacing.lg),

            // ── Charts Section ──
            _sectionTitle(theme, 'Charts'),
            const SizedBox(height: KinSpacing.sm),

            KinCard(
              child: Padding(
                padding: const EdgeInsets.all(KinSpacing.md),
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    KinText.titleMedium('Bar Chart', color: theme.onSurface),
                    const SizedBox(height: KinSpacing.sm),
                    KinChart.bar(
                      entries: _barEntries,
                      height: 160,
                      gridStyle: const KinChartGridStyle(dashed: true),
                      axisStyle: const KinChartAxisStyle(
                        showYAxisLabels: true,
                      ),
                    ),
                  ],
                ),
              ),
            ),
            const SizedBox(height: KinSpacing.md),

            KinCard(
              child: Padding(
                padding: const EdgeInsets.all(KinSpacing.md),
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    KinText.titleMedium(
                        'Line Chart (Smooth)', color: theme.onSurface),
                    const SizedBox(height: KinSpacing.sm),
                    KinChart.line(
                      entries: _lineEntries,
                      height: 160,
                      lineStyle: KinChartLineStyle.smooth,
                      axisStyle: const KinChartAxisStyle(
                        showYAxisLabels: true,
                        yAxisWidth: 36,
                      ),
                    ),
                  ],
                ),
              ),
            ),
            const SizedBox(height: KinSpacing.md),

            KinCard(
              child: Padding(
                padding: const EdgeInsets.all(KinSpacing.md),
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    KinText.titleMedium(
                        'Area Chart', color: theme.onSurface),
                    const SizedBox(height: KinSpacing.sm),
                    KinChart.area(
                      entries: _lineEntries,
                      height: 140,
                      lineStyle: KinChartLineStyle.smooth,
                    ),
                  ],
                ),
              ),
            ),
            const SizedBox(height: KinSpacing.md),

            KinCard(
              child: Padding(
                padding: const EdgeInsets.all(KinSpacing.md),
                child: Column(
                  children: [
                    KinText.titleMedium('Donut Chart', color: theme.onSurface),
                    const SizedBox(height: KinSpacing.sm),
                    KinChart.donut(
                      entries: _pieEntries,
                      height: 140,
                      donutCenter: KinText.bodyMedium(
                        '100%',
                        color: theme.onSurface,
                      ),
                      legendPosition: KinChartLegendPosition.bottom,
                    ),
                  ],
                ),
              ),
            ),
            const SizedBox(height: KinSpacing.md),

            KinCard(
              child: Padding(
                padding: const EdgeInsets.all(KinSpacing.md),
                child: Column(
                  children: [
                    KinText.titleMedium('Pie Chart', color: theme.onSurface),
                    const SizedBox(height: KinSpacing.sm),
                    KinChart.pie(
                      entries: _pieEntries,
                      height: 140,
                      legendPosition: KinChartLegendPosition.bottom,
                    ),
                  ],
                ),
              ),
            ),
            const SizedBox(height: KinSpacing.md),

            KinCard(
              child: Padding(
                padding: const EdgeInsets.all(KinSpacing.md),
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    KinText.titleMedium(
                        'Horizontal Bar', color: theme.onSurface),
                    const SizedBox(height: KinSpacing.sm),
                    KinChart.horizontalBar(
                      entries: const [
                        KinChartEntry(label: 'Flutter', value: 92),
                        KinChartEntry(label: 'React', value: 78),
                        KinChartEntry(label: 'Swift', value: 65),
                        KinChartEntry(label: 'Kotlin', value: 58),
                      ],
                      height: 160,
                    ),
                  ],
                ),
              ),
            ),
            const SizedBox(height: KinSpacing.lg),

            // ── Dialogs Section ──
            _sectionTitle(theme, 'Dialogs & Pickers'),
            const SizedBox(height: KinSpacing.sm),

            Wrap(
              spacing: KinSpacing.sm,
              runSpacing: KinSpacing.sm,
              children: [
                KinButton(
                  label: 'Color Picker',
                  variant: KinButtonVariant.secondary,
                  leading: Container(
                    width: 16,
                    height: 16,
                    decoration: BoxDecoration(
                      color: _pickedColor,
                      shape: BoxShape.circle,
                    ),
                  ),
                  onTap: () async {
                    final color = await KinColorPicker.show(
                      context: context,
                      initialColor: _pickedColor,
                      showOpacity: true,
                    );
                    if (color != null) {
                      setState(() => _pickedColor = color);
                    }
                  },
                ),
                KinButton(
                  label: 'Date Picker',
                  variant: KinButtonVariant.secondary,
                  onTap: () async {
                    final date = await KinDatePicker.show(context: context);
                    if (date != null && mounted) {
                      KinSnackbar.show(
                        context,
                        message:
                            'Selected: ${date.day}/${date.month}/${date.year}',
                      );
                    }
                  },
                ),
                KinButton(
                  label: 'Time Picker',
                  variant: KinButtonVariant.secondary,
                  onTap: () async {
                    final time = await KinTimePicker.show(context: context);
                    if (time != null && mounted) {
                      KinSnackbar.show(
                        context,
                        message: 'Selected: ${time.format(context)}',
                      );
                    }
                  },
                ),
                KinButton(
                  label: 'Dialog',
                  variant: KinButtonVariant.secondary,
                  onTap: () {
                    KinDialog.show(
                      context: context,
                      title: 'Confirm Action',
                      message: 'Are you sure you want to proceed?',
                      confirmLabel: 'Yes',
                      cancelLabel: 'No',
                    );
                  },
                ),
                KinButton(
                  label: 'Rate  ⭐ $_rating',
                  variant: KinButtonVariant.secondary,
                  onTap: () async {
                    final result = await KinRatingPicker.show(
                      context: context,
                      title: 'How was your experience?',
                      initialRating: _rating,
                    );
                    if (result != null) {
                      setState(() => _rating = result);
                    }
                  },
                ),
              ],
            ),
            const SizedBox(height: KinSpacing.lg),

            // ── Slider Section ──
            _sectionTitle(theme, 'Slider'),
            const SizedBox(height: KinSpacing.sm),

            KinCard(
              child: Padding(
                padding: const EdgeInsets.all(KinSpacing.md),
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Row(
                      mainAxisAlignment: MainAxisAlignment.spaceBetween,
                      children: [
                        KinText.bodyMedium('Volume',
                            color: theme.onSurface),
                        KinText.bodyMedium(
                          '${(_sliderValue * 100).round()}%',
                          color: theme.onSurfaceVariant,
                        ),
                      ],
                    ),
                    const SizedBox(height: KinSpacing.sm),
                    KinSlider(
                      value: _sliderValue,
                      onChanged: (v) => setState(() => _sliderValue = v),
                    ),
                  ],
                ),
              ),
            ),
            const SizedBox(height: KinSpacing.lg),

            // ── Multi-series Chart ──
            _sectionTitle(theme, 'Multi-Series Line Chart'),
            const SizedBox(height: KinSpacing.sm),

            KinCard(
              child: Padding(
                padding: const EdgeInsets.all(KinSpacing.md),
                child: KinChart(
                  type: KinChartType.line,
                  series: [
                    KinChartSeries(
                      name: 'Revenue',
                      entries: const [
                        KinChartEntry(label: 'Q1', value: 30),
                        KinChartEntry(label: 'Q2', value: 55),
                        KinChartEntry(label: 'Q3', value: 45),
                        KinChartEntry(label: 'Q4', value: 80),
                      ],
                      lineStyle: KinChartLineStyle.smooth,
                      showArea: true,
                    ),
                    KinChartSeries(
                      name: 'Costs',
                      entries: const [
                        KinChartEntry(label: 'Q1', value: 20),
                        KinChartEntry(label: 'Q2', value: 35),
                        KinChartEntry(label: 'Q3', value: 40),
                        KinChartEntry(label: 'Q4', value: 50),
                      ],
                      lineStyle: KinChartLineStyle.smooth,
                      showArea: true,
                    ),
                  ],
                  entries: const [
                    KinChartEntry(label: 'Q1', value: 80),
                    KinChartEntry(label: 'Q2', value: 55),
                    KinChartEntry(label: 'Q3', value: 45),
                    KinChartEntry(label: 'Q4', value: 80),
                  ],
                  height: 180,
                  showLabels: true,
                  axisStyle: const KinChartAxisStyle(showYAxisLabels: true),
                  gridStyle:
                      const KinChartGridStyle(dashed: true),
                ),
              ),
            ),

            const SizedBox(height: KinSpacing.lg),

            // ── Search Bar Section ──
            _sectionTitle(theme, 'Search Bar'),
            const SizedBox(height: KinSpacing.sm),

            KinSearchBar(
              hint: 'Search anything…',
              size: KinSearchBarSize.small,
              onChanged: (v) {},
            ),
            const SizedBox(height: KinSpacing.sm),
            KinSearchBar(
              hint: 'Medium search bar',
              size: KinSearchBarSize.medium,
              onChanged: (v) {},
            ),
            const SizedBox(height: KinSpacing.sm),
            KinSearchBar(
              hint: 'Large default',
              onChanged: (v) {},
            ),
            const SizedBox(height: KinSpacing.lg),

            // ── Data Table Section ──
            _sectionTitle(theme, 'Data Table'),
            const SizedBox(height: KinSpacing.sm),

            KinDataTable(
              sortColumnIndex: _sortCol,
              sortDirection: _sortDir,
              onSort: (i) {
                setState(() {
                  if (_sortCol == i) {
                    _sortDir = _sortDir == KinSortDirection.ascending
                        ? KinSortDirection.descending
                        : KinSortDirection.ascending;
                  } else {
                    _sortCol = i;
                    _sortDir = KinSortDirection.ascending;
                  }
                });
              },
              columns: const [
                KinDataColumn(label: 'Name', sortable: true, flex: 2),
                KinDataColumn(label: 'Role', flex: 2),
                KinDataColumn(label: 'Score', sortable: true, width: 70, alignment: Alignment.centerRight),
              ],
              rows: const [
                KinDataRow(cells: [KinDataCell.text('Alice'), KinDataCell.text('Designer'), KinDataCell.text('92')]),
                KinDataRow(cells: [KinDataCell.text('Bob'), KinDataCell.text('Developer'), KinDataCell.text('87')]),
                KinDataRow(cells: [KinDataCell.text('Charlie'), KinDataCell.text('PM'), KinDataCell.text('78')]),
                KinDataRow(cells: [KinDataCell.text('Diana'), KinDataCell.text('QA Lead'), KinDataCell.text('95')]),
                KinDataRow(cells: [KinDataCell.text('Eve'), KinDataCell.text('DevOps'), KinDataCell.text('83')]),
              ],
            ),

            const SizedBox(height: KinSpacing.xl),
          ],
        ),
      ),
    );
  }

  Widget _sectionTitle(KinTheme theme, String text) {
    return KinText.titleMedium(text, color: theme.onSurface);
  }
}
1
likes
0
points
31
downloads

Publisher

unverified uploader

Weekly Downloads

A Native inspired Flutter design system. Tokens, primitives, components, adaptive shell, and templates out of the box.

Repository (GitHub)
View/report issues

Topics

#ui #design-system #widget #theming

License

unknown (license)

Dependencies

crypto, flutter, flutter_svg, lucide_icons

More

Packages that depend on kin_ui