dacs 0.6.0 copy "dacs: ^0.6.0" to clipboard
dacs: ^0.6.0 copied to clipboard

Tailwind-like utility classes for Flutter. Apply text styles, padding, margins, colors, and borders via concise string expressions.

example/lib/main.dart

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

const dacsConfig = <String, Object?>{
  'theme': {
    'extend': {
      'colors': {
        'brand-primary': {'DEFAULT': '#0057B8', 'dark': '#8AB4F8'},
        'brand-on-primary': {'DEFAULT': '#FFFFFF', 'dark': '#0B1220'},
        'brand-surface': {'DEFAULT': '#F3F7FC', 'dark': '#111827'},
        'brand-muted': {'DEFAULT': '#6B7280', 'dark': '#CBD5E1'},
      },
      'spacing': {'content': '24', 'control': '12'},
      'borderRadius': {'card': '16', 'control': '10'},
      'boxShadow': {'floating': '0 8 24 rgba(0, 0, 0, 0.18)'},
      'screens': {'compact': '0', 'medium': '600', 'expanded': '840'},
      // DACS references font families; it does not bundle or load font files.
      // Register local fonts in pubspec.yaml or preload external fonts in the app
      // before using them here.
      'fontFamily': {'brand': 'Inter, Roboto, Arial, sans-serif'},
      'fontSize': {
        'body-copy': [
          '16',
          {'lineHeight': '24', 'letterSpacing': '0'},
        ],
      },
      'transitionDuration': {'standard': '200ms', 'short': '100ms'},
      'transitionTimingFunction': {'standard': 'cubic-bezier(0.2, 0, 0, 1)'},
      'motion': {
        'standard': 'duration-standard ease-standard',
        'fade-short': 'duration-short ease-out',
      },
      'typography': {
        'hero': 'font-brand text-2xl font-bold text-brand-primary',
        'body-copy': 'font-brand text-body-copy text-brand-muted',
        'label': 'font-brand text-sm font-medium tracking-wide',
      },
    },
  },
};

void main() {
  Dacs.configure(config: dacsConfig);
  runApp(const DacsExampleApp());
}

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'DACS Example',
      debugShowCheckedModeBanner: false,
      theme: ThemeData.light(useMaterial3: true),
      darkTheme: ThemeData.dark(useMaterial3: true),
      home: const HomePage(),
    );
  }
}

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

class _HomePageState extends State<HomePage>
    with SingleTickerProviderStateMixin {
  late final AnimationController _controller = AnimationController(
    vsync: this,
    duration: const Duration(seconds: 2),
  )..repeat(reverse: true);

  final _cardGroup = DacsStyle.apply('rounded-xl shadow-md p-4 bg-white');

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    final begin = DacsStyle()..opacity = 1;
    final end = DacsStyle()..opacity = 0.3;
    final animated = _controller.dAnimated(begin, end);

    return Scaffold(
      appBar: AppBar(title: const Text('DACS Example'), centerTitle: true),
      body: ListView(
        padding: 'p-4'.dPads,
        children: [
          SectionHeader(title: 'Text Styles'),
          Text('Heading 2xl', style: 'text-2xl font-bold text-gray-900'.dText),
          const SizedBox(height: 8),
          Text(
            'Body medium',
            style: 'text-base font-medium text-gray-600'.dText,
          ),
          const SizedBox(height: 8),
          Text('Small italic', style: 'text-sm italic text-sky-500'.dText),
          const SizedBox(height: 8),
          Text(
            'Underline decoration',
            style: 'text-lg underline decoration-wavy decoration-sky-500'.dText,
          ),

          SectionHeader(title: 'Theme Colors'),
          Container(
            padding: 'p-4'.dPads,
            decoration: 'bg-primaryContainer rounded-lg'.dBoxOf(context),
            child: Text(
              'Uses ColorScheme (primaryContainer)',
              style: 'text-onPrimaryContainer font-medium'.dTextOf(context),
            ),
          ),

          SectionHeader(title: 'Semantic Tokens'),
          Container(
            padding: 'p-content'.dPads,
            decoration:
                'bg-brand-surface rounded-card shadow-floating border border-brand-primary'
                    .dBoxOf(context),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Text(
                  'Configured design tokens',
                  style: 'type-hero'.dTextOf(context),
                ),
                const SizedBox(height: 8),
                Text(
                  'Colors, spacing, radius, shadow, font family, font size, and typography aliases come from Dacs.configure(config: ...).',
                  style: 'type-body-copy'.dTextOf(context),
                ),
                const SizedBox(height: 16),
                Wrap(
                  spacing: DacsStyle.apply('gap-control').gap ?? 12,
                  runSpacing: DacsStyle.apply('gap-control').gap ?? 12,
                  children: [
                    _tokenPill(context, 'bg-brand-primary'),
                    _tokenPill(context, 'rounded-card'),
                    _tokenPill(context, 'p-content'),
                    _tokenPill(context, 'font-brand'),
                    _tokenPill(context, 'text-body-copy'),
                  ],
                ),
              ],
            ),
          ),

          SectionHeader(title: 'Arbitrary Values'),
          Container(
            padding: 'p-4'.dPads,
            decoration: 'bg-[#ff00ff] rounded-[16]'.dBox,
            child: const Text(
              'Custom hex bg + 16px radius',
              style: TextStyle(
                color: Colors.white,
                fontWeight: FontWeight.bold,
              ),
            ),
          ),

          SectionHeader(title: 'Apply (Reusable Groups)'),
          Container(
            padding: 'p-4'.dPads,
            decoration: _cardGroup.toBoxDecoration(),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Text(
                  'Card style via apply()',
                  style: 'text-lg font-bold'.dText,
                ),
                const SizedBox(height: 4),
                Text(
                  'DacsStyle.apply("rounded-xl shadow-md p-4 bg-white")',
                  style: 'text-sm text-gray-500'.dText,
                ),
              ],
            ),
          ),

          SectionHeader(title: 'Gap & Flex Helpers'),
          Container(
            padding: 'p-4'.dPads,
            decoration: 'bg-gray-50 dark:bg-gray-800 rounded-lg'.dBoxOf(
              context,
            ),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Text(
                  'Flex row with gap-3',
                  style: 'text-sm font-medium text-gray-600 dark:text-gray-300'
                      .dTextOf(context),
                ),
                const SizedBox(height: 8),
                Row(
                  spacing: DacsStyle.apply('gap-3').gap ?? 12,
                  children: [1, 2, 3].map((i) {
                    return Container(
                      width: 60,
                      height: 60,
                      decoration: 'bg-primary rounded-lg'.dBoxOf(context),
                      child: Center(
                        child: Text(
                          '$i',
                          style: 'text-white font-bold text-xl'.dText,
                        ),
                      ),
                    );
                  }).toList(),
                ),
                const SizedBox(height: 12),
                Text(
                  'items-center + justify-between',
                  style: 'text-sm font-medium text-gray-600 dark:text-gray-300'
                      .dTextOf(context),
                ),
                const SizedBox(height: 8),
                Container(
                  padding: 'p-3'.dPads,
                  decoration: 'bg-white dark:bg-gray-700 rounded-lg'.dBoxOf(
                    context,
                  ),
                  child: Row(
                    mainAxisAlignment: MainAxisAlignment.spaceBetween,
                    crossAxisAlignment: CrossAxisAlignment.center,
                    children: [
                      Text('Left', style: 'font-medium'.dText),
                      Text('Center', style: 'text-gray-500'.dText),
                      Text('Right', style: 'font-medium'.dText),
                    ],
                  ),
                ),
              ],
            ),
          ),

          SectionHeader(title: 'Box Decoration'),
          Container(
            padding: 'p-4'.dPads,
            decoration:
                'bg-gradient-to-r from-sky-400 to-blue-600 rounded-xl shadow-lg'
                    .dBox,
            child: Text(
              'Gradient card',
              style: 'text-white font-bold text-lg'.dText,
            ),
          ),
          const SizedBox(height: 12),
          Container(
            padding: 'px-4 py-3'.dPads,
            decoration:
                'bg-white rounded-lg border border-gray-200 shadow-sm'.dBox,
            child: Text(
              'Bordered card with shadow',
              style: 'text-gray-700 text-base'.dText,
            ),
          ),

          SectionHeader(title: 'Material Widget Extensions'),
          ElevatedButton(
            style: 'bg-primary text-white rounded-lg'.dButton(context),
            onPressed: () {},
            child: const Text('Styled Button'),
          ),
          const SizedBox(height: 8),
          ElevatedButton(
            onPressed: () {},
            style: 'bg-primary text-white rounded-lg w-48'.dButton(context),
            child: const Text('Fixed width via w-48'),
          ),
          const SizedBox(height: 8),
          CheckboxTheme(
            data: 'checked:bg-primary unchecked:bg-surface'.dCheckbox(context),
            child: Checkbox(value: true, onChanged: (_) {}),
          ),

          SectionHeader(title: 'TextField InputDecoration'),
          TextField(
            style: 'text-onSurface'.dTextOf(context),
            decoration:
                ('label-[Email] hint-[you@example.com] '
                        'helper-[TextField.style handles typed text; '
                        'dInputOf handles decoration.] '
                        'filled dense bg-surface border-outline '
                        'focus:border-primary disabled:border-outlineVariant '
                        'error:border-error focus:error:border-primaryContainer '
                        'rounded-lg p-4')
                    .dInputOf(context),
          ),
          const SizedBox(height: 8),
          TextField(
            enabled: false,
            style: 'text-onSurfaceVariant'.dTextOf(context),
            decoration:
                'label-[Disabled] hint-[Native disabledBorder] filled dense '
                        'bg-surfaceVariant border-outline disabled:border-error '
                        'rounded-lg p-4'
                    .dInputOf(context),
          ),

          SectionHeader(title: 'Date / Time Picker Themes'),
          Theme(
            data: Theme.of(context).copyWith(
              datePickerTheme:
                  ('bg-surface text-onSurface rounded-lg shadow-md '
                          'date-header-bg-primary date-header-text-onPrimary '
                          'date-day-text-onSurface selected:date-day-bg-primary '
                          'hover:date-day-overlay-secondary '
                          'date-today-text-secondary date-divider-outline')
                      .dDatePicker(context),
              timePickerTheme:
                  ('bg-surface text-onSurface rounded-lg shadow-md p-4 '
                          'time-dial-bg-surfaceVariant time-dial-hand-primary '
                          'time-hour-minute-bg-surfaceVariant '
                          'selected:time-hour-minute-bg-secondary '
                          'time-hour-minute-text-onSurface '
                          'selected:time-hour-minute-text-onSecondary '
                          'time-separator-outline')
                      .dTimePicker(context),
            ),
            child: Wrap(
              spacing: 8,
              runSpacing: 8,
              children: [
                ElevatedButton(
                  style: 'bg-primary text-onPrimary rounded-lg'.dButton(
                    context,
                  ),
                  onPressed: () {
                    showDatePicker(
                      context: context,
                      firstDate: DateTime(2020),
                      lastDate: DateTime(2030),
                      initialDate: DateTime.now(),
                    );
                  },
                  child: const Text('Open date picker'),
                ),
                ElevatedButton(
                  style: 'bg-secondary text-onSecondary rounded-lg'.dButton(
                    context,
                  ),
                  onPressed: () {
                    showTimePicker(
                      context: context,
                      initialTime: TimeOfDay.now(),
                    );
                  },
                  child: const Text('Open time picker'),
                ),
              ],
            ),
          ),

          SectionHeader(title: 'Dark / Light Mode'),
          Container(
            padding: 'p-4'.dPads,
            decoration: 'bg-white dark:bg-gray-800 rounded-xl shadow'.dBoxOf(
              context,
            ),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Text(
                  'Toggle system theme to see variants in action.',
                  style: 'text-sm text-gray-500 dark:text-gray-400'.dTextOf(
                    context,
                  ),
                ),
                const SizedBox(height: 8),
                Text(
                  'Title',
                  style: 'text-xl font-bold text-gray-900 dark:text-white'
                      .dTextOf(context),
                ),
                const SizedBox(height: 4),
                Text(
                  'This text adapts to dark and light mode automatically.',
                  style: 'text-base text-gray-600 dark:text-gray-300'.dTextOf(
                    context,
                  ),
                ),
              ],
            ),
          ),

          SectionHeader(title: 'Accessibility Variants'),
          Container(
            padding: 'p-4'.dPads,
            decoration:
                ('bg-brand-surface border border-outline rounded-card '
                        'high-contrast:border-black high-contrast:border-4')
                    .dBoxOf(context),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Text(
                  'High contrast + reduced motion',
                  style: 'type-hero high-contrast:text-black'.dTextOf(context),
                ),
                const SizedBox(height: 8),
                Text(
                  'DACS reads MediaQuery.highContrast and disableAnimations for high-contrast:* and motion-* variants.',
                  style: 'type-body-copy'.dTextOf(context),
                ),
                const SizedBox(height: 12),
                ElevatedButton(
                  style:
                      ('bg-brand-primary text-brand-on-primary rounded-control '
                              'motion-standard motion-reduce:motion-fade-short '
                              'motion-disabled:motion-none')
                          .dButton(context),
                  onPressed: () {},
                  child: const Text('Motion-aware button'),
                ),
              ],
            ),
          ),

          SectionHeader(title: 'WidgetState & Chained Variants'),
          ElevatedButton(
            style:
                ('bg-primary hover:bg-primaryContainer '
                        'disabled:bg-surface '
                        'rounded-lg hover:rounded-xl')
                    .dButton(context),
            onPressed: () {},
            child: const Text('Hover shape: rounded-xl'),
          ),
          const SizedBox(height: 8),
          ElevatedButton(
            style: 'bg-primary dark:hover:bg-error'.dButton(context),
            onPressed: () {},
            child: const Text('Dark + Hover (chained)'),
          ),

          SectionHeader(title: 'Important (!)'),
          Text(
            'This ignores dark mode override',
            style: 'text-base text-red-500! dark:text-blue-300'.dTextOf(
              context,
            ),
          ),

          SectionHeader(title: 'Overflow'),
          Container(
            height: 60,
            decoration: 'bg-gray-100 dark:bg-gray-800 rounded-lg'.dBoxOf(
              context,
            ),
            child: Row(
              children: [
                Container(
                  width: 80,
                  height: 80,
                  decoration: 'bg-red-300 rounded'.dBox,
                  child: const Center(child: Text('Overflow')),
                ),
              ],
            ),
          ),

          SectionHeader(title: 'Responsive'),
          Container(
            padding: 'p-4'.dPads,
            decoration: 'bg-amber-50 dark:bg-amber-900 rounded-lg'.dBoxOf(
              context,
            ),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Text(
                  'Resize the window to see responsive variants.',
                  style: 'text-xs text-amber-800 dark:text-amber-200'.dTextOf(
                    context,
                  ),
                ),
                const SizedBox(height: 8),
                Text(
                  'Responsive heading',
                  style:
                      'text-base medium:text-xl expanded:text-2xl lg:text-3xl'
                          .dTextOf(context),
                ),
                const SizedBox(height: 4),
                Text(
                  'This text uses custom medium/expanded breakpoints.',
                  style: 'text-sm medium:text-base expanded:text-lg'.dTextOf(
                    context,
                  ),
                ),
              ],
            ),
          ),

          SectionHeader(title: 'Logical Spacing & Position'),
          Directionality(
            textDirection: TextDirection.rtl,
            child: Container(
              padding: 'ps-content pe-control py-3'.dPadsGeometry,
              decoration: 'bg-brand-surface rounded-card border-brand-primary'
                  .dBoxOf(context),
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  Text(
                    'RTL padding via ps/pe',
                    style: 'type-hero'.dTextOf(context),
                  ),
                  const SizedBox(height: 8),
                  Text(
                    'ps-content becomes right padding in RTL; pe-control becomes left padding.',
                    style: 'type-body-copy'.dTextOf(context),
                  ),
                  const SizedBox(height: 12),
                  SizedBox(
                    height: 56,
                    child: Stack(
                      children: [
                        Container(
                          decoration: 'bg-white rounded-control'.dBoxOf(
                            context,
                          ),
                        ),
                        Positioned.directional(
                          textDirection: TextDirection.rtl,
                          top: 'top-2 start-4'.dPositionDirectional.top,
                          start: 'top-2 start-4'.dPositionDirectional.start,
                          child: Container(
                            padding: 'px-control py-1'.dPads,
                            decoration: 'bg-brand-primary rounded-control'
                                .dBoxOf(context),
                            child: Text(
                              'start-4',
                              style: 'text-brand-on-primary text-sm'.dTextOf(
                                context,
                              ),
                            ),
                          ),
                        ),
                      ],
                    ),
                  ),
                ],
              ),
            ),
          ),

          SectionHeader(title: 'RTL Border Radius'),
          Wrap(
            spacing: 8,
            runSpacing: 8,
            children: [
              _radiusBox('rounded-ts-lg'),
              _radiusBox('rounded-te-lg'),
              _radiusBox('rounded-be-lg'),
              _radiusBox('rounded-bs-lg'),
            ],
          ),

          SectionHeader(title: 'Position (Stack)'),
          SizedBox(
            height: 100,
            child: Stack(
              children: [
                Container(decoration: 'bg-sky-100 rounded-lg'.dBox),
                Positioned(
                  left: 16,
                  top: 16,
                  child: Container(
                    padding: 'px-3 py-1'.dPads,
                    decoration: 'bg-sky-500 rounded'.dBox,
                    child: Text(
                      'top-4 left-4',
                      style: 'text-white text-xs font-medium'.dText,
                    ),
                  ),
                ),
                Positioned(
                  right: 16,
                  bottom: 16,
                  child: Container(
                    padding: 'px-3 py-1'.dPads,
                    decoration: 'bg-purple-500 rounded'.dBox,
                    child: Text(
                      'bottom-4 right-4',
                      style: 'text-white text-xs font-medium'.dText,
                    ),
                  ),
                ),
              ],
            ),
          ),

          SectionHeader(title: 'Transform'),
          Transform(
            transform: 'scale-125 rotate-12'.dTransform,
            child: Container(
              padding: 'px-4 py-2'.dPads,
              decoration: 'bg-green-500 rounded-lg'.dBox,
              child: Text(
                'Scaled & rotated',
                style: 'text-white font-bold'.dText,
              ),
            ),
          ),

          SectionHeader(title: 'Animated (pulsing opacity)'),
          AnimatedBuilder(
            animation: animated,
            builder: (context, child) {
              final s = animated.value;
              return Opacity(
                opacity: s.opacity ?? 1,
                child: Container(
                  padding: 'px-4 py-2'.dPads,
                  decoration: 'bg-purple-500 rounded-lg'.dBox,
                  child: const Text(
                    'Pulsing',
                    style: TextStyle(
                      color: Colors.white,
                      fontWeight: FontWeight.bold,
                    ),
                  ),
                ),
              );
            },
          ),

          SectionHeader(title: 'Shadows'),
          Wrap(
            spacing: 12,
            runSpacing: 12,
            children: ['shadow-sm', 'shadow', 'shadow-md', 'shadow-lg']
                .map(
                  (s) => Container(
                    width: 80,
                    height: 80,
                    decoration: 'bg-white $s rounded-lg'.dBox,
                    child: Center(child: Text(s, style: 'text-xs'.dText)),
                  ),
                )
                .toList(),
          ),

          const SizedBox(height: 24),
        ],
      ),
    );
  }

  Widget _radiusBox(String cls) {
    return Container(
      width: 80,
      height: 60,
      decoration: 'bg-teal-100 $cls border border-teal-300'.dBox,
      child: Center(
        child: Text(cls, style: 'text-[10px] text-teal-800 font-medium'.dText),
      ),
    );
  }

  Widget _tokenPill(BuildContext context, String label) {
    return Container(
      padding: 'px-control py-2'.dPads,
      decoration: 'bg-brand-primary rounded-control'.dBoxOf(context),
      child: Text(
        label,
        style: 'type-label text-brand-on-primary'.dTextOf(context),
      ),
    );
  }
}

class SectionHeader extends StatelessWidget {
  final String title;
  const SectionHeader({super.key, required this.title});

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.only(top: 24, bottom: 8),
      child: Text(
        title,
        style: 'text-lg font-bold text-gray-800 dark:text-gray-200'.dTextOf(
          context,
        ),
      ),
    );
  }
}
1
likes
150
points
233
downloads

Documentation

Documentation
API reference

Publisher

unverified uploader

Weekly Downloads

Tailwind-like utility classes for Flutter. Apply text styles, padding, margins, colors, and borders via concise string expressions.

Repository (GitHub)
View/report issues
Contributing

License

MIT (license)

Dependencies

analyzer, flutter, vector_math

More

Packages that depend on dacs